Alipay, China's leading third-party online payment solutionAlipay, China's leading third-party online payment solution

托管模式

本文描述了如何通过托管模式集成银行卡支付方式。托管模式可保护您免受 PCI-DSS 限制,因为敏感数据不会通过您的服务器,并且无需您获得 PCI 资格。在此模式下,Antom 提供了一个支付信息收集页面,该页面可捕获支付信息并将其存储为 cardToken 以供后续流程使用。

用户体验

以下图示展示了首次支付和已保存的银行卡支付的用户体验。

首次支付

Web 用户体验

国际卡-PC-商户无PCI-首次.png

已保存的银行卡支付

Web 用户体验

国际卡-PC-商户无PCI-二次.png

支付流程

对于托管模式下的银行卡支付,支付流程包括以下步骤。

银行卡支付-托管模式-通用卡-中.png

注意:韩国本地卡认证支付涉及多个卡品牌,为提高支付体验,建议您将卡品牌展示在您的页面上从而减少中间页的跳转。此场景下请注意以下几种情况:

  • 在您的收银台页面展示卡品牌。
  • 在发起支付请求时指定买家选择的卡品牌信息。
  • Antom 返回具体卡品牌支付的页面,不返回卡品牌选择的中间页。

集成步骤

大多数银行卡支付遵循 Antom 提供的通用支付流程和集成过程。开始您的集成,请按照以下步骤操作。

  1. (可选)显示支付方式
  2. 授权支付
  3. 获取支付结果
  4. 请款
  5. 获取请款结果

注意:韩国卡存在认证和非认证两种支付类型。韩国卡的非认证支付遵循常规银行卡支付流程,但韩国卡的认证支付涉及额外的操作步骤。

步骤 1:(可选) 显示支付方式 客户端

添加您计划集成的支付方式的标识和名称。这使得买家可以轻松选择他们更喜欢的支付方式。您可以通过以下两种方式获取标识和名称:

  • 联系 Antom 技术支持。
  • 调用 咨询 接口,根据货币、交易发起终端类型、买家所在地区以及已签约的支付方式,获取当前交易支持的支付方式和标识链接。

添加支付方式后的页面效果如下所示:

image.png

步骤 2:授权支付 服务端

当买家选择由 Antom 提供的支付方式时,会显示银行卡信息收集页面给买家。Antom 将收集买家的银行卡信息、环境和订单信息。调用 支付(收银台)接口,为支付提交授权请求。

发起支付请求 服务端

Antom 提供了多种语言的服务器端接口库。以下代码以 Java 为例,需要安装 Java 6 或更高版本。

安装接口库

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

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

初始化请求实例

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);

}

创建支付请求

在发送 支付 接口请求时,可以根据业务需求选择以下功能:

  • 3DS
    • 启用 3D 验证:在 支付 接口中设置 is3DSAuthentication 字段,以确定交易是否通过 3D Secure 进行验证。
    • 智能恢复交易:如果发卡行要求,将自动对非 3D Secure 交易发起 3D Secure 验证以恢复失败的交易。
    • MPI 能力:商户在交易发起前优先进行第三方验证,将验证结果信息传递到支付请求中,并指定非 3D 验证。如果商户未获取银行卡信息,则无法进行非 3D 验证。

注意韩国本地卡不涉及 3DS 功能。

  • 欺诈保护
    • 增值服务风险控制Antom在交易层面提供升级的风险控制服务,根据交易的风险等级智能决定风险控制策略。
    • 地址验证系统(AVS)服务:该服务验证提供的账单地址是否与发卡行记录中的持卡人地址匹配。AVS 有助于防止欺诈交易。
  • 令牌化
    • 存储银行卡信息:在首次支付时获取买家同意存储银行卡信息,以便下次支付时无需再次输入银行卡信息。
  • 分期付款
    • 分期付款:在支付时,买家可以选择分期付款方式,并按每个分期周期进行定期付款。买家完成首期分期付款后, Antom 会根据合同中指定的结算周期结算全额订单金额。
  • 特定功能
    • 商户发起交易(MIT):可在无需买家参与的情况下发起计划内或计划外的交易。
    • 指定银行卡品牌:当买家选择双标卡支付时,您可以指定银行卡品牌或授权支付的地区。

支付请求中包含以下参数。

参数名称

是否必需?

描述

productCode

代表合同规定使用的支付产品。对于收银台支付,值设置为CASHIER_PAYMENT

paymentRequestId

为识别支付请求而分配的专属 ID。

paymentAmount

商户请求在订单货币中接收的支付金额。

paymentMethod

商户或收单机构用来收款的支付方式。

paymentRedirectUrl

支付完成后,买家被重定向到的商户页面链接。

settlementStrategy

支付请求的结算策略。

order

订单信息,如买家、商户、商品、金额、配送信息和购买环境。

paymentExpiryTime

支付会话过期的具体日期和时间。

env

环境信息:用于提高支付成功率。

selectedCardBrand

对于韩国本地卡认证场景,指定 selectedCardBrand 参数时需注意以下情况:

  • 商户提供银行列表时需指定 selectedCardBrand 为具体的卡品牌。
  • Antom 提供银行列表时无需传入此参数。

请参见银行卡品牌以获取银行卡品牌列表。

requireIssuerAuthentication

对于韩国本地卡认证场景,您需要指定 requireIssuerAuthentication 参数为 true

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

调用支付接口的示例代码

以下示例代码用于发起支付:

copy
public static void payByCard() {
    AlipayPayRequest alipayPayRequest = new AlipayPayRequest();
    alipayPayRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);

    // replace with your paymentRequestId
    String paymentRequestId = UUID.randomUUID().toString();
    alipayPayRequest.setPaymentRequestId(paymentRequestId);

    // set amount
    Amount amount = Amount.builder().currency("SGD").value("4200").build();
    alipayPayRequest.setPaymentAmount(amount);

    // set paymentMethod
    PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("CARD").build();
    alipayPayRequest.setPaymentMethod(paymentMethod);

    // replace with your orderId
    String orderId = UUID.randomUUID().toString();

    // set buyer info
    Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();

    // set order info
    Order order = Order.builder().referenceOrderId(orderId)
            .orderDescription("antom testing order").orderAmount(amount).buyer(buyer).build();
    alipayPayRequest.setOrder(order);

    // set env info
    Env env = Env.builder().terminalType(TerminalType.WEB).clientIp("1.2.3.4").build();
    alipayPayRequest.setEnv(env);

    // set auth capture payment mode
    PaymentFactor paymentFactor = PaymentFactor.builder().isAuthorization(true).build();
    alipayPayRequest.setPaymentFactor(paymentFactor);

    // replace with your notify url
    alipayPayRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com");

    // replace with your redirect url
    alipayPayRequest.setPaymentRedirectUrl("https://www.yourMerchantWeb.com");

    // do Payment
    AlipayPayResponse alipayPayResponse = null;
    try {
        alipayPayResponse = CLIENT.execute(alipayPayRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}

以下代码显示了请求消息的示例:

通用银行卡支付请求
copy
{
  "env": {
    "clientIp": "1.2.3.4",
    "terminalType": "WEB"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "SGD",
      "value": "4200"
    },
    "orderDescription": "antom testing order",
    "referenceOrderId": "referenceOrderId01"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentFactor": {
    "isAuthorization": true
  },
  "paymentMethod": {
    "paymentMethodType": "CARD"
  },
  "paymentNotifyUrl": "https://www.yourNotifyUrl.com",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "productCode": "CASHIER_PAYMENT"
}

常见问题

问:如何设置 terminalType

答:terminalType 的有效值为:

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

问:请求参数的值可以使用中文字符吗?

答: 为了避免特定支付方式的兼容性问题,请求中的字段请勿使用中文字符。

问: 如何设置接收支付通知的链接?

答:在 支付会话创建(收银台)接口中指定 paymentNotifyUrl 字段,以接收支付结果的异步通知(支付通知),或者在 Antom Dashboard 中配置接收链接。如果请求和 Antom Dashboard 中都指定了链接,请求中的值优先。

接收支付响应

返回的参数包含以下内容:

  • normalUrl:跳转链接地址。
  • paymentId:订单 ID。

以下是示例响应代码:

授权成功
copy
{
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "VISA",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "networkTransactionId": "networkTransIdXXXX",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

常见问题

问:什么是 normalUrl

答:对于 Web 或 WAP 交易,Antom 会返回 normalUrl,服务器端需要将其传递给客户端进行重定向。当您再次为同一订单发起支付时,需要获取新的 normalUrl 进行重定向。

问:什么是 paymentId

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

跳转到支付推进链接 客户端

商户服务器将 normalUrl 传递给客户端,由客户端页面处理重定向到 normalUrl 的过程。

步骤 3:获取支付结果 服务端

当买家完成支付或支付超时,您可以通过 Antom 异步通知或主动查询支付结果来获取相应的支付结果。

从异步通知和 支付结果查询 获取的响应包含授权支付结果以及其它关键信息,例如:

接口

授权结果

AVS 信息

CVV 信息

3DS 身份验证信息

支付通知

resultStatus

avsResultRaw

cvvResultRaw

threeDSResult仅 3DS 身份验证授权时可用)

支付结果查询

paymentStatus

avsResultRaw

cvvResultRaw

threeDSResult仅 3DS 身份验证授权时可用)

接收异步通知

当支付成功或失败时,Antom 会向您在 支付(收银台)接口的 paymentNotifyUrl 参数中指定的地址发送异步通知(支付通知)。如果每个支付的地址相同,您也可以在 Antom Dashboard 中配置该地址。

以下是一个 3D 支付通知的示例代码:

copy
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "eci": "02",
      "threeDSVersion": "2.2.0",
      "caav": "cavvSample"
    }
  },
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

以下是一个非 3D 支付通知的示例代码:

copy
{
  "actualPaymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "cardInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "XXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentCreateTime": "2024-01-01T00:00:00+08:00",
  "paymentId": "20240101123456789XXXX",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "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"
  }
}

如何验证通知的签名并做出响应,请参阅签名与验签

常见问题

问:何时会发送通知?

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

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

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

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

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

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

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

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

问:我在通知中需要使用哪些关键参数?

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

  • result:表示订单的支付结果。
  • paymentRequestId:用于咨询、取消和对账的支付请求 ID。
  • paymentId:表示由Antom生成的支付订单 ID,用于退款和对账。
  • paymentAmount:表示支付金额。

查询支付结果

调用 支付结果查询 接口,通过以下参数查询支付结果:

参数名称

是否必需?

描述

paymentRequestId

商户生成的支付请求号

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

copy
public static void inquiryPayment() {
    AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();

    // replace with your paymentRequestId
    alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");

    AlipayPayQueryResponse alipayPayQueryResponse = null;
    try {
        alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}

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

copy
{
  "paymentRequestId": "paymentRequestId01"
}

以下代码展示了 3D 支付的响应报文示例:

copy
{
  "authExpiryTime": "2024-01-08T00:01:00+08:00",
  "cardInfo": {
    "cardBrand": "MASTERCARD",
    "funding": "DEBIT",
    "issuingCountry": "US"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "CARD",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "networkTransIdXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "eci": "02",
      "threeDSVersion": "2.2.0",
      "caav": "cavvSample"
    }
  },
  "paymentResultMessage": "success",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

以下代码展示了非 3D 支付的响应报文示例:

copy
{
  "authExpiryTime": "2024-01-08T00:01:00+08:00",
  "cardInfo": {
    "cardBrand": "MASTERCARD",
    "funding": "DEBIT",
    "issuingCountry": "US"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentId": "20240101123456789XXXX",
  "paymentMethodType": "CARD",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "paymentResultCode": "SUCCESS",
  "paymentResultInfo": {
    "avsResultRaw": "A",
    "cardBrand": "MASTERCARD",
    "cardNo": "****************",
    "cvvResultRaw": "Y",
    "funding": "DEBIT",
    "issuingCountry": "US",
    "networkTransactionId": "networkTransIdXXXX",
    "paymentMethodRegion": "GLOBAL",
    "threeDSResult": {
      "cavv": "",
      "eci": ""
    }
  },
  "paymentResultMessage": "success",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2024-01-01T00:01:00+08:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

常见问题

问:我应该多久调用一次 支付结果查询 接口?

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

问:我在通知中需要使用哪些关键参数?

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

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

步骤 4:请款 服务端

默认情况下,Antom 会自动为您处理资金请款。如果您在调用 支付(收银台)接口时将 paymentFactor.captureMode 的值设置为MANUAL,则必须通过调用 请款(收银台)接口来手动进行资金请款。

  • 自动请款Antom 会在买家授权支付后立即自动进行资金请款。请款结果会通过异步通知传达给您。当满足以下任一条件时,自动请款将被激活:
    • 您在 支付(收银台)接口 中将 paymentFactor.captureMode 的值设置为 AUTOMATIC
    • 您保留了 paymentFactor.captureMode 支付(收银台)接口中的值为空,或者没有传递此参数。
  • 手动请款:成功授权后七天内,您必须通过调用 请款(收银台)接口来发起资金请款,否则 Antom 将自动解冻支付的授权资金。请款总额必须等于授权总额。

注意

  • 对于银行卡支付,建议在发货前确认成功的请款结果。
  • 韩国本地卡认证场景仅支持自动请款,不支持手动请款。

请款(收银台)接口中的主要请求参数如下表所示:

参数

描述

captureRequestId

您为请款请求分配的专属 ID。

paymentId

Antom 为订单分配的专属 ID。

captureAmount

请款金额,必须等于授权的总金额。

以下示例代码用于发起一次请款。

copy
public static void capture() {
    AlipayCaptureRequest alipayCaptureRequest = new AlipayCaptureRequest();

    Amount amount = Amount.builder().currency("SGD").value("4200").build();
    alipayCaptureRequest.setCaptureAmount(amount);

    // replace with your captureRequestId
    String captureRequestId = UUID.randomUUID().toString();
    alipayCaptureRequest.setCaptureRequestId(captureRequestId);

    // replace with your paymentId
    alipayCaptureRequest.setPaymentId("20240101123456789XXXX");

    AlipayCaptureResponse alipayCaptureResponse = null;
    try {
        alipayCaptureResponse = CLIENT.execute(alipayCaptureRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
    }
}

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

copy
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "captureRequestId": "captureRequestId01",
  "paymentId": "20240101123456789XXXX"
}

步骤 5:获取请款结果 服务端

当买家完成请款或请款超时,您可以通过Antom异步通知或主动查询支付结果来获取相应的支付结果。

接收异步通知

完成请款或请款失败时,Antom会通过 请款通知(收银台)发送异步通知。您可以在 支付(收银台)接口中通过 paymentNotifyUrl 参数指定。如果每个请款的地址相同,您也可以在 Antom Dashboard 中进行配置。

以下是一个成功支付的通知示例:

copy
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "notifyType": "CAPTURE_RESULT",
  "captureId": "20240101987654321XXXX",
  "captureRequestId": "captureRequestId01",
  "captureTime": "2024-01-01T00:00:02+08:00",
  "paymentId": "20240101123456789XXXX",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

以下是一个支付失败通知的示例:

copy
{
  "captureAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "notifyType": "CAPTURE_RESULT",
  "captureId": "20240101123456789XXXX",
  "captureRequestId": "captureRequestId01",
  "captureTime": "2024-01-01T00:00:02+08:00",
  "paymentId": "20240101123456789XXXX",
  "result": {
    "resultCode": "PROCESS_FAIL",
    "resultMessage": "fail.",
    "resultStatus": "F"
  }
}

如何验证通知的签名并作出响应,参见签名与验签

常见问题

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

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

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

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

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

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

问:我需要使用通知中的哪些关键参数?

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

  • result:表示订单的请款结果。
  • notifyType:通知类型为 CAPTURE_RESULT
  • paymentRequestId:您生成的支付请求 ID,用于查询、取消和对账。
  • paymentIdAntom 生成的支付订单 ID,用于退款和对账。
  • acquirerReferenceNo:集成新加坡和香港内银行卡支付服务的商户将在通知中收到特定的收单机构 ID。

查询请款结果

调用 支付结果查询 接口,通过以下参数查询请款结果:

参数名

是否必需?

描述

paymentRequestId

商户生成的支付请求 ID

以下示例代码展示了如何调用 支付结果查询 接口:

copy
public static void inquiryPayment() {
    AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();

    // replace with your paymentRequestId
    alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");

    AlipayPayQueryResponse alipayPayQueryResponse = null;
    try {
        alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
    } catch (AlipayApiException e) {
        String errorMsg = e.getMessage();
        // handle error condition
    }
}

以下是请求报文:

copy
{
  "paymentRequestId": "paymentRequestId01"
}

请款状态的值

接口响应中 transactions 字段的值表示请款状态:

参数

描述

transactions.transactionType

值为CAPTURE,表示请款状态。

transactions.transactionResult

请款结果。

transactions 表示请款状态。请参阅以下请款成功代码示例:

copy
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "S",
        "resultCode": "SUCCESS",
        "resultMessage": "success"
      }
    }
  ]
}

transactions 表示请款状态。请查看以下请款失败的代码示例:

copy
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "F",
        "resultCode": "PROCESS_FAIL",
        "resultMessage": "General business failure. No retry."
      }
    }
  ]
}

transactions 表示请款状态。请查看以下处理中的请款代码示例:

copy
{
  "transactions": [
    {
      "transactionType": "CAPTURE",
      "transactionStatus": "SUCCESS",
      "transactionRequestId": "captureRequestId01",
      "transactionAmount": {
        "currency": "SGD",
        "value": "4200"
      },
      "transactionTime": "2024-01-01T00:00:02+08:00",
      "transactionId": "20240101123456789XXXX",
      "transactionResult": {
        "resultStatus": "U",
        "resultCode": "PAYMENT_IN_PROCESS",
        "resultMessage": "payment in process"
      }
    }
  ]
}

常见问题

问:我应该多久调用一次 支付结果查询 接口?

答:以 2 秒的间隔持续调用 支付结果查询 接口,直到获取最终的支付结果或收到异步支付结果通知。

最佳实践

遵循以下最佳实践以提高集成效率。

自定义支付超时时间

在收银台支付场景中,Antom 端的默认超时时间为 14 分钟。超时后,买家无法继续支付。 您可以通过 支付(收银台)接口中的 paymentExpireTime 参数指定超时时间。 超过指定时间后,买家将无法扫码或登录结账页面。

以下示例代码展示了如何在 支付(收银台)接口中指定 paymentExpireTime 参数:

copy
{
  "env": {
    "clientIp": "1.2.3.4",
    "terminalType": "WEB"
  },
  "order": {
    "buyer": {
      "referenceBuyerId": "yourBuyerId"
    },
    "orderAmount": {
      "currency": "SGD",
      "value": "4200"
    },
    "orderDescription": "antom testing order",
    "referenceOrderId": "referenceOrderId01"
  },
  "paymentAmount": {
    "currency": "SGD",
    "value": "4200"
  },
  "paymentExpiryTime": "2024-01-01T00:30:00+08:00",
  "paymentFactor": {
    "isAuthorization": true
  },
  "paymentMethod": {
    "paymentMethodMetaData": {
      "cvv": "123",
      "cardholderName": {
        "firstName": "John",
        "lastName": "Doe"
      },
      "expiryMonth": "12",
      "expiryYear": "99",
      "cardNo": "4054695723100768",
      "tokenize": false
    },
    "paymentMethodType": "CARD"
  },
  "paymentNotifyUrl": "https://www.yourNotifyUrl.com",
  "paymentRedirectUrl": "https://www.yourMerchantWeb.com",
  "paymentRequestId": "paymentRequestId01",
  "productCode": "CASHIER_PAYMENT"
}

建议将接口超时时间设置为 10 秒,以提高响应成功率。

商户结果页面处理逻辑建议

  1. 处理重定向问题

当买家成功完成支付,但在跳转到您指定的 paymentRedirectUrl 时遇到问题,无论是由于网络问题还是支付方式的限制,请注意以下两点:

    • 不能将客户端重定向作为判断支付成功的依据。
    • 如果支付方法页面的 paymentRedirectUrl 未能重定向到商户页面,买家可以手动点击原始商户页面。为了避免买家误以为订单未支付而再次尝试支付,建议在原始商户页面上实现一个弹出窗口,用于查询交易结果。当买家点击此弹出窗口时,应显示交易结果,防止重复支付尝试。
  1. 重定向后触发订单结果查询

如果在调用 支付结果查询 接口后,商户端弹出,建议处理以下不同的结果:

    • 支付成功:支付成功后,页面将显示与发货相关的内容。
    • 支付失败:表明支付失败,并提供重试支付的指导,以帮助订单完成。
    • 支付处理中:显示加载效果,并在 3-5 秒内暂停,然后再次查询服务器以获取支付结果。如果结果仍然不确定(既不是成功也不是失败),建议显示“订单处理中”或“通过订单管理门户查看最终结果”。避免将延迟归因于“网络处理”。

支付失败重试

当订单的支付尝试失败,且买家可以为同一订单重试支付时,我们建议遵循以下集成流程以实现无缝体验:

  1. 在支付请求中,将 referenceOrderId 设置为订单 ID,将 paymentRequestId 设置为支付订单 ID。
  2. 如果需要对同一订单重试支付,首先检查订单状态。如果支付已经成功,向买家显示“已完成支付”。如果没有,再次调用 支付(收银台)接口以获取新的 normalUrl 进行重定向。虽然 referenceOrderId 保持不变,因为它代表相同的订单,但后续支付尝试时必须更新 paymentRequestId
  3. 确保每个商户订单只与一个成功的支付相关联。如果检测到单个订单有多个成功的支付,调用 取消支付 接口来为买家发起退款。
  4. 对于不支持退款的支付方式,建议在发起新支付之前取消原始支付。

获取和核查支付结果的时间

为了确保稳定地获取支付结果,避免出现买家完成支付但您未收到支付结果的情况,建议您在以下阶段检查支付结果:

  1. 当显示商户支付结果页面时。
  2. 在发货给买家之前。
  3. 当您收到 Antom 对账文件时。