agentic-commerce-protocol
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAgentic Commerce Protocol (ACP) Skill
Agentic Commerce Protocol(ACP)技能
Overview
概述
The Agentic Commerce Protocol (ACP) is an open standard for connecting buyers, their AI agents, and businesses to complete purchases seamlessly. Maintained by OpenAI and Stripe, ACP enables AI agents to initiate and complete commerce transactions on behalf of users.
Key Capabilities:
- AI agents can discover and purchase products/services
- Businesses expose checkout endpoints to AI agents
- Payment providers handle secure payment token exchange
- Support for carts, orders, fulfillment, and extensions
- Date-based versioning (format)
YYYY-MM-DD
Current Version:
2026-04-17Agentic Commerce Protocol(ACP)是一个开放标准,用于连接买家、他们的AI代理与企业,实现无缝完成交易。由OpenAI和Stripe维护,ACP允许AI代理代表用户发起并完成商务交易。
核心功能:
- AI代理可发现并购买产品/服务
- 企业向AI代理暴露结账端点
- 支付服务商处理安全的支付令牌交换
- 支持购物车、订单、履约及扩展功能
- 基于日期的版本控制(格式)
YYYY-MM-DD
当前版本:
2026-04-17Installation & Setup
安装与设置
For Merchants (Implementing Checkout Endpoints)
面向商家(实现结账端点)
- Clone the specification repository:
bash
git clone https://github.com/agentic-commerce-protocol/agentic-commerce-protocol.git
cd agentic-commerce-protocol- Review the OpenAPI specification:
bash
undefined- 克隆规范仓库:
bash
git clone https://github.com/agentic-commerce-protocol/agentic-commerce-protocol.git
cd agentic-commerce-protocol- 查看OpenAPI规范:
bash
undefinedLatest stable spec
最新稳定版规范
cat spec/2026-04-17/openapi/openapi.agentic_checkout.yaml
3. **Install dependencies for your implementation:**
Node.js/Express example:
```bash
npm init -y
npm install express body-parser express-validatorPython/Flask example:
bash
pip install flask flask-cors jsonschemacat spec/2026-04-17/openapi/openapi.agentic_checkout.yaml
3. **安装实现所需依赖:**
Node.js/Express示例:
```bash
npm init -y
npm install express body-parser express-validatorPython/Flask示例:
bash
pip install flask flask-cors jsonschemaFor AI Agent Developers
面向AI代理开发者
Review the specification and integrate with a reference implementation:
查看规范并集成参考实现:
Core Concepts
核心概念
1. Agentic Checkout Flow
1. Agentic结账流程
The basic checkout flow involves these endpoints:
- - Discover seller capabilities
POST /agentic-checkout/capabilities - - Initialize checkout session
POST /agentic-checkout/create-checkout - - Update checkout details
POST /agentic-checkout/update-checkout - - Finalize and confirm purchase
POST /agentic-checkout/confirm-checkout
基础结账流程涉及以下端点:
- - 发现卖家功能
POST /agentic-checkout/capabilities - - 初始化结账会话
POST /agentic-checkout/create-checkout - - 更新结账详情
POST /agentic-checkout/update-checkout - - 完成并确认购买
POST /agentic-checkout/confirm-checkout
2. Payment Handlers
2. 支付处理器
ACP supports multiple payment handler types:
- Delegate Payment Handler - Agent handles payment collection
- Seller-Backed Payment Handler - Seller collects payment directly
- Payment Link Handler - Redirect to payment page
ACP支持多种支付处理器类型:
- Delegate Payment Handler - 代理处理收款
- Seller-Backed Payment Handler - 卖家直接收款
- Payment Link Handler - 跳转至支付页面
Implementation Examples
实现示例
Basic Express.js Seller Implementation
基础Express.js卖家实现
javascript
const express = require('express');
const bodyParser = require('body-parser');
const { v4: uuidv4 } = require('uuid');
const app = express();
app.use(bodyParser.json());
// In-memory store (use database in production)
const checkoutSessions = new Map();
// Capabilities endpoint
app.post('/agentic-checkout/capabilities', (req, res) => {
res.json({
version: '2026-04-17',
supported_features: [
'cart',
'orders',
'fulfillment',
'extensions'
],
payment_handlers: [
{
type: 'delegate_payment',
supported_methods: ['card', 'bank_transfer']
}
],
extensions: [
{
type: 'discount',
supported_discount_types: ['percentage', 'fixed_amount']
}
]
});
});
// Create checkout endpoint
app.post('/agentic-checkout/create-checkout', (req, res) => {
const { items, buyer_info, payment_handler } = req.body;
// Validate required fields
if (!items || !Array.isArray(items) || items.length === 0) {
return res.status(400).json({
error: {
type: 'invalid_request',
message: 'Items are required'
}
});
}
// Create session
const sessionId = uuidv4();
const session = {
id: sessionId,
status: 'open',
items: items.map(item => ({
id: item.id,
name: item.name,
quantity: item.quantity || 1,
unit_price: item.unit_price,
total: (item.quantity || 1) * item.unit_price
})),
buyer_info: buyer_info || {},
payment_handler,
created_at: new Date().toISOString()
};
// Calculate totals
session.subtotal = session.items.reduce((sum, item) => sum + item.total, 0);
session.total = session.subtotal;
checkoutSessions.set(sessionId, session);
res.json({
checkout_id: sessionId,
status: 'open',
items: session.items,
subtotal: session.subtotal,
total: session.total,
payment_handler: session.payment_handler
});
});
// Update checkout endpoint
app.post('/agentic-checkout/update-checkout', (req, res) => {
const { checkout_id, items, buyer_info, shipping_address } = req.body;
const session = checkoutSessions.get(checkout_id);
if (!session) {
return res.status(404).json({
error: {
type: 'checkout_not_found',
message: 'Checkout session not found'
}
});
}
if (session.status !== 'open') {
return res.status(400).json({
error: {
type: 'invalid_state',
message: 'Checkout is not in open state'
}
});
}
// Update session
if (items) {
session.items = items.map(item => ({
id: item.id,
name: item.name,
quantity: item.quantity || 1,
unit_price: item.unit_price,
total: (item.quantity || 1) * item.unit_price
}));
session.subtotal = session.items.reduce((sum, item) => sum + item.total, 0);
session.total = session.subtotal;
}
if (buyer_info) {
session.buyer_info = { ...session.buyer_info, ...buyer_info };
}
if (shipping_address) {
session.shipping_address = shipping_address;
}
res.json({
checkout_id: session.id,
status: session.status,
items: session.items,
subtotal: session.subtotal,
total: session.total
});
});
// Confirm checkout endpoint
app.post('/agentic-checkout/confirm-checkout', (req, res) => {
const { checkout_id, payment_token } = req.body;
const session = checkoutSessions.get(checkout_id);
if (!session) {
return res.status(404).json({
error: {
type: 'checkout_not_found',
message: 'Checkout session not found'
}
});
}
if (session.status !== 'open') {
return res.status(400).json({
error: {
type: 'invalid_state',
message: 'Checkout is not in open state'
}
});
}
// Process payment (integrate with payment processor)
// For demo purposes, we'll simulate success
session.status = 'completed';
session.payment_token = payment_token;
session.completed_at = new Date().toISOString();
const orderId = `ord_${uuidv4()}`;
session.order_id = orderId;
res.json({
checkout_id: session.id,
status: 'completed',
order_id: orderId,
confirmation: {
order_number: orderId,
total: session.total,
items: session.items
}
});
});
app.listen(3000, () => {
console.log('ACP server listening on port 3000');
});javascript
const express = require('express');
const bodyParser = require('body-parser');
const { v4: uuidv4 } = require('uuid');
const app = express();
app.use(bodyParser.json());
// 内存存储(生产环境请使用数据库)
const checkoutSessions = new Map();
// 功能端点
app.post('/agentic-checkout/capabilities', (req, res) => {
res.json({
version: '2026-04-17',
supported_features: [
'cart',
'orders',
'fulfillment',
'extensions'
],
payment_handlers: [
{
type: 'delegate_payment',
supported_methods: ['card', 'bank_transfer']
}
],
extensions: [
{
type: 'discount',
supported_discount_types: ['percentage', 'fixed_amount']
}
]
});
});
// 创建结账端点
app.post('/agentic-checkout/create-checkout', (req, res) => {
const { items, buyer_info, payment_handler } = req.body;
// 验证必填字段
if (!items || !Array.isArray(items) || items.length === 0) {
return res.status(400).json({
error: {
type: 'invalid_request',
message: 'Items are required'
}
});
}
// 创建会话
const sessionId = uuidv4();
const session = {
id: sessionId,
status: 'open',
items: items.map(item => ({
id: item.id,
name: item.name,
quantity: item.quantity || 1,
unit_price: item.unit_price,
total: (item.quantity || 1) * item.unit_price
})),
buyer_info: buyer_info || {},
payment_handler,
created_at: new Date().toISOString()
};
// 计算总计
session.subtotal = session.items.reduce((sum, item) => sum + item.total, 0);
session.total = session.subtotal;
checkoutSessions.set(sessionId, session);
res.json({
checkout_id: sessionId,
status: 'open',
items: session.items,
subtotal: session.subtotal,
total: session.total,
payment_handler: session.payment_handler
});
});
// 更新结账端点
app.post('/agentic-checkout/update-checkout', (req, res) => {
const { checkout_id, items, buyer_info, shipping_address } = req.body;
const session = checkoutSessions.get(checkout_id);
if (!session) {
return res.status(404).json({
error: {
type: 'checkout_not_found',
message: 'Checkout session not found'
}
});
}
if (session.status !== 'open') {
return res.status(400).json({
error: {
type: 'invalid_state',
message: 'Checkout is not in open state'
}
});
}
// 更新会话
if (items) {
session.items = items.map(item => ({
id: item.id,
name: item.name,
quantity: item.quantity || 1,
unit_price: item.unit_price,
total: (item.quantity || 1) * item.unit_price
}));
session.subtotal = session.items.reduce((sum, item) => sum + item.total, 0);
session.total = session.subtotal;
}
if (buyer_info) {
session.buyer_info = { ...session.buyer_info, ...buyer_info };
}
if (shipping_address) {
session.shipping_address = shipping_address;
}
res.json({
checkout_id: session.id,
status: session.status,
items: session.items,
subtotal: session.subtotal,
total: session.total
});
});
// 确认结账端点
app.post('/agentic-checkout/confirm-checkout', (req, res) => {
const { checkout_id, payment_token } = req.body;
const session = checkoutSessions.get(checkout_id);
if (!session) {
return res.status(404).json({
error: {
type: 'checkout_not_found',
message: 'Checkout session not found'
}
});
}
if (session.status !== 'open') {
return res.status(400).json({
error: {
type: 'invalid_state',
message: 'Checkout is not in open state'
}
});
}
// 处理支付(与支付处理器集成)
// 演示用,模拟支付成功
session.status = 'completed';
session.payment_token = payment_token;
session.completed_at = new Date().toISOString();
const orderId = `ord_${uuidv4()}`;
session.order_id = orderId;
res.json({
checkout_id: session.id,
status: 'completed',
order_id: orderId,
confirmation: {
order_number: orderId,
total: session.total,
items: session.items
}
});
});
app.listen(3000, () => {
console.log('ACP server listening on port 3000');
});Python/Flask Seller Implementation
Python/Flask卖家实现
python
from flask import Flask, request, jsonify
from flask_cors import CORS
import uuid
from datetime import datetime
app = Flask(__name__)
CORS(app)python
from flask import Flask, request, jsonify
from flask_cors import CORS
import uuid
from datetime import datetime
app = Flask(__name__)
CORS(app)In-memory store
内存存储
checkout_sessions = {}
@app.route('/agentic-checkout/capabilities', methods=['POST'])
def capabilities():
return jsonify({
'version': '2026-04-17',
'supported_features': [
'cart',
'orders',
'fulfillment'
],
'payment_handlers': [
{
'type': 'delegate_payment',
'supported_methods': ['card']
}
]
})
@app.route('/agentic-checkout/create-checkout', methods=['POST'])
def create_checkout():
data = request.json
items = data.get('items', [])
if not items:
return jsonify({
'error': {
'type': 'invalid_request',
'message': 'Items are required'
}
}), 400
session_id = str(uuid.uuid4())
# Process items
processed_items = []
subtotal = 0
for item in items:
quantity = item.get('quantity', 1)
unit_price = item.get('unit_price', 0)
total = quantity * unit_price
processed_items.append({
'id': item.get('id'),
'name': item.get('name'),
'quantity': quantity,
'unit_price': unit_price,
'total': total
})
subtotal += total
session = {
'id': session_id,
'status': 'open',
'items': processed_items,
'buyer_info': data.get('buyer_info', {}),
'payment_handler': data.get('payment_handler'),
'subtotal': subtotal,
'total': subtotal,
'created_at': datetime.utcnow().isoformat()
}
checkout_sessions[session_id] = session
return jsonify({
'checkout_id': session_id,
'status': 'open',
'items': processed_items,
'subtotal': subtotal,
'total': subtotal
})@app.route('/agentic-checkout/confirm-checkout', methods=['POST'])
def confirm_checkout():
data = request.json
checkout_id = data.get('checkout_id')
payment_token = data.get('payment_token')
session = checkout_sessions.get(checkout_id)
if not session:
return jsonify({
'error': {
'type': 'checkout_not_found',
'message': 'Checkout session not found'
}
}), 404
if session['status'] != 'open':
return jsonify({
'error': {
'type': 'invalid_state',
'message': 'Checkout is not in open state'
}
}), 400
# Process payment
session['status'] = 'completed'
session['payment_token'] = payment_token
order_id = f"ord_{uuid.uuid4()}"
session['order_id'] = order_id
return jsonify({
'checkout_id': checkout_id,
'status': 'completed',
'order_id': order_id,
'confirmation': {
'order_number': order_id,
'total': session['total'],
'items': session['items']
}
})if name == 'main':
app.run(port=3000, debug=True)
undefinedcheckout_sessions = {}
@app.route('/agentic-checkout/capabilities', methods=['POST'])
def capabilities():
return jsonify({
'version': '2026-04-17',
'supported_features': [
'cart',
'orders',
'fulfillment'
],
'payment_handlers': [
{
'type': 'delegate_payment',
'supported_methods': ['card']
}
]
})
@app.route('/agentic-checkout/create-checkout', methods=['POST'])
def create_checkout():
data = request.json
items = data.get('items', [])
if not items:
return jsonify({
'error': {
'type': 'invalid_request',
'message': 'Items are required'
}
}), 400
session_id = str(uuid.uuid4())
# 处理商品
processed_items = []
subtotal = 0
for item in items:
quantity = item.get('quantity', 1)
unit_price = item.get('unit_price', 0)
total = quantity * unit_price
processed_items.append({
'id': item.get('id'),
'name': item.get('name'),
'quantity': quantity,
'unit_price': unit_price,
'total': total
})
subtotal += total
session = {
'id': session_id,
'status': 'open',
'items': processed_items,
'buyer_info': data.get('buyer_info', {}),
'payment_handler': data.get('payment_handler'),
'subtotal': subtotal,
'total': subtotal,
'created_at': datetime.utcnow().isoformat()
}
checkout_sessions[session_id] = session
return jsonify({
'checkout_id': session_id,
'status': 'open',
'items': processed_items,
'subtotal': subtotal,
'total': subtotal
})@app.route('/agentic-checkout/confirm-checkout', methods=['POST'])
def confirm_checkout():
data = request.json
checkout_id = data.get('checkout_id')
payment_token = data.get('payment_token')
session = checkout_sessions.get(checkout_id)
if not session:
return jsonify({
'error': {
'type': 'checkout_not_found',
'message': 'Checkout session not found'
}
}), 404
if session['status'] != 'open':
return jsonify({
'error': {
'type': 'invalid_state',
'message': 'Checkout is not in open state'
}
}), 400
# 处理支付
session['status'] = 'completed'
session['payment_token'] = payment_token
order_id = f"ord_{uuid.uuid4()}"
session['order_id'] = order_id
return jsonify({
'checkout_id': checkout_id,
'status': 'completed',
'order_id': order_id,
'confirmation': {
'order_number': order_id,
'total': session['total'],
'items': session['items']
}
})if name == 'main':
app.run(port=3000, debug=True)
undefinedCapability Negotiation
功能协商
javascript
// Client-side capability check
async function checkSellerCapabilities(sellerUrl) {
const response = await fetch(`${sellerUrl}/agentic-checkout/capabilities`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
const capabilities = await response.json();
// Check if seller supports required features
const requiredFeatures = ['cart', 'orders'];
const hasRequiredFeatures = requiredFeatures.every(feature =>
capabilities.supported_features?.includes(feature)
);
return {
compatible: hasRequiredFeatures,
capabilities
};
}javascript
// 客户端功能检查
async function checkSellerCapabilities(sellerUrl) {
const response = await fetch(`${sellerUrl}/agentic-checkout/capabilities`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
const capabilities = await response.json();
// 检查卖家是否支持所需功能
const requiredFeatures = ['cart', 'orders'];
const hasRequiredFeatures = requiredFeatures.every(feature =>
capabilities.supported_features?.includes(feature)
);
return {
compatible: hasRequiredFeatures,
capabilities
};
}Extension Support (Discounts)
扩展支持(折扣)
javascript
// Apply discount extension
app.post('/agentic-checkout/update-checkout', (req, res) => {
const { checkout_id, extensions } = req.body;
const session = checkoutSessions.get(checkout_id);
if (!session) {
return res.status(404).json({ error: 'Session not found' });
}
// Process discount extension
const discountExt = extensions?.find(ext => ext.type === 'discount');
if (discountExt) {
const { discount_type, value, code } = discountExt;
// Validate discount code
if (code === 'SAVE10') {
if (discount_type === 'percentage') {
session.discount = session.subtotal * (value / 100);
} else if (discount_type === 'fixed_amount') {
session.discount = value;
}
session.total = session.subtotal - session.discount;
}
}
res.json({
checkout_id: session.id,
subtotal: session.subtotal,
discount: session.discount || 0,
total: session.total
});
});javascript
// 应用折扣扩展
app.post('/agentic-checkout/update-checkout', (req, res) => {
const { checkout_id, extensions } = req.body;
const session = checkoutSessions.get(checkout_id);
if (!session) {
return res.status(404).json({ error: 'Session not found' });
}
// 处理折扣扩展
const discountExt = extensions?.find(ext => ext.type === 'discount');
if (discountExt) {
const { discount_type, value, code } = discountExt;
// 验证折扣码
if (code === 'SAVE10') {
if (discount_type === 'percentage') {
session.discount = session.subtotal * (value / 100);
} else if (discount_type === 'fixed_amount') {
session.discount = value;
}
session.total = session.subtotal - session.discount;
}
}
res.json({
checkout_id: session.id,
subtotal: session.subtotal,
discount: session.discount || 0,
total: session.total
});
});Order Management
订单管理
javascript
// Get order status
app.post('/agentic-checkout/get-order', (req, res) => {
const { order_id } = req.body;
// Find session by order_id
const session = Array.from(checkoutSessions.values())
.find(s => s.order_id === order_id);
if (!session) {
return res.status(404).json({
error: {
type: 'order_not_found',
message: 'Order not found'
}
});
}
res.json({
order_id: session.order_id,
status: session.status,
created_at: session.created_at,
items: session.items,
total: session.total,
fulfillment: {
status: 'pending',
tracking_number: null
}
});
});javascript
// 获取订单状态
app.post('/agentic-checkout/get-order', (req, res) => {
const { order_id } = req.body;
// 通过order_id查找会话
const session = Array.from(checkoutSessions.values())
.find(s => s.order_id === order_id);
if (!session) {
return res.status(404).json({
error: {
type: 'order_not_found',
message: 'Order not found'
}
});
}
res.json({
order_id: session.order_id,
status: session.status,
created_at: session.created_at,
items: session.items,
total: session.total,
fulfillment: {
status: 'pending',
tracking_number: null
}
});
});Configuration
配置
Environment Variables
环境变量
bash
undefinedbash
undefinedServer configuration
服务器配置
PORT=3000
NODE_ENV=production
PORT=3000
NODE_ENV=production
Payment processor
支付处理器
PAYMENT_PROCESSOR_API_KEY=your_payment_api_key
PAYMENT_PROCESSOR_SECRET=your_payment_secret
PAYMENT_PROCESSOR_API_KEY=your_payment_api_key
PAYMENT_PROCESSOR_SECRET=your_payment_secret
Security
安全设置
WEBHOOK_SECRET=your_webhook_secret
ALLOWED_ORIGINS=https://agent1.example.com,https://agent2.example.com
WEBHOOK_SECRET=your_webhook_secret
ALLOWED_ORIGINS=https://agent1.example.com,https://agent2.example.com
Database
数据库
DATABASE_URL=postgresql://user:password@localhost:5432/acp_db
DATABASE_URL=postgresql://user:password@localhost:5432/acp_db
ACP version
ACP版本
ACP_VERSION=2026-04-17
undefinedACP_VERSION=2026-04-17
undefinedConfiguration File Example
配置文件示例
javascript
// config/acp.config.js
module.exports = {
version: process.env.ACP_VERSION || '2026-04-17',
features: {
cart: true,
orders: true,
fulfillment: true,
extensions: true,
authentication: false
},
paymentHandlers: [
{
type: 'delegate_payment',
methods: ['card', 'bank_transfer'],
processor: 'stripe'
}
],
extensions: [
{
type: 'discount',
supportedTypes: ['percentage', 'fixed_amount', 'code']
}
],
security: {
requireAuth: false,
allowedOrigins: process.env.ALLOWED_ORIGINS?.split(',') || [],
webhookSecret: process.env.WEBHOOK_SECRET
}
};javascript
// config/acp.config.js
module.exports = {
version: process.env.ACP_VERSION || '2026-04-17',
features: {
cart: true,
orders: true,
fulfillment: true,
extensions: true,
authentication: false
},
paymentHandlers: [
{
type: 'delegate_payment',
methods: ['card', 'bank_transfer'],
processor: 'stripe'
}
],
extensions: [
{
type: 'discount',
supportedTypes: ['percentage', 'fixed_amount', 'code']
}
],
security: {
requireAuth: false,
allowedOrigins: process.env.ALLOWED_ORIGINS?.split(',') || [],
webhookSecret: process.env.WEBHOOK_SECRET
}
};Common Patterns
常见模式
1. Idempotent Request Handling
1. 幂等请求处理
javascript
const processedRequests = new Map();
app.post('/agentic-checkout/confirm-checkout', (req, res) => {
const idempotencyKey = req.headers['idempotency-key'];
if (idempotencyKey && processedRequests.has(idempotencyKey)) {
// Return cached response
return res.json(processedRequests.get(idempotencyKey));
}
// Process request
const result = processCheckout(req.body);
if (idempotencyKey) {
processedRequests.set(idempotencyKey, result);
}
res.json(result);
});javascript
const processedRequests = new Map();
app.post('/agentic-checkout/confirm-checkout', (req, res) => {
const idempotencyKey = req.headers['idempotency-key'];
if (idempotencyKey && processedRequests.has(idempotencyKey)) {
// 返回缓存的响应
return res.json(processedRequests.get(idempotencyKey));
}
// 处理请求
const result = processCheckout(req.body);
if (idempotencyKey) {
processedRequests.set(idempotencyKey, result);
}
res.json(result);
});2. Webhook Event Handling
2. Webhook事件处理
javascript
app.post('/webhooks/acp', (req, res) => {
const signature = req.headers['x-acp-signature'];
// Verify signature
if (!verifyWebhookSignature(req.body, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = req.body;
switch (event.type) {
case 'checkout.completed':
handleCheckoutCompleted(event.data);
break;
case 'checkout.cancelled':
handleCheckoutCancelled(event.data);
break;
case 'order.fulfilled':
handleOrderFulfilled(event.data);
break;
}
res.json({ received: true });
});javascript
app.post('/webhooks/acp', (req, res) => {
const signature = req.headers['x-acp-signature'];
// 验证签名
if (!verifyWebhookSignature(req.body, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = req.body;
switch (event.type) {
case 'checkout.completed':
handleCheckoutCompleted(event.data);
break;
case 'checkout.cancelled':
handleCheckoutCancelled(event.data);
break;
case 'order.fulfilled':
handleOrderFulfilled(event.data);
break;
}
res.json({ received: true });
});3. Error Handling
3. 错误处理
javascript
// Standard error response format
function sendError(res, type, message, statusCode = 400) {
res.status(statusCode).json({
error: {
type,
message,
timestamp: new Date().toISOString()
}
});
}
// Usage
app.post('/agentic-checkout/create-checkout', (req, res) => {
try {
const { items } = req.body;
if (!items || items.length === 0) {
return sendError(res, 'invalid_request', 'Items are required');
}
// Process checkout...
} catch (error) {
console.error('Checkout error:', error);
sendError(res, 'internal_error', 'An error occurred', 500);
}
});javascript
// 标准错误响应格式
function sendError(res, type, message, statusCode = 400) {
res.status(statusCode).json({
error: {
type,
message,
timestamp: new Date().toISOString()
}
});
}
// 使用示例
app.post('/agentic-checkout/create-checkout', (req, res) => {
try {
const { items } = req.body;
if (!items || items.length === 0) {
return sendError(res, 'invalid_request', 'Items are required');
}
// 处理结账...
} catch (error) {
console.error('Checkout error:', error);
sendError(res, 'internal_error', 'An error occurred', 500);
}
});4. Cart Management
4. 购物车管理
javascript
// Add item to cart
app.post('/agentic-checkout/add-to-cart', (req, res) => {
const { checkout_id, item } = req.body;
const session = checkoutSessions.get(checkout_id);
if (!session) {
return sendError(res, 'checkout_not_found', 'Session not found', 404);
}
// Add or update item
const existingIndex = session.items.findIndex(i => i.id === item.id);
if (existingIndex >= 0) {
session.items[existingIndex].quantity += item.quantity || 1;
} else {
session.items.push({
id: item.id,
name: item.name,
quantity: item.quantity || 1,
unit_price: item.unit_price,
total: (item.quantity || 1) * item.unit_price
});
}
// Recalculate totals
session.subtotal = session.items.reduce((sum, i) => sum + i.total, 0);
session.total = session.subtotal - (session.discount || 0);
res.json({
checkout_id: session.id,
items: session.items,
subtotal: session.subtotal,
total: session.total
});
});javascript
// 添加商品到购物车
app.post('/agentic-checkout/add-to-cart', (req, res) => {
const { checkout_id, item } = req.body;
const session = checkoutSessions.get(checkout_id);
if (!session) {
return sendError(res, 'checkout_not_found', 'Session not found', 404);
}
// 添加或更新商品
const existingIndex = session.items.findIndex(i => i.id === item.id);
if (existingIndex >= 0) {
session.items[existingIndex].quantity += item.quantity || 1;
} else {
session.items.push({
id: item.id,
name: item.name,
quantity: item.quantity || 1,
unit_price: item.unit_price,
total: (item.quantity || 1) * item.unit_price
});
}
// 重新计算总计
session.subtotal = session.items.reduce((sum, i) => sum + i.total, 0);
session.total = session.subtotal - (session.discount || 0);
res.json({
checkout_id: session.id,
items: session.items,
subtotal: session.subtotal,
total: session.total
});
});Testing
测试
Test Suite Example
测试套件示例
javascript
const request = require('supertest');
const app = require('./server');
describe('ACP Checkout Flow', () => {
let checkoutId;
test('GET capabilities', async () => {
const res = await request(app)
.post('/agentic-checkout/capabilities')
.expect(200);
expect(res.body.version).toBe('2026-04-17');
expect(res.body.supported_features).toContain('cart');
});
test('POST create-checkout', async () => {
const res = await request(app)
.post('/agentic-checkout/create-checkout')
.send({
items: [
{
id: 'prod_123',
name: 'Test Product',
quantity: 2,
unit_price: 1000
}
],
payment_handler: {
type: 'delegate_payment'
}
})
.expect(200);
checkoutId = res.body.checkout_id;
expect(res.body.status).toBe('open');
expect(res.body.total).toBe(2000);
});
test('POST confirm-checkout', async () => {
const res = await request(app)
.post('/agentic-checkout/confirm-checkout')
.send({
checkout_id: checkoutId,
payment_token: 'tok_test_12345'
})
.expect(200);
expect(res.body.status).toBe('completed');
expect(res.body.order_id).toBeDefined();
});
});javascript
const request = require('supertest');
const app = require('./server');
describe('ACP Checkout Flow', () => {
let checkoutId;
test('GET capabilities', async () => {
const res = await request(app)
.post('/agentic-checkout/capabilities')
.expect(200);
expect(res.body.version).toBe('2026-04-17');
expect(res.body.supported_features).toContain('cart');
});
test('POST create-checkout', async () => {
const res = await request(app)
.post('/agentic-checkout/create-checkout')
.send({
items: [
{
id: 'prod_123',
name: 'Test Product',
quantity: 2,
unit_price: 1000
}
],
payment_handler: {
type: 'delegate_payment'
}
})
.expect(200);
checkoutId = res.body.checkout_id;
expect(res.body.status).toBe('open');
expect(res.body.total).toBe(2000);
});
test('POST confirm-checkout', async () => {
const res = await request(app)
.post('/agentic-checkout/confirm-checkout')
.send({
checkout_id: checkoutId,
payment_token: 'tok_test_12345'
})
.expect(200);
expect(res.body.status).toBe('completed');
expect(res.body.order_id).toBeDefined();
});
});Troubleshooting
故障排除
Common Issues
常见问题
1. Invalid version error
Error: Unsupported ACP versionSolution: Ensure your implementation supports the version specified in the request. Check for the current stable version.
spec/2026-04-17/2. Payment handler mismatch
Error: Unsupported payment handler typeSolution: Verify the payment handler type in your capabilities response matches what the agent is requesting.
3. Checkout session not found
Error: checkout_not_foundSolution: Implement proper session storage (Redis, database) instead of in-memory maps for production. Sessions should persist across server restarts.
4. CORS errors
Access-Control-Allow-Origin header missingSolution: Add CORS middleware with appropriate allowed origins:
javascript
const cors = require('cors');
app.use(cors({
origin: process.env.ALLOWED_ORIGINS.split(','),
credentials: true
}));5. Idempotency issues
Duplicate checkout createdSolution: Implement idempotency key handling for all mutating operations.
1. 版本无效错误
Error: Unsupported ACP version解决方案:确保你的实现支持请求中指定的版本。查看获取当前稳定版。
spec/2026-04-17/2. 支付处理器不匹配
Error: Unsupported payment handler type解决方案:验证你的功能响应中的支付处理器类型与代理请求的类型一致。
3. 结账会话未找到
Error: checkout_not_found解决方案:生产环境请使用Redis或数据库等持久化存储替代内存映射,确保会话在服务器重启后仍能保留。
4. CORS错误
Access-Control-Allow-Origin header missing解决方案:添加CORS中间件并配置合适的允许来源:
javascript
const cors = require('cors');
app.use(cors({
origin: process.env.ALLOWED_ORIGINS.split(','),
credentials: true
}));5. 幂等性问题
Duplicate checkout created解决方案:为所有变更操作实现幂等键处理。
Validation
验证
Use the JSON schemas provided in the spec for validation:
javascript
const Ajv = require('ajv');
const ajv = new Ajv();
const checkoutSchema = require('./spec/2026-04-17/json-schema/checkout.schema.json');
const validate = ajv.compile(checkoutSchema);
app.post('/agentic-checkout/create-checkout', (req, res) => {
const valid = validate(req.body);
if (!valid) {
return res.status(400).json({
error: {
type: 'validation_error',
message: validate.errors
}
});
}
// Process request...
});使用规范中提供的JSON Schema进行验证:
javascript
const Ajv = require('ajv');
const ajv = new Ajv();
const checkoutSchema = require('./spec/2026-04-17/json-schema/checkout.schema.json');
const validate = ajv.compile(checkoutSchema);
app.post('/agentic-checkout/create-checkout', (req, res) => {
const valid = validate(req.body);
if (!valid) {
return res.status(400).json({
error: {
type: 'validation_error',
message: validate.errors
}
});
}
// 处理请求...
});Additional Resources
额外资源
- Official Documentation: https://agenticcommerce.dev
- OpenAPI Spec:
spec/2026-04-17/openapi/openapi.agentic_checkout.yaml - Examples:
examples/2026-04-17/ - Governance:
docs/governance.md - Contributing:
CONTRIBUTING.md
- 官方文档: https://agenticcommerce.dev
- OpenAPI规范:
spec/2026-04-17/openapi/openapi.agentic_checkout.yaml - 示例:
examples/2026-04-17/ - 治理:
docs/governance.md - 贡献指南:
CONTRIBUTING.md