b2c-ordering
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseB2C Ordering
B2C订单管理
The OrderMgr API provides order creation, status management, and querying. Understanding the order lifecycle is essential for checkout implementation and order processing.
OrderMgr API提供订单创建、状态管理和查询能力,理解订单生命周期对于结账功能实现和订单处理至关重要。
Order Lifecycle
订单生命周期
Orders progress through these statuses:
Basket → CREATED → NEW → (COMPLETED or CANCELLED or FAILED)| Status | Description | Can Transition To |
|---|---|---|
| Order created, not yet placed | |
| Order placed, awaiting fulfillment | |
| Order in processing | |
| Order fulfilled | - |
| Order cancelled | |
| Order failed (payment, validation) | - (cannot be reopened) |
Important: Once an order reaches status, it cannot be reopened or cancelled. Use to reopen the basket for retry instead.
FAILEDfailOrder(order, true)订单会依次经过以下状态:
Basket → CREATED → NEW → (COMPLETED or CANCELLED or FAILED)| 状态 | 描述 | 可转换为 |
|---|---|---|
| 订单已创建,尚未提交 | |
| 订单已提交,等待履约 | |
| 订单处理中 | |
| 订单已履约 | - |
| 订单已取消 | |
| 订单失败(支付、校验问题) | -(无法重新打开) |
重要提示: 订单一旦进入状态,就无法重新打开或取消,可调用重新打开购物篮供用户重试。
FAILEDfailOrder(order, true)Creating Orders
创建订单
Standard Flow (Synchronous)
标准流程(同步)
javascript
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 };
}javascript
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() {
// 从购物篮创建订单(状态:CREATED)
order = OrderMgr.createOrder(basket);
});
if (!order) {
return { error: true, message: 'Order creation failed' };
}
// 支付授权
var paymentResult = authorizePayment(order);
if (!paymentResult.success) {
Transaction.wrap(function() {
OrderMgr.failOrder(order, true); // 重新打开购物篮
});
return { error: true, message: 'Payment failed' };
}
// 提交订单(状态:CREATED → NEW)
var placeResult;
Transaction.wrap(function() {
placeResult = OrderMgr.placeOrder(order);
});
if (placeResult.error) {
return { error: true, message: 'Order placement failed' };
}
// 设置确认状态
Transaction.wrap(function() {
order.setConfirmationStatus(order.CONFIRMATION_STATUS_CONFIRMED);
});
return { error: false, order: order };
}Async Flow (SCAPI Pattern)
异步流程(SCAPI模式)
For SCAPI/headless, create the order before payment authorization:
javascript
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
// Step 1: Create order (before payment)
function createOrderAsync(basket, orderNo) {
var order;
Transaction.wrap(function() {
// Create with specific order number (for idempotency)
order = OrderMgr.createOrder(basket, orderNo);
});
return order;
}
// Step 2: After payment success, place the order
function placeOrderAfterPayment(order) {
Transaction.wrap(function() {
OrderMgr.placeOrder(order);
order.setConfirmationStatus(order.CONFIRMATION_STATUS_CONFIRMED);
order.setExportStatus(order.EXPORT_STATUS_READY);
});
}
// Step 2 (alt): Payment failed, fail the order
function failOrderAfterPayment(order) {
Transaction.wrap(function() {
OrderMgr.failOrder(order, false); // Don't reopen basket
});
}针对SCAPI/ headless场景,在支付授权前先创建订单:
javascript
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
// 步骤1:创建订单(支付前)
function createOrderAsync(basket, orderNo) {
var order;
Transaction.wrap(function() {
// 使用指定订单号创建(保证幂等性)
order = OrderMgr.createOrder(basket, orderNo);
});
return order;
}
// 步骤2:支付成功后提交订单
function placeOrderAfterPayment(order) {
Transaction.wrap(function() {
OrderMgr.placeOrder(order);
order.setConfirmationStatus(order.CONFIRMATION_STATUS_CONFIRMED);
order.setExportStatus(order.EXPORT_STATUS_READY);
});
}
// 步骤2(备选):支付失败,标记订单失败
function failOrderAfterPayment(order) {
Transaction.wrap(function() {
OrderMgr.failOrder(order, false); // 不重新打开购物篮
});
}OrderMgr API Reference
OrderMgr API参考
Order Creation
订单创建
| Method | Description |
|---|---|
| Create order with auto-generated number |
| Create order with specific number |
| Generate next order number |
| Get next sequence number (for custom formatting) |
| 方法 | 描述 |
|---|---|
| 使用自动生成的订单号创建订单 |
| 使用指定订单号创建订单 |
| 生成下一个订单号 |
| 获取下一个序列号(用于自定义订单号格式) |
Order Status
订单状态
| Method | Description |
|---|---|
| Place order (CREATED → NEW) |
| Fail order (set to FAILED status) |
| Cancel order (set to CANCELLED status) |
| Revert cancelled order to NEW |
Note: There is no method. Failed orders cannot be reopened. Use to reopen the basket for retry.
undoFailOrder()failOrder(order, true)| 方法 | 描述 |
|---|---|
| 提交订单(CREATED → NEW) |
| 标记订单失败(设置为FAILED状态) |
| 取消订单(设置为CANCELLED状态) |
| 将已取消的订单恢复为NEW状态 |
注意: 不存在方法,失败的订单无法重新打开,请使用重新打开购物篮供用户重试。
undoFailOrder()failOrder(order, true)Order Queries
订单查询
| Method | Description |
|---|---|
| Get order by number |
| Search for single order |
| Search for multiple orders |
| Query single order |
| Query multiple orders |
| 方法 | 描述 |
|---|---|
| 根据订单号获取订单 |
| 搜索单个订单 |
| 搜索多个订单 |
| 查询单个订单 |
| 查询多个订单 |
Querying Orders
查询订单
Get Order by Number
根据订单号获取订单
javascript
var OrderMgr = require('dw/order/OrderMgr');
var order = OrderMgr.getOrder('00001234');
if (order) {
var status = order.status.value;
var total = order.totalGrossPrice;
}javascript
var OrderMgr = require('dw/order/OrderMgr');
var order = OrderMgr.getOrder('00001234');
if (order) {
var status = order.status.value;
var total = order.totalGrossPrice;
}Search Orders
搜索订单
javascript
var OrderMgr = require('dw/order/OrderMgr');
// Search by customer email
var orders = OrderMgr.searchOrders(
'customerEmail = {0} AND status != {1}',
'creationDate desc',
'customer@example.com',
dw.order.Order.ORDER_STATUS_FAILED
);
while (orders.hasNext()) {
var order = orders.next();
// Process order
}
orders.close();javascript
var OrderMgr = require('dw/order/OrderMgr');
// 根据客户邮箱搜索
var orders = OrderMgr.searchOrders(
'customerEmail = {0} AND status != {1}',
'creationDate desc',
'customer@example.com',
dw.order.Order.ORDER_STATUS_FAILED
);
while (orders.hasNext()) {
var order = orders.next();
// 处理订单
}
orders.close();Query by Date Range
根据日期范围查询
javascript
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();javascript
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();
// 处理订单
}
orders.close();Order Status Management
订单状态管理
Cancel Order
取消订单
javascript
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 };
}javascript
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' };
}
// 仅可取消NEW或OPEN状态的订单
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 };
}Fail Order
标记订单失败
javascript
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);
});
}javascript
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
function failOrder(order, reopenBasket) {
// reopenBasket: true = 客户可重试结账
// false = 购物篮不可用
Transaction.wrap(function() {
OrderMgr.failOrder(order, reopenBasket);
});
}Handling Failed Orders
处理失败订单
Failed orders cannot be reopened. Instead, use to reopen the basket:
failOrder(order, true)javascript
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.' };
}失败的订单无法重新打开,请使用重新打开购物篮:
failOrder(order, true)javascript
var OrderMgr = require('dw/order/OrderMgr');
var Transaction = require('dw/system/Transaction');
// 支付失败时,标记订单失败并重新打开购物篮
function handlePaymentFailure(order) {
Transaction.wrap(function() {
// reopenBasket=true允许客户重试结账
OrderMgr.failOrder(order, true);
});
// 购物篮现在已重新对客户开放
return { error: true, message: 'Payment failed. Please try again.' };
}SCAPI: Fail with Reopen (B2C 24.3+)
SCAPI:失败并重新打开购物篮(B2C 24.3+)
For SCAPI integrations, use the status to fail an order while reopening the basket:
failed_with_reopenhttp
PATCH /checkout/orders/v1/organizations/{orgId}/orders/{orderNo}?siteId={siteId}
Authorization: Bearer {token}
Content-Type: application/json
{
"status": "failed_with_reopen"
}This is equivalent to in Script API.
OrderMgr.failOrder(order, true)针对SCAPI集成,可使用状态标记订单失败,同时重新打开购物篮:
failed_with_reopenhttp
PATCH /checkout/orders/v1/organizations/{orgId}/orders/{orderNo}?siteId={siteId}
Authorization: Bearer {token}
Content-Type: application/json
{
"status": "failed_with_reopen"
}该操作等效于Script API中的。
OrderMgr.failOrder(order, true)Undo Cancelled Order
恢复已取消的订单
Cancelled orders can be reopened using :
undoCancelOrder()javascript
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 };
}已取消的订单可通过方法重新打开:
undoCancelOrder()javascript
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() {
// 恢复为NEW状态
OrderMgr.undoCancelOrder(order);
});
return { error: false, order: order };
}Order Properties
订单属性
| Property | Description |
|---|---|
| Order number |
| Current order status |
| Confirmation status |
| Export status for OMS |
| Payment status |
| Shipping status |
| Customer email |
| Customer name |
| Order total (with tax) |
| Order total (without tax) |
| Total tax amount |
| Order creation date |
| Line items in order |
| Order shipments |
| Payment instruments |
| 属性 | 描述 |
|---|---|
| 订单号 |
| 当前订单状态 |
| 确认状态 |
| OMS导出状态 |
| 支付状态 |
| 配送状态 |
| 客户邮箱 |
| 客户姓名 |
| 订单总价(含税) |
| 订单总价(不含税) |
| 总税额 |
| 订单创建日期 |
| 订单商品行 |
| 订单配送信息 |
| 支付工具信息 |
Custom Order Numbers
自定义订单号
Use the hook for custom order number generation:
dw.order.createOrderNojavascript
// hooks.json
{
"hooks": [
{
"name": "dw.order.createOrderNo",
"script": "./hooks/orderNo.js"
}
]
}javascript
// 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;
};可使用钩子实现自定义订单号生成逻辑:
dw.order.createOrderNojavascript
// hooks.json
{
"hooks": [
{
"name": "dw.order.createOrderNo",
"script": "./hooks/orderNo.js"
}
]
}javascript
// 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;
};Best Practices
最佳实践
Do
推荐做法
- Always wrap order operations in transactions
- Check order status before transitions
- Close order iterators when done
- Use to let customers retry
failOrder(order, true) - Implement idempotent order creation (use specific order numbers)
- Set appropriate export/confirmation status
- 所有订单操作始终包裹在事务中
- 状态转换前先检查当前订单状态
- 订单迭代器使用完毕后记得关闭
- 使用允许客户重试
failOrder(order, true) - 实现幂等的订单创建逻辑(使用指定订单号)
- 设置合适的导出/确认状态
Don't
禁止做法
- Place orders before successful payment authorization
- Cancel orders without refund processing
- Leave orders in CREATED status indefinitely
- Forget to handle concurrent order modifications
- Skip status validation before transitions
- 支付授权成功前提交订单
- 未处理退款就取消订单
- 让订单长期处于CREATED状态
- 忽略订单并发修改的处理
- 状态转换前跳过状态校验
Error Handling
错误处理
| Scenario | Solution |
|---|---|
| Basket is empty | Validate basket before |
| Invalid basket | Check for missing shipping/billing addresses |
| Payment failed | Use |
| Order number exists | Use auto-generated numbers or validate uniqueness |
| Status transition invalid | Check current status before calling status methods |
| 场景 | 解决方案 |
|---|---|
| 购物篮为空 | 调用 |
| 购物篮信息无效 | 检查是否缺少配送/账单地址 |
| 支付失败 | 使用 |
| 订单号已存在 | 使用自动生成的订单号或提前校验唯一性 |
| 状态转换无效 | 调用状态修改方法前先检查当前状态 |
Related Skills
相关技能
- b2c-hooks - Order hooks (calculate, payment, createOrderNo)
- b2c-hooks - 订单钩子(计算、支付、createOrderNo)