Smaregi交易資料與ReceiptRoller交易資料的對應關係
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.TransactionId及ExternalTransactionId。
交易標頭的欄位對應
以下是Smaregi /pos/transactions 的回應(SmaregiTransaction)與ReceiptRoller的 PosTransactionDto 的對應關係。
| Smaregi | ReceiptRoller | 備註 |
|---|---|---|
transactionHeadId | TransactionId / ExternalTransactionId | 相同值保存於2個欄位。作為冪等upsert的鍵。 |
transactionDateTime | TransactionDateTime | 將JST字串轉換為UTC後保存。 |
| (幣別) | Currency | 固定保存為JPY。 |
storeId | (不直接保存) | 連動時已作為 PosTerminal.SmaregiStoreId 保存。交易端則置換為 PosTerminal.StoreId(ReceiptRoller門市ID)。 |
terminalId | (不直接保存) | 連動時已作為 PosTerminal.SmaregiTerminalId 保存。交易端則置換為 PosTerminal.TerminalId(ReceiptRoller終端ID)。 |
customerId / customerCode | ExternalIds.ProviderCustomerId(以及供CRM解析用) | 作為顧客比對鍵(後述)傳遞給CRM解析邏輯,同時也作為跨供應商ID保存於交易中。 |
staffId | StaffId | 原樣保存。 |
staffName | StaffName | 若為空值,則從 /pos/staffs/{staffId} 取得後補齊。 |
total | TotalAmount | 因Smaregi以字串形式回傳數值,故使用 decimal.TryParse。 |
subtotal | SubtotalAmount | 若為0,則從 total - tax 計算。 |
tax | TaxAmount | 同上字串解析。 |
discount | DiscountAmount | 同上。 |
status / cancelDivision | Status | 參見後述的狀態轉換表。 |
receiptNumber / terminalTransactionId | ReceiptNumber | 終端發行的收據編號。 |
paymentMethods[] | Payments[] / PaymentMethod | 各支付方式完整保存於 Payments[](對應分割結帳)。PaymentMethod 則保存主要支付方式(後述)。 |
狀態碼的轉換
Smaregi的狀態值以數值字串形式回傳。ReceiptRoller內部則正規化為字串標籤。
| Smaregi值 | 意義 | ReceiptRoller Status |
|---|---|---|
"1" | 已完成 | Completed |
"2" | 已取消 | Voided |
"3" | 退款 | Refunded |
| 不明值、空字串 | — | Pending(備援) |
依規格不同,欄位名稱有時會同時使用 status 與 cancelDivision。系統會綜合查看兩者的數值進行判斷,只要能取得其中一項,即可正確分類。
支付方式的正規化
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 SmaregiTransactionDetail | ReceiptRoller PosTransactionLineItemDto | 備註 |
|---|---|---|
productName | ProductName | 原樣。 |
quantity | Quantity | 將字串四捨五入為整數。0以下則補正為1。 |
price | UnitPrice | 字串解析。 |
subtotal | Subtotal | 字串解析。 |
taxRate | TaxRate | 字串解析。 |
tax | TaxAmount | 明細單位的稅額。不僅稅率,金額本身也一併保存。 |
productId | CatalogObjectId / ProductId | 供系統間連動使用的目錄ID。 |
categoryName | Category | 原樣。 |
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(交易發生時間點)不會改變。
匯入流程的整體概觀
- Smaregi端發生交易 → 由Smaregi Platform向ReceiptRoller發送Webhook
- ReceiptRoller的Webhook接收端點執行自訂標頭驗證
- 從負載中擷取
transactionHeadIds(可能有多個) - 針對各ID,從Platform API取得交易標頭+明細+員工資訊
- 透過
SmaregiTransactionMapper轉換為PosTransactionDto - 將顧客比對鍵傳遞給
IPosCustomerMatchService,執行CRM解析 - 透過
PosTransactionService.UpsertAsync保存(重複則覆寫更新) - 更新
PosTerminal.LastTransactionAt(供QR掃描路徑的最新交易顯示使用) - 若已判明顧客身分,則交予自動發送服務(電子收據發送)
相關文章
- PosTransactionDto規格(欄位參考文件) — 各欄位的詳細規格
- 與Square交易資料的對應關係 — Square版
- Smaregi的POS連動設定 — 連動步驟
- 與POS的連動
- Square的POS連動設定
- Smaregi、Square的會員資訊雙向同步
- 顧客別購買履歷(POS連動)
-
Smaregi商品資料與ReceiptRoller商品資料的對應關係說明Smaregi的商品主檔資料如何轉換為ReceiptRoller的商品主檔(ProductDto),逐欄位整理商品代碼、商品名稱、分類、售價、成本、稅率的對應關係,以及Smaregi特有的注意事項。
-
Smaregi員工資料與ReceiptRoller員工資料的對應關係說明Smaregi的員工主檔資料如何轉換為ReceiptRoller的員工資料(StaffDto),逐欄位整理對應關係。內容涵蓋staffName的姓名拆分邏輯、staffCode對應EmployeeNumber、以及displayFlag如何略過未顯示的員工等重點。
-
Smaregi會員資料與ReceiptRoller顧客資料的對應關係說明Smaregi的會員主檔如何轉換為ReceiptRoller的顧客資料(CrmCustomerDto)。內容涵蓋會員編號、姓名、聯絡方式、地址、生日的對應關係,以及電話號碼的優先順序、透過Webhook的同步時機等重點。
-
Smaregi・Square 與會員資訊的雙向同步ReceiptRoller 的會員資訊與連動的 POS(Smaregi・Square 等)雙向同步。本文說明雙向同步的機制、同步項目、同步時機、衝突時的優先順序、支援的 POS、設定方式、疑難排解。
-
Smaregi × ReceiptRoller — 電子收據、顧客管理、銷售分析整合於一個應用程式只要用 Smaregi 結帳,就能自動觸發電子收據發行、顧客會員管理、結合購買資料的銷售分析與 AI 建議、Apple/Google Wallet 會員證、社群媒體串連、傳單發送。只需在 Smaregi App Market 安裝「ReceiptRoller Link」,無需繁瑣的 API 設定,今天就能開始使用。