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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions