Smaregi交易資料與ReceiptRoller交易資料的對應關係

Smaregi POS連動 資料對應 技術詳細 交易資料 API

ReceiptRoller與包含Smaregi在內的多個POS供應商連動。無論從哪個供應商匯入的交易,內部都能以共通的交易資料模型(PosTransactionDto)處理,因此會將供應商特有的欄位正規化。本文將技術性地解說Smaregi Platform API的交易資料,如何對應至ReceiptRoller的內部模型。

本文是給想理解POS連動內部規格的開發者、營運負責人參考的資料。日常連動的設定步驟請參閱Smaregi的POS連動設定。欄位層級的正式模型規格請參閱PosTransactionDto規格(欄位參考文件)

層級結構的對應

Smaregi Platform API擁有合約、門市、終端、交易這4個層級。ReceiptRoller端則以商業帳戶、門市、POS終端、交易這4個層級,在設計上一對一對應。

  • 合約(contractId) ↔ ReceiptRoller的商業帳戶。在Smaregi安裝「ReceiptRoller連結」App時,該合約便會連結至ReceiptRoller的一個商業帳戶(SmaregiContract.OrganizationId)。
  • Smaregi門市(storeId) ↔ ReceiptRoller門市。透過 PosTerminal.SmaregiStoreId 連結至ReceiptRoller端的POS終端。
  • Smaregi終端(terminalId) ↔ ReceiptRoller的POS終端。保存於 PosTerminal.SmaregiTerminalId,1個ReceiptRoller POS終端(收銀機)對應1個Smaregi終端。
  • 交易(transactionHeadId) ↔ ReceiptRoller的交易。同一ID會被保存為 PosTransaction.TransactionIdExternalTransactionId

交易標頭的欄位對應

以下是Smaregi /pos/transactions 的回應(SmaregiTransaction)與ReceiptRoller的 PosTransactionDto 的對應關係。

Smaregi ReceiptRoller 備註
transactionHeadIdTransactionId / ExternalTransactionId相同值保存於2個欄位。作為冪等upsert的鍵。
transactionDateTimeTransactionDateTime將JST字串轉換為UTC後保存。
(幣別)Currency固定保存為JPY。
storeId(不直接保存)連動時已作為 PosTerminal.SmaregiStoreId 保存。交易端則置換為 PosTerminal.StoreId(ReceiptRoller門市ID)。
terminalId(不直接保存)連動時已作為 PosTerminal.SmaregiTerminalId 保存。交易端則置換為 PosTerminal.TerminalId(ReceiptRoller終端ID)。
customerId / customerCodeExternalIds.ProviderCustomerId(以及供CRM解析用)作為顧客比對鍵(後述)傳遞給CRM解析邏輯,同時也作為跨供應商ID保存於交易中。
staffIdStaffId原樣保存。
staffNameStaffName若為空值,則從 /pos/staffs/{staffId} 取得後補齊。
totalTotalAmount因Smaregi以字串形式回傳數值,故使用 decimal.TryParse
subtotalSubtotalAmount若為0,則從 total - tax 計算。
taxTaxAmount同上字串解析。
discountDiscountAmount同上。
status / cancelDivisionStatus參見後述的狀態轉換表。
receiptNumber / terminalTransactionIdReceiptNumber終端發行的收據編號。
paymentMethods[]Payments[] / PaymentMethod各支付方式完整保存於 Payments[](對應分割結帳)。PaymentMethod 則保存主要支付方式(後述)。

狀態碼的轉換

Smaregi的狀態值以數值字串形式回傳。ReceiptRoller內部則正規化為字串標籤。

Smaregi值意義ReceiptRoller Status
"1"已完成Completed
"2"已取消Voided
"3"退款Refunded
不明值、空字串Pending(備援)

依規格不同,欄位名稱有時會同時使用 statuscancelDivision。系統會綜合查看兩者的數值進行判斷,只要能取得其中一項,即可正確分類。

支付方式的正規化

Smaregi的 paymentMethods 以陣列形式回傳,每個元素都包含支付方式名稱與金額(分割結帳時會有多個元素)。ReceiptRoller將所有支付方式明細完整保存於 Payments[],另外為方便後續互換,僅將「主要支付方式」保存於1個 PaymentMethod 中。主要方式是從陣列中採用金額最大的元素,並將其日文表記正規化為內部代碼。

Smaregi的表記ReceiptRoller內部代碼
含「現金」Cash
含「信用卡」CreditCard
含「QR」QR
含「電子錢包」或「IC」IC
陣列為空、無對應項目Other

Smaregi的交易一覽API有時不含支付方式,此時會從另一個端點補充取得。實作的最新狀況請參閱原始碼(SmaregiTransactionMapper)。

明細(行項目)的對應關係

與交易標頭分開,系統會從 /pos/transactions/{id}/details 取得明細資料,並轉換為 PosTransactionLineItemDto 的陣列,序列化保存至 LineItemsJson

Smaregi SmaregiTransactionDetailReceiptRoller PosTransactionLineItemDto備註
productNameProductName原樣。
quantityQuantity將字串四捨五入為整數。0以下則補正為1。
priceUnitPrice字串解析。
subtotalSubtotal字串解析。
taxRateTaxRate字串解析。
taxTaxAmount明細單位的稅額。不僅稅率,金額本身也一併保存。
productIdCatalogObjectId / ProductId供系統間連動使用的目錄ID。
categoryNameCategory原樣。

ItemCount(交易整體的購買點數)是以明細 Quantity 的合計計算得出。

關於明細單位的折扣金額,預計於確定Smaregi transactionDetails的對應欄位名稱後進行對應。在確定之前,DiscountAmount 將維持為null,並保存於原始負載(RawJson)中,以防止資料遺失。

原始資料(RawJson)的保存

匯入時,系統會將交易標頭+明細的來源原始負載保存至 RawJson。這是為了讓未建模的欄位日後也能還原的安全措施,僅供伺服器內部使用(API不會回傳此欄位)。

顧客資訊的解析(CRM連動)

從Smaregi取得的 customerId / customerCode,除了作為顧客比對鍵傳遞給CRM解析服務(IPosCustomerMatchService)之外,也會作為跨供應商ID保存於 ExternalIds.ProviderCustomerId。若比對成功,交易便會自動連結至ReceiptRoller的CRM顧客檔案,並用於計算顧客別的購買履歷及流失風險預測分數。

比對鍵的主要種類如下(實作請參照 PosCustomerMatchDto)。

  • 會員編號(會員資格代碼)— Smaregi的 customerCode
  • 外部顧客ID — Smaregi的 customerId
  • 電子郵件地址、電話號碼 — 僅限能從Smaregi取得的情況

比對未成立的交易,也可透過門市終端的QR掃描,讓顧客事後自行連結。

員工資訊的補齊

有些情況下交易標頭僅含 staffId。此時會另行呼叫 /pos/staffs/{staffId} 取得 displayName,並保存至 StaffName。即使取得員工姓名失敗,交易匯入本身也不會失敗,會保留空值繼續進行(以防止交易資料缺損)。

取得路徑(Source)的區別

即使是同一筆交易,系統也會以 Source 欄位區分是透過哪個路徑匯入的。

  • Webhook — 由Smaregi即時推送的路徑
  • Sync — 門市經營者按下「與Smaregi同步」按鈕的手動同步路徑
  • API — 其他透過Platform API取得的方式(如QR掃描時的即時取得等)

即使同一個 transactionHeadId 透過多個路徑送達,也會以同一ID為鍵進行upsert,因此交易不會重複。Source值會反映最後一次匯入的路徑

時區的處理

Smaregi Platform API以JST(+09:00)的ISO 8601格式回傳日期時間。ReceiptRoller端一律以UTC保存,顯示時再轉換為JST。向Platform API傳送日期時間篩選條件時,也會將UTC轉換為JST並進行URL編碼後傳送(以避免 +09:00 中的 + 符號被誤解為空白)。

冪等性

交易的upsert以 transactionHeadId 為鍵進行。即使同一筆交易同時透過Webhook與手動同步兩種路徑送達,最終也會歸併為1筆記錄。UpdatedAt 會更新為最新的匯入時間點,但 TransactionDateTime(交易發生時間點)不會改變。

匯入流程的整體概觀

  1. Smaregi端發生交易 → 由Smaregi Platform向ReceiptRoller發送Webhook
  2. ReceiptRoller的Webhook接收端點執行自訂標頭驗證
  3. 從負載中擷取 transactionHeadIds(可能有多個)
  4. 針對各ID,從Platform API取得交易標頭+明細+員工資訊
  5. 透過 SmaregiTransactionMapper 轉換為 PosTransactionDto
  6. 將顧客比對鍵傳遞給 IPosCustomerMatchService,執行CRM解析
  7. 透過 PosTransactionService.UpsertAsync 保存(重複則覆寫更新)
  8. 更新 PosTerminal.LastTransactionAt(供QR掃描路徑的最新交易顯示使用)
  9. 若已判明顧客身分,則交予自動發送服務(電子收據發送)

相關文章

發布日期: 2026-05-28 更新日期: 2026-07-03
相關文章