Payment Element 集成
Antom Payment Element 是基于 SDK 集成的支付组件,旨在为您打造完美无缝的支付体验,助力提升支付转化率。针对不同的终端类型,Antom 提供以下适配方案:
- Web/WAP 端:适用于浏览器及移动网页环境的 Web Element
- App 端(Android & iOS & Flutter):专为商户自有移动应用设计的 Mobile Element
各端 Payment Element 支持的能力如下表所示:
Web/WAP
iOS
Android
Flutter
用户体验
Web
WAP
以下图片展示了不同场景下使用 Payment Element 的用户体验:
Payment Element 渲染支付方式列表
商户自行渲染支付方式
以下图片展示了嵌入 Payment Element 渲染的支付方式的模板:

如您选择由 Payment Element 渲染支付方式列表,Payment Element 默认在收银台页面上渲染所有支持的支付方式。以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
存卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

由 Payment Element 处理存卡支付场景:

以下图片展示了商户自行渲染支付方式的模板:

如您通过自行指定支付方式渲染支付方式列表,以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

以下图片展示了不同场景下使用 Payment Element 的用户体验:
Payment Element 渲染支付方式列表
商户自行渲染支付方式
以下图片展示了嵌入 Payment Element 渲染的支付方式的模板:

如您选择由 Payment Element 渲染支付方式列表,Payment Element 默认在收银台页面上渲染所有支持的支付方式。以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
存卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

由 Payment Element 处理存卡支付场景:

以下图片展示了商户自行渲染支付方式的模板:

如您通过自行指定支付方式渲染支付方式列表,以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

订单生命周期
以下是不同支付方式的生命周期:
APM 支付
卡支付、Apple Pay、Google Pay

支付流程
以下图片展示了如何通过 Payment Element 集成单笔支付:
Payment Element 渲染支付方式
商户自行渲染支付方式


- 买家进入结账页面并发起支付。
- 创建支付会话请求。
您可以调用 createPaymentSession(单笔支付)接口获取支付会话。 - 调用 Payment Element。
在客户端,通过支付会话调用 Payment Element。您可以选择由 Payment Element 或者您自行渲染支付方式,同时 Payment Element 会根据支付方式的特性处理信息、收集支付要素、进行重定向、应用调用、二维码显示、验证等流程。当支付完成后,根据您的设置以及支付方式特性,您需要按照 方法返回的结果处理跳转流程或者由系统自动回跳到您的支付结果页面。 - 获取支付结果。
通过以下两种方法之一获取支付结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 notifyPayment 接口来查询支付状态。
注意:在卡支付、Apple Pay、Google Pay 支付场景下,采用的是授权请款模式。步骤 1 至 4 仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- 发起请款并获取请款结果。
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 Web/WAP 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新或不低于 1.46.0 版本的 SDK。
集成步骤
请按照以下步骤开始集成:
- 创建支付会话
- 调用 Payment Element
- 获取支付结果
- 发起请款
步骤 1:创建支付会话 服务端
传入订单信息以调用 createPaymentSession(单笔支付)接口来创建支付会话,获取唤起 Payment Element 的 paymentSessionData。您可选择由您自定义收银台的支付方式列表或由 Payment Element 为您渲染支付方式列表,并在调用 createPaymentSession(单笔支付)接口时传入相应的参数:
Payment Element 渲染支付方式
商户自行渲染支付方式
当您使用 Payment Element 渲染的支付方式列表时,您只需传入以下参数。Payment Element 默认在收银台页面上渲染所有支持的支付方式,您也可以通过指定支付方式来选择您需要的支付方式。
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的环境信息
Env env = Env.builder().terminalType(TerminalType.WAP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}如果由 Payment Element 渲染收银台的支付方式列表,则会展示所有支付方式。以下代码展示了一个请求报文的示例:
{
"env": {
"terminalType": "WAP",
"clientIp": "***.***.***.***", // 买家 IP 地址
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}当您自行渲染支付方式列表时,您必须传入下表中列出的指定支付方式参数。请注意,对于部分支付方式(例如卡支付),您需要嵌入 Payment Element 渲染的支付要素组件。以下是提供卡支付选项时调用 createPaymentSession(单笔支付)接口的最佳时机:
- 如果 Payment Element 需要采集支付要素:在买家选择支付方式后调用 createPaymentSession(单笔支付)接口,并传入下表中列出的卡支付信息参数。
- 如果 Payment Element 不需要采集支付要素:在买家选择支付方式并提交支付后调用 createPaymentSession(单笔支付)接口。
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的环境信息
Env env = Env.builder().terminalType(TerminalType.WAP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// 替换为您的指定支付方式
AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
.paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
.paymentMethodType("ALIPAY_CN")
.build()))
.build();
alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}当您自行渲染支付方式列表时,需要通过指定单个支付方式集成。以下代码展示了一个请求报文的示例:
{
"env": {
"terminalType": "WAP",
"clientIp": "***.***.***.***", // 买家 IP 地址
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // 指定支付方式
}
]
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********u.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}以下代码展示了一个响应的示例,其中包含以下参数:
- result.resultStatus:createPaymentSession(单笔支付)接口的调用结果。
- paymentSessionData:将返回给前端的支付会话数据。
- paymentSessionExpiryTime:支付会话的过期时间。
{
"paymentSessionData": "gpZy************fQ==",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}以下是创建支付会话响应中 result.resultStatus 可能返回的值,请您根据指引进行处理:
注意:如果您未收到响应报文,可能是网络超时所致。建议更换 paymentRequestId 重新调用接口。如果问题未解决,请联系 Antom 技术支持。
常见问题
问:请求参数的值可以使用中文字符吗?
答:为了避免特定支付方式的兼容性问题,请求中的参数请勿使用中文字符。
问:如何设置接收支付通知的地址?
答:在 createPaymentSession(单笔支付)接口的请求中指定 paymentNotifyUrl 参数,以接收支付结果的异步通知(notifyPayment),或者在 Antom Dashboard 中配置接收地址。如果请求和 Antom Dashboard 中都指定了地址,请求中的值优先。
问:返回的 paymentSessionData 是否需要处理后再传给客户端?
答:请勿对 paymentSessionData 进行任何处理,否则可能会导致调用 Payment Element 失败。
步骤 2:调用 Payment Element 客户端
在您的客户端使用 paymentSessionData 调用 Payment Element,在买家提交支付后,Payment Element 会根据不同支付方式,负责展示二维码、跳转支付方式页面、3DS 认证、回跳商户结果页等流程。
根据您在步骤 1 中选择渲染支付方式列表的方式(由您自行渲染或由 Payment Element 渲染支付方式列表),以下是不同渲染方式的对比:
- 在服务端获取到 paymentSessionData 后,使用 类来创建 Payment Element 实例。以下是使用 CDN 或 npm 实例化 SDK 的示例代码:
CDN
npm
// 获取浏览器语言
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // 将 "-" 替换为 "_"
// 创建 Payment Element 实例
const elementPayment = new window.AMSElement({
environment: "sandbox",
locale: "en_US",
sessionData:sessionData
})import { AMSElement, ThemeType, PaymentElementLayout } from '@alipay/ams-checkout' // 包管理
// 获取浏览器语言
let language = navigator.language || navigator.userLanguage;
language = language.replace("-", "_"); // 将 "-" 替换为 "_"
// 创建 AMSElement 实例
const elementPayment = new AMSElement({
environment: "sandbox",
locale: "en_US",
sessionData:sessionData
})- 使用实例对象中的 方法来创建支付组件,如果需要嵌入组件则将组件嵌入到指定视图里。调用 方法前,您可以自行添加 loading 效果,并在 .then()方法中处理回调时关闭 loading 效果。若回调结果包含错误信息,请通过 error?.code 判断具体错误类型,并参阅回调函数事件码获取详细错误原因及处理建议。如果不存在错误信息,则表示 渲染成功。
注意:
- 如您需要嵌入支付要素采集组件(详见需要嵌入的支付方式),建议嵌入 Payment Element 的容器宽度不小于 375px,并且不限制高度,以便由 Payment Element 自动撑开容器。
- 方法中 notRedirectAfterComplete 参数的不同配置会影响商户页面的跳转方式,详情请参阅回跳商户页面。
- 由 Payment Element 渲染支付方式列表时, 方法中的 merchantAppointParam.singleOption 参数默认值为 skip,当仅指定一个支付方式时,会跳过支付方式列表,直接进入支付流程。若需展示支付方式列表,可将该参数的值改为list。
let loading = false;
// 自定义外观
const appearance = {
theme: "default",
layout: {
type: "Accordion"
},
variables: {},
};
// 调用 mount 时先设置外部容器的 loading 状态
loading = true;
// 嵌入 document.querySelector("#payment-element") 这个节点中
elementPayment.mount({
type: 'payment',
appearance: appearance,
notRedirectAfterComplete: false,
merchantAppointParam: {
singleOption: 'skip'
}
},
'#payment-element',
).then(({
error
}) => {
// 自行关闭外部容器的 loading 状态
loading = false;
// 消费错误信息,根据 error.code 处理异常
if (error && error?.code) {
// PARAM_INVALID: SDK 入参异常,建议检查集成代码
// UI_STATE_ERROR: mount 调用时机异常,建议检查集成代码
console.log(error.message);
if (error?.code === 'INITALIZE_API_TIMEOUT') {
// 支付信息查询接口超时,导致收银台渲染失败,建议引导买家重试
} else if (error?.code === 'INITALIZE_WEB_TIMEOUT') {
// 收银台静态资源加载超时,建议引导买家重试
}...
return;
}
// mount 渲染成功,无需处理
})- 买家点击您自定义的支付按钮后,您需调用 方法提交支付。调用 方法前,您可以自行添加 loading 效果,并在 .then()方法中处理回调时关闭 loading 效果。建议在买家点击支付按钮后展示 loading 状态,以避免其在短时间内重复提交。收到 Payment Element 返回的支付结果后,可根据实际结果引导买家重新发起支付或跳转至支付结果页。
- 若回调结果包含错误信息,您可根据 status 的值简化集成处理,具体操作请参考以下示例代码。您也可根据 error?.code 来进行精细化的异常处理,并参阅回调函数事件码获取详细错误原因及处理建议。
- 如不存在错误信息,请根据 status 的值进行后续操作。
let loading = false;
function checkout() {
loading = true;
// 当买家点击支付按钮时:
elementPayment.submitPayment().then(({ status, userCanceled3D, session, error }) => {
// 自行关闭外部容器的 loading 状态
loading = false;
if (error) { // 先处理错误信息
const { code, message, traceId, context } = error;
if (userCanceled3D) {
// 买家主动关闭 3D 弹窗,建议从服务端轮询结果
}
if (status === 'PROCESSING') {
// 因网络异常或渠道不稳定导致状态未知. 建议从服务端轮询结果
} else {
// FAIL 失败
// 表单校验不通过,Payment Element 已提示买家,建议忽略
if (code === 'FORM_INVALID') {
return;
}
toast(message);
// 或根据 code 精细化定制体验
if (code) {
// xxx
}
}
return;
}
if (status === 'SUCCESS') {
// 成功 SUCCESS。部分场景 Payment Element 会有 toast 提示,建议直接跳转结果页
} else if (status === 'CANCELLED') {
// 订单已取消, 如无该场景可忽略
} else {
// 可添加监控
}
})
}- (可选)您可调用 方法传入 handleActions 参数以控制是否由 Payment Element 处理自动跳转:
let loading = false;
function checkout() {
loading = true;
// 当买家点击支付按钮时:
elementPayment.submitPayment({ handleActions: false }).then(({ status, userCanceled3D, session, error }) => {
// 自行关闭外部容器的 loading 状态
loading = false;
if (error) { // 先处理错误信息
const { code, message, traceId, context } = error;
if (userCanceled3D) {
// 买家主动关闭 3DS 弹窗,建议从服务端轮询结果
}
if (status === 'PROCESSING') {
// 因网络异常或渠道不稳定导致状态未知. 建议从服务端轮询结果
} else {
// FAIL 失败
// 表单校验不通过,Payment Element 已提示买家,建议忽略
if (code === 'FORM_INVALID') {
return;
}
toast(message);
// 或根据 code 精细化定制体验
if (code) {
// xxx
}
}
return;
}
if (status === 'SUCCESS') {
// 成功 SUCCESS。部分场景 Payment Element 会有 toast 提示,建议直接跳转结果页
} else if (status === 'CANCELLED') {
// 订单已取消, 如无该场景可忽略
} else {
// 可添加监控
}
if (session && session.nextAction) {
const { normalUrl, appLinkUrl, schemeUrl } = session.nextAction;
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
if (/iphone|ipad|ipod/i.test(userAgent)) {
// iOS 浏览器端
if (appLinkUrl) {
window.open(appLinkUrl, '_blank');
return;
} else if (schemeUrl) {
window.open(schemeUrl, '_blank');
return;
}
} else if (/android/i.test(userAgent)) {
// Android 浏览器端
if (appLinkUrl) {
window.open(schemeUrl, '_blank');
return;
} else if (schemeUrl) {
window.open(appLinkUrl, '_blank');
return;
}
}
// PC 端/Web 端/WAP 端
window.open(normalUrl, '_blank');
}
})
}- (可选)您可调用 方法传入 shippingInfo 参数以提交收货地址信息:
let loading = false;
const shippingInfo = {
shippingAddress: {
region: 'CN',
state: 'SM',
city: 'Shanghai',
address1: '88 Century Avenue',
address2: 'Floor 20, Tower A, Lujiazui',
zipCode: '200120'
},
shippingPhoneNo: '+86 18200000000',
shippingName: {
firstName: 'Cui',
lastName: 'Tom',
middleName: '**',
fullName: 'Tom ** Cui'
}
}
function checkout() {
loading = true;
// 当买家点击支付按钮时:
elementPayment.submitPayment({shippingInfo: shippingInfo, handleActions: true }).then(({ status, userCanceled3D, session, error }) => {
// 自行关闭外部容器的 loading 状态
loading = false;
if (error) { // 先处理错误信息
const { code, message, traceId, context } = error;
if (userCanceled3D) {
// 买家主动关闭 3D 弹窗,建议从服务端轮询结果
}
if (status === 'PROCESSING') {
// 因网络异常或渠道不稳定导致状态未知. 建议从服务端轮询结果
} else {
// FAIL 失败
// 表单校验不通过,Payment Element 已提示买家,建议忽略
if (code === 'FORM_INVALID') {
return;
}
toast(message);
// 或根据 code 精细化定制体验
if (code) {
// xxx
}
}
return;
}
if (status === 'SUCCESS') {
// 成功 SUCCESS。部分场景 Payment Element 会有 toast 提示,建议直接跳转结果页
} else if (status === 'CANCELLED') {
// 订单已取消, 如无该场景可忽略
} else {
// 可添加监控
}
if (session && session.nextAction) {
const { normalUrl, appLinkUrl, schemeUrl } = session.nextAction;
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
if (/iphone|ipad|ipod/i.test(userAgent)) {
// iOS 浏览器端
if (appLinkUrl) {
window.open(appLinkUrl, '_blank');
return;
} else if (schemeUrl) {
window.open(schemeUrl, '_blank');
return;
}
} else if (/android/i.test(userAgent)) {
// Android 浏览器端
if (appLinkUrl) {
window.open(schemeUrl, '_blank');
return;
} else if (schemeUrl) {
window.open(appLinkUrl, '_blank');
return;
}
}
// PC 端/Web 端/WAP 端
window.open(normalUrl, '_blank');
}
})
}校验当前所选支付方式的支付要素
调用 方法可验证当前所选支付方式下的表单要素是否填写完整且格式有效,方便您在提交支付前执行自定义校验流程或业务逻辑。该方法会根据已选择的支付方式自动识别并校验所需参数,您无需手动维护参数列表。即使未主动调用 ,在执行 时,若表单存在异常,组件也会自动展示相应的错误提示:
let loading = false;
function checkout() {
loading = true;
// 校验当前所选支付方式支付要素
elementPayment.validateFields().then(({isValid}) => {
console.log(isValid);
// 表单校验不通过
if (!isValid) {
console.log('表单校验不通过');
return;
}
});
// 校验通过后可发起 submitPayment()
elementPayment.submitPayment().then(({ status, userCanceled3D, session, error }) => {
...
})
}存卡支付场景配置 CVV 验证
为提升支付便捷性及交易成功率, 方法中的 merchantAppointParam.storedCard.needCVV 参数默认值为
false
,即存卡支付场景默认不进行 CVV 验证。如您的业务场景对支付安全有特殊要求,可将该参数设为 true
以启用 CVV 验证。注意:若非必要,建议您保持默认值
false
,避免要求买家再次输入 CVV 码,以优化支付体验并提高交易成功率。以下是指定存卡支付场景需要 CVV 验证的示例代码:
// 嵌入 document.querySelector("#payment-element") 这个节点中
elementPayment.mount({
...
merchantAppointParam: {
storedCard: {
needCVV: false
}
}
},
'#payment-element',
).then(({
error
}) => {
...
})监听组件事件
- 事件:当买家切换支付方式时触发,回调函数接收一个参数 payload,其中包含支付方式变更相关数据。
elementPayment.on('paymentMethodChanged', (({type, name}) => {
console.log(type + name);
}));- 事件:当买家编辑账单地址表单数据时触发,回调函数接收一个参数 payload,其中包含最新的账单地址表单数据。
elementPayment.on('billingAddressChanged', (({sameAsShipping, billingAddress}) => {
console.log(sameAsShipping + JSON.stringify(billingAddress));
}));卸载 Payment Element
elementPayment.destroy();常见问题
问:是否可以在 PC 应用或移动应用中使用 Webview 集成 Web Element?
答:目前不支持。
步骤 3:获取支付结果 服务端
在买家完成支付或支付超时后, Antom 会通过服务器交互将相应的支付结果发送给您,您可以通过以下方法之一获取支付结果:
- 接收来自 Antom 的异步通知
- 主动查询支付结果
接收异步通知
主动查询结果
1. 设置接收通知的 webhook URL
完成支付或支付失败时,Antom 会向您设置的 webhook URL 发送异步通知,您可以选择以下两种方法中的一种来设置接收通知的 webhook URL(若两者都设置,则以接口请求中指定的 URL 优先):
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createPaymentSession(单笔支付)接口请求的 paymentNotifyUrl 参数传入该笔订单的异步通知接收 URL。
- 若您的所有订单有统一的通知 URL,您可以在 Antom Dashboard > 开发者 > 通知地址 中设置 webhook URL。具体操作请参阅通知地址。
以下是异步通知请求体的代码示例:
卡支付、Apple Pay、Google Pay
APM 支付
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // 存储 cardToken 用于后续存卡支付使用
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"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);
}
}无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:什么时候会发送通知?
答:这取决于支付是否完成:
- 如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。对于现金支付,通知可能会稍有延迟。
- 如果支付未完成,Antom 需要先关闭订单,然后发送异步通知。不同支付方式关闭订单所需的时间会有所不同,通常默认为 14 分钟。
问:Antom 会重新发送异步通知吗?
答:会。对于以下情况,异步通知将在 24 小时内自动重新发送:
- 由于网络原因未收到异步通知。
- 如果收到来自 Antom 的异步通知,但您没有按照返回收到确认信息的格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和15 小时。
问:在响应异步通知时,需要添加签名吗?
问:我在通知中需要使用哪些关键参数?
答:请注意以下关键参数:
- result:对于 APM 支付,其表示支付最终结果。对于 Apple Pay、Google Pay 和卡支付,则仅代表授权结果,需要进一步发起请款。
- paymentRequestId:用于咨询、取消和对账的支付请求 ID。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
- paymentAmount:表示支付金额。
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// 替换为您的 paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了请求报文的示例:
{
"paymentRequestId": "paymentRequestId01"
}以下代码展示了响应报文的示例:
APM 支付
卡支付、Apple Pay、Google Pay
{
"actualPaymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "TRUEMONEY",
"paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentMethodType": "TRUEMONEY",
"paymentTime": "2025-02-17T08:06:43-08:00",
"pspCustomerInfo": {
"pspName": "TRUEMONEY"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}{
"actualPaymentAmount": {
"currency": "USD",
"value": "5000"
},
"authExpiryTime": "2024-12-17T21:56:56-08:00",
"cardInfo": {
"cardBrand": "VISA",
"funding": "CREDIT",
"issuingCountry": "US"
},
"paymentAmount": {
"currency": "USD",
"value": "5000"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "CARD",
"paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultInfo": {
"avsResultRaw": "M",
"cardBrand": "VISA",
"cardNo": "************9954",
"cvvResultRaw": "U",
"funding": "CREDIT",
"issuingCountry": "US",
"networkTransactionId": "123qwe456rew",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-12-10T21:56:57-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}答:请注意以下关键参数:
- result:仅表示本次 inquiryPayment 接口的调用结果。对于 APM 支付,订单的支付结果需要根据 paymentStatus 进行判断(SUCCESS成功/FAIL失败/PROCESSING处理中)。对于卡支付、Apple Pay 和 Google Pay,paymentStatus 仅代表授权结果,是否发货需要依赖请款结果决策。
- paymentAmount:用于核对支付金额。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
步骤 4:请款 服务端仅卡支付、Apple Pay、Google Pay
用户体验
以下图片展示了不同场景下使用 Payment Element 的用户体验:
Payment Element 渲染支付方式
商户自行渲染支付方式
以下图片展示了以弹窗形式调用 Payment Element 渲染的支付方式的模板:

如您选择由 Payment Element 渲染支付方式列表,Payment Element 默认在收银台页面上渲染所有支持的支付方式。以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
存卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

由 Payment Element 处理存卡支付场景:

以下图片展示了商户自行渲染支付方式的模板:

如您通过自行指定支付方式渲染支付方式列表,以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

订单生命周期
以下是不同支付方式的生命周期。
APM 支付
卡支付、Apple Pay、Google Pay

支付流程
以下图片展示了如何通过 Payment Element 集成单笔支付:
Payment Element 渲染支付方式
商户自行渲染支付方式


- 买家进入结账页面并发起支付。
- 创建支付会话请求。
您可以调用 createPaymentSession(单笔支付)接口获取支付会话。 - 调用 Payment Element。
在客户端,通过支付会话调用 Payment Element。您可以选择由 Payment Element 或者您自行渲染支付方式,同时 Payment Element 会根据支付方式的特性处理信息、收集支付要素、进行重定向、应用调用、二维码显示、验证等流程。当支付完成后,根据您的设置以及支付方式特性,您需要按照 方法返回的结果处理跳转流程或者由系统自动回跳到您的支付结果页面。 - 获取支付结果。
通过以下两种方法之一获取支付结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付状态。
注意:在卡支付、Apple Pay 和 Google Pay 支付场景下,采用的是授权请款模式。步骤 1 至 4 仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- 发起请款并获取请款结果。
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 notifyPayment 接口来查询请款状态。
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 iOS 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新或不低于 1.46.0 版本的 SDK。
集成步骤
请按照以下步骤开始集成:
- (可选)预加载 SDK
- 创建支付会话
- 调用 Payment Element
- 获取支付结果
- 发起请款
(可选)步骤 1:预加载 SDK 客户端
[AMSPaymentElement.shared preload];步骤 2:创建支付会话 服务端
传入订单信息以调用 createPaymentSession(单笔支付)接口来创建支付会话,获取唤起 Payment Element 的 paymentSessionData。您可选择自行渲染支付方式列表或由 Payment Element 渲染支付方式列表。
Payment Element 渲染支付方式
商户自行渲染支付方式
当您使用 Payment Element 渲染的支付方式列表时,您只需传入以下参数。Payment Element 默认在收银台页面上渲染所有支持的支付方式,您也可以通过指定支付方式来选择您需要的支付方式。
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的环境信息
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}如果由 Payment Element 渲染收银台的支付方式列表,则会展示所有支付方式。以下代码展示了一个请求报文的示例:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // 买家 IP 地址
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}当您自行渲染支付方式列表时,您必须传入下表中列出的指定支付方式参数。如果 Payment Element 需要采集支付要素,则需要传入下表中列出的卡支付信息参数。
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的环境信息
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// 替换为您的指定支付方式
AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
.paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
.paymentMethodType("ALIPAY_CN")
.build()))
.build();
alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}当您自行渲染支付方式列表时,需要通过指定单个支付方式集成。以下代码展示了一个请求报文的示例:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // 买家 IP 地址
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // 指定支付方式
}
]
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********u.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}以下代码展示了一个响应的示例,其中包含以下参数:
- result.resultStatus:createPaymentSession(单笔支付)接口的调用结果。
- paymentSessionData:将返回给前端的支付会话数据。
- paymentSessionExpiryTime:支付会话的过期时间。
{
"paymentSessionData": "gpZy************fQ==",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}以下是创建支付会话响应中 result.resultStatus 可能返回的值,请您根据指引进行处理:
注意:如果您未收到响应报文,可能是网络超时所致。建议更换 paymentRequestId 重新调用接口。如果问题未解决,请联系 Antom 技术支持。
常见问题
问:请求参数的值可以使用中文字符吗?
答:为了避免特定支付方式的兼容性问题,请求中的参数请勿使用中文字符。
问:如何设置接收支付通知的地址?
答:在 createPaymentSession(单笔支付)接口的请求中指定 paymentNotifyUrl 参数,以接收支付结果的异步通知(notifyPayment),或者在 Antom Dashboard 中配置接收地址。如果请求和 Antom Dashboard 中都指定了地址,请求中的值优先。
问:返回的 paymentSessionData 是否需要处理后再传给客户端?
答:请勿对 paymentSessionData 进行任何处理,否则可能会导致调用 Payment Element 失败。
步骤 3:调用 Payment Element 客户端
在您的客户端使用 paymentSessionData 调用 Payment Element,在买家提交支付后,Payment Element 会根据不同支付方式,负责展示二维码、跳转支付方式页面、3DS 认证、回跳商户结果页等流程。
- 在服务端获取到 paymentSessionData 后,使用 类创建 Payment Element 实例。
- 创建对象,并完成 SDK 配置。
- 实现,用于处理后续流程中的相应事件。
#import <AMSComponent/AMSComponent-Swift.h>
// 创建一个 AMSPaymentElementConfiguration 对象
AMSPaymentElementConfiguration *componentConfig = [AMSPaymentElementConfiguration new];
componentConfig.locale = @"en_US";
NSString *appearance = @"{\n \"theme\": \"night\",\n \"layout\": {\n \"type\": \"Tabs\"\n },\n \"variables\": {\n \"content-quaternary\": \"#FFFF00\"\n }\n}";
// 设置沙箱环境。如果将其置空,则默认使用线上正式环境
NSDictionary *options = @{@"showLoading": @"true",
@"sandbox": @"true",
@"appearance": appearance
};
componentConfig.options = options;
// initConfiguration 用法
[[AMSPaymentElement shared] initConfiguration:componentConfig completion:^(AMSStatusResult * _Nonnull result) {
// 处理 initConfiguration 用法阶段错误事件
if (result.error) {
// 处理失败
if ([result.error.code isEqualToString:@"UI_STATE_ERROR"]) {
NSLog(@"integration code error, please check the integration code");
} else {
NSLog(@"unknown error, please contact support");
}
} else {
// 处理成功
}
}];
// 设置回调来监听收银台页面的支付事件
[AMSPaymentElement shared].paymentDelegate = self;
// 服务端调用 创建支付会话 接口以获取 paymentSessionData
#pragma AMSPaymentProtocol
// 回调事件码方式 处理 submitPay 阶段事件码
- (void)onSubmitPayCallback:(AMSStatusResult *)eventResult {
AMSStatusResultType statusType = eventResult.status;
AMSResultError *error = eventResult.error;
switch (statusType) {
case AMSStatusResultTypePROCESSING:
if (error && error.code) {
if ([@"PAYMENT_IN_PROCESS" isEqualToString:error.code]) {
NSLog(@"payment is in processing, please try polling the payment result from the server");
} else if ([@"USER_CANCELED" isEqualToString:error.code]) {
NSLog(@"user cancelled the payment process, please try invoke createComponent again");
} else if ([@"UNKNOWN_EXCEPTION" isEqualToString:error.code]) {
NSLog(@"unknown exception, please contact support");
} else if ([@"PAYMENT_RESULT_TIMEOUT" isEqualToString:error.code]) {
NSLog(@"get payment result timeout, please try polling the payment result from the server");
}
}
break;
case AMSStatusResultTypeCANCELLED:
// 继续执行下一 case
case AMSStatusResultTypeSUCCESS:
NSLog(@"payment cancelled or success, do nothing");
break;
case AMSStatusResultTypeFAIL:
if (error && error.code) {
if ([@"ORDER_IS_CANCELLED" isEqualToString:error.code]) {
NSLog(@"the merchant has proactively canceled the order, please check on your own.");
} else if ([@"ORDER_IS_CLOSED" isEqualToString:error.code]) {
NSLog(@"the order has timed out and is closed, please re-initiate payment using a new paymentRequestId.");
} else {
NSLog(@"unknown error, please contact support");
}
}
break;
default:
break;
}
}- 使用实例对象中的 方法来调用 Payment Element。
// 回调事件码方式 createComponent 用法
[[AMSPaymentElement shared] createComponent:paymentSessionData completion:^(AMSStatusResult * _Nonnull result) {
if (result.error) {
// 处理失败
if ([result.error.code isEqualToString:@"UI_STATE_ERROR"]) {
NSLog(@"integration code error, please check the integration code");
} else if ([result.error.code isEqualToString:@"PARAM_INVALID"]) {
NSLog(@"session data invalid, please check the session data");
} else if ([result.error.code isEqualToString:@"INITIALIZE_WEB_TIMEOUT"]) {
NSLog(@"web app timeout, please invoke component again");
} else {
NSLog(@"unknown error, please contact support");
}
} else {
// 处理成功
}
}];
卸载 Payment Element
// 释放 SDK 组件资源
[[AMSPaymentElement shared] onDestroy];步骤 4:获取支付结果 服务端
在买家完成支付或支付超时后, Antom 会通过服务器交互将相应的支付结果发送给您,您可以通过以下方法之一获取支付结果:
- 接收来自 Antom 的异步通知
- 主动查询支付结果
接收异步通知
主动查询结果
1. 设置接收通知的 webhook URL
完成支付或支付失败时,Antom 会向您设置的 webhook URL 发送异步通知,您可以选择以下两种方法中的一种来设置接收通知的 webhook URL(若两者都设置,则以接口请求中指定的 URL 优先):
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createPaymentSession(单笔支付)接口请求的 paymentNotifyUrl 参数传入该笔订单的异步通知接收 URL。
- 若您的所有订单有统一的通知 URL,您可以在 Antom Dashboard > 开发者 > 通知地址 中设置 webhook URL。具体操作请参阅通知地址。
以下是异步通知请求体的代码示例:
卡支付、Apple Pay、Google Pay
APM 支付
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // 存储 cardToken 用于后续存卡支付使用
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"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);
}
}无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:什么时候会发送通知?
答:这取决于支付是否完成:
- 如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。对于现金支付,通知可能会稍有延迟。
- 如果支付未完成,Antom 需要先关闭订单,然后发送异步通知。不同支付方式关闭订单所需的时间会有所不同,通常默认为 14 分钟。
问:Antom 会重新发送异步通知吗?
答:会。对于以下情况,异步通知将在 24 小时内自动重新发送:
- 由于网络原因未收到异步通知。
- 如果收到来自 Antom 的异步通知,但您没有按照返回收到确认信息的格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和15 小时。
问:在响应异步通知时,需要添加签名吗?
问:我在通知中需要使用哪些关键参数?
答:请注意以下关键参数:
- result:对于 APM 支付,其表示支付最终结果。对于 Apple Pay、Google Pay 和卡支付,则仅代表授权结果,需要进一步发起请款。
- paymentRequestId:用于咨询、取消和对账的支付请求 ID。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
- paymentAmount:表示支付金额。
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// 替换为您的 paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了请求报文的示例:
{
"paymentRequestId": "paymentRequestId01"
}以下代码展示了响应报文的示例:
APM 支付
卡支付、Apple Pay、Google Pay
{
"actualPaymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "TRUEMONEY",
"paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentMethodType": "TRUEMONEY",
"paymentTime": "2025-02-17T08:06:43-08:00",
"pspCustomerInfo": {
"pspName": "TRUEMONEY"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}{
"actualPaymentAmount": {
"currency": "USD",
"value": "5000"
},
"authExpiryTime": "2024-12-17T21:56:56-08:00",
"cardInfo": {
"cardBrand": "VISA",
"funding": "CREDIT",
"issuingCountry": "US"
},
"paymentAmount": {
"currency": "USD",
"value": "5000"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "CARD",
"paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultInfo": {
"avsResultRaw": "M",
"cardBrand": "VISA",
"cardNo": "************9954",
"cvvResultRaw": "U",
"funding": "CREDIT",
"issuingCountry": "US",
"networkTransactionId": "123qwe456rew",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-12-10T21:56:57-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}答:请注意以下关键参数:
- result:仅表示本次 inquiryPayment 接口的调用结果。对于 APM 支付,订单的支付结果需要根据 paymentStatus 进行判断(SUCCESS成功/FAIL失败/PROCESSING处理中)。对于卡支付、Apple Pay 和 Google Pay,paymentStatus 仅代表授权结果,是否发货需要依赖请款结果决策。
- paymentAmount:用于核对支付金额。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
步骤 5:请款 服务端仅卡支付、Apple Pay
用户体验
以下图片展示了不同场景下使用 Payment Element 的用户体验:
Payment Element 渲染支付方式
商户自行渲染支付方式
以下图片展示了以弹窗形式调用 Payment Element 渲染的支付方式的模板:

如您选择由 Payment Element 渲染支付方式列表,Payment Element 默认在收银台页面上渲染所有支持的支付方式。以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
存卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

由 Payment Element 处理存卡支付场景:

以下图片展示了商户自行渲染支付方式的模板:

如您通过自行指定支付方式渲染支付方式列表,以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

订单生命周期
以下是不同支付方式的生命周期。
APM 支付
卡支付、Apple Pay、Google Pay

支付流程
以下图片展示了如何通过 Payment Element 集成单笔支付:
Payment Element 渲染支付方式
商户自行渲染支付方式


- 买家进入结账页面并发起支付。
- 创建支付会话请求。
您可以调用 createPaymentSession(单笔支付)接口获取支付会话。 - 调用 Payment Element。
在客户端,通过支付会话调用 Payment Element。您可以选择由 Payment Element 或者您自行渲染支付方式,同时 Payment Element 会根据支付方式的特性处理信息、收集支付要素、进行重定向、应用调用、二维码显示、验证等流程。当支付完成后,根据您的设置以及支付方式特性,您需要按照 方法返回的结果处理跳转流程或者由系统自动回跳到您的支付结果页面。 - 获取支付结果。
通过以下两种方法之一获取支付结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付状态。
注意:在卡支付、Apple Pay 和 Google Pay 支付场景下,采用的是授权请款模式。步骤 1 至 4 仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- 发起请款并获取请款结果。
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 Android 端集成 SDK 资源包文档来集成客户端 SDK 资源包,并注意使用最新或不低于 1.46.0 版本的 SDK。
集成步骤
请按照以下步骤开始集成:
- (可选)预加载 SDK
- 创建支付会话
- 调用 Payment Element
- 获取支付结果
- 发起请款
(可选)步骤 1:预加载 SDK 客户端
AMSPaymentElement.preload(getApplicationContext());步骤 2:创建支付会话 服务端
传入订单信息以调用 createPaymentSession(单笔支付)接口来创建支付会话,获取唤起 Payment Element 的 paymentSessionData。您可选择自行渲染支付方式列表或由 Payment Element 渲染支付方式列表。
Payment Element 渲染支付方式
商户自行渲染支付方式
当您使用 Payment Element 渲染的支付方式列表时,您只需传入以下参数。Payment Element 默认在收银台页面上渲染所有支持的支付方式,您也可以通过指定支付方式来选择您需要的支付方式。
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的环境信息
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.ANDROID).build();
alipayPaymentSessionRequest.setEnv(env);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}如果由 Payment Element 渲染收银台的支付方式列表,则会展示所有支付方式。以下代码展示了一个请求报文的示例:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // 买家 IP 地址
"osType": "ANDROID"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}当您自行渲染支付方式列表时,您必须传入下表中列出的指定支付方式参数。如果 Payment Element 需要采集支付要素,则需要传入下表中列出的卡支付信息参数。
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的环境信息
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.ANDROID).build();
alipayPaymentSessionRequest.setEnv(env);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// 替换为您的指定支付方式
AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
.paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
.paymentMethodType("ALIPAY_CN")
.build()))
.build();
alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}当您自行渲染支付方式列表时,需要通过指定单个支付方式集成。以下代码展示了一个请求报文的示例:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // 买家 IP 地址
"osType": "ANDROID"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // 指定支付方式
}
]
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********u.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}以下代码展示了一个响应的示例,其中包含以下参数:
- result.resultStatus:createPaymentSession(单笔支付)接口的调用结果。
- paymentSessionData:将返回给前端的支付会话数据。
- paymentSessionExpiryTime:支付会话的过期时间。
{
"paymentSessionData": "gpZy************fQ==",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}以下是创建支付会话响应中 result.resultStatus 可能返回的值,请您根据指引进行处理:
注意:如果您未收到响应报文,可能是网络超时所致。建议更换 paymentRequestId 重新调用接口。如果问题未解决,请联系 Antom 技术支持。
常见问题
问:请求参数的值可以使用中文字符吗?
答:为了避免特定支付方式的兼容性问题,请求中的参数请勿使用中文字符。
问:如何设置接收支付通知的地址?
答:在 createPaymentSession(单笔支付)接口的请求中指定 paymentNotifyUrl 参数,以接收支付结果的异步通知(notifyPayment),或者在 Antom Dashboard 中配置接收地址。如果请求和 Antom Dashboard 中都指定了地址,请求中的值优先。
问:返回的 paymentSessionData 是否需要处理后再传给客户端?
答:请勿对 paymentSessionData 进行任何处理,否则可能会导致调用 Payment Element 失败。
步骤 3:调用 Payment Element 客户端
在您的客户端使用 paymentSessionData 调用 Payment Element,在买家提交支付后,Payment Element 会根据不同支付方式,负责展示二维码、跳转支付方式页面、3DS 认证、回跳商户结果页等流程。
- 在服务端获取到 paymentSessionData 后,使用 类来创建 SDK 实例。
- 创建 对象,并完成 SDK 配置。
- 注册 监听器,用于处理调用支付组件及拉起支付页面流程中的相关事件。
- 注册 ,用于处理发起支付过程中的相关事件。
AMSPaymentElementConfiguration configuration = new AMSPaymentElementConfiguration();
configuration.setLocale(new Locale("en", "US"));
configuration.setOption("showLoading", "true");
configuration.setOption("sandbox", "true");
configuration.setOption("notRedirectAfterComplete", "false");
String appearance = "{\"theme\":\"night\",\"layout\":{\"type\":\"accordion\"},\"variables\":{\"content-primary\":\"#ff5b4d\"}}";
configuration.setOption("appearance", appearance);
configuration.setOnCreateComponentListener(new OnCreateComponentListener() {
@Override
public void onCreateComponentCallback(AMSStatusResult statusResult) {
if (statusResult.getError() != null) {
switch (statusResult.getError().getCode()) {
case "UI_STATE_ERROR":
System.out.println("integration code error, please check the integration code");
break;
case "PARAM_INVALID":
System.out.println("session data invalid, please check the session data");
break;
case "INITIALIZE_WEB_TIMEOUT":
System.out.println("web app timeout, please invoke component again");
break;
default:
System.out.println("unknown error, please contact support");
break;
}
}
}
});
configuration.setOnSubmitPayListener(new OnSubmitPayListener() {
@Override
public void onSubmitPayCallback(AMSStatusResult statusResult) {
AMSStatus status = statusResult.getStatus();
AMSResultError error = statusResult.getError();
if (status == AMSStatus.PROCESSING) {
if (error != null && error.getCode() != null) {
if ("PAYMENT_IN_PROCESS".equals(error.getCode())) {
System.out.println("payment is in processing, please try polling the payment result from the server");
} else if ("USER_CANCELED".equals(error.getCode())){
System.out.println("user cancelled the payment process, please try invoke createComponent again");
} else if ("UNKNOWN_EXCEPTION".equals(error.getCode())) {
System.out.println("unknown exception, please contact support");
} else if ("PAYMENT_RESULT_TIMEOUT".equals(error.getCode())){
System.out.println("get payment result timeout, please try polling the payment result from the server");
}
}
} else if (status == AMSStatus.CANCELLED || status == AMSStatus.SUCCESS) {
System.out.println("payment cancelled or success, do nothing");
} else if (status == AMSStatus.FAIL) {
if (error != null && error.getCode() != null) {
if ("ORDER_IS_CANCELLED".equals(error.getCode())) {
System.out.println("the merchant has proactively canceled the order, please check on your own.");
} else if ("ORDER_IS_CLOSED".equals(error.getCode()) || "INQUIRY_PAYMENT_SESSION_FAILED".equals(error.getCode())){
System.out.println("the order has timed out and is closed, please re-initiate payment using a new paymentRequestId.");
} else {
System.out.println("unknown error, please contact support");
}
}
}
}
});
AMSPaymentElement amsPaymentElement = new AMSPaymentElement.Builder(this, (AMSPaymentElementConfiguration) configuration).build();
- 使用实例对象中的 方法来调用 Payment Element:
// 创建支付会话时获取的 paymentSessionData
String paymentSessionData = "exxxxe";
amsPaymentElement.createComponent(this, paymentSessionData);卸载 Payment Element
// 释放 SDK 组件资源
amsPaymentElement.onDestroy();步骤 4:获取支付结果 服务端
在买家完成支付或支付超时后, Antom 会通过服务器交互将相应的支付结果发送给您,您可以通过以下方法之一获取支付结果:
- 接收来自 Antom 的异步通知
- 主动查询支付结果
接收异步通知
主动查询结果
1. 设置接收通知的 webhook URL
完成支付或支付失败时,Antom 会向您设置的 webhook URL 发送异步通知,您可以选择以下两种方法中的一种来设置接收通知的 webhook URL(若两者都设置,则以接口请求中指定的 URL 优先):
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createPaymentSession(单笔支付)接口请求的 paymentNotifyUrl 参数传入该笔订单的异步通知接收 URL。
- 若您的所有订单有统一的通知 URL,您可以在 Antom Dashboard > 开发者 > 通知地址 中设置 webhook URL。具体操作请参阅通知地址。
以下是异步通知请求体的代码示例:
卡支付、Apple Pay、Google Pay
APM 支付
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // 存储 cardToken 用于后续存卡支付使用
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"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);
}
}无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:什么时候会发送通知?
答:这取决于支付是否完成:
- 如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。对于现金支付,通知可能会稍有延迟。
- 如果支付未完成,Antom 需要先关闭订单,然后发送异步通知。不同支付方式关闭订单所需的时间会有所不同,通常默认为 14 分钟。
问:Antom 会重新发送异步通知吗?
答:会。对于以下情况,异步通知将在 24 小时内自动重新发送:
- 由于网络原因未收到异步通知。
- 如果收到来自 Antom 的异步通知,但您没有按照返回收到确认信息的格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和15 小时。
问:在响应异步通知时,需要添加签名吗?
问:我在通知中需要使用哪些关键参数?
答:请注意以下关键参数:
- result:对于 APM 支付,其表示支付最终结果。对于 Apple Pay、Google Pay 和卡支付,则仅代表授权结果,需要进一步发起请款。
- paymentRequestId:用于咨询、取消和对账的支付请求 ID。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
- paymentAmount:表示支付金额。
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// 替换为您的 paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了请求报文的示例:
{
"paymentRequestId": "paymentRequestId01"
}以下代码展示了响应报文的示例:
APM 支付
卡支付、Apple Pay、Google Pay
{
"actualPaymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "TRUEMONEY",
"paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentMethodType": "TRUEMONEY",
"paymentTime": "2025-02-17T08:06:43-08:00",
"pspCustomerInfo": {
"pspName": "TRUEMONEY"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}{
"actualPaymentAmount": {
"currency": "USD",
"value": "5000"
},
"authExpiryTime": "2024-12-17T21:56:56-08:00",
"cardInfo": {
"cardBrand": "VISA",
"funding": "CREDIT",
"issuingCountry": "US"
},
"paymentAmount": {
"currency": "USD",
"value": "5000"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "CARD",
"paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultInfo": {
"avsResultRaw": "M",
"cardBrand": "VISA",
"cardNo": "************9954",
"cvvResultRaw": "U",
"funding": "CREDIT",
"issuingCountry": "US",
"networkTransactionId": "123qwe456rew",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-12-10T21:56:57-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}答:请注意以下关键参数:
- result:仅表示本次 inquiryPayment 接口的调用结果。对于 APM 支付,订单的支付结果需要根据 paymentStatus 进行判断(SUCCESS成功/FAIL失败/PROCESSING处理中)。对于卡支付、Apple Pay 和 Google Pay,paymentStatus 仅代表授权结果,是否发货需要依赖请款结果决策。
- paymentAmount:用于核对支付金额。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
步骤 5:请款 服务端仅卡支付、Google Pay
用户体验
以下图片展示了不同场景下使用 Payment Element 的用户体验:
iOS
Android
Payment Element 渲染支付方式
商户自行渲染支付方式
以下图片展示了以弹窗形式调用 Payment Element 渲染的支付方式的模板:

如您选择由 Payment Element 渲染支付方式列表,Payment Element 默认在收银台页面上渲染所有支持的支付方式。以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
存卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

由 Payment Element 处理存卡支付场景:

以下图片展示了商户自行渲染支付方式的模板:

如您通过自行指定支付方式渲染支付方式列表,以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

Payment Element 渲染支付方式
商户自行渲染支付方式
以下图片展示了以弹窗形式调用 Payment Element 渲染的支付方式的模板:

如您选择由 Payment Element 渲染支付方式列表,Payment Element 默认在收银台页面上渲染所有支持的支付方式。以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
存卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

由 Payment Element 处理存卡支付场景:

以下图片展示了商户自行渲染支付方式的模板:

如您通过自行指定支付方式渲染支付方式列表,以下图片展示了不同支付方式的用户体验:
扫码支付
跳转支付方式页面支付
新卡支付
由 Payment Element 展示二维码以完成支付:

由 Payment Element 负责跳转到支付方式的页面以完成支付:

由 Payment Element 展示卡要素收集页以完成支付:

订单生命周期
以下是不同支付方式的生命周期。
APM 支付
卡支付、Apple Pay、Google Pay

支付流程
以下图片展示了如何通过 Payment Element 集成单笔支付:
Payment Element 渲染支付方式
商户自行渲染支付方式


- 买家进入结账页面并发起支付。
- 创建支付会话请求。
您可以调用 createPaymentSession(单笔支付)接口获取支付会话。 - 调用 Payment Element。
在客户端,通过支付会话调用 Payment Element。您可以选择由 Payment Element 或者您自行渲染支付方式,同时 Payment Element 会根据支付方式的特性处理信息、收集支付要素、进行重定向、应用调用、二维码显示、验证等流程。当支付完成后,根据您的设置以及支付方式特性,您需要按照 方法返回的结果处理跳转流程或者由系统自动回跳到您的支付结果页面。 - 获取支付结果。
通过以下两种方法之一获取支付结果:
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当支付成功或过期时,Antom 会使用 notifyPayment 接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询支付状态。
注意:在卡支付、Apple Pay 和 Google Pay 支付场景下,采用的是授权请款模式。步骤 1 至 4 仅完成了授权部分,即买家使用银行卡完成支付,其资金处于冻结状态。为了将买家的冻结资金转至您的账户,您还需要集成请款步骤。请款成功的结果将作为您发货的依据。
- 发起请款并获取请款结果。
- 异步通知:在 createPaymentSession(单笔支付)接口中设置 paymentNotifyUrl 参数或在 Antom Dashboard 里指定接收通知的地址。当请款完成时,Antom 会使用 notifyCapture(单笔支付)接口向您发送异步通知。
- 同步查询:调用 inquiryPayment 接口来查询请款状态。
集成准备
- 已获得 client ID。
- 已完成密钥配置。
- 已完成异步通知接收地址的配置。
- 集成 Antom 服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK。
- 参阅 Flutter SDK 文档来集成客户端 SDK 资源包。
集成步骤
请按照以下步骤开始集成:
- (可选)预加载 SDK
- 创建支付会话
- 调用 Payment Element
- 获取支付结果
- 发起请款
(可选)步骤 1:预加载 SDK 客户端
// 预加载 Payment Element SDK
AMSPaymentElement.preload();步骤 2:创建支付会话 服务端
传入订单信息以调用 createPaymentSession(单笔支付)接口来创建支付会话,获取唤起 Payment Element 的 paymentSessionData。您可选择自行渲染支付方式列表或由 Payment Element 渲染支付方式列表。
Payment Element 渲染支付方式
商户自行渲染支付方式
当您使用 Payment Element 渲染的支付方式列表时,您只需传入以下参数。Payment Element 默认在收银台页面上渲染所有支持的支付方式,您也可以通过指定支付方式来选择您需要的支付方式。
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的环境信息
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}如果由 Payment Element 渲染收银台的支付方式列表,则会展示所有支付方式。以下代码展示了一个请求报文的示例:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // 买家 IP 地址
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}自行渲染支付方式列表:当您自行渲染支付方式列表时,您必须传入下表中列出的指定支付方式参数。如果 Payment Element 需要采集支付要素,则需要传入下表中列出的卡支付信息参数。
@PostMapping("/payment/createSession")
public ResponseEntity<ApiResponse> createPaymentSession(@RequestBody PaymentVO payment) {
AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
alipayPaymentSessionRequest.setProductScene(ProductSceneConstants.ELEMENT_PAYMENT);
// 替换为您的环境信息
Env env = Env.builder().terminalType(TerminalType.APP).osType(OsType.IOS).build();
alipayPaymentSessionRequest.setEnv(env);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);
// 转换金额单位(实际应用中,金额应在您的服务器端计算)
// 详情请参考:<a href="https://docs.antom.com/ac/ref_zh-cn/cc">金额的使用规则</a>
long amountMinorLong = Money.of(CurrencyUnit.of(payment.currency), new BigDecimal(payment.amountValue)).getAmountMinorLong();
// 设置金额
Amount amount = Amount.builder().currency(payment.currency).value(String.valueOf(amountMinorLong)).build();
alipayPaymentSessionRequest.setPaymentAmount(amount);
// 设置支付策略
// 替换为您现有的结算货币
SettlementStrategy settlementStrategy = SettlementStrategy.builder().settlementCurrency("USD").build();
alipayPaymentSessionRequest.setSettlementStrategy(settlementStrategy);
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId).
orderDescription("antom sdk testing order").orderAmount(amount).buyer(buyer).build();
alipayPaymentSessionRequest.setOrder(order);
// 替换为您的通知地址
// 或者在 Antom Dashboard 配置: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">通知地址</a>
alipayPaymentSessionRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com/payment/receivePaymentNotify");
// 替换为您的跳转地址
alipayPaymentSessionRequest.setPaymentRedirectUrl(
"https://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);
// 替换为您的指定支付方式
AvailablePaymentMethod availablePaymentMethods = AvailablePaymentMethod.builder()
.paymentMethodTypeList(List.of(PaymentMethodTypeItem.builder()
.paymentMethodType("ALIPAY_CN")
.build()))
.build();
alipayPaymentSessionRequest.setAvailablePaymentMethod(availablePaymentMethods);
AlipayPaymentSessionResponse alipayPaymentSessionResponse;
try {
long startTime = System.currentTimeMillis();
System.out.println("payment request: " + JSON.toJSONString(alipayPaymentSessionRequest));
alipayPaymentSessionResponse = CLIENT.execute(alipayPaymentSessionRequest);
System.out.println("payment response: " + JSON.toJSONString(alipayPaymentSessionResponse));
System.out.println("payment request cost time: " + (System.currentTimeMillis() - startTime) + "ms\n");
} catch (AlipayApiException e) {
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), e));
}
return ResponseEntity.ok().body(new ApiResponse(paymentRequestId, payment.getUserId(), alipayPaymentSessionResponse));
}当您自行渲染支付方式列表时,需要通过指定单个支付方式集成。以下代码展示了一个请求报文的示例:
{
"env": {
"terminalType": "APP",
"clientIp": "***.***.***.***", // 买家 IP 地址
"osType": "IOS"
},
"order": {
"buyer": {
"referenceBuyerId": "yourBuyerId"
},
"orderAmount": {
"currency": "HKD",
"value": "300"
},
"orderDescription": "AMSDM_GIFT",
"referenceOrderId": "PAYMENT_2025*********138_AUTO"
},
"paymentAmount": {
"currency": "HKD",
"value": "300"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"availablePaymentMethod": {
"paymentMethodTypeList": [
{
"paymentMethodType": "ALIPAY_CN" // 指定支付方式
}
]
},
"paymentNotifyUrl": "https://www.*********.com",
"paymentRedirectUrl": "https://www.*********u.com",
"paymentRequestId": "PAYMENT_2025*********201_AUTO",
"productCode": "CASHIER_PAYMENT",
"productScene": "ELEMENT_PAYMENT"
}以下代码展示了一个响应的示例,其中包含以下参数:
- result.resultStatus:createPaymentSession(单笔支付)接口的调用结果。
- paymentSessionData:将返回给前端的支付会话数据。
- paymentSessionExpiryTime:支付会话的过期时间。
{
"paymentSessionData": "gpZy************fQ==",
"paymentSessionExpiryTime": "2023-04-06T03:28:49+08:00",
"paymentSessionId": "paymentSessionId****",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}以下是创建支付会话响应中 result.resultStatus 可能返回的值,请您根据指引进行处理:
注意:如果您未收到响应报文,可能是网络超时所致。建议更换 paymentRequestId 重新调用接口。如果问题未解决,请联系 Antom 技术支持。
常见问题
问:请求参数的值可以使用中文字符吗?
答:为了避免特定支付方式的兼容性问题,请求中的参数请勿使用中文字符。
问:如何设置接收支付通知的地址?
答:在 createPaymentSession(单笔支付)接口的请求中指定 paymentNotifyUrl 参数,以接收支付结果的异步通知(notifyPayment),或者在 Antom Dashboard 中配置接收地址。如果请求和 Antom Dashboard 中都指定了地址,请求中的值优先。
问:返回的 paymentSessionData 是否需要处理后再传给客户端?
答:请勿对 paymentSessionData 进行任何处理,否则可能会导致调用 Payment Element 失败。
步骤 3:调用 Payment Element 客户端
在您的客户端使用 paymentSessionData 调用 Payment Element,在买家提交支付后,Payment Element 会根据不同支付方式,负责展示二维码、跳转支付方式页面、3DS 认证、回跳商户结果页等流程。
- 在服务端获取到 paymentSessionData 后,使用 类来创建 Payment Element 实例。
final element = AMSPaymentElement();
element.init(
{
"locale": "en_US",
"showLoading": "true",
"sandbox": "true",
"notRedirectAfterComplete": "false",
"appearance":
"{"theme":"default","layout":{"type":"accordion"},"variables":{}}",
},
(result) {
if (result.getStatus() == AMSStatus.SUCCESS) {
// 初始化成功,继续调用 createComponent()
print('Initialization succeeded');
} else {
// 初始化失败,检查 result.getError()
final error = result.getError();
print('Initialization failed: ${error?.getCode()} - ${error?.getMessage()}');
}
},
);c. (可选)在 方法中实现 回调函数,用于监控支付过程中的事件,请参阅回调参数中的错误 code 和 message 进行处理。
d. 调用 方法创建并展示支付组件 UI,并实现 回调函数,用于监控支付组件创建流程中的异常事件,请参阅回调参数中的错误 code 和 message 进行处理。
AMSPaymentElement.preload();
// 创建 AMSPaymentElement 实例
AMSPaymentElement amsPaymentElement = AMSPaymentElement();
// 设置配置项,参数设置可参考下文
Map<String, dynamic> amsPaymentElementConfiguration = {
"locale": "en_US",
"showLoading": "true",
"sandbox": "true",
"notRedirectAfterComplete": "false",
"appearance":
"{"theme":"default","layout":{"type":"accordion"},"variables":{}}",
};
// 初始化并监听初始化结果
amsPaymentElement?.init(config, (result) {
if (result.getError() != null && result.getError()?.getCode() != null) {
print(
"code: ${result.getError()?.getCode()}, message: ${result.getError()?.getMessage()}",
);
}
});
// 可选,但强烈建议设置支付状态监听,按照错误码和错误信息进行相应处理,具体处理建议请参考事件码列表
amsPaymentElement?.setOnSubmitPayListener((result) {
AMSStatus? status = result.getStatus();
if (status != AMSStatus.SUCCESS) {
AMSResultError? error = result.getError();
String code = error?.getCode() ?? "";
String message = error?.getMessage() ?? "";
print("code: $code, message: $message");
}
});
// 创建支付会话时获取的 paymentSessionData
String paymentSessionData = "exxxxe";
// 使用实例对象中的 createComponent 方法来调用 Payment Element,并设置调用结果监听,如果错误码不为空,可参考事件码列表进行处理
amsPaymentElement.createComponent(sessionData, (result) {
if (result.getError() != null && result.getError()?.getCode() != null) {
print(
"code: ${result.getError()?.getCode()}, message: ${result.getError()?.getMessage()}",
);
}
});卸载 Payment Element
// 释放 SDK 组件资源
amsPaymentElement.destroy();步骤 4:获取支付结果 服务端
在买家完成支付或支付超时后, Antom 会通过服务器交互将相应的支付结果发送给您,您可以通过以下方法之一获取支付结果:
- 接收来自 Antom 的异步通知
- 主动查询支付结果
接收异步通知
主动查询结果
1. 设置接收通知的 webhook URL
完成支付或支付失败时,Antom 会向您设置的 webhook URL 发送异步通知,您可以选择以下两种方法中的一种来设置接收通知的 webhook URL(若两者都设置,则以接口请求中指定的 URL 优先):
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 createPaymentSession(单笔支付)接口请求的 paymentNotifyUrl 参数传入该笔订单的异步通知接收 URL。
- 若您的所有订单有统一的通知 URL,您可以在 Antom Dashboard > 开发者 > 通知地址 中设置 webhook URL。具体操作请参阅通知地址。
以下是异步通知请求体的代码示例:
卡支付、Apple Pay、Google Pay
APM 支付
{
"actualPaymentAmount": {
"currency": "SGD",
"value": "4200"
},
"cardInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe",
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "SGD",
"value": "4200"
},
"paymentMethodType": "CARD",
"paymentCreateTime": "2024-01-01T00:00:00+08:00",
"paymentId": "20240101123456789XXXX",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
"avsResultRaw": "A",
"cardBrand": "MASTERCARD",
"cardNo": "****************",
"cardToken":"exxxxe", // 存储 cardToken 用于后续存卡支付使用
"cvvResultRaw": "Y",
"funding": "DEBIT",
"issuingCountry": "US",
"networkTransactionId": "XXXXX",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentTime": "2024-01-01T00:01:00+08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}下表展示了支付结果的异步通知中 result.resultStatus 参数可能返回的值,请您根据指引进行处理:
{
"actualPaymentAmount": {
"currency": "HKD",
"value": "100"
},
"notifyType": "PAYMENT_RESULT",
"paymentAmount": {
"currency": "HKD",
"value": "100"
},
"paymentCreateTime": "2025-02-04T22:11:19-08:00",
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "ALIPAY_HK",
"paymentRequestId": "paymentRequestId01",
"paymentResultInfo": {
},
"paymentTime": "2025-02-04T22:14:25-08:00",
"pspCustomerInfo": {
"pspCustomerId": "216022003753XXXX",
"pspName": "ALIPAY_HK"
},
"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);
}
}无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}常见问题
问:什么时候会发送通知?
答:这取决于支付是否完成:
- 如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。对于现金支付,通知可能会稍有延迟。
- 如果支付未完成,Antom 需要先关闭订单,然后发送异步通知。不同支付方式关闭订单所需的时间会有所不同,通常默认为 14 分钟。
问:Antom 会重新发送异步通知吗?
答:会。对于以下情况,异步通知将在 24 小时内自动重新发送:
- 由于网络原因未收到异步通知。
- 如果收到来自 Antom 的异步通知,但您没有按照返回收到确认信息的格式进行响应。
通知可以重发最多 8 次,或者直到收到正确的响应以终止传递。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和15 小时。
问:在响应异步通知时,需要添加签名吗?
问:我在通知中需要使用哪些关键参数?
答:请注意以下关键参数:
- result:对于 APM 支付,其表示支付最终结果。对于 Apple Pay、Google Pay 和卡支付,则仅代表授权结果,需要进一步发起请款。
- paymentRequestId:用于咨询、取消和对账的支付请求 ID。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
- paymentAmount:表示支付金额。
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// 替换为您的 paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// 处理错误情况
}
}以下代码展示了请求报文的示例:
{
"paymentRequestId": "paymentRequestId01"
}以下代码展示了响应报文的示例:
APM 支付
卡支付、Apple Pay、Google Pay
{
"actualPaymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentAmount": {
"currency": "THB",
"value": "299"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "TRUEMONEY",
"paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentMethodType": "TRUEMONEY",
"paymentTime": "2025-02-17T08:06:43-08:00",
"pspCustomerInfo": {
"pspName": "TRUEMONEY"
},
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}{
"actualPaymentAmount": {
"currency": "USD",
"value": "5000"
},
"authExpiryTime": "2024-12-17T21:56:56-08:00",
"cardInfo": {
"cardBrand": "VISA",
"funding": "CREDIT",
"issuingCountry": "US"
},
"paymentAmount": {
"currency": "USD",
"value": "5000"
},
"paymentId": "20240101123456789XXXX",
"paymentMethodType": "CARD",
"paymentRedirectUrl": "http://gol.alipay.net:8080/amsdemo/result?paymentRequestId=amsdmpay_yanfei_wzh_20240111_191505_666",
"paymentRequestId": "paymentRequestId01",
"paymentResultCode": "SUCCESS",
"paymentResultInfo": {
"avsResultRaw": "M",
"cardBrand": "VISA",
"cardNo": "************9954",
"cvvResultRaw": "U",
"funding": "CREDIT",
"issuingCountry": "US",
"networkTransactionId": "123qwe456rew",
"paymentMethodRegion": "GLOBAL",
"threeDSResult": {
"cavv": "",
"eci": ""
}
},
"paymentResultMessage": "success.",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-12-10T21:56:57-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}答:请注意以下关键参数:
- result:仅表示本次 inquiryPayment 接口的调用结果。对于 APM 支付,订单的支付结果需要根据 paymentStatus 进行判断(SUCCESS成功/FAIL失败/PROCESSING处理中)。对于卡支付、Apple Pay 和 Google Pay,paymentStatus 仅代表授权结果,是否发货需要依赖请款结果决策。
- paymentAmount:用于核对支付金额。
- paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。
步骤 5:请款 服务端仅卡支付、Google Pay
支付后操作
完成支付后,您可对交易进行以下支付后的操作:
取消交易 服务端
退款 服务端
争议 服务端
支付方式特性
本节内容为您阐述各类支付方式在支持特性方面的差异。
默认关单时间
注意:由于 Payment Element 订单默认有效期为 1 小时,实际关单时间需在支付方式原有默认时间基础上增加 1 小时。例如,若某支付方式默认关单时间为 14 分钟,则 Payment Element 订单的实际关单时间将为 1 小时 14 分钟。
集成要点
卡支付特性
Payment Element 支持以下卡支付特性,点击了解不同特性的具体信息及使用方法:
更多内容
Antom 还为您提供以下定制化内容:
- 自定义外观样式:Antom 提供了丰富的样式自定义能力,包含主题、布局以及 CSS 样式自定义功能。
- Google Pay:通过 Google Pay 服务,买家可以使用存储在其 Google 账户中的信用卡或借记卡来进行支付。使用 Payment Element,您无需另外集成 Google Pay 的 SDK,Payment Element 会为您加载 Google Pay,并可指定 Google Pay 为极速支付形式。
- Apple Pay:通过 Apple Pay 服务,买家可以使用存储在其 Apple Pay 账户中的信用卡或借记卡来进行支付。使用 Payment Element,您无需另外集成 Apple Pay 的 SDK,Payment Element 会为您加载 Apple Pay,并可指定 Apple Pay 为极速支付形式。
指定支付方式
您可以通过在 createPaymentSession(单笔支付)接口传入参数,指定在 Payment Element 上展示的支付方式、支付方式列表的排序,以及极速支付方式的展示。此功能为您带来以下优势:
- 根据您的业务地区过滤当地的支付方式
- 按照您的偏好对支付方式进行排序
- 可以将主流的支付方式如 Alipay、Apple Pay、Google Pay 以极速支付的形式展示(仅支持 App 端)
需要嵌入的支付方式
以下支付方式需要您嵌入支付要素采集组件:
支付重试机制
Antom 为您提供支付重试机制。通过 createPaymentSession(单笔支付)接口创建的支付会话,允许买家在支付会话有效期内多次尝试支付并自由切换支付方式,无需商户服务端重新调用接口。更多信息请参阅支付重试机制。
