Square 取引データとレシートローラー取引データのマッピング

Square POS連携 データマッピング 技術詳細 取引データ API

Square API から取得した取引データを、レシートローラーの取引データモデルにマッピングする仕組みの技術解説です。フィールド単位の対応表、ステータスコードの変換、支払い方法の正規化、明細・顧客・スタッフ情報の解決、タイムゾーンと冪等性の扱いなど、内部仕様を理解したい開発者・運用担当者向けに整理しています。

本記事はレシートローラー側の SquarePaymentMapper の挙動をまとめたものです。一般的な「Square と連携する」「同期するとどうなる」といった操作手順は Square の POS 連携設定 をご覧ください。

基本構造

Square と レシートローラーでは、取引データの粒度に違いがあります。

  • Square 側は Payment(支払い)と Order(注文)の 2 つに分かれています。Payment が決済情報、Order が明細情報を持ちます
  • レシートローラー側は 1 つの PosTransactionDto に支払い + 明細 + 顧客 + スタッフを集約します
  • 取得時は Payment を起点に、関連する Order・TeamMember・Customer を追加で取りに行きます

主要フィールドの対応表

レシートローラー側Square 側備考
TransactionIdPayment.idSquare の支払い ID をそのまま採用。冪等な upsert のキーになります
ExternalTransactionIdPayment.id同上(外部参照用に重複保持)
TransactionDateTimePayment.created_atISO 8601 文字列 → UTC DateTime へ変換
TotalAmountPayment.amount_money.amountJPY はそのまま、他通貨は smallest unit (cents) → 主単位に変換
TaxAmountPayment.tax_money.amount同上
SubtotalAmount計算値amount - tax
DiscountAmountPayment.discount_money.amount同上
PaymentMethodPayment.card_details の有無カードデータがあれば CreditCard、なければ Other
StatusPayment.status下記「ステータス対応表」
ReceiptNumberPayment.receipt_numberSquare が発番
StaffIdPayment.team_member_id未割当の場合は空
StaffNameTeamMember.display_name別途 TeamMembers API で解決
Source固定値 "API" または "Webhook"取得経路に応じて
NotesPayment.receipt_urlレシート URL がある場合に「Receipt: ...」形式で格納
LineItemsOrder.line_items[]別途 Orders API で解決。下記「明細のマッピング」

ステータス対応表

Square Payment.statusレシートローラー Status意味
COMPLETEDCompleted会計完了
CANCELEDVoidedキャンセル
FAILEDVoided失敗(売上には含めません)
その他Pending処理中・未確定

金額の通貨変換

Square の Money オブジェクトは通貨ごとに最小単位の扱いが異なります。

  • JPY: 1 円が最小単位。amount をそのまま採用
  • USD・EUR など: 1 セントが最小単位。amount / 100 で主単位に変換

レシートローラー側はすべて主単位 (decimal) で保持します。

明細のマッピング

Square の Payment には明細情報が含まれていないため、関連する Order を別途取得して明細を展開します。Order が取得できなかった場合(権限不足・API エラー・OAuth トークン期限切れなど)は明細なしで取引が保存され、後から再同期で補完できます。

レシートローラー 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 桁で四捨五入
Category現状は常に空。Square Catalog API での解決は将来検討

顧客マッチキーの抽出

レシートローラーの自動配信パイプライン(CRM 連携)に渡すため、Square 側の顧客識別子を抽出します。

  • 主キー: Payment.customer_id(Square Customer Directory の顧客 ID)
  • フォールバック: Payment.card_details.card.fingerprint(カード番号のハッシュ。PAN ではなく Square が生成した安定識別子)

電話番号・メールは Square Payment には含まれないため、Customer Directory への追加 API 呼び出しが必要です。現状はカード fingerprint で十分マッチするケースが多いため省略しています。

取得経路

Square からの取得は 2 つの経路があり、どちらも上記マッピングを通します。

  • Webhook(リアルタイム): Square から payment.created / payment.updated/api/v1/pos/square/webhook に届きます。即座に Order・TeamMember を解決して保存。Source = "Webhook"
  • 手動同期(プル): POS 端末詳細画面の「Squareと同期」ボタンから、最終同期日 → 現在の範囲の Payment を一括取得。Source = "API"

OAuth トークンの自動リフレッシュ

Square OAuth アクセストークンは約 30 日で期限切れになります。Webhook 経路では、明細・スタッフ名取得の直前に terminal.AccessToken の有効期限を確認し、60 秒以内に切れる場合は RefreshToken で自動更新します(更新後は端末レコードに永続化)。これにより長期間 webhook 駆動の店舗でも明細の取りこぼしが起きません。

冪等性

同じ取引が複数回届いた場合(Square 側のリトライ・手動同期と Webhook の重複など)も、Payment.id をキーにした upsert で安全に再保存されます。レシートローラー側で重複レシートが発行されることはありません。

関連記事

公開日: 2026-05-29 更新日: 2026-05-29