APM 支付

收银台支付服务为您的网站和应用程序提供全方位的支付解决方案,支持桌面浏览器、移动浏览器等多场景无缝对接。通过一次性集成即可快速接入多种在线支付方式,包括电子钱包、网银转账和银行卡支付等,有效降低技术门槛。您可以根据个人偏好选择便捷安全的支付方式,享受更优质的支付体验。

用户体验

以下为各类支付方式的用户体验:

一种基于独立账户体系的电子支付解决方案。通过电子钱包账户,买家可轻松完成线上购物或线下消费支付,实现高效、安全、便捷的支付体验。

image.png

支付流程

各类支付方式的支付流程由以下集成步骤组成:

APM.png

  1. 买家进入结账页面。
  2. 创建支付请求。
    买家选择支付方式并提交订单后,商户服务端根据支付方式、金额、币种、商品等交易信息,调用 支付(收银台)接口以发起支付请求
  3. 处理支付推进链接。
    商户客户端跳转至支付请求返回的 URL 页面,或唤起相关应用程序完成支付。支付推进链接根据支付方式的特性执行不同的操作,如收集信息、重定向买家、调用应用、显示二维码和进行验证。
  4. 获取支付结果。
    商户服务端接收 Antom 服务端返回的支付结果通知,并根据结果进行相应的业务处理。通过以下两种方法之一获取支付结果:
    • 异步通知:在 支付(收银台)接口中设置 paymentNotifyUrl 字段,以指定接收异步通知的地址。当支付成功或过期时, Antom 会使用 支付通知 向您发送异步通知。
    • 主动查询:调用 支付结果查询 接口来查询支付状态。

支付集成

开始集成,请按照以下步骤操作:

  1. 添加支付方式列表
  2. 创建支付订单
  3. 获取跳转支付推进链接
  4. 接收异步通知

步骤 1:添加支付方式列表 客户端

在买家下单页面的支付方式列表中,展示本次需要集成的支付方式标识和名称,供买家根据自身需求和偏好选择。

您可以通过以下两种方式获取标识和名称:

  • 推荐自助获取:可通过品牌资产自助获取支付方式的标识和名称。如遇部分支付方式无法在线获取,请联系 Antom 技术支持协助获取。
  • 调用 咨询 接口:根据币种、交易发起终端类型、买家所在地区以及已签约的支付方式,获取当前交易支持的支付方式和标识链接(logoUrl)。

注意

  • 支付方式列表页面需要由您自行实现。
  • 如果您选择自主获取支付方式的标识和名称,可跳过以下步骤,直接跳转至步骤 2:创建支付订单继续集成流程。

Antom 提供了多种语言的服务器端接口库。以下代码以 Java 为例,其他语言请集成 Antom SDK

1. 安装接口库

您可以在 GitHub 上找到最新版本。

copy
<dependency>
    <groupId>com.alipay.global.sdk</groupId>
    <artifactId>global-open-sdk-java</artifactId>
    <version>{latest_version}</version>
</dependency>

2. 初始化请求实例

创建一个单例资源以向 Antom 发起请求。

copy
import com.alipay.global.api.AlipayClient;
import com.alipay.global.api.DefaultAlipayClient;
import com.alipay.global.api.model.constants.EndPointConstants;

public class Sample {
    public static final String        CLIENT_ID            = "";
    public static final String        ANTOM_PUBLIC_KEY     = "";
    public static final String        MERCHANT_PRIVATE_KEY = "";

    private final static AlipayClient CLIENT               = new DefaultAlipayClient(
            EndPointConstants.SG, MERCHANT_PRIVATE_KEY, ANTOM_PUBLIC_KEY, CLIENT_ID);

}

3. 创建支付咨询请求

支付咨询请求包含以下关键参数。

参数名称

是否必需?

描述

productCode

此场景下该字段固定为 CASHIER_PAYMENT

paymentFactor.presentmentMode

此场景下该字段固定为 TILE

paymentAmount

支付金额,需按下单币种的最小单位设置。

settlementStrategy.settlementCurrency

该笔支付的结算币种,若业务签约了多个结算币种,需在接口中指定。

env.terminalType

买家发起交易的环境:

  • WEB:客户端终端类型为网站,通过 PC 浏览器打开。
  • WAP:客户端终端类型为 H5 页面,通过移动浏览器打开。
  • APP:客户端终端类型为移动应用。

有关完整参数的更多信息,请参阅 咨询 接口。

以下代码为调用 咨询 接口的示例:

copy
public static void executeConsult() {
        AlipayPayConsultRequest alipayPayConsultRequest = new AlipayPayConsultRequest();
        alipayPayConsultRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);

        // 设置 amount
        Amount amount = Amount.builder().value("4200").currency("USD").build();
        alipayPayConsultRequest.setPaymentAmount(amount);

        // 设置 env 信息
        Env env = Env.builder().terminalType(TerminalType.WEB).build();
        alipayPayConsultRequest.setEnv(env);

        AlipayPayConsultResponse alipayPayConsultResponse = null;

        try {
            alipayPayConsultResponse = CLIENT.execute(alipayPayConsultRequest);
        } catch (AlipayApiException e) {
            String errorMsg = e.getMessage();
            // 处理错误情况
        }
    }

以下代码显示了请求报文的示例:

copy
{
    "env": {
        "terminalType": "WEB"
    },
    "paymentAmount": {
        "currency": "USD",
        "value": "30000"
    },
    "settlementStrategy": {
        "settlementCurrency": "USD"
    },
    "paymentFactor": {
        "presentmentMode": "TILE"
    },
    "productCode": "CASHIER_PAYMENT"
}

响应代码中涉及以下关键参数。

参数名称描述

result.resultStatus

咨询 接口的调用状态。

paymentOptions.enabled

用于判断支付方式是否可用

paymentOptions.logo.logoName

支付方式的标识名称。

paymentOptions.logo.logoUrl

支付方式的标识链接

以下代码显示了响应报文的示例:

copy
{
    "paymentOptions": [
        {
          "enabled": true,
            "logo": {
                "logoName": "FPX",
                "logoUrl": "https://resource.alipayplus.com/storage/ipaymentmngfd5e514400714344/2024/06/13/e08cb444-be0d-45b9-8a8d-44966aad5825.png"
            },
            "paymentMethodCategory": "ONLINE_BANKING",
            "paymentMethodRegion": [
                "MY"
            ],
            "paymentMethodType": "ONLINEBANKING_FPX",
            "preferred": false
        },
      {
            "disableReason": "CURRENT_CHANNEL_NOT_EXIST",
            "enabled": false,
            "logo": {
                "logoName": "Bank of Ayudhya Online Banking",
                "logoUrl": "https://gw.alipay.com/antom/icon/medium/default/BankofAyutthaya.svg"
            },
            "paymentMethodCategory": "ONLINE_BANKING",
            "paymentMethodRegion": [
                "TH"
            ],
            "paymentMethodType": "ONLINEBANKING_BANKOFAYUDHYA",
            "preferred": false
        }
    ],
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}

下表展示了响应代码中 result.resultStatus 字段可能返回的值,请您根据指引进行处理:

result.resultStatus

信息

后续操作

S

调用成功。

paymentOptions.enabledtrue 时,取当前数组内的 logo.logoNamelogo.logoUrl 展示。

F

调用失败。

请参考错误码进行下一步操作。

U

未知原因。

若返回 UNKNOWN_EXCEPTION 结果码,表示由于未知原因,接口调用失败。请求重试。

注意:如果您未收到响应报文,可能是网络超时所致,请重新调用接口以解决问题。

下图展示了添加支付方式后的页面效果:

page.png

常见问题

问:什么是 allowedPaymentMethodRegions

答:指支付方式所属国家或地区的代码列表,此参数的值为二位字母的 ISO 3166 国家代码GLOBAL。若不传入该值,将全量返回支持的所有支付方式列表。若传入 HK,则会以白名单形式生效,仅返回中国香港地区支持的支付方式列表。

问:什么是 userRegion

答:指买家所在国家或地区的代码,请参阅 ISO 3166 国家代码标准了解更多信息。若不传入该值,不会影响支付方式列表的筛选,仅起到排序功能。若传入 HK,则会将中国香港地区的支付方式在返回列表中以高优先级排序。

步骤 2:创建支付订单 服务端

调用 支付(收银台)接口,您需要收集买家的支付方式、订单信息、设备信息、支付金额等提交支付请求。

注意:如果您在步骤 1 中选择通过 调用 API 接口 方式添加支付方式列表,表示已安装接口库和发送初始化请求。此时您无需再次操作,可直接跳转至创建支付请求继续集成流程

Antom 提供了多种语言的服务器端接口库。以下代码以 Java 为例,其他语言请集成 Antom SDK

1. 安装接口库

您可以在 GitHub 上找到最新版本。

copy
<dependency>
    <groupId>com.alipay.global.sdk</groupId>
    <artifactId>global-open-sdk-java</artifactId>
    <version>{latest_version}</version>
</dependency>

2. 初始化请求

创建一个单例资源以向 Antom 发起请求。

copy
import com.alipay.global.api.AlipayClient;
import com.alipay.global.api.DefaultAlipayClient;
import com.alipay.global.api.model.constants.EndPointConstants;

public class Sample {
    public static final String        CLIENT_ID            = "";
    public static final String        ANTOM_PUBLIC_KEY     = "";
    public static final String        MERCHANT_PRIVATE_KEY = "";

    private final static AlipayClient CLIENT               = new DefaultAlipayClient(
            EndPointConstants.SG, MERCHANT_PRIVATE_KEY, ANTOM_PUBLIC_KEY, CLIENT_ID);

}

3. 创建支付请求

支付请求包含以下关键参数。

参数名称

是否必需?

描述

productCode

在此场景中,该字段设置为 CASHIER_PAYMENT

paymentRequestId

商户生成的专属 ID。

paymentAmount

支付金额,以支付货币的最小单位设置。

paymentMethod

支付方式枚举值。

paymentRedirectUrl

商户端支付结果页,需根据服务端结果展示,非固定为成功页。

paymentNotifyUrl

支付结果通知地址,可通过接口指定或在门户上设置固定值。

settlementStrategy

支付请求的结算策略。如果您签署了多个结算货币,需要在接口中指定。

order

包括订单金额、订单 ID 和订单描述的订单信息。

env.terminalType

买家发起交易的环境:

  • WEB:客户端终端类型为网站,通过 PC 浏览器打开。
  • WAP:客户端终端类型为 H5 页面,通过移动浏览器打开。
  • APP:客户端终端类型为移动应用。

env.osType

买家发起交易的环境。当在商户手机浏览器网站发起,则 env.osType = ANDROID 或者 IOS

有关完整参数的更多信息,请参阅 支付(收银台)接口。

以下代码为调用 支付(收银台)接口以发起支付请求的示例:

copy
public static void executePayWithCard() {
        AlipayPayRequest alipayPayRequest = new AlipayPayRequest();
        alipayPayRequest.setClientId(CLIENT_ID);
        alipayPayRequest.setPath("/ams/api/v1/payments/pay");
        alipayPayRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);

        // 替换为您的 paymentRequestId
        alipayPayRequest.setPaymentRequestId("paymentRequestId01");

        // 设置 amount
        Amount amount = new Amount();
        amount.setCurrency("HKD");
        amount.setValue("100");
        alipayPayRequest.setPaymentAmount(amount);

        // 设置 paymentMethod
        PaymentMethod paymentMethod = new PaymentMethod();
        paymentMethod.setPaymentMethodType("ALIPAY_HK");
        alipayPayRequest.setPaymentMethod(paymentMethod);

        // 设置 order 信息
        Order order = new Order();
        order.setReferenceOrderId("referenceOrderId01");
        order.setOrderDescription("antom test order");
        order.setOrderAmount(amount);
        alipayPayRequest.setOrder(order);

        //设置 env 信息
        Env env = new Env();
        env.setTerminalType(TerminalType.WAP);
        env.setClientIp("114.121.121.01");
        env.setOsType(OsType.ANDROID);
        alipayPayRequest.setEnv(env);

        // 替换为您的 notifyUrl
        alipayPayRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com");

        // 替换为您的 redirectUrl
        alipayPayRequest.setPaymentRedirectUrl("http://www.yourRedirectUrl.com");

        //进行支付
        AlipayPayResponse alipayPayResponse = null;
        try {
          alipayPayResponse = defaultAlipayClient.execute(alipayPayRequest);
        } catch (AlipayApiException e) {
          String errorMsg = e.getMessage();
          // 处理错误情况
        }
    }

以下代码显示了请求报文的示例:

copy
{
  "paymentNotifyUrl": "http://www.yourNotifyUrl.com",
  "paymentRequestId": "paymentRequestId01",
  "env": {
    "terminalType": "WAP",
    "clientIp": "114.121.121.01",
    "osType": "ANDROID"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "100"
  },
  "productCode": "CASHIER_PAYMENT",
  "paymentRedirectUrl": "http://www.yourRedirectUrl.com",
  "paymentMethod": {
    "paymentMethodType": "ALIPAY_HK"
  },
  "order": {
    "orderAmount": {
      "currency": "HKD",
      "value": "100"
    },
    "referenceOrderId": "referenceOrderId01",
    "orderDescription": "antom test order"
  }
}

响应代码中涉及以下关键参数。

参数名称描述

result.resultStatus

支付(收银台)接口的调用状态。

normalUrl

将买家跳转到默认浏览器或嵌入式 WebView 中的 WAP 或 WEB 页面的链接。

applinkUrl

将买家跳转到已安装的目标应用中,或未安装目标应用的 WAP 页面中的链接。

schemeUrl

在 Android 或 iOS 系统中,应用安装完成后,将买家跳转到应用的 URL scheme。

以下代码显示了响应报文的示例:

copy
{
    "appIdentifier": "my.com.myboost",
    "applinkUrl": "https://myboost.app.link/IvWm7QZkfjb?%24fallback_url=https%3A%2F%2Fmsp.boost-my.com%2Fonlinepayment%2Fauthorise&source=alipay-connect&codeValue=https%3A%2F%2Fglobal.alipay.com%2F281002040098ZClz8ZTk46JEsh1jzyU3zx0A",
    "normalUrl": "https://msp.boost-my.com/onlinepayment/authorise?source=alipay-connect&codeValue=https%3A%2F%2Fglobal.alipay.com%2F281002040098ZClz8ZTk46JEsh1jzyU3zx0A",
    "orderCodeForm": {
        "codeDetails": [
            {
                "codeValue": "https://global.alipay.com/281002040098ZClz8ZTk46JEsh1jzyU3zx0A",
                "displayType": "TEXT"
            },
            {
                "codeValue": "https://global.alipay.com/merchant/order/showQrImage.htm?code=https%3A%2F%2Fglobal.alipay.com%2F281002040098ZClz8ZTk46JEsh1jzyU3zx0A&picSize=L",
                "displayType": "BIGIMAGE"
            },
            {
                "codeValue": "https://global.alipay.com/merchant/order/showQrImage.htm?code=https%3A%2F%2Fglobal.alipay.com%2F281002040098ZClz8ZTk46JEsh1jzyU3zx0A&picSize=M",
                "displayType": "MIDDLEIMAGE"
            },
            {
                "codeValue": "https://global.alipay.com/merchant/order/showQrImage.htm?code=https%3A%2F%2Fglobal.alipay.com%2F281002040098ZClz8ZTk46JEsh1jzyU3zx0A&picSize=S",
                "displayType": "SMALLIMAGE"
            }
        ],
        "expireTime": "2025-04-03T01:18:36-07:00"
    },
    "paymentActionForm": "{\"method\":\"GET\",\"paymentActionFormType\":\"RedirectActionForm\",\"redirectUrl\":\"https://myboost.app.link/IvWm7QZkfjb?%24fallback_url=https%3A%2F%2Fmsp.boost-my.com%2Fonlinepayment%2Fauthorise&source=alipay-connect&codeValue=https%3A%2F%2Fglobal.alipay.com%2F281002040098ZClz8ZTk46JEsh1jzyU3zx0A\"}",
    "paymentAmount": {
        "currency": "MYR",
        "value": "230"
    },
    "paymentCreateTime": "2025-04-03T01:04:37-07:00",
    "paymentData": "{\"codeValue\":\"https://global.alipay.com/281002040098ZClz8ZTk46JEsh1jzyU3zx0A\",\"displayPaymentAmount\":\"2.30\",\"displayPaymentCurrency\":\"MYR\",\"wallets\":[{\"enabled\":true,\"redirectionInfo\":{\"appIdentifier\":\"my.com.myboost\",\"applinkUrl\":\"https://myboost.app.link/IvWm7QZkfjb?%24fallback_url=https%3A%2F%2Fmsp.boost-my.com%2Fonlinepayment%2Fauthorise&source=alipay-connect&codeValue=${codeValue}\",\"normalUrl\":\"https://msp.boost-my.com/onlinepayment/authorise?source=alipay-connect&codeValue=${codeValue}\",\"schemeUrl\":\"boostapp://inAppDeeplink?deeplink_path=deeplink/onetimepayment&source=alipay-connect&codeValue=${codeValue}\"},\"walletBrandName\":\"Boost\",\"walletLogo\":{\"logoName\":\"BOOST\",\"logoUrl\":\"https://gw.alipay.com/icon/large/rectangle/BOOST.png\"},\"walletName\":\"BOOST\"}]}",
    "paymentId": "20250403194010800100188550285911975",
    "paymentRequestId": "PAY_20250403160436230",
    "redirectActionForm": {
        "method": "GET",
        "redirectUrl": "https://myboost.app.link/IvWm7QZkfjb?%24fallback_url=https%3A%2F%2Fmsp.boost-my.com%2Fonlinepayment%2Fauthorise&source=alipay-connect&codeValue=https%3A%2F%2Fglobal.alipay.com%2F281002040098ZClz8ZTk46JEsh1jzyU3zx0A"
    },
    "schemeUrl": "boostapp://inAppDeeplink?deeplink_path=deeplink/onetimepayment&source=alipay-connect&codeValue=https%3A%2F%2Fglobal.alipay.com%2F281002040098ZClz8ZTk46JEsh1jzyU3zx0A",
    "result": {
        "resultCode": "PAYMENT_IN_PROCESS",
        "resultMessage": "payment in process",
        "resultStatus": "U"
    }
}

下表展示了响应代码中 result.resultStatus 字段可能返回的值,请您根据指引进行处理:

result.resultStatus

信息

后续操作

S

支付成功。

无需进一步操作。

F

支付失败。关闭当前交易订单或重新更换 paymentRequestId 后再次发起支付请求

U

未知原因。

  • 若返回 PAYMENT_IN_PROCESS 结果码,获取任意一个链接 (applinkUrl/normalUrl/schemeUrl) 并打开收银页面。
  • 若返回其他结果码,关闭当前交易订单或重新更换 paymentRequestId 后再次发起支付请求

注意:如果您未收到响应报文,可能是网络超时所致。关闭当前交易订单或重新更换 paymentRequestId 后再次发起支付请求

常见问题

问:如何确认响应代码中需要消费的 URL 类型?

答:不同支付方式在不同端类型下,Antom 可能会返回以下三种 URL 中的一种或多种:normalUrlapplinkUrlschemeUrl。商户服务端需将这些 URL 传递给商户前端,可以选择任选一种 URL 进行跳转消费。

问:什么是 paymentId

答:如果您需要存储相应的订单 ID 以备后续退款和对账,可以指定 paymentId

问:如何设置 terminalType

答:terminalType 的有效值为:

  • 如果买家在 PC 端发起交易,需要将 terminalType 指定为 WEB
  • 如果买家在移动浏览器上发起交易,需要将 terminalType 指定为 WAP。添加 osType 参数,并根据买家的手机填写相应的系统参数 ANDROIDIOS
  • 如果买家在应用内发起交易,需要将 terminalType 指定为 APP

步骤 3:获取跳转支付推进链接 客户端

商户服务端拿到 Antom 返回的支付推进链接后,将该地址传递给前端,由商户前端跳转至支付方式页面。不同类型的支付推进链接如下表所示:

类型

描述

示例 URL

normalUrl

一个 HTTPS 地址的链接,用于在同一浏览器页面上重定向到支付方式的网站页面。

URL=serverResponse.normal

applinkUrl

在支付过程中用于重定向的 Android App Link 或 iOS Universal Link。

URL=serverResponse.applink

schemeUrl

用于打开支付方式应用的 URL scheme。

URL=serverResponse.scheme

请参阅支付推进链接了解更多内容。

以下为商户前端加载支付推进链接的示例代码:

copy
if (URL != null) {
    window.open(URL, '_blank');
}

下图展示支付方式收银台页面的效果:

page2.png

不同支付方式在不同终端会返回不同的支付推进链接,Antom 基于您传入的 paymentMethodterminalType 决策返回不同的支付推进链接。下表列举了不同终端返回的支付推进链接类型及其用户体验。关于具体的不同支付方式返回的支付推进链接内容,请参阅支付方式返回链接了解更多详情。

支付推进链接类型

功能

用户体验

applinkUrl

  • 买家已安装支付方式应用程序时可拉起应用程序。
  • 买家未安装支付方式应用程序时可拉起浏览器 H5 页面。
  • 可以自动判断买家是否安装支付方式应用程序。
  • 一般在买家商户应用程序或手机网站发起支付时会返回该 URL,具体依赖于支付方式是否支持。
  • 买家已安装支付方式应用程序

image.png

  • 买家未安装支付方式应用程序

image.png

schemeUrl

  • 通过支付方式应用程序的 scheme 直接拉起应用程序。
  • 买家未安装支付方式应用程序时无法拉起且会显示异常,请参阅最佳实践了解更多详情。
  • 一般在买家商户应用程序或手机网站发起支付时会返回该 URL,具体依赖于支付方式是否支持。
  • 买家已安装支付方式应用程序

image.png

  • 买家未安装支付方式应用程序:不支持

normalUrl

  • 支付方式的 H5 页面。
  • 不同支付方式的 H5 页面体验不同,部分支付方式支持登录后直接支付,还有部分支付方式需要中间页拉起支付方式应用程序后进行支付。
  • 买家从商户 Web 端发起支付时,均返回此 URL,具体依赖于支付方式是否支持。
  • Web 端支付:

image.png

  • H5 页面支付:

image.png

  • 中间页拉起支付方式应用程序

image.png

您在 支付(收银台)接口中指定的 paymentRedirectUrl 字段提供了一个 HTTPS 地址,该地址用于在商户端页面显示支付结果。以下为您的支付结果页面示例:

page3.png

常见问题

问:如何处理不同的支付体验?

答:您无需处理不同支付方式的不同体验,只需通过前端页面重定向到 normalUrl。不同的支付体验由 normalUrl 负责完成渲染和支付流程。

问:如何展示支付结果页内容?

答:在支付成功和失败的情况下,可能都有入口可以从支付方式端回跳到商户页面。为避免引起误解,请以服务端返回的结果为准,不要将 paymentRedirectUrl 固定为“支付成功页面”。如果从 App 端发起交易,paymentRedirectUrl 需设置为商户应用程序的 scheme 地址。

问:回跳至商户结果页面是否代表支付成功?

答:不能仅凭回跳至商户页面来判断支付是否成功,可能存在以下情况导致回跳商户页失败:

  • 买家支付成功后,可能因网络等原因导致未能回跳至商户页面。
  • 当买家未完成支付时,也可能通过支付方式端的入口回跳至商户页面。
  • Antom 不会在 paymentRedirectUrl 拼接表示支付结果的字段信息。

步骤 4:接收异步通知 服务端

完成支付或支付失败时,Antom 会通过 支付(收银台)接口中的参数 paymentNotifyUrl 指定的地址发送异步通知(支付通知)。

  1. 您可以选择以下两种方法中的一种来设置接收通知的地址:
    • 若您的每个订单都有单独的通知 URL,建议在每笔请求中设置通知 URL。您可以通过 支付(收银台)接口请求的 paymentNotifyUrl 字段中传入该笔订单的异步通知接收地址。
    • 若您的所有订单有统一的通知 URL,您可以在 Antom Dashboard > 开发者 > 通知地址 中设置通知 URL。具体操作请参阅通知地址

支付通知中涉及以下关键参数:

参数名称

是否必需?

描述

resultStatus

表示订单支付结果的状态。

paymentRequestId

商户发起支付的唯一 ID。

paymentAmount

表示支付金额。

有关完整参数的更多信息,请参阅 支付通知

以下代码显示了请求报文的示例:

copy
{
  "notifyType": "PAYMENT_RESULT",
  "result": {
    "resultCode": "SUCCESS",
    "resultStatus": "S",
    "resultMessage": "success"
  },
  "paymentRequestId": "2020010123456789XXXX",
  "paymentId": "2020010123456789XXXX",
  "paymentAmount": {
    "value": "8000",
    "currency": "EUR"
  },
  "paymentCreateTime": "2020-01-01T12:01:00+08:30",
  "paymentTime": "2020-01-01T12:01:01+08:30"
}

下表展示了支付结果的异步通知中 result.resultStatus 字段可能返回的值,请您根据指引进行处理:

result.resultStatus

信息

后续操作

S

支付成功。

可从中获取以下字段信息:

  • paymentId:表示由 Antom 生成的支付订单 ID,用于退款和对账。

F

支付失败。关闭当前交易订单或更换 paymentRequestId 后再次发起支付请求。

注意:完成支付或支付失败时,商户的服务端都会收到异步通知。但当部分失败场景(如参数异常)时,支付(收银台)接口会同步返回 F,Antom 不会发送异步通知,您可根据返回的 F 状态直接关闭订单。

  1. 当您收到 Antom 的异步通知,需要您在返回中按照示例代码格式返回响应,但无需做加签处理。

您需要按照以下方法对 Antom 发送的支付通知进行验签:

copy
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 会重新发送异步通知。

copy
{
    "result": {
        "resultCode": "SUCCESS",
        "resultStatus": "S",
        "resultMessage": "success"
    }
}

常见问题

问:何时会发送支付结果通知?

答:这取决于支付是否完成:

  • 如果支付成功完成,Antom 通常会在 3 到 5 秒内发送异步通知。对于某些支付方式,如现金支付,通知可能会稍有延迟。
  • 如果支付未完成,Antom 需要先关闭订单,然后发送异步通知。不同支付方式关闭订单所需的时间会有所不同,通常默认为 14 分钟。

问:异步通知会被重新发送吗?

答:是的,对于以下情况,异步通知会在 24 小时内自动重新发送:

  • 如果由于网络原因未收到异步通知。
  • 如果您收到来自 Antom 的异步通知,但您没有按照处理通知的示例代码格式对通知做出响应。

通知最多可以重发 8 次,或者直到收到正确的响应以终止发送。发送间隔如下:0 分钟、2 分钟、10 分钟、10 分钟、1 小时、2 小时、6 小时和15 小时。

问:在响应异步通知时,我需要加签吗?

答:如果您收到来自 Antom 的异步通知,您需要按照处理通知的示例代码格式返回响应,但不需要对响应进行签名。

问:收到支付结果通知后是否需要验签?

答: 需要。为确保回调请求确实由 Antom 发送,在验签时需要进行验证。在拼装待验签的报文时,必须按照以下标准顺序处理:<http-method> <http-uri> <client-id>.<request-time>.<request-body>。请注意拼装 request-body 时应直接取其原始值,而不要解析成 JSON 后再拼装。

支付后操作

以下内容将介绍支付后如何通过服务端主动查询交易状态、发起交易取消以及退款操作的具体方法,帮助您实现稳定可靠的支付管理体验。

查询交易 服务端

Antom 提供发送异步通知的功能,同时也支持主动查询支付结果。调用 支付结果查询 接口,通过以下参数查询支付结果:

参数名称

是否必需?

描述

paymentRequestId

商户生成的支付请求 ID。

有关完整参数的更多信息,请参阅 支付结果查询 接口

以下为调用 支付结果查询 接口的代码示例:

copy
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();
        // 处理错误情况
    }
}

以下为请求示例:

copy
{
    "paymentRequestId": "REQUEST_20250327164938236"
}

以下为响应的代码示例:

copy
{
  "actualPaymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentAmount": {
    "currency": "THB",
    "value": "299"
  },
  "paymentId": "20250217194010800100188760278262487",
  "paymentMethodType": "TRUEMONEY",
  "paymentRedirectUrl": "https://kademo.intlalipay.cn/melitigo/Test_114.html",
  "paymentRequestId": "3IOS47F3C9B7D96",
  "paymentResultCode": "SUCCESS",
  "paymentResultMessage": "success.",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2025-02-17T08:06:43-08:00",
  "pspCustomerInfo": {
    "pspName": "TRUEMONEY"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

请根据响应中的 paymentStatus 字段进行处理:

paymentStatus

描述

后续操作

SUCCESS

支付成功。

无需后续操作。

FAIL

支付失败。

关闭订单或更换 paymentRequestId 再次发起请求。

PROCESSING

支付进行中。

建议等待一段时间后继续查询状态或关闭订单再重新查询。

常见问题

问:调用 支付结果查询 接口时应该消费哪些字段?

答:请注意以下关键参数:

  • result:表示此 支付结果查询 接口调用的结果,需要根据 paymentStatus 来判断订单状态:
    • SUCCESSFAIL 表示最终结果。
    • PROCESSING 表示处理中。
  • paymentAmount:表示支付的金额。

问:发起查询的推荐间隔是多久?

答:推荐以轮询的形式调用 支付结果查询 接口,间隔 2 秒,直到获取最终的支付结果或收到异步支付结果通知为止。

取消交易 服务端

对于支付成功后的订单,如果买家在当天内申请取消订单或退款,您可以通过 Antom 提供的取消支付能力将订单状态取消或解冻。此外,对于尚未完成支付的订单,您也可以直接进行取消。请参阅取消交易了解关于取消支付集成方案的更多内容。

退款 服务端

在支付成功后,您可以通过以下两种方法发起退款:

  • 调用接口:您可以通过调用 退款 接口对成功支付的交易发起退款。
  • 使用 Antom Dashboard 退款:关于如何发起退款并查看退款结果,请参阅发起退款

Antom 支持的退款能力如下:

  • 支持全额退款。
  • 支持部分多次退款,多次退款的总金额需小于等于请款金额。

请参阅退款了解关于退款集成方案的更多内容。

最佳实践

为了提高集成效率,Antom 为您提供客户端优化、回跳商户页展示、支付失败重试、接口超时时间设置、中间页优化等最佳实践方案,请参阅最佳实践了解详情。

支付方式特性

本部分内容旨在系统阐述各类支付方式在支持特性方面的差异。

取消交易能力

不同支付方式的取消交易窗口期有差异,请参阅取消交易了解详情。

退款能力

不同支付方式的退款能力不同,主要为能否支持退款和支持退款的周期。请参阅支持的支付方式,了解更多关于退款能力的内容。

默认关单时间

请参阅默认关单时间,了解更多关于支付方式支持的关单详情。

集成要点

以下为不同支付方式的集成点及建议方案。

支付方式

建议方案

PayPay

  • paymentRedirectUrl 字段有长度限制。
  • 退款次数不能超过 20 次。

paymentRedirectUrl 字段长度不要超过 255 字符。

QRIS

存在单边账情况。

调用单边账的 支付结果查询 接口以获取支付结果并提前感知单边账的发生,请联系 Antom 技术支持获取更多内容。

PromptPay

存在单边账情况。

调用单边账的 支付结果查询 接口以获取支付结果并提前感知单边账的发生,请联系 Antom 技术支持获取更多内容。

Maybank

支付完成后,会延迟 5 分钟发送异步通知。

为买家展示订单确认中的状态提示。

OVO/Pix/BANCOMAT Pay

无法自动拉起钱包。

需手动拉起钱包完成支付。

Siam Commercial Bank

  • 支付有手续费。
  • 不支持 PC 端。

提示买家可能存在支付手续费(由买家在银行的等级决策收取的费用金额)。

Bank of Ayudhya

  • 支付有手续费。
  • 不支持 PC 端。

提示买家可能存在支付手续费(由买家在银行的等级决策收取的费用金额)。

GoPay/Bangkok Bank/KrungThai Bank

不支持 PC 端。

NAVER Pay

PC 客户端需额外集成:买家登录后,支付不会在原页面直接完成,而是自动打开一个新的标签页重定向。

开启浏览器弹窗权限,并在代码中通过创建新的 browser 对象(或窗口)打开弹窗页面进行支付处理。

Mercado Pago (巴西)

会消费 buyerEmail 字段从而导致支付直接失败。

传入 payerEmail 字段。