托管收银台

托管支付页面是 Antom 提供的标准化解决方案,适用于未维护收银台列表、希望由 Antom 托管收银台页面的商户。您可以在自有页面展示商品信息,买家支付时,Antom 托管收银台页面将展示支付方式和价格,供买家选择并完成支付。系统支持商户品牌和标识自定义配置,实现快速部署且免开发、零维护。

用户体验

下图展示一般场景下,从商户页面跳转至 Antom 支付页面的用户体验流程:

image.png

支付流程

使用 Antom 全球商家账户全托管模式支付的流程包括以下步骤:

yuque_diagram (23).png

  1. 买家进入结账页面
  2. 创建支付请求
  1. 处理 Antom 支付页面 URL
    • 商户服务端获取 normalUrl 后,将该 normalUrl 传递给前端,由商户前端跳转至支付页面。 
  1. 获取支付结果
    • 买家完成支付后,商户端通过异步通知或者支付查询接口获取支付结果。 您需要在 createPaymentSession(单笔支付)接口中设置paymentNotifyUrl 参数以接收异步通知,如果支付成功或者支付过期,Antom 会通过 notifyPayment 发送通知给到商户。

集成准备

在您开始集成前,请阅读集成指南接口概述文档,了解服务端接口的集成步骤及调用接口的注意事项,并确保已完成以下预配置:

  • 已获得 client ID。
  • 已完成密钥配置。
  • 已完成异步通知接收地址的配置。
  • 集成服务端 SDK 资源包,并完成接口库安装及请求示例初始化。具体操作请参阅服务端 SDK

集成步骤

按照以下步骤开始集成:

  1. 创建支付请求
  2. 跳转至 Antom 支付页面
  3. 获取支付结果

步骤 1:创建支付请求 服务端

创建支付会话包括以下参数:

字段类型

字段名

是否必需?

描述

基本字段

paymentRequestId

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

商户请求以订单币种收取的支付金额。

paymentRedirectUrl

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

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

paymentMethodType

支付方法选项中包含的支付方法类型。 

订单字段

order.orderAmount

商户端订单金额。

order.referenceOrderId

商户端订单号。

order.goods

货物信息,包括订单中货物的 ID、名称、价格和数量。需注意:

  • 在机票相关的交易场景下,goodsName 的值必须格式化为 “机票-日期-航班号-出发-到达”。 订单含多件商品时,每个产品的信息必须采用此格式,用逗号分隔,同时需同步录入所有商品信息。
  • 在酒店场景下,goodsName 的值必须格式化为 “住宿时间 (20250101-20250102),酒店名称”。订单含多件商品时,每个产品的信息必须采用此格式,用逗号分隔,同时需同步录入所有商品信息。
  • orderAmount paymentAmount 的值等于所有 goods 的金额之和。 当一个订单中涉及多个产品时,请参考以下公式: goodsUnitAmount No.1 * goodsQuantity No.1 +goodsUnitAmount No.2 * goodsQuantity No.2 =orderAmount /paymentAmount。
  • goods 字段中的 referenceGoodsIdgoodsNamegoodsUnitAmount goodsQuantity 四个字段为必填项。
order.buyer

包括买家的 ID、姓名、电话号码和电子邮件的买家信息。传入该参数时,必须同时传入 referenceBuyerId buyerName.fullName

order.transit

行程信息,包括出行方式、行程段和乘客信息。在机票相关的交易场景下,此字段为必填项。若 transit 信息为必填项,则 transitType legs.departureTimelegs.departureAddress.citylegs.arrivalAddress.city legs.carrierNo 字段为必传。

上述参数是创建支付会话的基本参数。 有关特定支付方式的完整和附加要求,请参阅 createPaymentSession(单笔支付)接口。

以下代码为调用 createPaymentSession(单笔支付)接口以发起支付请求的示例:

copy
public static void createPaymentSession() {
    AlipayPaymentSessionRequest alipayPaymentSessionRequest = new AlipayPaymentSessionRequest();
    alipayPaymentSessionRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
    // 设置 amount
    Amount amount = Amount.builder().currency("SGD").value("6000").build();
    alipayPaymentSessionRequest.setPaymentAmount(amount);

    // 替换为您的 paymentRequestId
    String paymentRequestId = UUID.randomUUID().toString();
    alipayPaymentSessionRequest.setPaymentRequestId(paymentRequestId);

    // 替换为您的 orderId
    String orderId = UUID.randomUUID().toString();

    // 设置 buyer 信息
    Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();

    // 设置 goods 信息
    Goods goods = Goods.builder().goodsBrand("Antom Brand").goodsCategory("outdoor goods/bag").goodsName("Classic Woman Bag").goodsQuantity("1")
    .goodsSkuName("Black").goodsImageUrl("https://mdn.alipayobjects.com/portal_pdqp4x/afts/file/A*H8M9RrxlArAAAAAAAAAAAAAAAQAAAQ")
    .goodsUnitAmount(amount).goodsUrl("https://yourGoodsUrl").referenceGoodsId("yourGoodsId").build();

    // 设置 order 信息
    Order order = Order.builder().referenceOrderId(orderId)
    .orderDescription("antom ckp testing order").orderAmount(amount).buyer(buyer).goods(Stream.of(goods).collect(Collectors.toList())).build();
    alipayPaymentSessionRequest.setOrder(order);

    // 替换为您的 notifyUrl
    // 或在此处配置您的通知 url: <a href="https://dashboard.antom.com/global-payments/developers/iNotify">Notification URL</a>
    alipayPaymentSessionRequest.setPaymentNotifyUrl("http://www.yourNotifyUrl.com/payment/receiveNotify");
    // 替换为您的 redirectUrl
    alipayPaymentSessionRequest.setPaymentRedirectUrl(
        "http://localhost:8080/index.html?paymentRequestId=" + paymentRequestId);

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

以下代码展示了不同支付场景下请求报文的示例:

普通支付

copy
{
    "order": {
        "transit": {
            "transitType": "FLIGHT",
            "legs": [
                {
                    "departureTime": "2024-11-27T12:01:01+08:00",
                   "departureAddress": {
                        "city": "SZX" //需要符合IATA三位码
                    },
                    "arrivalAddress": {
                        "city": "HKG" //需要符合IATA三位码
                    },
                    "carrierNo": "111"
                }
            ]
        },
        "orderAmount": {
            "currency": "CNY",
            "value": "1000"
        },
        "orderDescription": "Cappuccino #grande (Mika's coffee shop)",
        "referenceOrderId": "ORDER_2022111414171****",
        "buyer": {
            "referenceBuyerId": "test1234****",
            "buyerEmail": "alipay@alipay.com",
            "buyerName": {
                "fullName": "Dehua Skr Liu"
            }
        },
      "goods": [
        {
            "referenceGoodsId": "GoodsId-32078",
            "goodsUnitAmount": {
                "currency": "CNY",
                "value": "1000"
            },
            "goodsQuantity": "1",
            "goodsName": "机票-日期-航班号-出发-到达"
        }
    ],
    },
    "env": {
        "terminalType": "WEB"  
    },
    "paymentAmount": {
        "currency": "CNY",
        "value": "1000"
    },
    "paymentMethod": {
        "paymentMethodType": "ANTOM_BIZ_ACCOUNT"
        },
      "settlementStrategy": {
            "settlementCurrency": "CNY"
        },
        "paymentNotifyUrl": "https://www.alipay.com/notify",
        "paymentRedirectUrl": "https://www.alipay.com",
        "paymentRequestId": "PAY_2022111414171****",
        "productCode": "CASHIER_PAYMENT",
        "productScene": "CHECKOUT_PAYMENT"
    }

以下是包含相关参数的示例响应代码:

  • paymentSessionExpiryTime:支付会话的过期时间。
  • normalUrl: 支付页面的跳转链接。
copy
{
    "normalUrl": "https://ac.alipay.com/page/antom-web-checkout/src/checkout/paymentPage/index.html?sessionData=6WaYoQqC8UG+OrtKL20nf1apMnYKw4+zAbyy2Kv0AEIx0PyZhBU5y0Y/PmBfg/zK4Bu8/XdfWTgWXowmSd+M1A==&&SG&&188&&eyJwYXltZW50U2Vzc2lvbkNvbmZpZyI6eyJwYXltZW50TWV0aG9kQ2F0ZWdvcnlUeXBlIjoiQUxMIiwicHJvZHVjdFNjZW5lIjoiQ0hFQ0tPVVRfUEFZTUVOVCIsInByb2R1Y3RTY2VuZVZlcnNpb24iOiIxLjAifX0=",
    "paymentSessionData": "6WaYoQqC8UG+OrtKL20nf1apMnYKw4+zAbyy2Kv0AEIx0PyZhBU5y0Y/PmBfg/zK4Bu8/XdfWTgWXowmSd+M1A==&&SG&&188&&eyJwYXltZW50U2Vzc2lvbkNvbmZpZyI6eyJwYXltZW50TWV0aG9kQ2F0ZWdvcnlUeXBlIjoiQUxMIiwicHJvZHVjdFNjZW5lIjoiQ0hFQ0tPVVRfUEFZTUVOVCIsInByb2R1Y3RTY2VuZVZlcnNpb24iOiIxLjAifX0=",
    "paymentSessionExpiryTime": "2024-04-19T17:10:09+08:00",
    "paymentSessionId": "6WaYoQqC8UG+OrtKL20nf1apMnYKw4+zAbyy2Kv0AEKxd/W4uVKjKYL6QfTqUS8s",
    "result": {
        "resultCode": "SUCCESS",
        "resultMessage": "success.",
        "resultStatus": "S"
    }
}

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

result.resultStatus

信息

后续操作

S

请求成功。

成功获取到 normalUrl,并返回给商户前端。

U

未知问题。

更换 paymentRequestId 重新调用接口以解决问题。如果问题未解决,请联系 Antom 技术支持。

F

支付会话创建失败。

检查并验证当前接口所需的请求字段(包括头部字段和正文字段)是否正确传递并有效。

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

步骤 2:处理 Antom 支付页面 URL 客户端

商户服务端获取 normalUrl 后,将该 normalUrl 传递给前端,由商户前端跳转至支付页面。 

获取 normalUrl 后,您需要在浏览器将页面重定向至 Antom 支付页面,或在新标签页打开。

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

下图为跳转的 Antom 支付页面的渲染页面:

image.png

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

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

接收异步通知

您可以选择以下两种方法中的一种来设置接受通知的 webhook URL:

  • 在每笔请求中设置:您可以通过 createPaymentSession(单笔支付)接口中的 paymentNotifyUrl 字段传入该笔订单的接收异步通知 URL,适用于每个订单有单独通知 URL 的商户。
  • 不在请求中设置:您则可以 Antom Dashboard开发者 > 通知地址 中设置 webhook URL,适用于对于所有订单统一一个通知 URL 的商户。具体操作请参见通知地址

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

copy
{
  "actualPaymentAmount": {
    "currency": "HKD",
    "value": "1000"
  },
  "notifyType": "PAYMENT_RESULT",
  "paymentAmount": {
    "currency": "HKD",
    "value": "1000"
  },
  "paymentCreateTime": "2024-05-27T02:27:13-07:00",
  "paymentId": "20240527194010800100188420225534863",
  "paymentRequestId": "101520240527410134510924020002",
  "paymentResultInfo": {},
  "paymentTime": "2024-05-27T02:27:27-07:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

您可能会收到请求报文中 result.resultStatus 字段的不同值,请您根据指引进行处理:

result.resultStatus

信息

后续操作

S

支付成功。

存储 paymentId 用于后续的取消交易和退款。

F

支付失败。

关闭当前交易或重新更换 paymentRequestId 后再次下单。

当您收到 Antom 的异步通知,需要您在返回中按照示例代码格式返回响应,但无需做加签处理。您需要对 Antom 发送的支付通知进行验签,关于如何验证通知的签名并做出响应,请参阅处理通知

无论订单是否支付成功,每个通知请求均需按以下固定格式响应。否则,Antom 会重新发送异步通知。

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

查询结果

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

参数名称

是否必需?

描述

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": "101520240527410134510924020002"
}

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

copy
{
  "actualPaymentAmount": {
    "currency": "HKD",
    "value": "1000"
  },
  "paymentAmount": {
    "currency": "HKD",
    "value": "1000"
  },
  "paymentId": "20240527194010800100188420225534863",
  "paymentMethodType": "ANTOM_BIZ_ACCOUNT",
  "paymentRedirectUrl": "https://xxx.com/bgt_launch_app_callback.html?browser_callback_new=1&chTransId=SO000124052709420662253642020002",
  "paymentRequestId": "101520240527410134510924020002",
  "paymentResultCode": "SUCCESS",
  "paymentResultMessage": "success",
  "paymentStatus": "SUCCESS",
  "paymentTime": "2024-05-27T02:27:27-07:00",
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "success.",
    "resultStatus": "S"
  }
}

通过 result 字段返回接口调用结果。订单状态需要根据 paymentStatus 来判断:

  • SUCCESS:支付成功。
  • FAIL:支付失败,关闭订单或更换 paymentRequestId 再次发起支付。
  • PROCESSING:支付进行中,继续查询或关单时间后再查询。

支付后

取消交易

下单后您可以在一定时间窗口期内通过使用 cancel 接口主动关闭某笔交易,支付成功后可在 T+1日的 00:15(UTC+8:00)之前取消(T 为交易日)。具体操作参见取消交易

退款

在支付成功后,您可以通过调用 refund 接口对成功支付的交易发起退款。具体操作参见退款

对账

交易完成后,您可以使用 Antom 提供的财务报告进行对账。请参阅对账了解关于如何对账和 Antom 结算规则的更多信息。

最佳实践

Antom 为您提供支付结果展示、支付失败重试、接口超时时间设置等最佳实践方案,请参阅最佳实践了解详情。