绑卡 (SDK)
下架通知:
本指南内容已停止更新。
本文指导您如何通过 SDK 集成独立绑卡,以允许买家在支付过程的任何阶段绑定银行卡。在此方案中,Antom 负责采集买家的卡明文信息并进行存储,绑定成功后 Antom 会返回对应的卡令牌(cardToken)。SDK 集成可保护您免受 PCI-DSS 限制,因为敏感数据不会通过您的服务器,并且无需您 PCI 合规。在后续的交易中,您可以直接使用 cardToken 参数来发起支付,而无需再次收集买家的卡信息。关于令牌(cardToken)支付,请查看卡信息存档交易(COF)。
用户体验
下列图片展示了买家在 Web 端和 Mobile 端进行绑卡(包括嵌入式及浮层式绑卡体验)与后续支付流程的用户体验:
Web 端
Mobile 端
嵌入式绑卡体验
浮层式绑卡体验
后续支付



嵌入式绑卡体验
浮层式绑卡体验
后续支付



绑卡流程
绑卡流程包括以下步骤:

- 买家点击绑卡按钮。
- 调用 createVaultingSession 接口,发起绑卡请求。
买家点击绑卡按钮后,您的服务端向 Antom 服务端调用 createVaultingSession 接口来发起绑卡请求。 - 调用客户端 SDK 组件。
使用 createVaultingSession 接口返回的 vaultingSessionData 调用 SDK 组建。SDK 会展示卡要素搜集页面。 - 买家完成绑卡。
买家在卡要素搜集页面输入卡信息完成绑卡。 - (可选)买家完成 3D 验证。
如果您指定需要 3D 验证,买家完成绑定后则需要完成 3DS 验证流程。 - 获取绑卡结果。
通过以下两种方法之一获取绑卡结果:
- 异步通知:Antom 会使用 notifyVaulting 接口向您发送绑卡结果通知。
- 同步查询:调用 inquireVaulting 接口来查询绑卡状态。
Web/WAP
Android
iOS
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 Web/WAP 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新版本的 SDK。
集成步骤
请按照以下步骤开始集成。
- (可选)预加载绑卡页面
- 创建绑卡会话
- 调用 SDK 组件
- 获取绑卡结果
步骤 1:(可选)预加载绑卡页面 客户端
当加载绑卡页面时,强烈建议您执行预加载操作,以提升收银台页面的渲染速度,该操作不会影响您的页面性能。请按照以下代码示例执行预加载操作:
Web/WAP
// import { AMSVaulting } from '@alipay/ams-checkout';
AMSVaulting.preload();步骤 2:创建绑卡会话 服务端
当买家选择 Antom 提供的支付方式时,您需要收集绑定请求 ID、绑定重定向页面链接、绑定结果通知链接等关键信息,并调用 createVaultingSession 接口来创建一个绑卡会话,并将绑定会话返回给客户端。
创建绑卡会话涉及以下参数:
public static void createVaultingSession(){
AlipayVaultingSessionRequest alipayVaultingSessionRequest = new AlipayVaultingSessionRequest();
// 替换为您的 paymentRequestId
String vaultingRequestId = UUID.randomUUID().toString();
alipayVaultingSessionRequest.setVaultingRequestId(vaultingRequestId);
alipayVaultingSessionRequest.setPaymentMethodType("CARD");
alipayVaultingSessionRequest.setVaultingNotificationUrl("http://www.yourNotifyUrl.com");
alipayVaultingSessionRequest.setRedirectUrl("http://www.yourRedirectUrl.com");
// 绑卡
AlipayVaultingSessionResponse alipayVaultingSessionResponse;
try{
alipayVaultingSessionResponse = CLIENT.execute(alipayVaultingSessionRequest);
}catch (AlipayApiException e){
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了一个请求的示例:
{
"paymentMethodType": "CARD",
"redirectUrl": "http://www.yourRedirectUrl.com",
"vaultingNotificationUrl": "http://www.yourNotifyUrl.com",
"vaultingRequestId": "4a17609d-1749-4f53-a2fb-8bdba8d5aad8"
}以下代码展示了一个响应的示例,其中包含以下参数:
- vaultingSessionData:需要返回给前端的绑定会话数据。
- vaultingSessionExpiryTime:绑定会话的过期时间。
{
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
},
"vaultingSessionData": "qOnxVjFYB/QNieiGGnf3P7XOreGIRi7dSZDMzCzT5DzGLaI5a5paDhEAgmG8IwVuTCHscscPdJg==&&SG&&188&&eyJleHRlbmRJbmZvIjoie1widmVyc2lvbk1hcFwiOntcIndlYlwiOntcIjEuMS4wXCI6e1widGFyZ2V0V2ViVmVyaXNvblwiOlwiMS4xLjBcIn0sXCIxLjIuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMi4wXCJ9fSxcImlPU1wiOntcIjEuMS4wXCI6e1widGFyZ2V0V2ViVmVyaXNvblwiOlwiMS4xLjBcIn0sXCIxLjIuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMi4wXCJ9fSxcIkFuZHJvaWRcIjp7XCIxLjEuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMS4wXCJ9LFwiMS4yLjBcIjp7XCJ0YXJnZXRXZWJWZXJpc29uXCI6XCIxLjIuMFwifX19fSIsInBheW1lbnRTZXNzaW9uQ29uZmlnIjp7InBheW1lbnRNZXRob2RDYXRlZ29yeVR5cGUiOiJDQVJEIiwicHJvZHVjdFNjZW5lIjoiVkFVTFRJTkciLCJwcm9kdWN0U2NlbmVWZXJzaW9uIjoiMS4wIn0sInNraXBSZW5kZXJQYXltZW50TWV0aG9kIjpm******",
"vaultingSessionExpiryTime": "2024-12-31T12:06:05+08:00",
"vaultingSessionId": "********qOnxVjFYB/QNieiGGnf3P7XOreGIRi7fAxqpLf+1appjsXAs5Eq1H"
}步骤 3:调用 SDK 组件 客户端
商户客户端使用 vaultingSessionData 调用 SDK ,SDK 会渲染对应的卡支付要素收集页面、3D 处理流程等,让买家可以完成端到端的绑卡。
1. 实例化客户端 SDK
通过使用
AMSVaulting
并指定基本参数来创建 SDK 实例。配置对象包括以下参数:以下示例代码展示了如何实例化 SDK:
npm 实例化 SDK
CDN 实例化 SDK
npm 实例化 SDK
import { AMSVaulting } from '@alipay/ams-checkout' // 包管理
const checkoutApp = new AMSVaulting({
environment: "sandbox",
locale: "en_US",
onEventCallback: ({ code, result }) => {}
});CDN 实例化 SDK
const checkoutApp = new window.AMSVaulting({
environment: "sandbox",
locale: "en_US",
onEventCallback: ({ code, result }) => {}
});以下示例代码展示了如何获取浏览器语言:
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // Replace "-" with "_"2. 创建绑卡组件
使用实例对象中的
createComponent
或 mountComponent
方法来创建绑卡组件,配置对象包括以下参数:您可以通过浮层式或嵌入式在页面上展示组件,以下为对应的示例代码:
浮层式体验
嵌入式体验
async function create(sessionData) {
await checkoutApp.createComponent({
sessionData: sessionData,
notRedirectAfterComplete: true,
});
}
async function create(sessionData) {
await checkoutApp.mountComponent({
sessionData: sessionData,
appearance:{
showSubmitButton: false, // 配置支付按钮是否由组件呈现。
},
notRedirectAfterComplete: true,
},'#ContainerNodeId');
}
checkoutApp.submit().then(({code, message})=>{}) //使用嵌入式渲染和自定义提交按钮时,记得主动调用提交方法来启动提交过程。 3. SDK 回调事件码处理
根据 notRedirectAfterComplete 参数配置,对应处理后续流程:
- 如果设置 notRedirectAfterComplete 为 false,完成绑卡后,买家将被重定向到在 createVaultingSession 接口中提供的vaultingRedirectUrl。您可以再获取到绑卡结果后并展示给买家。
- 如果 notRedirectAfterComplete 为true,绑卡结果将通过onEventCallback方法给出。这里的绑卡结果仅用于前端展示,最终绑卡状态以服务器端为准。
事件码(case code)
以下是由
onEventCallback
返回的绑卡结果可能的事件码(case code):以下示例代码展示了如何处理回调事件
onEventCallback
: function onEventCallback({ code, result }) {
switch (code) {
case code:
'SDK_ASSET_BINDING_SUCCESSFUL';
// 绑卡成功,释放 SDK 组件资源并跳转至绑卡结果页。
break;
case code:
'SDK_ASSET_BINDING_FAIL';
// 绑卡失败,可根据 vaultingResultCode 错误码提示信息引导买家重新绑卡。
break;
case code:
'SDK_ASSET_BINDING_ERROR';
// 绑卡异常,可等待绑卡结果通知或重新引导买家绑卡。
break;
case code:
'SDK_ASSET_BINDING_CANCEL';
// 引导买家重新尝试绑卡。
break;
default:
break;
}
}以下为
onEventCallback
方法给出绑卡结果的示例代码:绑卡成功
{
"code": "SDK_ASSET_BINDING_SUCCESSFUL", // 前端事件码
"result": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "Success"
}
}绑卡失败
{
"code": "SDK_ASSET_BINDING_FAIL", // 前端事件码
"result": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "Success"
},
"vaultingStatus":"FAIL",
"vaultingResultCode":"PROCESS_FAIL",
"vaultingResultMessage":"A general business failure occurred."
}4. 销毁组件
在以下情况下,调用
unmount
方法来释放 SDK 组件资源:- 当买家切换视图离开绑定页面时,释放 createVaultingSession 中创建的组件资源。
- 当买家发起多笔绑卡时,且绑卡中的参数发生变更,回收上一次 createVaultingSession 接口中创建的组件资源。
- 在获取绑卡结果后释放组件资源。
注意:同一时间只能创建一个组件,如果需要使用不同 vaultingSessionData 或重新创建组件,需要先执行卸载方法。
// 释放 SDK 组件资源。
checkoutApp.unmount();步骤 4:获取绑卡结果 服务端
您可以通过以下方法之一获取绑卡结果:
- 接收异步通知
- 主动查询结果
接收异步通知
主动查询结果
接收异步通知
1. 设置接收通知的 webhook URL
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createVaultingSession 接口请求的 vaultingNotificationUrl 字段传入该笔订单的接收异步通知 URL。
以下是异步通知请求的代码示例:
{
"paymentMethodDetail": {
"card": {
"brand": "MASTERCARD",
"cardToken": "ALIPAY34RlcCU3ZtZ***********************sVYl8x244tyWCloE4MwfmN48sP1+rSPQ==",
"maskedCardNo": "************1310",
"networkTransactionId": "112000********575887"
},
"paymentMethodType": "CARD"
},
"vaultingRequestId": "VAULT_2025*******348834_AUTO",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success",
"resultStatus": "S"
}
}
下表展示了绑卡通知中 result.resultStatus 字段可能返回的值,请您根据指引进行处理:
2. 异步通知验签
您需要按照以下方法对 Antom 发送的绑卡通知进行验签:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {
// 从 http 请求中获取所需参数
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// 从请求头中获取所需参数
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// 通知验签
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// 反序列化通知主体
// 根据通知结果更新订单状态
// 响应服务端已接收通知
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// 处理错误情况
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}您无需对响应通知结果做加签处理,但是对于每个通知请求均需按以下固定格式响应,与绑卡成功与否无关。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:绑定成功后会立即发送异步通知吗?
答:绑定结果的异步通知会秒级发送,一般会 3-5 秒发送。
问:绑定失败后会发送异步通知吗?
答:会发送。
问:异步通知会被重新发送吗?
答:是的,对于以下情况,异步通知会在 24 小时内自动重新发送:
- 如果由于网络原因未收到异步通知。
- 如果您收到来自 Antom 的异步通知,但您没有按照处理通知的示例代码格式对通知做出响应。
通知最多可以重发 8 次,或者直到收到正确的响应以终止发送。发送间隔如下:0 分钟、2 分钟、10 分钟、10 分钟、1 小时、2 小时、6 小时和15 小时。
问:收到绑卡结果通知是否需要验签?
答:需要。通过验签 Antom 会发送保障回调请求给您,验签时请注意拼装待验签报文时需按标准处理:<http-method> <http-uri> <client-id>.<request-time>.<request-body>,特别是针对 <request-body> 需直接取值而非解析 JSON 后拼装。
问:返回的 cardToken 有效期是多久?
答:cardToken 本身永久有效,若卡片到期,则会同时失效。若卡片到期,您再次调用支付请求,Antom 会返回 INVALID_EXPIRATION_DATE 错误码,建议您引导买家重新绑定更新后的卡信息。
主动查询结果
除了可以通过异步通知的功能获取绑卡结果,同时也支持您通过主动查询服务来获取对应的结果。您可以调用 inquireVaulting 接口,可使用绑定支付方式中的 vaultingRequestId 查询绑卡状态。
public static void inquireVaulting(){
AlipayVaultingQueryRequest alipayVaultingQueryRequest = new AlipayVaultingQueryRequest();
//替换为您的 vaultingRequestId
alipayVaultingQueryRequest.setVaultingRequestId("c7f3ee64-c472-4d12-b8de-3157804ed55f");
AlipayVaultingQueryResponse alipayVaultingQueryResponse;
try{
alipayVaultingQueryResponse = CLIENT.execute(alipayVaultingQueryRequest);
}catch (AlipayApiException e){
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了一个请求报文的示例:
{
"vaultingRequestId": "VAULT_20250508183612361_AUTO"
}以下代码展示了一个响应报文的示例:
{
"paymentMethodDetail": {
"card": {
"brand": "MASTERCARD",
"cardToken": "ALIPAYEfG2DFbGx2Eh****************************XA7nyWCloE4MwfmN48sP1+rSPQ==",
"maskedCardNo": "************1310",
"networkTransactionId": "112000********575887"
},
"paymentMethodType": "CARD"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
},
"vaultingRequestId": "VAULT_2025********361_AUTO",
"vaultingStatus": "SUCCESS"
}下表展示了响应报文中 result.resultStatus 字段可能的值:
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 Android 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新版本的 SDK。
集成步骤
请按照以下步骤开始集成。
- (可选)预加载绑卡页面
- 创建绑卡会话
- 调用 SDK 组件
- 获取绑卡结果
步骤 1:(可选)预加载绑卡页面 客户端
当加载绑卡页面时,强烈建议您执行预加载操作,以提升收银台页面的渲染速度,该操作不会影响您的页面性能。请按照以下代码示例执行预加载操作:
Android
AMSVaulting.preload(context.getApplicationContext());
//context-(必须)-Android 应用上下文对象。步骤 2: 创建绑卡会话 服务端
当买家选择 Antom 提供的支付方式时,您需要收集绑定请求 ID、绑定重定向页面链接、绑定结果通知链接等关键信息,并调用 createVaultingSession 接口来创建一个绑卡会话,并将绑定会话返回给客户端。
创建绑卡会话涉及以下参数:
public static void createVaultingSession(){
AlipayVaultingSessionRequest alipayVaultingSessionRequest = new AlipayVaultingSessionRequest();
// 替换为您的 paymentRequestId
String vaultingRequestId = UUID.randomUUID().toString();
alipayVaultingSessionRequest.setVaultingRequestId(vaultingRequestId);
alipayVaultingSessionRequest.setPaymentMethodType("CARD");
alipayVaultingSessionRequest.setVaultingNotificationUrl("http://www.yourNotifyUrl.com");
alipayVaultingSessionRequest.setRedirectUrl("http://www.yourRedirectUrl.com");
// 绑卡
AlipayVaultingSessionResponse alipayVaultingSessionResponse;
try{
alipayVaultingSessionResponse = CLIENT.execute(alipayVaultingSessionRequest);
}catch (AlipayApiException e){
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了一个请求的示例:
{
"paymentMethodType": "CARD",
"redirectUrl": "http://www.yourRedirectUrl.com",
"vaultingNotificationUrl": "http://www.yourNotifyUrl.com",
"vaultingRequestId": "4a17609d-1749-4f53-a2fb-8bdba8d5aad8"
}以下代码展示了一个响应的示例,其中包含以下参数:
- vaultingSessionData:需要返回给前端的绑定会话数据。
- vaultingSessionExpiryTime:绑定会话的过期时间。
{
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
},
"vaultingSessionData": "qOnxVjFYB/QNieiGGnf3P7XOreGIRi7dSZDMzCzT5DzGLaI5a5paDhEAgmG8IwVuTCHscscPdJg==&&SG&&188&&eyJleHRlbmRJbmZvIjoie1widmVyc2lvbk1hcFwiOntcIndlYlwiOntcIjEuMS4wXCI6e1widGFyZ2V0V2ViVmVyaXNvblwiOlwiMS4xLjBcIn0sXCIxLjIuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMi4wXCJ9fSxcImlPU1wiOntcIjEuMS4wXCI6e1widGFyZ2V0V2ViVmVyaXNvblwiOlwiMS4xLjBcIn0sXCIxLjIuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMi4wXCJ9fSxcIkFuZHJvaWRcIjp7XCIxLjEuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMS4wXCJ9LFwiMS4yLjBcIjp7XCJ0YXJnZXRXZWJWZXJpc29uXCI6XCIxLjIuMFwifX19fSIsInBheW1lbnRTZXNzaW9uQ29uZmlnIjp7InBheW1lbnRNZXRob2RDYXRlZ29yeVR5cGUiOiJDQVJEIiwicHJvZHVjdFNjZW5lIjoiVkFVTFRJTkciLCJwcm9kdWN0U2NlbmVWZXJzaW9uIjoiMS4wIn0sInNraXBSZW5kZXJQYXltZW50TWV0aG9kIjpm******",
"vaultingSessionExpiryTime": "2024-12-31T12:06:05+08:00",
"vaultingSessionId": "********qOnxVjFYB/QNieiGGnf3P7XOreGIRi7fAxqpLf+1appjsXAs5Eq1H"
}步骤 3:调用 SDK 组件 客户端
商户客户端使用 vaultingSessionData 调用 SDK ,SDK 会渲染对应的卡支付要素收集页面、3D 处理流程等,让买家可以完成端到端的绑卡。
1. 实例化客户端 SDK
通过使用
AMSVaulting
并指定基本参数来创建 SDK 实例。配置对象包括以下参数:以下示例代码展示了如何实例化 SDK:
实例化 SDK
AMSVaultingConfiguration configuration = new AMSVaultingConfiguration();
configuration.setLocale(new Locale("en", "US"));
// 设置沙箱环境
configuration.setOption("sandbox", "true");
// 设置收银台回调监听
configuration.setOnCheckoutListener(new OnCheckoutListener() {
@Override
public void onEventCallback(String eventCode, AMSEventResult eventResult) {
Log.e(TAG, "onEventCallback eventCode=" + eventCode + " eventResult=" + eventResult.toString());
}
});
// 创建 AMSVaulting 实例化
AMSVaulting checkout = new AMSVaulting.Builder(activity, configuration).build();2. 创建绑卡组件
使用实例对象中的
createComponent
或 mountComponent
方法来创建绑卡组件,配置对象包括以下参数:您可以通过浮层式或嵌入式在页面上展示组件,以下为对应的示例代码:
浮层式体验
嵌入式体验
checkout.createComponent(activity,sessionData);
//卸载组件
checkout.onDestroy();// 触发渲染内嵌组件
Map<String, Object> appearanceConfig = new HashMap<>();
appearanceConfig.put("showSubmitButton", false);
appearanceConfig.put("showSubmitLoading", true);
AMSPaymentAppearance appearance = AMSPaymentAppearance.create(appearanceConfig);
checkout.mountComponent(activity, appearance, sessionData, parentViewGroup);
String dataString = "{"billingAddress":{"zipCode":"310000","region":"CN"}}";
// 用户输入完成提交绑定
checkout.submit(dataString);3. SDK 回调事件码处理
根据 notRedirectAfterComplete 参数配置,对应处理后续流程:
- 如果设置 notRedirectAfterComplete 为 false,完成绑卡后,买家将被重定向到在 createVaultingSession 接口中提供的vaultingRedirectUrl。您可以再获取到绑卡结果后并展示给买家。
- 如果 notRedirectAfterComplete 为true,绑卡结果将通过onEventCallback方法给出。这里的绑卡结果仅用于前端展示,最终绑卡状态以服务器端为准。
事件码(case code)
以下是由
onEventCallback
返回的绑卡结果可能的事件码(case code):以下示例代码展示了如何处理回调事件
onEventCallback
: public void onEventCallback(String eventCode, AMSEventResult eventResult) {
Log.e(TAG, "onEventCallback eventCode=" + eventCode + " eventResult=" + eventResult.toString());
if (!TextUtils.isEmpty(eventCode)) {
if ("SDK_ASSET_BINDING_SUCCESSFUL".equals(eventCode)) {
//绑卡成功,需要注销SDK。建议重定向到绑卡结果页。
} else if ("SDK_ASSET_BINDING_FAIL".equals(eventCode)) {
// 绑卡失败。建议您根据 vaultingResultCode 错误码提示信息,并重新引导买家绑卡。
} else if ("SDK_ASSET_BINDING_ERROR".equals(eventCode)) {
// 绑卡异常。建议您等待绑卡结果通知或重新引导买家绑卡。
} else if ("SDK_ASSET_BINDING_CANCEL".equals(eventCode)) {
// 引导买家重新尝试绑卡。
} else{
// 其它自定义关注的事件或错误
}
}
}以下为
onEventCallback
方法给出绑卡结果的示例代码:绑卡成功
{
"code": "SDK_ASSET_BINDING_SUCCESSFUL", // 前端事件码
"result": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "Success"
}
}绑卡失败
{
"code": "SDK_ASSET_BINDING_FAIL", // 前端事件码
"result": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "Success"
},
"vaultingStatus":"FAIL",
"vaultingResultCode":"PROCESS_FAIL",
"vaultingResultMessage":"A general business failure occurred."
}4. 销毁组件
调用实例对象中的
onDestroy()
方法,可以销毁已经创建的组件。如下情况下您需要卸载组件:- 如果你的客户端设置了超时时间,到达所设置的超时时间时。
- 买家退出绑卡页面时。
- 您收到绑卡结果回调时。
注意:同一时间只能创建一个组件,如果需要使用不同 vaultingSessionData 或重新创建组件,需要先执行卸载方法。
checkout.onDestroy();步骤 4:获取绑卡结果 服务端
您可以通过以下方法之一获取绑卡结果:
- 接收异步通知
- 主动查询结果
接收异步通知
主动查询结果
接收异步通知
1. 设置接收通知的 webhook URL
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createVaultingSession 接口请求的 vaultingNotificationUrl 字段传入该笔订单的接收异步通知 URL。
以下是异步通知请求的代码示例:
{
"paymentMethodDetail": {
"card": {
"brand": "MASTERCARD",
"cardToken": "ALIPAY34RlcCU3ZtZ***********************sVYl8x244tyWCloE4MwfmN48sP1+rSPQ==",
"maskedCardNo": "************1310",
"networkTransactionId": "112000********575887"
},
"paymentMethodType": "CARD"
},
"vaultingRequestId": "VAULT_2025*******348834_AUTO",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}
下表展示了绑卡通知中 result.resultStatus 字段可能返回的值,请您根据指引进行处理:
2. 异步通知验签
您需要按照以下方法对 Antom 发送的绑卡通知进行验签:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {
// 从 http 请求中获取所需参数
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// 从请求头中获取所需参数
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// 通知验签
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// 反序列化通知主体
// 根据通知结果更新订单状态
// 响应服务端已接收通知
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// 处理错误情况
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}您无需对响应通知结果做加签处理,但是对于每个通知请求均需按以下固定格式响应,与绑卡成功与否无关。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:绑定成功后会立即发送异步通知吗?
答:绑定结果的异步通知会秒级发送,一般会 3-5 秒发送。
问:绑定失败后会发送异步通知吗?
答:会发送。
问:异步通知会被重新发送吗?
答:是的,对于以下情况,异步通知会在 24 小时内自动重新发送:
- 如果由于网络原因未收到异步通知。
- 如果您收到来自 Antom 的异步通知,但您没有按照处理通知的示例代码格式对通知做出响应。
通知最多可以重发 8 次,或者直到收到正确的响应以终止发送。发送间隔如下:0 分钟、2 分钟、10 分钟、10 分钟、1 小时、2 小时、6 小时和15 小时。
问:收到绑卡结果通知是否需要验签?
答:需要。通过验签 Antom 会发送保障回调请求给您,验签时请注意拼装待验签报文时需按标准处理:<http-method> <http-uri> <client-id>.<request-time>.<request-body>,特别是针对 <request-body> 需直接取值而非解析 JSON 后拼装。
问:返回的 cardToken 有效期是多久?
答:cardToken 本身永久有效,若卡片到期,则会同时失效。若卡片到期,您再次调用支付请求,Antom 会返回 INVALID_EXPIRATION_DATE 错误码,建议您引导买家重新绑定更新后的卡信息。
主动查询结果
除了可以通过异步通知的功能获取绑卡结果,同时也支持您通过主动查询服务来获取对应的结果。您可以调用 inquireVaulting 接口,可使用绑定支付方式中的 vaultingRequestId 查询绑卡状态。
public static void inquireVaulting(){
AlipayVaultingQueryRequest alipayVaultingQueryRequest = new AlipayVaultingQueryRequest();
//替换为您的 vaultingRequestId
alipayVaultingQueryRequest.setVaultingRequestId("c7f3ee64-c472-4d12-b8de-3157804ed55f");
AlipayVaultingQueryResponse alipayVaultingQueryResponse;
try{
alipayVaultingQueryResponse = CLIENT.execute(alipayVaultingQueryRequest);
}catch (AlipayApiException e){
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了一个请求报文的示例:
{
"vaultingRequestId": "VAULT_20250508183612361_AUTO"
}以下代码展示了一个响应报文的示例:
{
"paymentMethodDetail": {
"card": {
"brand": "MASTERCARD",
"cardToken": "ALIPAYEfG2DFbGx2Eh****************************XA7nyWCloE4MwfmN48sP1+rSPQ==",
"maskedCardNo": "************1310",
"networkTransactionId": "112000********575887"
},
"paymentMethodType": "CARD"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
},
"vaultingRequestId": "VAULT_2025********361_AUTO",
"vaultingStatus": "SUCCESS"
}下表展示了响应报文中 result.resultStatus 字段可能的值:
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 iOS 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新版本的 SDK。
集成步骤
请按照以下步骤开始集成。
- (可选)预加载绑卡页面
- 创建绑卡会话
- 调用 SDK 组件
- 获取绑卡结果
步骤 1:(可选)预加载绑卡页面 客户端
当加载绑卡页面时,强烈建议您执行预加载操作,以提升收银台页面的渲染速度,该操作不会影响您的页面性能。请按照以下代码示例执行预加载操作:
iOS
[[AMSVaulting shared] preload];步骤 2:创建绑卡会话 服务端
当买家选择 Antom 提供的支付方式时,您需要收集绑定请求 ID、绑定重定向页面链接、绑定结果通知链接等关键信息,并调用 createVaultingSession 接口来创建一个绑卡会话,并将绑定会话返回给客户端。
创建绑卡会话涉及以下参数:
public static void createVaultingSession(){
AlipayVaultingSessionRequest alipayVaultingSessionRequest = new AlipayVaultingSessionRequest();
// 替换为您的 paymentRequestId
String vaultingRequestId = UUID.randomUUID().toString();
alipayVaultingSessionRequest.setVaultingRequestId(vaultingRequestId);
alipayVaultingSessionRequest.setPaymentMethodType("CARD");
alipayVaultingSessionRequest.setVaultingNotificationUrl("http://www.yourNotifyUrl.com");
alipayVaultingSessionRequest.setRedirectUrl("http://www.yourRedirectUrl.com");
// 绑卡
AlipayVaultingSessionResponse alipayVaultingSessionResponse;
try{
alipayVaultingSessionResponse = CLIENT.execute(alipayVaultingSessionRequest);
}catch (AlipayApiException e){
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了一个请求的示例:
{
"paymentMethodType": "CARD",
"redirectUrl": "http://www.yourRedirectUrl.com",
"vaultingNotificationUrl": "http://www.yourNotifyUrl.com",
"vaultingRequestId": "4a17609d-1749-4f53-a2fb-8bdba8d5aad8"
}以下代码展示了一个响应的示例,其中包含以下参数:
- vaultingSessionData:需要返回给前端的绑定会话数据。
- vaultingSessionExpiryTime:绑定会话的过期时间。
{
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
},
"vaultingSessionData": "qOnxVjFYB/QNieiGGnf3P7XOreGIRi7dSZDMzCzT5DzGLaI5a5paDhEAgmG8IwVuTCHscscPdJg==&&SG&&188&&eyJleHRlbmRJbmZvIjoie1widmVyc2lvbk1hcFwiOntcIndlYlwiOntcIjEuMS4wXCI6e1widGFyZ2V0V2ViVmVyaXNvblwiOlwiMS4xLjBcIn0sXCIxLjIuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMi4wXCJ9fSxcImlPU1wiOntcIjEuMS4wXCI6e1widGFyZ2V0V2ViVmVyaXNvblwiOlwiMS4xLjBcIn0sXCIxLjIuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMi4wXCJ9fSxcIkFuZHJvaWRcIjp7XCIxLjEuMFwiOntcInRhcmdldFdlYlZlcmlzb25cIjpcIjEuMS4wXCJ9LFwiMS4yLjBcIjp7XCJ0YXJnZXRXZWJWZXJpc29uXCI6XCIxLjIuMFwifX19fSIsInBheW1lbnRTZXNzaW9uQ29uZmlnIjp7InBheW1lbnRNZXRob2RDYXRlZ29yeVR5cGUiOiJDQVJEIiwicHJvZHVjdFNjZW5lIjoiVkFVTFRJTkciLCJwcm9kdWN0U2NlbmVWZXJzaW9uIjoiMS4wIn0sInNraXBSZW5kZXJQYXltZW50TWV0aG9kIjpm******",
"vaultingSessionExpiryTime": "2024-12-31T12:06:05+08:00",
"vaultingSessionId": "********qOnxVjFYB/QNieiGGnf3P7XOreGIRi7fAxqpLf+1appjsXAs5Eq1H"
}步骤 3:调用 SDK 组件 客户端
商户客户端使用 vaultingSessionData 调用 SDK ,SDK 会渲染对应的卡支付要素收集页面、3D 处理流程等,让买家可以完成端到端的绑卡。
1. 实例化客户端 SDK
通过使用
AMSVaulting
并指定基本参数来创建 SDK 实例。以下示例代码展示了如何实例化 SDK:
实例化 SDK
#import <AMSComponent/AMSComponent-Swift.h>
AMSVaultingConfiguration *componentConfig = [AMSVaultingConfiguration new];
componentConfig.locale = @"en_US";
// sandbox变更设置沙箱环境,不设置为线上正式环境
NSDictionary *options = @{@"sandbox": @"true",
@"notRedirectAfterComplete": @"true"
};
componentConfig.options = options;
[[AMSVaulting shared] initConfiguration:componentConfig];
[AMSVaulting shared].paymentDelegate = self;
[[AMSVaulting shared] createComponent:vaultingSessionData];
#pragma AMSPaymentProtocol
- (void)onEventCallback:(NSString *)eventCode eventResult:(AMSEventResult *)eventResult
{
NSLog(@"eventCode%@ eventResult%@", eventCode, eventResult);
}2. 创建绑卡组件
使用实例对象中的
createComponent
或 mountComponent
方法来创建绑卡组件,配置对象包括以下参数:您可以通过浮层式或嵌入式在页面上展示组件,以下为对应的示例代码:
浮层式体验
嵌入式体验
[[AMSVaulting shared] createComponent:sessionData];
//销毁组件
[[AMSVaulting shared] onDestroy];[[AMSVaulting shared] mountComponent:sessionData];
// 用户输入完成提交绑定
NSString *dataString = @"{"billingAddress":{"zipCode":"310000","region":"CN"}}";
[[AMSVaulting shared] submit: dataString];
//卸载组件
[[AMSVaulting shared] onDestroy];3. SDK 回调事件码处理
根据 notRedirectAfterComplete 参数配置,对应处理后续流程:
- 如果设置 notRedirectAfterComplete 为 false,完成绑卡后,买家将被重定向到在 createVaultingSession 接口中提供的vaultingRedirectUrl。您可以再获取到绑卡结果后并展示给买家。
- 如果 notRedirectAfterComplete 为true,绑卡结果将通过onEventCallback方法给出。这里的绑卡结果仅用于前端展示,最终绑卡状态以服务器端为准。
SDK 事件码(case code)
以下是由
onEventCallback
返回的绑卡结果可能的事件码(case code):以下示例代码展示了如何处理回调事件
onEventCallback
: #import <AMSComponent/AMSComponent-Swift.h>
#pragma AMSPaymentProtocol
- (void)onEventCallback:(NSString *)eventCode eventResult:(AMSEventResult *)eventResult
{
if ([eventCode isEqualToString:@"SDK_ASSET_BINDING_SUCCESSFUL"]) {
// 绑卡成功,需要注销 SDK。建议重定向到绑卡结果页。
} else if ([eventCode isEqualToString:@"SDK_ASSET_BINDING_FAIL"]) {
// 绑卡失败。建议您根据 vaultingResultCode 错误码提示信息,并重新引导买家绑卡。
} else if ([eventCode isEqualToString:@"SDK_ASSET_BINDING_ERROR"]) {
// 绑卡异常。建议您等待绑卡结果通知或重新引导买家绑卡。
} else if ([eventCode isEqualToString:@"SDK_ASSET_BINDING_CANCEL"]) {
// 引导买家重新尝试绑卡。
} else {
// 其它自定义关注的事件或错误
}
NSLog(@"eventCode%@ eventResult%@", eventCode, eventResult);
}以下为
onEventCallback
方法给出绑卡结果的示例代码:绑卡成功
{
"code": "SDK_ASSET_BINDING_SUCCESSFUL", // 前端事件码
"result": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "Success"
}
}绑卡失败
{
"code": "SDK_ASSET_BINDING_FAIL", // 前端事件码
"result": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "Success"
},
"vaultingStatus":"FAIL",
"vaultingResultCode":"PROCESS_FAIL",
"vaultingResultMessage":"A general business failure occurred."
}4. 销毁组件
调用实例对象中的
onDestroy()
方法,可以销毁已经创建的组件。如下情况下您需要卸载组件:- 如果你的客户端设置了超时时间,到达所设置的超时时间时。
- 买家退出绑卡页面时。
- 您收到绑卡结果回调时。
注意:同一时间只能创建一个组件,如果需要使用不同 vaultingSessionData 或重新创建组件,需要先执行卸载方法。
[[AMSVaulting shared] onDestroy];步骤 4:获取绑卡结果 服务端
您可以通过以下方法之一获取绑卡结果:
- 接收异步通知
- 主动查询结果
接收异步通知
主动查询结果
接收异步通知
1. 设置接收通知的 webhook URL
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createVaultingSession 接口请求的 vaultingNotificationUrl 字段传入该笔订单的接收异步通知 URL。
以下是异步通知请求的代码示例:
{
"paymentMethodDetail": {
"card": {
"brand": "MASTERCARD",
"cardToken": "ALIPAY34RlcCU3ZtZ***********************sVYl8x244tyWCloE4MwfmN48sP1+rSPQ==",
"maskedCardNo": "************1310",
"networkTransactionId": "112000********575887"
},
"paymentMethodType": "CARD"
},
"vaultingRequestId": "VAULT_2025*******348834_AUTO",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}
下表展示了绑卡通知中 result.resultStatus 字段可能返回的值,请您根据指引进行处理:
2. 异步通知验签
您需要按照以下方法对 Antom 发送的绑卡通知进行验签:
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {
// 从 http 请求中获取所需参数
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// 从请求头中获取所需参数
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// 通知验签
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// 反序列化通知主体
// 根据通知结果更新订单状态
// 响应服务端已接收通知
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// 处理错误情况
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}您无需对响应通知结果做加签处理,但是对于每个通知请求均需按以下固定格式响应,与绑卡成功与否无关。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:绑定成功后会立即发送异步通知吗?
答:绑定结果的异步通知会秒级发送,一般会 3-5 秒发送。
问:绑定失败后会发送异步通知吗?
答:会发送。
问:异步通知会被重新发送吗?
答:是的,对于以下情况,异步通知会在 24 小时内自动重新发送:
- 如果由于网络原因未收到异步通知。
- 如果您收到来自 Antom 的异步通知,但您没有按照处理通知的示例代码格式对通知做出响应。
通知最多可以重发 8 次,或者直到收到正确的响应以终止发送。发送间隔如下:0 分钟、2 分钟、10 分钟、10 分钟、1 小时、2 小时、6 小时和15 小时。
问:收到绑卡结果通知是否需要验签?
答:需要。通过验签 Antom 会发送保障回调请求给您,验签时请注意拼装待验签报文时需按标准处理:<http-method> <http-uri> <client-id>.<request-time>.<request-body>,特别是针对 <request-body> 需直接取值而非解析 JSON 后拼装。
问:返回的 cardToken 有效期是多久?
答:cardToken 本身永久有效,若卡片到期,则会同时失效。若卡片到期,您再次调用支付请求,Antom 会返回 INVALID_EXPIRATION_DATE 错误码,建议您引导买家重新绑定更新后的卡信息。
主动查询结果
除了可以通过异步通知的功能获取绑卡结果,同时也支持您通过主动查询服务来获取对应的结果。您可以调用 inquireVaulting 接口,可使用绑定支付方式中的 vaultingRequestId 查询绑卡状态。
public static void inquireVaulting(){
AlipayVaultingQueryRequest alipayVaultingQueryRequest = new AlipayVaultingQueryRequest();
//替换为您的 vaultingRequestId
alipayVaultingQueryRequest.setVaultingRequestId("c7f3ee64-c472-4d12-b8de-3157804ed55f");
AlipayVaultingQueryResponse alipayVaultingQueryResponse;
try{
alipayVaultingQueryResponse = CLIENT.execute(alipayVaultingQueryRequest);
}catch (AlipayApiException e){
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了一个请求报文的示例:
{
"vaultingRequestId": "VAULT_20250508183612361_AUTO"
}以下代码展示了一个响应报文的示例:
{
"paymentMethodDetail": {
"card": {
"brand": "MASTERCARD",
"cardToken": "ALIPAYEfG2DFbGx2Eh****************************XA7nyWCloE4MwfmN48sP1+rSPQ==",
"maskedCardNo": "************1310",
"networkTransactionId": "112000********575887"
},
"paymentMethodType": "CARD"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
},
"vaultingRequestId": "VAULT_2025********361_AUTO",
"vaultingStatus": "SUCCESS"
}下表展示了响应报文中 result.resultStatus 字段可能的值: