Skip to content

ユニバーサル コマース プロトコル(UCP)の対応 #1300

@nanasess

Description

@nanasess

refs EC-CUBE/ec-cube#6574

概要(Overview)

Google Merchant の ユニバーサル コマース プロトコル(UCP) を使用した購入完了機能の実装

https://developers.google.com/merchant/ucp/guides/checkout/native?hl=ja

2系に元々ある API 機能の実装は古すぎるので無視してよいと思います

期待する内容(Expect) or 要望(Requirement)

ユニバーサル コマース プロトコル(UCP)を使用して購入完了できる


実装必須の3つのエンドポイント

1. 購入手続きセッション作成エンドポイント

  • エンドポイント: POST /checkout-sessions
  • 役割: ユーザーが商品購入を決定した際に、購入検討中の商品を含むセッションを作成
  • リクエスト: 商品情報(ID、タイトル)、数量、通貨
  • レスポンス: セッションID、合計額、税金(推定)、決済ハンドラー情報、利用規約・プライバシーポリシーへのリンク

2. セッション更新エンドポイント

  • エンドポイント: PUT /checkout-sessions/{id}
  • 役割: 配送先住所更新時の税金・配送オプション再計算など、セッション情報の変更対応
  • リクエスト: 更新された配送先、決済情報を含む完全なチェックアウトオブジェクト
  • レスポンス: 再計算された税金、送料、合計額、配送方法オプション

3. セッション完了エンドポイント

  • エンドポイント: POST /checkout-sessions/{id}/complete
  • 役割: ユーザーが「注文する」をクリックした際のセッション完了と注文確定
  • リクエスト: 決済情報とリスクシグナル
  • レスポンス: 注文IDと注文へのパーマリンクURL

追加が必要なデータフィールド

1. 新規テーブル: dtb_checkout_session(必須)

UCPのセッション管理用に新規テーブルが必要

カラム名 Default Nullable Comment
checkout_session_id integer (auto) false チェックアウトセッションID (PRIMARY KEY)
session_id text false UCPセッションID(UUID形式、UNIQUE)
status smallint 1 false セッション状態: 1=incomplete / 2=completed
currency text 'JPY' false 通貨コード
expires_at timestamp true セッション有効期限
order_id integer true 関連受注ID(完了後に設定)
order_temp_id text true 関連受注一時ID
buyer_data text true 購入者情報(JSON: first_name, last_name, email)
fulfillment_data text true 配送先・配送方法選択情報(JSON)
payment_data text true 決済情報(JSON)
selected_shipping_option text true 選択された配送オプションID
create_date timestamp CURRENT_TIMESTAMP false 作成日時
update_date timestamp false 更新日時
del_flg smallint 0 false 削除フラグ

インデックス:

  • dtb_checkout_session_session_id_key ON (session_id) - UNIQUE
  • dtb_checkout_session_order_id_key ON (order_id)

2. 店舗設定への追加フィールド(dtb_baseinfo

カラム名 Default Nullable Comment
privacy_policy_url text true プライバシーポリシーURL
terms_of_service_url text true 利用規約URL
ucp_enabled smallint 0 false UCP機能有効フラグ (0=無効, 1=有効)
google_pay_merchant_id text true Google Pay マーチャントID
google_pay_merchant_name text true Google Pay マーチャント名

3. 配送業者への追加フィールド(dtb_deliv)(任意)

カラム名 Default Nullable Comment
estimated_delivery_days_min integer true 最短お届け日数
estimated_delivery_days_max integer true 最長お届け日数
carrier_code text true 配送業者コード

データ形式のマッピング対応

住所フォーマット変換(EC-CUBE 2系 → UCP)

EC-CUBE 2系は電話番号・郵便番号が分割されているため、結合処理が必要

EC-CUBE 2 UCP 変換処理
order_name01 + order_name02 recipient_name 姓名結合
order_zip01 + order_zip02 または order_zipcode postal_code 結合または海外対応フィールド使用
mtb_pref.name (via order_pref) region 都道府県名取得
order_addr01 locality 市区町村
order_addr02 address1, address2 番地・建物名
mtb_country.iso_code (via order_country_id) country ISO 3166-1 alpha-2
order_tel01 + order_tel02 + order_tel03 phone 電話番号結合

購入者情報マッピング

EC-CUBE 2 UCP 備考
order_name01 last_name
order_name02 first_name
order_email email メールアドレス
order_tel01-order_tel03 phone 電話番号(結合)

金額単位変換(センス/マイナー単位)

UCPでは金額をマイナー単位(整数)で表現する。

通貨 補助単位 変換例
USD(米ドル) セント $10.50 → 1050
EUR(ユーロ) セント €10.50 → 1050
JPY(日本円) なし ¥1000 → 1000(変換不要)

日本円は「ゼロデシマル通貨」のため、基本的に変換不要(numeric → int のキャストのみ)

// JPY専用のシンプルな実装
$ucpAmount = (int) round($order['total']);

// 多通貨対応の場合
function toMinorUnits($amount, $currency = 'JPY') {
    $decimals = array(
        'JPY' => 0, 'KRW' => 0, 'TWD' => 0,  // ゼロデシマル通貨
    );
    $dec = isset($decimals[$currency]) ? $decimals[$currency] : 2;
    
    if ($dec === 0) {
        return (int) round($amount);
    }
    return (int) round($amount * pow(10, $dec));
}

実装タスク

Phase 1: 基盤構築

  • dtb_checkout_session テーブル作成(マイグレーションSQL)
  • dtb_baseinfo へのUCP関連カラム追加
  • SC_Helper_CheckoutSession ヘルパークラス作成

Phase 2: API実装

  • LC_Page_Api_CheckoutSession クラス作成
  • POST /checkout-sessions エンドポイント実装
  • PUT /checkout-sessions/{id} エンドポイント実装
  • POST /checkout-sessions/{id}/complete エンドポイント実装
  • 既存 SC_Helper_Purchase との連携

Phase 3: 変換・サービス層

  • 住所フォーマット変換関数実装(電話番号・郵便番号結合)
  • 金額単位変換関数実装
  • 税金・送料再計算ロジック実装

Phase 4: 品質・セキュリティ

  • リクエストバリデーション実装(SC_CheckError 活用)
  • エラーハンドリング(UCPプロトコル準拠のJSON形式)
  • API認証・セキュリティ対策
  • CSRF対策

Phase 5: テスト・運用

  • PHPUnit テスト作成
  • API仕様書作成
  • Google Merchant設定手順ドキュメント

EC-CUBE 4系との実装差異

項目 EC-CUBE 2系 EC-CUBE 4系
アーキテクチャ 手続き型・LC_Page ベース Symfony Controller ベース
ORM SC_Query(生SQL) Doctrine ORM
購入処理 SC_Helper_Purchase PurchaseFlow(プロセッサパターン)
バリデーション SC_CheckError Symfony Validator
セッション管理 $_SESSION 直接操作 Symfony Session
JSONレスポンス 手動echo JsonResponse
電話番号 3分割(tel01, tel02, tel03) 1フィールド(phone_number)
郵便番号 2分割 or 海外対応1フィールド 1フィールド(postal_code)
受注一時情報 dtb_order_temp テーブル pre_order_id による管理

既存クラスの活用

既存クラス 用途
SC_Helper_Purchase 受注処理(registerOrderComplete, registerOrder等)
SC_Helper_Delivery 配送業者・送料取得
SC_Helper_TaxRule 税率計算
SC_CartSession カート操作
SC_CheckError バリデーション
SC_Response レスポンス出力

技術的考慮事項

  1. 既存購入フローとの共存: 既存の LC_Page_Shopping_* による購入フローとUCP経由の購入フローの統合
  2. 受注一時テーブル活用: dtb_order_temp を活用したセッション管理の検討
  3. トランザクション管理: 受注完了時の複合トランザクション(dtb_order, dtb_order_detail, dtb_shipping, dtb_shipment_item)
  4. 在庫管理: SC_Helper_Purchase::registerOrderComplete() 内の在庫減少処理との連携
  5. ポイント管理: add_point, use_point との整合性
  6. セッション有効期限: dtb_checkout_session.expires_at による期限切れ処理
  7. クリーンアップ: 期限切れセッションの定期削除(cron)

参考リソース

  • Google UCP ドキュメント
  • EC-CUBE 4系 UCP Issue
  • 既存実装参考:
    • data/class/helper/SC_Helper_Purchase.php
    • data/class/pages/shopping/LC_Page_Shopping_Complete.php
    • data/class/SC_CartSession.php
  • テーブル定義:
    • docs/database-schema/public.dtb_order.md
    • docs/database-schema/public.dtb_shipping.md
    • docs/database-schema/public.dtb_baseinfo.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions