--- title: 预授权撤销 permalink: /notes/zh/integrate/modify/Void/ createTime: '2025/03/07 16:02:02' description: '说明如何撤销已授权但未请款的交易,释放预留资金,并通过通知或查询确认最终结果。' --- 对于支持单独 Capture(请款)的支付方式(如国际信用卡支付),支付过程通常分为两个步骤: - [Authorization](/notes/zh/technicalterm/Authorization/):验证买家支付信息并预留资金。 - [Capture](/notes/zh/technicalterm/Capture/):将预留资金正式请款并结算。 [预授权撤销](/notes/zh/technicalterm/Void/) 用于在 Authorization 成功但尚未 Capture 时取消交易,释放已预留资金,确保资金不会从买家账户中扣除。如果原交易已经完成 Capture,则不能再使用预授权撤销,应改为发起 [退款](/notes/zh/integrate/modify/Refund/)。 ## 撤销流程 ```mermaid sequenceDiagram participant Server as 🏪 商户服务端 participant PP as 🔄 PingPongCheckout Server->>PP: 1. 调用预授权撤销 PP-->>Server: 2. 返回撤销结果(SUCCESS / FAILED / PROCESSING) opt [status = PROCESSING] Server->>PP: 3. 调用预授权撤销查询获取结果 PP-->>Server: 4. 返回撤销状态 end PP-->>Server: 5. 推送预授权撤销通知(成功 / 失败) ``` 流程说明: 1. 商户服务端调用 [预授权撤销](/notes/zh/checkout/api/modifications/void/) 发起撤销。 2. 同步响应可能直接返回 `SUCCESS`、`FAILED` 或 `PROCESSING`。 3. 如果同步响应为 `PROCESSING`,商户可调用 [预授权撤销查询](/notes/zh/checkout/api/getVoid/) 主动确认撤销状态。 4. PingPongCheckout 也会通过 [预授权撤销异步通知](/notes/zh/notify/status/voidNotify/) 返回最终撤销结果。 ## 撤销状态机 预授权撤销只能在原支付单处于 `AUTH_SUCCESS` 且尚未完成 Capture 时发起。撤销成功后,已预留资金会被释放;撤销失败时,请以撤销对象的 `status` 记录失败原因,并结合业务场景决定是否重试或继续等待原授权交易处理。 ```mermaid flowchart LR ORIGINAL[原支付单状态: AUTH_SUCCESS] -.-> START((发起预授权撤销)) START --> PROCESSING[PROCESSING] PROCESSING -->|撤销成功| SUCCESS[SUCCESS] PROCESSING -.->|撤销失败| FAILED[FAILED] SUCCESS --> END((END)) FAILED --> END ``` ## 集成步骤 请按以下步骤完成集成: 1. [发起撤销请求](#步骤-1-发起撤销请求) 2. [获取撤销结果](#步骤-2-获取撤销结果) ### 步骤 1:发起撤销请求 调用 [预授权撤销](/notes/zh/checkout/api/modifications/void/) API 发起撤销。请根据原交易流水号和本次撤销流水号组装请求;如果希望在 `PROCESSING` 场景下异步接收最终结果,请正确配置 `notificationUrl`。 预授权撤销请求关键字段: | 字段 | 必填 | 说明 | |:---|:---:|:---| | `bizContent.merchantTransactionId` | 是 | 商户网站的原交易流水号 | | `bizContent.notificationUrl` | 是 | 用于接收撤销结果的异步通知地址 | | `bizContent.merchantVoidId` | 是 | 商户侧预授权撤销流水号,全局唯一 | | `bizContent.amount` | 是 | 撤销金额,应与原授权金额一致 | | `bizContent.currency` | 是 | 交易币种 | 有关完整参数的更多信息,请参阅[预授权撤销接口](/notes/zh/checkout/api/modifications/void/)。 预授权撤销请求示例: ```json { "accId": "2023042011040310224447", "clientId": "2023042011040310224", "signType": "SHA256", "sign": "{{Sign}}", "version": "1.0", "bizContent": { "merchantVoidId": "VOID_202606260001", "merchantTransactionId": "AUTH_202606260001", "amount": 100, "currency": "USD", "notificationUrl": "https://www.example.com/void/notify" } } ``` ::: warning 注意 - 仅对已授权未捕获的交易发起撤销;如果无法确认原交易当前是否已 Capture,可先调用 [交易查询](/notes/zh/checkout/api/getOne/) 确认原交易状态。 - 当前暂不支持部分预授权撤销,撤销金额必须等于原授权金额;并非所有支付方式都支持单独 Authorization / Capture / 预授权撤销,具体能力请以[支付方式](/notes/zh/paymentMethods/overview/)或目标支付方式文档为准。 - [预授权撤销](/notes/zh/checkout/api/modifications/void/) API 基于 `merchantVoidId` 做幂等控制:同一笔撤销请求重复提交时请保持 `merchantVoidId` 不变;如果上一笔撤销请求失败且需要重新发起,请使用新的 `merchantVoidId`。 ::: 预授权撤销响应关键字段: | 字段 | 说明 | |:---|:---| | `bizContent.merchantVoidId` | 商户侧预授权撤销流水号 | | `bizContent.merchantTransactionId` | 商户网站的原交易流水号 | | `bizContent.transactionId` | PingPong 原交易流水号 | | `bizContent.status` | 撤销状态,可能为 `SUCCESS`、`FAILED` 或 `PROCESSING` | | `bizContent.voidEndingTime` | 撤销到达终态时间;如果同步已返回终态,可用于记录完成时间 | 预授权撤销响应示例: ```json { "accId": "2023042011040310224447", "bizContent": "{\"amount\":\"100.000000\",\"merchantVoidId\":\"VOID_202606260001\",\"transactionId\":\"2024050750046462\",\"voidEndingTime\":\"1715049613278\",\"voidTime\":\"1715049612000\",\"merchantTransactionId\":\"AUTH_202606260001\",\"currency\":\"USD\",\"status\":\"SUCCESS\"}", "clientId": "2023042011040310224", "code": "000000", "description": "Transaction succeeded", "sign": "0474235D375F8A81E9FD17E278ED3F11039F8462F64650A1F0D613FADAE5B04F", "signType": "SHA256" } ``` 调用预授权撤销接口后,同步响应中的 `status` 可能为以下值: - `SUCCESS`:撤销成功,可直接更新撤销状态 - `FAILED`:撤销失败,应结合错误原因判断是否允许重试 - `PROCESSING`:撤销处理中,需继续等待撤销通知或主动查询 ### 步骤 2:获取撤销结果 预授权撤销发起后,商户应通过以下方式确认最终结果: 1. 接收 [预授权撤销异步通知](/notes/zh/notify/status/voidNotify/) 2. 如异步通知延迟、未达、网络异常或需要再次核验结果,可主动调用 [预授权撤销查询](/notes/zh/checkout/api/getVoid/) 如果您通过异步通知接收结果,可参考以下通知示例与处理方式。 预授权撤销通知示例: ```json { "clientId": "2023042011040310224", "code": "000000", "bizContent": "{\"amount\":\"100.000000\",\"merchantVoidId\":\"VOID_202606260001\",\"transactionId\":\"2024050750046462\",\"notifyType\":\"VOID\",\"voidEndingTime\":\"1715049613880\",\"voidTime\":\"1715049612000\",\"merchantTransactionId\":\"AUTH_202606260001\",\"currency\":\"USD\",\"status\":\"SUCCESS\"}", "sign": "10FF6C109F36A5693BDE922F8FB5889348E43D64CAF88514A6D14E82CF615E4B", "accId": "2023042011040310224447", "description": "Transaction succeeded", "signType": "SHA256" } ``` 在预授权撤销异步通知场景下,`status` 会返回最终撤销结果,即 `SUCCESS` 或 `FAILED`。收到 `SUCCESS` 时可将撤销更新为成功;收到 `FAILED` 时可将撤销更新为失败。 收到通知后,商户服务端建议按以下方式处理: - 先返回 HTTP `2xx` 确认已接收,避免触发重复通知 - 再根据通知中的 `status` 更新撤销结果,并执行对应业务处理 通知响应示例: ```http HTTP/1.1 200 OK Content-Type: text/plain; charset=UTF-8 Content-Length: 2 OK ``` 如果异步通知延迟、未达,或商户侧因网络异常、回调处理失败、结果核验等原因暂时无法确认最终状态,可主动调用 [预授权撤销查询](/notes/zh/checkout/api/getVoid/) 获取撤销结果。 预授权撤销查询请求关键字段: | 字段 | 必填 | 说明 | |:---|:---:|:---| | `bizContent.merchantVoidId` | 是 | 商户侧预授权撤销流水号 | | `bizContent.merchantTransactionId` | 是 | 商户网站的原交易流水号 | 有关完整参数的更多信息,请参阅[预授权撤销查询接口](/notes/zh/checkout/api/getVoid/)。 预授权撤销查询请求示例: ```json { "accId": "2018092714313010016291", "clientId": "2018092714313010016", "signType": "SHA256", "sign": "{{Sign}}", "version": "1.0", "bizContent": { "merchantVoidId": "VOID_202606260001", "merchantTransactionId": "AUTH_202606260001" } } ``` 预授权撤销查询响应示例: ```json { "accId": "2023060217493010231446", "bizContent": "{\"amount\":\"100.000000\",\"resultCode\":\"000000\",\"transactionId\":\"2024050750046462\",\"voidTime\":\"1715049612000\",\"voidEndingTime\":\"1715049613278\",\"merchantTransactionId\":\"AUTH_202606260001\",\"currency\":\"USD\",\"resultMessage\":\"Transaction succeeded\",\"status\":\"SUCCESS\"}", "clientId": "2023060217493010231", "code": "001000", "description": "Successful request", "sign": "1EDDB8216409E900AD29095174BEC90710CDD5D2D4B72D84DBD4DF8F2C3E169B", "signType": "SHA256" } ``` 预授权撤销查询响应关键字段: | 字段 | 说明 | |:---|:---| | `bizContent.merchantTransactionId` | 商户订单号,用于关联原授权交易 | | `bizContent.transactionId` | PingPong 交易流水号 | | `bizContent.status` | 撤销状态,可能为 `SUCCESS`、`FAILED` 或 `PROCESSING` | | `bizContent.voidEndingTime` | 撤销到达终态时间,可用于记录最终完成时间 | 预授权撤销查询响应中的 `status` 可能返回 `SUCCESS`、`FAILED` 或 `PROCESSING`。如果查询结果为 `PROCESSING`,说明撤销结果尚未最终确认,建议稍后重试查询,或继续等待撤销通知。 ::: note 提示 预授权撤销查询请在同步响应返回之后调用;若查询过早,可能会出现查询异常。 :::