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: 基盤構築
Phase 2: API実装
Phase 3: 変換・サービス層
Phase 4: 品質・セキュリティ
Phase 5: テスト・運用
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 |
レスポンス出力 |
技術的考慮事項
- 既存購入フローとの共存: 既存の
LC_Page_Shopping_* による購入フローとUCP経由の購入フローの統合
- 受注一時テーブル活用:
dtb_order_temp を活用したセッション管理の検討
- トランザクション管理: 受注完了時の複合トランザクション(dtb_order, dtb_order_detail, dtb_shipping, dtb_shipment_item)
- 在庫管理:
SC_Helper_Purchase::registerOrderComplete() 内の在庫減少処理との連携
- ポイント管理:
add_point, use_point との整合性
- セッション有効期限:
dtb_checkout_session.expires_at による期限切れ処理
- クリーンアップ: 期限切れセッションの定期削除(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
refs EC-CUBE/ec-cube#6574
概要(Overview)
Google Merchant の ユニバーサル コマース プロトコル(UCP) を使用した購入完了機能の実装
https://developers.google.com/merchant/ucp/guides/checkout/native?hl=ja
期待する内容(Expect) or 要望(Requirement)
ユニバーサル コマース プロトコル(UCP)を使用して購入完了できる
実装必須の3つのエンドポイント
1. 購入手続きセッション作成エンドポイント
POST /checkout-sessions2. セッション更新エンドポイント
PUT /checkout-sessions/{id}3. セッション完了エンドポイント
POST /checkout-sessions/{id}/complete追加が必要なデータフィールド
1. 新規テーブル:
dtb_checkout_session(必須)UCPのセッション管理用に新規テーブルが必要
checkout_session_idsession_idstatuscurrencyexpires_atorder_idorder_temp_idbuyer_datafulfillment_datapayment_dataselected_shipping_optioncreate_dateupdate_datedel_flgインデックス:
dtb_checkout_session_session_id_keyON (session_id) - UNIQUEdtb_checkout_session_order_id_keyON (order_id)2. 店舗設定への追加フィールド(
dtb_baseinfo)privacy_policy_urlterms_of_service_urlucp_enabledgoogle_pay_merchant_idgoogle_pay_merchant_name3. 配送業者への追加フィールド(
dtb_deliv)(任意)estimated_delivery_days_minestimated_delivery_days_maxcarrier_codeデータ形式のマッピング対応
住所フォーマット変換(EC-CUBE 2系 → UCP)
EC-CUBE 2系は電話番号・郵便番号が分割されているため、結合処理が必要
order_name01+order_name02recipient_nameorder_zip01+order_zip02またはorder_zipcodepostal_codemtb_pref.name(viaorder_pref)regionorder_addr01localityorder_addr02address1,address2mtb_country.iso_code(viaorder_country_id)countryorder_tel01+order_tel02+order_tel03phone購入者情報マッピング
order_name01last_nameorder_name02first_nameorder_emailemailorder_tel01-order_tel03phone金額単位変換(センス/マイナー単位)
UCPでは金額をマイナー単位(整数)で表現する。
105010501000(変換不要)日本円は「ゼロデシマル通貨」のため、基本的に変換不要(numeric → int のキャストのみ)
実装タスク
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活用)Phase 5: テスト・運用
EC-CUBE 4系との実装差異
既存クラスの活用
SC_Helper_PurchaseSC_Helper_DeliverySC_Helper_TaxRuleSC_CartSessionSC_CheckErrorSC_Response技術的考慮事項
LC_Page_Shopping_*による購入フローとUCP経由の購入フローの統合dtb_order_tempを活用したセッション管理の検討SC_Helper_Purchase::registerOrderComplete()内の在庫減少処理との連携add_point,use_pointとの整合性dtb_checkout_session.expires_atによる期限切れ処理参考リソース
data/class/helper/SC_Helper_Purchase.phpdata/class/pages/shopping/LC_Page_Shopping_Complete.phpdata/class/SC_CartSession.phpdocs/database-schema/public.dtb_order.mddocs/database-schema/public.dtb_shipping.mddocs/database-schema/public.dtb_baseinfo.md