b2c-ordering について
Salesforce B2C Commerceの注文を扱う開発者向けのスキルです。OrderMgrによる作成、検索、状態遷移に加え、SCAPIでの決済認証と注文確定の流れを説明します。
主な機能
- 01注文ライフサイクルと状態遷移
- 02注文の作成と検索
- 03キャンセル、失敗、バスケット再開
- 04SCAPIの決済と注文確定の手順
活用シーン
- 01チェックアウトでの注文作成
- 02決済失敗後の再試行処理
- 03状態や日付による注文検索
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ salesforcecommercecloud/ b2c-developer-tooling --skill b2c-orderingインストール後、Claude Code で/b2c-orderingを入力して読み込まれたか確認します。
同梱ファイルevals/trigger-evals.json
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
B2C の注文
OrderMgr API は、注文の作成、ステータス管理、検索を提供します。注文のライフサイクルを理解することは、チェックアウトの実装と注文処理に不可欠です。
注文のライフサイクル
注文は次のステータスで進行します。
Basket → CREATED → NEW → (COMPLETED or CANCELLED or FAILED)
| ステータス | 説明 | 遷移可能なステータス |
|---|---|---|
CREATED | 注文が作成されましたが、まだ確定されていません | NEW、FAILED |
NEW | 注文が確定され、フルフィルメント待ちです | OPEN、COMPLETED、CANCELLED、FAILED |
OPEN | 注文を処理中です | COMPLETED、CANCELLED |
COMPLETED | 注文のフルフィルメントが完了しました | - |
CANCELLED | 注文がキャンセルされました | NEW(undoCancel 経由) |
FAILED | 注文に失敗しました(決済、検証) | -(再開できません) |
重要: 注文が FAILED ステータスになると、再開もキャンセルもできません。代わりに failOrder(order, true) を使用して、再試行できるようにバスケットを再開してください。
注文の作成
標準フロー(同期)
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
var Status = require('dw/system/Status');
function createOrder(basket) {
var order;
Transaction.wrap(function() {
// Create order from basket (status: CREATED)
order = OrderMgr.createOrder(basket);
});
if (!order) {
return { error: true, message: 'Order creation failed' };
}
// Authorize payment
var paymentResult = authorizePayment(order);
if (!paymentResult.success) {
Transaction.wrap(function() {
OrderMgr.failOrder(order, true); // Reopen basket
});
return { error: true, message: 'Payment failed' };
}
// Place the order (status: CREATED → NEW)
var placeResult;
Transaction.wrap(function() {
placeResult = OrderMgr.placeOrder(order);
});
if (placeResult.error) {
return { error: true, message: 'Order placement failed' };
}
// Set confirmation status
Transaction.wrap(function() {
order.setConfirmationStatus(order.CONFIRMATION_STATUS_CONFIRMED);
});
return { error: false, order: order };
}
SCAPI フロー:作成し、Order PI を通じて承認してから確定する
order.afterPOST から手動で確定するのではなく、Shopper Orders のステートマシンを先に使用します。
POST /checkout/shopper-orders/v1/organizations/{orgId}/orders
-> commits order in CREATED
PATCH /checkout/shopper-orders/v1/organizations/{orgId}/orders/{orderNo}/payment-instruments/{piId}
-> invokes dw.order.payment.authorizeCreditCard or dw.order.payment.authorize
-> passes successfullyAuthorized to order.payment_instrument.afterPATCH
-> default afterPATCH places when authorized coverage reaches the order total
NEW -> success
CREATED -> not fully placed; authorize remaining PIs, fail safely, or reconcile
カスタムの order-PI afterPATCH 実装が成功した場合は、undefined を返してください。これにより、プラットフォームのデフォルトのカバレッジベースの確定動作が実行されます。Status が null 以外の場合、実行は終了し、その実装は抑制されます。
決定的な決済失敗の場合は、reopenBasket=true を指定して Shopper Orders の失敗アクションを使用します。ゲートウェイの結果が不確定な場合は、重複承認のリスクを避けるため、照合できるよう CREATED 注文を保持します。
チェックアウトで、作成、承認、Commerce 側の確定または失敗の遷移を、単一のサーバー側フェーズで行う必要がある場合や、プロセッサーが order-PI 承認に対応できない場合は、代替手段として dw.ocapi.shop.order.afterPOST を使用します。このフックは注文作成のトランザクション内で実行されます。ネストした Transaction.wrap は追加しないでください。また、Status.ERROR によって Commerce の注文はロールバックされますが、外部ゲートウェイの副作用はロールバックされないことに注意してください。b2c-hooks を参照してください。
OrderMgr API リファレンス
注文の作成
| メソッド | 説明 |
|---|---|
createOrder(basket) | 自動生成された番号で注文を作成します |
createOrder(basket, orderNo) | 指定した番号で注文を作成します |
createOrderNo() | 次の注文番号を生成します |
createOrderSequenceNo() | 次のシーケンス番号を取得します(カスタム形式用) |
注文ステータス
| メソッド | 説明 |
|---|---|
placeOrder(order) | 注文を確定します(CREATED → NEW) |
failOrder(order, reopenBasket) | 注文を失敗として設定します(FAILED ステータスに設定) |
cancelOrder(order) | 注文をキャンセルします(CANCELLED ステータスに設定) |
undoCancelOrder(order) | キャンセルされた注文を NEW に戻します |
注: undoFailOrder() メソッドはありません。失敗した注文は再開できません。代わりに failOrder(order, true) を使用して、再試行できるようにバスケットを再開してください。
注文の検索
| メソッド | 説明 |
|---|---|
getOrder(orderNo) | 注文番号で注文を取得します |
searchOrder(query, ...args) | 単一の注文を検索します |
searchOrders(query, sortString, ...args) | 複数の注文を検索します |
queryOrder(query, ...args) | 単一の注文をクエリします |
queryOrders(query, sortString, ...args) | 複数の注文をクエリします |
注文の検索
注文番号で取得
var OrderMgr = require('dw/order/OrderMgr');
var order = OrderMgr.getOrder('00001234');
if (order) {
var status = order.status.value;
var total = order.totalGrossPrice;
}
注文の検索
var OrderMgr = require('dw/order/OrderMgr');
// Search by customer email
var orders = OrderMgr.searchOrders(
'customerEmail = {0} AND status != {1}',
'creationDate desc',
'[email protected]',
dw.order.Order.ORDER_STATUS_FAILED
);
while (orders.hasNext()) {
var order = orders.next();
// Process order
}
orders.close();
日付範囲でクエリ
var OrderMgr = require('dw/order/OrderMgr');
var Calendar = require('dw/util/Calendar');
var startDate = new Calendar();
startDate.add(Calendar.DAY_OF_YEAR, -7);
var orders = OrderMgr.searchOrders(
'creationDate >= {0} AND status = {1}',
'creationDate desc',
startDate.time,
dw.order.Order.ORDER_STATUS_NEW
);
while (orders.hasNext()) {
var order = orders.next();
// Process order
}
orders.close();
注文ステータスの管理
注文のキャンセル
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
var Order = require('dw/order/Order');
function cancelOrder(orderNo) {
var order = OrderMgr.getOrder(orderNo);
if (!order) {
return { error: true, message: 'Order not found' };
}
// Can only cancel NEW or OPEN orders
if (order.status.value !== Order.ORDER_STATUS_NEW &&
order.status.value !== Order.ORDER_STATUS_OPEN) {
return { error: true, message: 'Order cannot be cancelled' };
}
Transaction.wrap(function() {
OrderMgr.cancelOrder(order);
});
return { error: false };
}
注文の失敗
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
function failOrder(order, reopenBasket) {
// reopenBasket: true = customer can retry checkout
// false = basket is lost
Transaction.wrap(function() {
OrderMgr.failOrder(order, reopenBasket);
});
}
失敗した注文の処理
失敗した注文は再開できません。 代わりに failOrder(order, true) を使用して、バスケットを再開してください。
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
// When payment fails, fail the order and reopen basket
function handlePaymentFailure(order) {
Transaction.wrap(function() {
// reopenBasket=true allows customer to retry checkout
OrderMgr.failOrder(order, true);
});
// Basket is now available again for the customer
return { error: true, message: 'Payment failed. Please try again.' };
}
SCAPI:注文の失敗処理とバスケットの再開
SCAPI の統合では、決済の失敗が確定した後に Shopper Orders の失敗処理アクションを使用します。
POST /checkout/shopper-orders/v1/organizations/{orgId}/orders/{orderNo}/actions/fail?siteId={siteId}&reopenBasket=true
Authorization: Bearer {token}
Content-Type: application/json
{
"reasonCode": "payment_auth_failure"
}
現在、決済関連の理由コードは payment_auth_failure、payment_confirm_failure、payment_capture_failure です。注文が失敗処理可能な状態でなくなっている場合、エンドポイントは 409 を返します。バージョン固有のコードを生成する前に、現在の Shopper Orders スキーマを確認してください。
キャンセル済み注文の取り消し
undoCancelOrder() を使用して、キャンセル済みの注文を再開できます。
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
var Order = require('dw/order/Order');
function reopenCancelledOrder(orderNo) {
var order = OrderMgr.getOrder(orderNo);
if (order.status.value !== Order.ORDER_STATUS_CANCELLED) {
return { error: true, message: 'Order is not cancelled' };
}
Transaction.wrap(function() {
// Revert to NEW status
OrderMgr.undoCancelOrder(order);
});
return { error: false, order: order };
}
注文プロパティ
| プロパティ | 説明 |
|---|---|
orderNo | 注文番号 |
status | 現在の注文ステータス |
confirmationStatus | 確認ステータス |
exportStatus | OMS のエクスポートステータス |
paymentStatus | 決済ステータス |
shippingStatus | 配送ステータス |
customerEmail | 顧客のメールアドレス |
customerName | 顧客名 |
totalGrossPrice | 注文合計(税込み) |
totalNetPrice | 注文合計(税抜き) |
totalTax | 税額の合計 |
creationDate | 注文作成日 |
productLineItems | 注文の明細項目 |
shipments | 注文の出荷 |
paymentInstruments | 決済手段 |
カスタム注文番号
カスタム注文番号を生成するには、dw.order.createOrderNo フックを使用します。
// hooks.json
{
"hooks": [
{
"name": "dw.order.createOrderNo",
"script": "./hooks/orderNo.js"
}
]
}
// hooks/orderNo.js
var OrderMgr = require('dw/order/OrderMgr');
var Site = require('dw/system/Site');
exports.createOrderNo = function() {
var seqNo = OrderMgr.createOrderSequenceNo();
var prefix = Site.current.ID.toUpperCase();
var year = new Date().getFullYear();
return prefix + '-' + year + '-' + seqNo;
};
ベストプラクティス
実施すること
- 呼び出し元がすでにトランザクションを提供していない場合に限り、Script API による注文の変更をトランザクションで囲みます
- ステータスを遷移させる前に注文ステータスを確認します
- 処理が終わったら注文イテレーターを閉じます
- 顧客が再試行できるように
failOrder(order, true)を使用します - 冪等性のある注文作成を実装します(特定の注文番号を使用します)
- 適切なエクスポート/確認ステータスを設定します
実施しないこと
- 決済の承認が正常に完了する前に注文を作成する
- 返金処理を行わずに注文をキャンセルする
- 注文を CREATED ステータスのまま長期間放置する
- 注文に対する同時変更への対応を忘れる
- ステータスを遷移させる前のステータス検証を省略する
エラー処理
| シナリオ | 解決策 |
|---|---|
| バスケットが空 | createOrder() の前にバスケットを検証します |
| バスケットが無効 | 配送先住所や請求先住所が不足していないか確認します |
| 決済に失敗 | バスケットを再開するには failOrder(order, true) を使用します |
| 注文番号が存在する | 自動生成された番号を使用するか、一意性を検証します |
| ステータス遷移が無効 | ステータスメソッドを呼び出す前に現在のステータスを確認します |
関連スキル
- b2c-hooks - 注文フック(calculate、payment、createOrderNo)