CommercePayments 命名空间用例
CommercePayments 是 Salesforce 平台中支付处理的命名空间。它提供完整的支付基础设施——同步/异步支付网关适配器、授权撤销、令牌化服务、替代支付方法和幂等性支持。需要 PaymentPlatform 组织权限才能访问 CommercePayments API。
重要限制:支付网关适配器不能进行 Future 调用、使用 System.Http 的外部 callout、异步调用、Queueable 调用或通过 SOQL 执行 DML。不要编码包含合并字段(包括卡号和 CVV)的请求体——这可能导致读取编码请求体失败。
同步支付网关适配器
在同步支付配置中,Salesforce 支付平台发送交易信息到网关,然后等待包含最终交易状态的网关响应。Salesforce 仅在网关交易成功后才创建交易记录。同步适配器必须实现 PaymentGatewayAdapter 接口和 processRequest 方法。
processRequest 的三阶段实现:
- 阶段 1——构建网关可理解的支付请求:调用
gatewayContext.getPaymentRequestType()判断 RequestType(Capture、ReferencedRefund、AuthorizationReversal、Tokenize)。根据类型调用对应的构建方法(buildCaptureRequest/buildRefundRequest 等) - 阶段 2——发送到支付网关:使用
commercepayments.PaymentsHttp类(而非 System.Http)发送 HTTP POST 请求。捕获 CalloutException 并返回 GatewayErrorResponse(500 错误) - 阶段 3——创建响应对象:根据 RequestType 创建对应的响应(CaptureResponse/ReferencedRefundResponse)。设置 SalesforceResultCode、GatewayReferenceNumber、Async 标志等
global with sharing class SampleAdapter implements commercepayments.PaymentGatewayAdapter {
global SampleAdapter() {}
global commercepayments.GatewayResponse processRequest(
commercepayments.paymentGatewayContext gatewayContext) {
commercepayments.RequestType requestType = gatewayContext.getPaymentRequestType();
commercepayments.PaymentsHttp http = new commercepayments.PaymentsHttp();
HttpRequest req = new HttpRequest();
req.setMethod('POST');
String body;
if (requestType == commercepayments.RequestType.Capture) {
req.setEndpoint('/pal/servlet/Payment/v52/capture');
body = buildCaptureRequest((commercepayments.CaptureRequest)gatewayContext.getPaymentRequest());
} else if (requestType == commercepayments.RequestType.ReferencedRefund) {
req.setEndpoint('/pal/servlet/Payment/v52/refund');
body = buildRefundRequest((commercepayments.ReferencedRefundRequest)gatewayContext.getPaymentRequest());
}
req.setBody(body);
try { HttpResponse res = http.send(req); return createResponse(res, requestType); }
catch (CalloutException ce) { return new commercepayments.GatewayErrorResponse('500', ce.getMessage()); }
}
}
传递自定义数据:使用 Checkout Payments Connect API 的 paymentsData 参数——支持最多 4 个键值对(每对 255 字符)的序列化 Map<String, String>。仅适用于 Auth 和 PostAuth 请求。
设置步骤:1) 创建支付网关适配器 Apex 类;2) 创建命名凭据(Named Credential——URL 指向支付网关);3) 创建 PaymentGatewayProvider(通过 Tooling API POST);4) 创建 PaymentGateway 记录(Merchant Credential ID + Payment Gateway Provider ID + Status=Active)。
支付处理与安全
异步支付网关适配器:必须同时实现 PaymentGatewayAdapter 和 PaymentGatewayAsyncAdapter 接口。异步流程不同——平台发送交易后收到确认回执并创建待处理交易;网关处理完成后发送通知(包含最终交易状态);平台更新交易状态。
异步通知处理(processNotification)四阶段:
- 验证签名:使用 HMAC SHA256 验证通知请求中的签名(pspReference + originalReference + merchantAccountCode + merchantReference + amount + currencyCode + eventCode + success 的 HMAC 散列)
- 解析通知并构建通知对象:通过
gatewayNotificationContext.getPaymentGatewayNotificationRequest()获取请求体。根据 eventCode 创建 CaptureNotification 或 ReferencedRefundNotification。设置 status(Success/Failed)、gatewayReferenceNumber、amount - 记录通知结果:调用
commercepayments.NotificationClient.record(notification)在平台上保存结果 - 确认回执:无论是否成功保存,都必须调用
GatewayNotificationResponse返回 200 + '[accepted]' 回执
异步适配器设置额外步骤:创建 Salesforce Site → 设置公共访问为 Guest Access to the Payments API → 在外部网关的标准通知设置中配置 Webhook URL:https://MyDomainName.my.salesforce-sites.com/services/data/v58.0/commerce/payments/notify?provider=PROVIDER_ID。注意:processNotification 方法的调试日志不会出现在 Developer Console中——需要参考 Guest User Debug Logging 配置。
支付生命周期 API:Process Payments——获取 CaptureRequest → 设置 HTTP 请求 → 构建请求体 → 使用 PaymentsHttp 发送 → 返回 CaptureResponse。Process Refund——获取 ReferencedRefundRequest → 类似流程返回 ReferencedRefundResponse。创建 captureResponse 时如果异步处理需设置 setAsync(true)。
授权撤销服务
授权撤销是否定授权的交易——释放客户支付方式上冻结的资金。CommercePayments 使用 AuthorizationReversalRequest(扩展 BaseRequest)和 AuthorizationReversalResponse(扩展 AbstractResponse)管理撤销信息的创建和存储。不支持批量操作或自定义字段。
// 在 processRequest 中处理 AuthorizationReversal
if (requestType == commercepayments.RequestType.AuthorizationReversal) {
response = createAuthReversalResponse(
(commercepayments.AuthorizationReversalRequest)gatewayContext.getPaymentRequest());
}
// 构建撤销响应
global commercepayments.GatewayResponse createAuthReversalResponse(
commercepayments.AuthorizationReversalRequest authReversalRequest) {
commercepayments.AuthorizationReversalResponse authReversalResponse =
new commercepayments.AuthorizationReversalResponse();
if (authReversalRequest.amount != null) {
authReversalResponse.setAmount(authReversalRequest.amount);
} else { throw new SalesforceValidationException('Required Field Missing : Amount'); }
authReversalResponse.setGatewayDate(system.now());
authReversalResponse.setGatewayResultCode('00');
authReversalResponse.setGatewayReferenceNumber('SF' + referenceNumber);
authReversalResponse.setSalesforceResultCodeInfo(SUCCESS_SALESFORCE_RESULT_CODE_INFO);
return authReversalResponse;
}
撤销服务 API:POST /commerce/payments/authorizations/{authorizationId}/reversals。amount 为必填参数(大于零)。可选参数:accountId、effectiveDate、email、ipAddress、macAddress、phone、comments(<1000 字符)。撤销金额加到 OrderPaymentSummary 的 AuthorizationReversalAmount 中并从 AvailableToCaptureAmount 中减去(不低于 0)。
令牌化服务
信用卡令牌化流程将敏感客户信息替换为一次性算法生成的令牌。Salesforce 存储令牌作为信用卡的表示——无需在 Salesforce 中存储敏感数据(如信用卡号)。CommercePayments 使用 Salesforce Classic Encryption 安全加密 GatewayTokenEncrypted 字段(API 52.0+ 推荐——替代未加密的 GatewayToken)。CardPaymentMethod 和 DigitalWallet 不能同时设置 GatewayTokenEncrypted 和 GatewayToken。
令牌化适配器实现:在 processRequest 中检测 requestType == Tokenize,调用 createTokenizeResponse 方法:
if (requestType == commercepayments.RequestType.Tokenize) {
response = createTokenizeResponse(
(commercepayments.PaymentMethodTokenizationRequest)gatewayContext.getPaymentRequest());
}
public commercepayments.GatewayResponse createTokenizeResponse(
commercepayments.PaymentMethodTokenizationRequest tokenizeRequest) {
commercepayments.PaymentMethodTokenizationResponse tokenizeResponse =
new commercepayments.PaymentMethodTokenizationResponse();
tokenizeResponse.setGatewayTokenEncrypted(encryptedValue); // 推荐——加密
tokenizeResponse.setGatewayTokenDetails(tokenDetails);
tokenizeResponse.setGatewayAvsCode(avsCode);
tokenizeResponse.setGatewayResultCode(resultcode);
tokenizeResponse.setSalesforceResultCodeInfo(resultCodeInfo);
tokenizeResponse.setGatewayDate(system.now());
return tokenizeResponse;
}
令牌化 API:POST /commerce/payments/payment-methods。必需参数:cardPaymentMethod(包含卡信息如卡号/持卡人姓名/有效期/CVV/卡类型)、paymentGatewayId。可选:accountId、address、email、ipAddress、macAddress、phone、additionalData。支付平台接受客户支付方式数据传递给外部网关令牌服务器——服务器返回令牌值存储在 Salesforce 中。
替代支付方法与幂等性
替代支付方法(API 51.0+):允许客户存储不由 CardPaymentMethod 或 DigitalWallet 表示的支付方式信息。常见示例:CashOnDelivery、Klarna、Direct Debit。为每种替代支付方法创建唯一记录类型——不同的选择列表值和页面布局。推荐为每种记录类型创建对应的 GtwyProviderPaymentMethodType。默认使用私有共享模型——仅记录所有者和更高级别用户拥有 Read/Edit/Delete 访问权限。
幂等性(Idempotency):支付网关识别错误或恶意提交的重复请求并相应处理的能力。如果 Salesforce CCS Payment API 检测到重复请求且网关提供程序支持幂等性(paymentGatewayProvider 记录中的 idempotencySupported 值),请求体的 duplicate 参数变为 True。从请求对象获取幂等性键:request.idempotencyKey。GitHub 上有完整的 Payeezy 支付网关参考实现。
CommercePayments 提供了从支付令牌化到完整交易生命周期的标准化框架。通过选择同步或异步适配器、实现令牌化加密和授权撤销服务,你可以构建安全、合规、可靠的企业级支付解决方案。