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

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

從Square API取得的交易資料,是如何對應至ReceiptRoller交易資料模型的技術解說。內容涵蓋欄位層級的對應表、狀態碼的轉換、支付方式的正規化、明細/顧客/員工資訊的解析、時區與冪等性的處理等,整理成供想理解內部規格的開發者、營運負責人參考的文件。

本文整理的是ReceiptRoller端 SquarePaymentMapper 的運作方式。一般「如何與Square連動」「同步後會發生什麼」等操作步驟,請參閱Square的POS連動設定。欄位層級的正式模型規格請參閱PosTransactionDto規格(欄位參考文件)

基本結構

Square與ReceiptRoller在交易資料的顆粒度上有所差異。

  • Square端分為Payment(支付)與Order(訂單)兩者。Payment持有付款資訊,Order持有明細資訊
  • ReceiptRoller端則將支付+明細+顧客+員工整合為單一個PosTransactionDto
  • 取得時以Payment為起點,額外一併取得相關的Order、TeamMember、Customer

主要欄位對應表

ReceiptRoller端Square端備註
TransactionIdPayment.id直接沿用Square的支付ID。作為冪等upsert的鍵。
ExternalTransactionIdPayment.id同上(為供外部參照而重複保存)
TransactionDateTimePayment.created_atISO 8601字串 → 轉換為UTC DateTime
CurrencyPayment.amount_money.currency幣別代碼。預設JPY
TotalAmountPayment.amount_money.amountJPY直接沿用,其他幣別由最小單位(cents)轉換為主單位
TaxAmountPayment.tax_money.amount同上
SubtotalAmount計算值amount - tax
DiscountAmountPayment.discount_money.amount同上
TipAmountPayment.tip_money.amount小費。若有則帶入
PaymentMethodPayment.card_details 的有無若有卡片資料則為 CreditCard,否則為 Other(代表性支付方式。明細見下方 Payments
Payments[]Payment 1筆 + card_details.card支付方式明細。Method / Amounttotal_money)/ Brand(card_brand)/ Last4(last_4)
StatusPayment.status見下方「狀態對應表」
ReceiptNumberPayment.receipt_number由Square發放
ReceiptUrlPayment.receipt_url顧客用收據URL。保存於結構化欄位(過去曾存放於Notes,現已廢止)
ExternalIdsorder_id / location_id / customer_id跨供應商ID(ProviderOrderId / LocationId / ProviderCustomerId
StaffIdPayment.team_member_id未指派時為空
StaffNameTeamMember.display_name透過另一個TeamMembers API解析
Source固定值 "API""Webhook"依取得路徑而定
RawJsonPayment + Order的原始負載保留未建模的欄位(卡片fingerprint等),以便日後可還原。API不會回傳此欄位
LineItemsOrder.line_items[]透過另一個Orders API解析。見下方「明細的對應關係」

狀態對應表

Square Payment.statusReceiptRoller Status意義
COMPLETEDCompleted已完成結算
CANCELEDVoided已取消
FAILEDVoided失敗(不計入銷售額)
其他Pending處理中/未確定

金額的幣別轉換

Square的 Money 物件,依幣別不同,最小單位的處理方式也不同。

  • JPY:1圓為最小單位。直接沿用 amount
  • USD、EUR等:1分為最小單位。以 amount / 100 轉換為主單位

ReceiptRoller端一律以主單位(decimal)保存,並將幣別代碼保存於 Currency

明細的對應關係

因Square的 Payment 不含明細資訊,故需另行取得相關的 Order 以展開明細。若無法取得Order(權限不足、API錯誤、OAuth權杖過期等情況),交易將在無明細的狀態下先行儲存,之後可透過再次同步補齊。

ReceiptRoller LineItemSquare Order.line_items[]備註
ProductNamename + variation_name若有規格變化款,則以「商品名稱 (規格變化款名稱)」的形式呈現
Quantityquantity將字串解析為整數。失敗時預設為1
UnitPricebase_price_money.amount有幣別轉換
Subtotaltotal_money.amount若無法取得,則以 UnitPrice × Quantity 計算
TaxRate計算值(total_tax_money / (total_money - total_tax_money)) × 100,四捨五入至小數點後1位
TaxAmounttotal_tax_money.amount明細單位的稅額。不僅稅率,金額本身也一併保存
DiscountAmounttotal_discount_money.amount明細單位的折扣金額
CatalogObjectIdcatalog_object_id與Square目錄的關聯ID
Modifiersmodifiers[]選項、修飾項目(name + total_price_money
Category目前經常為空值。透過Square Catalog API解析為未來評估項目

顧客比對鍵的擷取

為傳遞給ReceiptRoller的自動發送管道(CRM連動),需擷取Square端的顧客識別碼。

  • 主鍵Payment.customer_id(Square Customer Directory的顧客ID)。交易中也以 ExternalIds.ProviderCustomerId 的形式保留
  • 備援Payment.card_details.card.fingerprint(卡號的雜湊值。並非PAN,而是Square產生的穩定識別碼。保存於 RawJson 內,API不會回傳此欄位)

由於Square Payment不含電話號碼、電子郵件,因此需要對Customer Directory進行額外的API呼叫。目前多數情況下卡片fingerprint即已足夠比對,故予以省略。

OAuth權杖的自動更新

Square OAuth存取權杖約30天到期。在Webhook路徑中,會於取得明細、員工姓名之前,先確認 terminal.AccessToken 的有效期限,若在60秒內即將到期,則以 RefreshToken 自動更新(更新後會持久化至終端紀錄)。這使得即使是長期以webhook驅動的門市,也不會發生明細取得中斷的情況。

冪等性

即使同一筆交易多次送達(如Square端的重試、手動同步與Webhook重複等情況),系統也會以 Payment.id 為鍵進行upsert,安全地重新保存。ReceiptRoller端不會因此發出重複的收據。

相關文章

發布日期: 2026-05-29 更新日期: 2026-07-03