争议

当某笔交易发生争议时,APO 为您提供统一的争议通知。APO 仅负责发送通知,具体的争议处理流程请咨询相关收单机构以获取详细信息。通常收单机构会有如下步骤:

  • 争议通知
  • 处理争议
  • 争议判责结果通知

注意:目前我们支持 Antom 和 PayPal,会陆续增加其他的收单机构。

接收争议通知

当买家发起争议时,APO 通过 争议通知 接口发送争议通知(NoD),并告知争议的相关信息。

步骤 1:设置接收通知的 webhook URL服务端

在接收异步通知之前,您需要设置一个通知地址。您可以在 APO Dashboard 开发者 > 通知地址 中设置 webhook URL

通知中包含的关键参数如下(详细信息请参阅 争议通知 接口): 

参数

描述

disputeAmount

存在争议的交易金额。

disputeId

APO 为识别争议而分配的专属 ID。

disputeNotificationType

争议通知的类型,请您根据返回的对应值进行处理。有效值包括:

  • DISPUTE_CREATED:表示发生了争议,您需要介入处理。Antom 和 PayPal 会返回。
  • DISPUTE_JUDGED:表示争议已被裁决。Antom 和 PayPal 会返回。

defenseDueTime

争议抗辩截止时间,超过此时间后您无法再为争议抗辩

disputeSource

负责处理争议的银行卡组织。

disputeNotificationType 的值为 DISPUTE_CREATEDDISPUTE_JUDGED 时返回此参数。

paymentId

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

paymentRequestId

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

表 1. 争议通知的关键参数

以下代码展示了争议通知的请求示例:

copy
{
  "acquirerInfo": {
    "acquirerMerchantId": "WH4P43AMLR9W8",
    "acquirerName": "PAYPAL",
    "acquirerReasonCode": "DUPLICATE_TRANSACTION",
    "acquirerReasonDescription": "The transaction was a duplicate",
    "acquirerTransactionId": "PP-R-VAD-568996120"
  },
  "defendable": true,
  "disputeAmount": {
    "currency": "USD",
    "value": "999"
  },
  "disputeId": "2025033129013101081705064668",
  "disputeNotificationType": "DISPUTE_CREATED",
  "disputeReasonCode": "2206",
  "disputeReasonMsg": "Duplicate Processing/Paid by Other Means",
  "disputeSource": "PAYPAL",
  "disputeTime": "2025-03-30T20:26:00-07:00",
  "disputeType": "CHARGEBACK",
  "paymentId": "20250331194010890100111070257852045",
  "paymentRequestId": "G153202503311054525768"
}

步骤 2:异步通知验签服务端

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

您需要对 APO 发送的争议通知进行验签。

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

        // retrieve the required parameters from http request.
        String requestUri = request.getRequestURI();
        String requestMethod = request.getMethod();

        // retrieve the required parameters from request header.
        String requestTime = request.getHeader("request-time");
        String clientId = request.getHeader("client-id");
        String signature = request.getHeader("signature");

        Result result;
        AlipayResponse response = new AlipayResponse();

        try {
            // verify the signature of notification
            boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
            if (!verifyResult) {
                throw new RuntimeException("Invalid notify signature");
            }

            // deserialize the notification body
            
            // update the order status with notify result

            // respond the server that the notification is received
            result = new Result("SUCCESS", "success", ResultStatusType.S);

        } catch (Exception e) {
            String errorMsg = e.getMessage();
            // handle error condition
            result = new Result("ERROR", errorMsg, ResultStatusType.F);
        }
        response.setResult(result);
        return ResponseEntity.ok().body(response);
    }

}

您无需对响应通知结果做加签处理,但是对于每个通知请求均需按以下固定格式响应,与订单支付成功与否无关。

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

注意

  • 您需记录从 APO 接收到的已处理通知,并正确处理幂等性,以避免多次处理同一请求。
  • 您需记录争议的关键信息,如 disputeIdpaymentId 和 paymentRequestId。在 defenseDueTime 规定的时限内处理争议。

处理争议

处理争议时,您可能会遇到以下四种情况: 

  • 争议撤销:买家撤销争议,APO 会给您发送异步通知,告知撤销结果。(注意:目前仅 Antom 支持。)
  • 接受争议可通过各机构门户进行处理。
  • 拒付抗辩若您不接受争议,可通过各机构门户进行抗辩处理。
  • 未及时处理争议:商户需在各机构规定的截止时间前完成争议处理,若未及时处理,APO 将根据收单机构的通知规则决定是否转发异步通知。注意:目前仅 Antom 支持。)

接收争议判责结果

该笔争议的责任判定完成后,您会收到 APO 发送的判责结果通知,此时通知中的 disputeNotificationType 字段值为 DISPUTE_JUDGED 。判责结果由 disputeJudgedResult 字段的值进行传递:

  • ACCEPT_BY_CUSTOMER:买家责任。
  • ACCEPT_BY_MERCHANT:商户责任。您需要承担争议损失。

当买家发起争议时,您可以通过接收 APO 争议通知 接口发送的争议通知来获取争议信息。