Ethoca

Ethoca API 对接指引(修订版)

更新日期:2026-07-15
适用对象:客户技术团队、支付/风控/售后系统负责人
PSP 辅助说明:Stripe、Checkout.com、CyberSource、Worldpay、Adyen
预警来源:TrustDecision Ethoca Dispute Notification API

文档边界:第 1~3 节定义 TrustDecision Ethoca 对接契约;第 4~7 节为交易匹配和 PSP 实施建议,不构成 TrustDecision 或 PSP 的完整 API 规范。实施前应以客户实际开通的环境、API 版本、账号权限和服务端联调结果为准。

1. 文档目标

本文档说明客户如何对接 TrustDecision Ethoca API,包括接收 Ethoca 拒付预警、理解预警字段、调用更新接口反馈处置结果。文档中补充的 PSP API 字段和退款接口说明,仅用于辅助客户在本地系统中完成交易匹配、退款确认和结果反馈,不作为完整 PSP 接入规范。

客户通常需要完成以下对接:

  1. 接收 Ethoca 预警:客户提供 HTTPS Webhook,接收 TrustDecision 推送的 Confirmed Fraud 或 Customer Dispute 预警。
  2. 反馈处置结果:退款、停止结算、未找到交易或转人工处理后,调用 Ethoca 更新接口反馈 outcome、refunded、amountStopped、actionTimestamp 等结果。
  3. 可选同步 PSP 交易:如客户希望自动匹配交易或自动触发退款,可参考本文档中的 PSP 辅助字段,从 Stripe、Checkout.com、CyberSource、Worldpay 或 Adyen 拉取交易/报表/事件,沉淀到统一交易库。

核心要求:

  • 预警最终处置建议在 24 小时内完成并反馈。第一个最终状态会被发送给发卡方,因此在资金动作尚未确认时不要提前提交最终状态。in_progress、shipper_contacted 仅适用于 Confirmed Fraud,且不应停留超过 24 小时。
  • “匹配成功”不等于“允许自动退款”。自动退款必须同时通过客户授权、唯一交易匹配、金额、币种、可退余额、交易状态、幂等和风险阈值校验;否则进入人工复核。
  • PSP 退款成功不等于 Ethoca 自动知晓。退款后必须调用 TrustDecision 的 Ethoca 更新接口反馈结果。
  • 仅在 PSP 层真实退款或真实停止结算/履约后,才能反馈 refunded 或 not settled,不能只更新 Ethoca 状态而不执行资金动作。

2. 端到端集成流程

推荐客户按以下流程建设:

  1. 客户在 TrustDecision 门户配置 Ethoca 预警接收 URL。
  2. TrustDecision 将 Ethoca 预警以 POST JSON 推送给客户。
  3. 客户先校验签名、时间戳和请求格式,再按 ethocaId 幂等落库。
  4. 接收成功后返回 HTTP 200 和 { "code": 200, "message": "" }。该响应只表示已接收,不代表已完成退款;其他响应可能触发 TrustDecision 按配置重试。
  5. 系统按 PSP 账号、商户号、交易日期、金额、币种、卡尾号、ARN、授权码等字段查找原交易。cardBin 只能与 cardLast4 同时使用,不得单独参与匹配。
  6. 唯一候选命中后,系统继续执行客户审批和退款前置校验;仅在满足客户自动退款策略时才调用 PSP Refund API。
  7. 系统监听 PSP webhook 或报表确认退款状态。
  8. 系统调用 TrustDecision Ethoca 更新接口反馈最终结果。
  9. 所有预警、匹配候选、退款请求、PSP 响应、Ethoca 更新响应均落库,便于争议追溯。

3. Ethoca 预警接入

3.1 预警推送接口

客户需要提供一个 HTTPS RESTful 接口,用于接收 TrustDecision 推送的 Ethoca 预警。一次推送可以包含一个或多个预警。

3.1.1 在 TrustDecision 门户配置订阅服务

客户开发接收接口后,需要先在 TrustDecision 门户完成订阅配置,TrustDecision 才会把 Ethoca 预警推送到客户指定地址。

操作路径和配置项如下:

  1. 进入 TrustDecision 门户,打开开发者相关页面,选择“订阅设置”。
  2. 点击“添加订阅服务”,在订阅服务中选择已分配给客户的 Ethoca 预警服务。
  3. 填写“推送地址”,该地址必须是客户可公网访问的 HTTPS URL,也就是本文档中的预警接收接口。
  4. 按需填写“告警邮箱”。当推送失败或配置异常时,客户可通过该邮箱接收通知。
  5. 如客户接口要求固定 Header,可在“请求头”处添加。Header 鉴权属于客户自定义校验,不替代 TrustDecision 推送签名。
  6. 保存后,列表中会展示推送地址、Access Key、Access Secret 和操作入口。客户服务端需要使用 Access Secret 校验 TrustDecision 推送请求签名。

Ethoca 预警订阅服务配置示意



推送请求概要:

项目要求
MethodPOST
Content-Typeapplication/json
Character SetUTF-8
鉴权参数timestamp、partner_code、access_key、sign
签名HmacSHA1(partner_code + timestamp + access_key, access_secret)
成功响应HTTP 200,响应体 { "code": 200, "message": "" }

鉴权参数应放在 URL query 中,timestamp 使用毫秒时间戳。

推送外层结构:

请求体根节点为 JSON 数组,数组内每个元素代表一种预警类型及其预警明细。

字段类型是否必传说明
typeString是预警类型,取值为 Confirmed Fraud 或 Customer Dispute
parametersArray是预警详情列表;同一次推送中可包含一个或多个预警对象

Confirmed Fraud 和 Customer Dispute 的 parameters 字段并不完全一致。客户解析时应先根据外层 type 判断预警类型,再按对应字段表处理。除外层 type、parameters 以及已由联调确认的字段外,客户端应允许明细字段缺失或为空,不应因单个非关键字段缺失而拒绝整批预警。

3.1.2 Confirmed Fraud 推送样例

Confirmed Fraud 是已确认欺诈预警,主要用于提示客户尽快停止履约、取消订单、退款或标记无法处理。该类型通常不包含拒付原因、拒付金额等 chargeback 字段。

[
  {
    "type": "Confirmed Fraud",
    "parameters": [
      {
        "ethocaId": "1E7543HNEG001VOURNV96Q857",
        "alertTimestamp": 1720592944328,
        "age": 13,
        "issuer": "TestIssuer",
        "cardNumber": "888888******2108",
        "cardBin": "888888",
        "cardLast4": "2108",
        "arn": "435HJ7674346895HJ767434",
        "authCode": "24545564",
        "transactionTimestamp": "2024-06-10T16:13:04.328Z",
        "merchantDescriptor": "TONGDUNTEST",
        "partnerMerchantId": "TRUST_DEC_1",
        "ethocaMerchantId": 9088,
        "mcc": "3000",
        "amount": 37.55,
        "currency": "USD",
        "amountUsd": 37.55,
        "transactionType": "swiped",
        "initiatedBy": "cardholder",
        "liability": "no",
        "source": "IssuingOrganisation",
        "merchantName": "Tongdun Sub Merchant"
      }
    ]
  }
]

3.1.3 Customer Dispute 推送样例

Customer Dispute 是客户争议预警。除交易基础字段外,该类型会返回拒付/争议相关字段,例如拒付原因、拒付金额、拒付币种,客户可用于判断是全额退款、部分退款还是转人工争议。

[
  {
    "type": "Customer Dispute",
    "parameters": [
      {
        "ethocaId": "1D7543HNEG001VOURNV96Q857",
        "alertTimestamp": "2024-06-10T16:13:04.328Z",
        "age": 19,
        "issuer": "MerchantBank",
        "transactionTimestamp": "2023-03-10T16:13:04.328Z",
        "amount": 121.10,
        "currency": "CAD",
        "cardBin": "555456",
        "cardLast4": "1240",
        "cardNumber": "555456******1240",
        "arn": "435HJ7674346895HJ767434",
        "authCode": "21HJ767",
        "merchantDescriptor": "TONGDUNTEST",
        "partnerMerchantId": "demo_prod001",
        "ethocaMerchantId": 3001,
        "mcc": "3000",
        "amountUsd": 88.51,
        "transactionType": "swiped",
        "initiatedBy": "cardholder",
        "liability": "no",
        "source": "IssuingOrganisation",
        "merchantName": "Tongdun Sub Merchant",
        "transactionId": "875HJ767434121",
        "chargebackReasonCode": "10.1",
        "chargebackReason": "EMV Liability Shift Counterfeit Fraud",
        "chargebackAmount": 121.10,
        "chargebackCurrency": "CAD"
      }
    ]
  }
]

3.2 预警类型

Ethoca type说明推荐动作
Confirmed Fraud发卡行或持卡人确认的欺诈预警尽快停止履约/服务,匹配原交易并退款或停止结算
Customer Dispute客户争议预警,通常带拒付原因、拒付金额、拒付币种匹配原交易,按客户策略退款、已退款确认或进入争议处理

3.3 关键预警字段

两类预警分别建模。不要先读取“公共字段”再拼接“差异字段”;客户应根据外层 type,直接使用对应的完整字段表解析。不同发卡行可能不提供部分明细字段,因此除已联调确认的必传字段外,客户端应允许字段缺失或为空,并保存完整原始报文。

3.3.1 Confirmed Fraud 完整字段

外层 type 固定为 Confirmed Fraud。该类型以匹配原交易、停止履约和阻止损失为主,通常不返回拒付原因、拒付金额等 Customer Dispute 字段。

字段类型/约束说明处理要求
ethocaIdString,最大 25 字符Ethoca 预警唯一 ID必须保存并作为幂等键
alertTimestampISO 8601 字符串或毫秒时间戳预警创建时间原始字段表与样例类型不一致;客户端应兼容两种格式,最终类型须联调确认
ageNumeric交易时间与预警时间的小时差允许为空
issuerString,最大 100 字符发卡行名称允许为空
cardNumberString完整或掩码卡号,取决于发卡行按敏感数据要求存储;不要假设总能取得完整卡号
cardBinString卡号前 6 位允许为空;不得单独参与匹配,使用时必须同时命中 cardLast4
cardLast4String,4 位卡号后 4 位允许为空;可与授权码、交易时间和交易金额组合匹配,不得单独确认交易
arnString,最大 64 字符Acquirer Reference Number已结算交易的强匹配字段;允许为空
authCodeString,最大 8 字符授权码注意字段名大小写;允许为空
transactionTimestampISO 8601 UTC原交易授权时间与 PSP 交易时间的允许偏差为 ±72 小时
merchantDescriptorString,最大 50 字符账单描述符商户路由辅助
partnerMerchantIdString,最大 50 字符合作方平台商户 ID商户路由辅助
ethocaMerchantIdNumber/String,以实际报文为准Ethoca 商户 ID建议原样保存,类型须联调确认
merchantNameString,最大 60 字符Ethoca 商户/子商户名称允许为空
mccString,最大 4 字符商户类别码允许为空
amountDecimal原交易金额必须与 currency 一起使用;同币种或跨币种换算后允许偏差均为 ±5%
currencyString,ISO 4217 三位代码原交易币种不得默认使用 USD;币种不同时按确认的汇率源换算后再比较
amountUsdDecimal折算美元金额仅用于分析,不替代原币金额
transactionTypeString 枚举keyed / swiped / e-commerce / unknown未知值应兼容存储
initiatedByString 枚举issuer / cardholder / not_available未知值应兼容存储
liabilityString 枚举yes / no / not_available仅作责任转移辅助判断
sourceString,最大 50 字符预警来源可能不返回

如果没有匹配到交易,建议按 arn、authCode、cardLast4、金额、币种和交易时间窗口逐级降级匹配。若使用 cardBin,必须同时命中 cardLast4;无法确认唯一交易时必须转人工复核。

3.3.2 Customer Dispute 完整字段

外层 type 固定为 Customer Dispute。除交易识别字段外,该类型还可能包含 transactionId、拒付原因、拒付金额和拒付币种。

字段类型/约束说明处理要求
ethocaIdString,最大 25 字符Ethoca 预警唯一 ID必须保存并作为幂等键
alertTimestampISO 8601 字符串或毫秒时间戳预警创建时间客户端应兼容两种格式,最终类型须联调确认
ageNumeric交易时间与预警时间的小时差允许为空
issuerString,最大 100 字符发卡行名称允许为空
cardNumberString完整或掩码卡号,取决于发卡行按敏感数据要求存储;不要假设总能取得完整卡号
cardBinString卡号前 6 位允许为空;不得单独参与匹配,使用时必须同时命中 cardLast4
cardLast4String,4 位卡号后 4 位允许为空;可与授权码、交易时间和交易金额组合匹配,不得单独确认交易
arnString,最大 64 字符Acquirer Reference Number已结算交易的强匹配字段;允许为空
authCodeString,最大 8 字符授权码注意字段名大小写;允许为空
transactionTimestampISO 8601 UTC原交易授权时间与 PSP 交易时间的允许偏差为 ±72 小时
merchantDescriptorString,最大 50 字符账单描述符商户路由辅助
partnerMerchantIdString,最大 50 字符合作方平台商户 ID商户路由辅助
ethocaMerchantIdNumber/String,以实际报文为准Ethoca 商户 ID建议原样保存,类型须联调确认
merchantNameString,最大 60 字符Ethoca 商户/子商户名称允许为空
mccString,最大 4 字符商户类别码允许为空
amountDecimal原交易金额必须与 currency 一起使用;同币种或跨币种换算后允许偏差均为 ±5%
currencyString,ISO 4217 三位代码原交易币种不得默认使用 USD;币种不同时按确认的汇率源换算后再比较
amountUsdDecimal折算美元金额仅用于分析,不替代原币金额
transactionTypeString 枚举keyed / swiped / e-commerce / unknown未知值应兼容存储
initiatedByString 枚举issuer / cardholder / not_available未知值应兼容存储
liabilityString 枚举yes / no / not_available仅作责任转移辅助判断
sourceString,最大 50 字符预警来源可能不返回
transactionIdString,最大 65 字符Ethoca 返回的卡组织交易标识仅保存用于预警追溯;不得与 PSP transaction ID、network transaction ID、payment ID 或客户 order ID/reference 直接匹配
chargebackReasonCodeString拒付原因代码风控辅助
chargebackReasonString拒付原因说明风控辅助
chargebackAmountDecimal拒付金额不一定等于原交易金额
chargebackCurrencyString,ISO 4217 三位代码拒付币种必须和 chargebackAmount 一起处理

chargebackAmount 不一定等于原交易 amount。自动退款前应同时校验 PSP 可退余额、客户退款策略、原交易金额和预警金额,避免超额退款或重复退款。

3.4 Ethoca 更新接口

退款、停止结算或人工处理完成后,客户需要调用 TrustDecision Ethoca 更新接口反馈结果。单次请求仅允许一个更新事件。

建议客户先看本节的“请求体字段表”,再看后面的枚举说明和样例。重复预警场景下,历史预警 ID 放在请求对象同一层的 historicalEthocaId 字段中。

环境Base URL
Sandboxhttps://sg-s.apitd.net/api/ethoca/alert/update
Productionhttps://sg.apitd.net/api/ethoca/alert/update

请求概要:

项目要求
MethodPOST
Content-Typeapplication/json
鉴权参数URL query 中传 partner_code、partner_key
请求体JSON 数组,但当前每次只放一个对象

3.4.1 请求参数

URL query 参数:

字段类型是否必传说明
partner_codeString是TrustDecision 分配的 Partner Code
partner_keyString是TrustDecision 分配的 Partner Key

请求体字段:

请求体是 JSON 数组;下表字段均放在数组内单个更新对象中。重复预警时,historicalEthocaId 与 ethocaId、matchTransactionResult 平级。

字段类型是否必传说明取值/格式
ethocaIdString是当前需要更新的 Ethoca 预警 ID最大 25 位
outcomeString是预警处置结果严格使用 3.5 中列出的枚举
refundedString是交易是否已退款、未退款或未结算refunded / not refunded / not settled
firstPartyFraudString否一方欺诈判断:持卡人声称未授权,但商户有充分依据认为持卡人知情、默许或从交易中获益yes / no
amountStoppedDecimal否实际阻止或部分退款金额;主要用于 partially_stopped,也可在 other / resolved 的部分退款场景记录大于 0,且小于或等于预警金额
actionTimestampString建议传因预警进行退款、停止结算或其他动作的时间ISO 8601,例如 2024-06-10T18:33:04.328Z
commentsString建议传备注;原始规范标记为 Optional,建议客户端固定传入以保持请求结构稳定最大 250 字符;是否允许中文及 other / Other 时是否强制非空,须联调确认
matchTransactionResultString建议传预警匹配结果严格使用 3.6 中列出的枚举
historicalEthocaIdString条件必传之前已处理的 Ethoca ID当 matchTransactionResult=Duplicate alert 时必传

3.4.2 Duplicate alert 完整请求样例

以下样例表示当前预警 2JFG5ULCLB8OQMWHQ7OAY7G7D 是重复预警,历史上已经处理过 1E7543HNEG001VOURNV96Q857。注意:

  • matchTransactionResult 必须传 Duplicate alert,中间使用空格。
  • historicalEthocaId 放在请求对象同一层,和 ethocaId、outcome、comments 平级。
  • 建议固定传 comments;本例不是 other / Other 场景,所以传空字符串。
curl -X POST "https://sg.apitd.net/api/ethoca/alert/update?partner_code=xxx&partner_key=xxx" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "ethocaId": "2JFG5ULCLB8OQMWHQ7OAY7G7D",
      "outcome": "stopped",
      "refunded": "refunded",
      "firstPartyFraud": "no",
      "amountStopped": 37.55,
      "actionTimestamp": "2024-06-10T18:33:04.328Z",
      "comments": "",
      "matchTransactionResult": "Duplicate alert",
      "historicalEthocaId": "1E7543HNEG001VOURNV96Q857"
    }
  ]'

3.4.3 更新响应参数

JSON 路径类型说明
codeInteger顶层业务状态码;200 只表示请求被服务端处理,不保证更新对象成功
messageString顶层状态信息;异常时返回错误原因
alertUpdateResponsesArray单条预警更新结果列表
alertUpdateResponses[].ethocaIdString本次更新的 Ethoca 预警 ID
alertUpdateResponses[].statusStringsuccess / failed
alertUpdateResponses[].updateEventErrorsArray单条更新失败时的错误列表
alertUpdateResponses[].updateEventErrors[].codeString错误码
alertUpdateResponses[].updateEventErrors[].descriptionString错误描述

客户端必须同时检查 HTTP 状态、顶层 code 和 alertUpdateResponses[].status。即使顶层 code=200,单条更新仍可能是 failed。

成功响应样例:

{
  "code": 200,
  "message": "Success",
  "alertUpdateResponses": [
    {
      "ethocaId": "2JFG5ULCLB8OQMWHQ7OAY7G7D",
      "status": "success"
    }
  ]
}

单条更新失败样例:

{
  "code": 200,
  "message": "Success",
  "alertUpdateResponses": [
    {
      "ethocaId": "2JFG5ULCLB8OQMWHQ7OAY7G7D",
      "status": "failed",
      "updateEventErrors": [
        {
          "code": "6",
          "description": "OutcomeQueueItem outcome should be valid value and not null"
        }
      ]
    }
  ]
}

顶层异常样例:

{
  "code": 9400,
  "message": "System Error"
}

原始文档列出了 200、001、9400、9401、9403 等业务码,但原表存在排版和含义不一致。正式上线前,应由 TrustDecision 提供完整错误码表;客户端不得只对 200 编码,其余未知业务码均应按失败处理并记录完整响应。

3.5 outcome 与 refunded 取值

下表是接口允许的组合,不是推荐值。表外组合可能导致更新失败。

Confirmed Fraud 合法组合:

outcome含义refundednot refundednot settled
stopped已停止订单/服务或退款阻止损失✓✓
partially_stopped只阻止部分金额或部分履约✓✓✓
previously_cancelled交易此前已取消✓✓
missed太晚,已发货或服务已使用✓✓✓
notfound未找到订单✓
account_suspended已暂停账户✓✓✓
in_progress正在处理中,仅为中间态✓✓✓
shipper_contacted已联系物流拦截,仅为中间态✓✓✓
other其他情况✓✓✓

Customer Dispute 合法组合:

outcome含义refundednot refundednot settled
resolved已与客户解决,预计不会发生拒付✓✓✓
previously_refunded收到预警前已经退款✓✓
unresolved_dispute商户不同意争议原因,将继续争议✓
notfound未找到订单✓
other其他情况✓✓✓

in_progress 和 shipper_contacted 仅属于 Confirmed Fraud。原始规范说明:如果客户对 Customer Dispute 发送 Confirmed Fraud outcome,Ethoca 可能执行自动映射,例如 stopped → resolved、in_progress → other。新接入不应依赖该兼容行为,应直接发送与预警类型对应的 outcome。

refunded 可用取值:

refunded使用条件
refundedPSP 已确认退款成功或已按客户确认标准进入不可撤销处理阶段;不得仅凭退款 API 已受理就填写
not refunded未退款,例如未找到交易、拒绝退款、转人工争议
not settled原交易未结算或已取消/void/reversal,不需要走 refund

3.6 matchTransactionResult 枚举

matchTransactionResult 是已上线接口枚举,必须严格按下表传值,不要改大小写、空格或下划线。

枚举值场景额外要求
Duplicate alert重复预警必须传 historicalEthocaId
Authentication failed支付认证失败无
Payment declined支付被拒绝无
Chargeback received after refunding the alert within 24 hours收到预警后退款 24 小时内产生拒付无
Unmatched transaction alert未匹配交易的预警无
Chargeback received before alert拒付后收到预警无
Refunded before alert收到预警前已退款无
Other其他建议 comments 传非空说明;是否服务端强制须联调确认

4. 匹配逻辑

4.1 推荐匹配顺序

匹配流程只分为两种情况:arn 匹配,以及 arn 缺失时的组合字段匹配。

4.1.1 arn 匹配

当 Ethoca 预警包含 arn 时,使用 arn 与 PSP 原交易进行完全一致匹配:

  • arn 完全一致:视为完全匹配,建议退款。
  • arn 不一致或查询到多个候选:不得继续按弱字段自动匹配,建议人工复核。

arn 完全匹配可以免除后续组合字段匹配,但实际退款仍须通过第 4.3 节的交易状态、可退余额、幂等和权限校验。

4.1.2 arn 缺失时的匹配

只有当 Ethoca 预警未返回 arn 时,才使用 transactionTimestamp、authCode、cardBin、cardLast4 和 amount 组合匹配。

  1. 先使用 transactionTimestamp ±72 小时查询 PSP 候选交易。
  2. Ethoca transactionTimestamp 为 UTC+0。商户必须将本地系统或 PSP 返回的交易时间转换到 UTC+0,或将双方转换到同一时区后再比较。
  3. 只保留满足金额容差的候选交易:
    • 同币种、不需要换算:Ethoca amount 与 PSP 原交易金额的偏差必须在 ±5% 内。
    • 跨币种、需要换算:按交易日汇率换算后,换算金额与 PSP 原交易金额的偏差必须在 ±5% 内。
  4. 在同时满足时间和金额条件的候选交易中,按第 4.2 节的五条规则依次匹配。

匹配限制:

  • cardBin 不能单独使用,必须和 cardLast4 同时匹配。
  • transactionId、PSP transaction ID、network transaction ID、payment ID、客户 order ID 和 reference 均不参与匹配。
  • 金额匹配使用 Ethoca 原交易 amount,不使用 amountUsd 或 chargebackAmount。
  • 多个 PSP 交易同时满足同一规则时,不视为匹配成功,转人工复核。

4.2 匹配组合与处置建议

下表按匹配置信度从高到低排序。参考分值用于表达相对置信度,不属于 Ethoca 接口规范,客户可根据历史回放结果调整。除 arn 规则外,其余规则仅在 arn 缺失时执行。

transactionTimestamp 表示 UTC+0 时间窗口 ±72 小时;amount 表示同币种直接比较 ±5%,或跨币种换算后比较 ±5%。

优先级匹配条件参考分值置信评价处理建议
1arn100完全匹配建议退款
2authCode + cardBin + cardLast4 + transactionTimestamp + amount95高置信匹配唯一命中时建议退款
3authCode + cardLast4 + transactionTimestamp + amount90高置信匹配唯一命中时建议退款
4authCode + transactionTimestamp + amount85高置信匹配建议退款
5cardBin + cardLast4 + transactionTimestamp + amount80中等置信匹配建议人工复核
6cardLast4 + transactionTimestamp + amount70低置信匹配建议人工复核

执行要求:

  • arn 完全一致时直接采用优先级 1,不再执行后续组合。
  • arn 缺失时,从优先级 2 开始依次判断;某条规则唯一命中时停止后续规则。
  • cardBin 必须与 cardLast4 同时使用,不能单独参与匹配。
  • 没有命中、出现多个候选或关键字段冲突时,建议人工复核。

4.3 自动退款前置校验

仅当客户明确启用自动退款且以下条件全部满足时,系统才可以执行自动退款:

  • 第 4.2 节处理建议为“建议退款”的规则唯一命中;处理建议为“建议人工复核”的规则不得直接触发自动退款。
  • PSP 交易已成功 capture/settle,且未全额退款。
  • 交易未被正式 dispute/chargeback 完全占用余额。
  • 退款金额不超过可退余额。
  • 退款币种与原交易授权币种一致。
  • 客户已授权该 PSP 账号的退款权限。
  • 同一 ethoca_id + provider_payment_id + amount 不存在成功或进行中的退款任务。
  • 大额、重复预警、预警前已拒付、多个候选或关键字段冲突等场景已按客户规则转人工。跨币种交易在按交易日汇率换算且金额偏差不超过 ±5% 时,可继续执行既定匹配规则。

5. PSP 字段采集原则

5.1 客户必须额外保存的字段

不是所有 PSP 都稳定返回完整 arn、authCode 等信息。客户在支付创建和支付成功时应保存以下数据,用于候选交易筛选、退款执行、对账和审计。保存某个字段不代表该字段可以直接参与 Ethoca 匹配;匹配字段和组合必须遵循第 4 节。

  • 商户订单号、PSP payment id、charge/capture/action id。
  • PSP merchant account、entity、子商户 ID、账单描述符。
  • 授权成功时间、capture 时间、结算时间。
  • 金额、币种、退款余额。
  • 卡 BIN、卡尾号、卡品牌、发卡国家;匹配时 BIN 必须与尾号同时使用。
  • 授权码、ARN、RRN、network transaction ID,只要 PSP webhook、action、report 或后台可返回就保存。其中 RRN 和 network transaction ID 仅作内部查询和审计,不与 Ethoca transactionId 直接匹配。
  • 3DS 结果、liability shift、ECI、CAVV/DS transaction id,可用于争议策略。

6. PSP 对接方案

6.1 Stripe

官方文档:

6.1.1 拉取交易

优先同步 PaymentIntent 获取订单级状态,再同步或 expand Charge 获取卡、退款、争议和网络字段。

curl -G https://api.stripe.com/v1/payment_intents \
  -u sk_live_xxx: \
  -d "created[gte]=1782748800" \
  -d "created[lte]=1782835199" \
  -d "limit=100"
curl -G https://api.stripe.com/v1/charges \
  -u sk_live_xxx: \
  -d "created[gte]=1782748800" \
  -d "created[lte]=1782835199" \
  -d "limit=100"

分页使用 has_more 和 starting_after。建议保存 5-10 分钟重叠窗口,避免边界漏单。

6.1.2 用于 Ethoca 匹配的字段

Ethoca 字段Stripe 字段/处理方式
金额/币种amount、amount_captured、currency
交易时间created
卡尾号payment_method_details.card.last4
卡品牌/国家/类型payment_method_details.card.brand、country、funding
授权码payment_method_details.card.authorization_code,需使用支持该字段的 Stripe API 版本并按账号验证
ARNStripe 原始付款 Charge 对象没有统一的 arn 字段;不要承诺客户一定能通过 API 取到原始付款 ARN
退款引用号Refund 对象的 destination_details.card.reference;当 reference_type=acquirer_reference_number 时表示退款 ARN,仅用于退款追踪,不用于匹配原始付款
账单描述符calculated_statement_descriptor
拒付状态disputed、Dispute webhook

在 Stripe 中,客户人工从后台找这些字段不直观,系统对接时应直接从 Charge 对象读取。推荐优先级:

  1. 不得将 Ethoca transactionId 与 Stripe network_transaction_id、Charge ID、PaymentIntent ID 或订单号直接匹配。
  2. Stripe 能返回 authorization_code 时,优先使用授权码,并结合 last4、金额、币种和时间窗口匹配。
  3. 缺少授权码时,只能使用 last4 + 金额 + 币种 + 时间窗口 筛选唯一候选,并进入人工复核。
  4. Stripe 的 BIN 不得单独与金额或时间组合匹配;如使用 BIN,必须同时命中 last4。
  5. Stripe 原始付款 Charge 没有统一 ARN 字段,且退款 destination_details.card.reference 是退款引用号,不得用于匹配原始付款。该引用号还可能在退款发起后延迟生成。

Charge 对象中建议保存的字段示例:

{
  "id": "ch_xxx",
  "payment_intent": "pi_xxx",
  "amount": 12110,
  "currency": "cad",
  "created": 1718029984,
  "payment_method_details": {
    "card": {
      "brand": "visa",
      "last4": "1240",
      "authorization_code": "21HJ767"
    }
  }
}

6.1.3 发起退款

curl https://api.stripe.com/v1/refunds \
  -u sk_live_xxx: \
  -H "Idempotency-Key: refund:stripe:acct_123:pi_xxx:ethoca_123:1000" \
  -d payment_intent=pi_xxx \
  -d amount=1000 \
  -d reason=fraudulent \
  -d "metadata[ethoca_id]=1E7543HNEG001VOURNV96Q857"

要点:

  • amount 是最小货币单位。
  • 可传 payment_intent 或 charge,建议保存两者。
  • 监听 refund.updated、charge.refunded、charge.dispute.created,并定时对账。
  • 如果 Ethoca 为 Confirmed Fraud 且客户策略确认欺诈,可用 reason=fraudulent,但需客户确认这会影响风控拦截名单策略。

6.1.4 Ethoca 反馈建议

PSP 结果Confirmed FraudCustomer Dispute
退款已通过 webhook/对账确认成功outcome=stopped,refunded=refundedoutcome=resolved,refunded=refunded
收到预警前已退款使用 Confirmed Fraud 合法组合并结合实际业务;不得传 previously_refundedoutcome=previously_refunded,refunded=refunded,matchTransactionResult=Refunded before alert
PaymentIntent 未 capture 且已成功取消/冲正outcome=previously_cancelled,refunded=not settledoutcome=resolved,refunded=not settled
找不到交易outcome=notfound,refunded=not refundedoutcome=notfound,refunded=not refunded

6.2 Checkout.com

官方文档:

6.2.1 拉取交易

使用 Payment Search API 查询交易。该接口需要 payments:search scope。以下使用官方已给出的 payment ID 查询语法演示请求结构;批量同步时应按 Checkout.com 当前支持的可搜索字段构造 query,并配合 from/to 限制时间窗口。

curl https://{prefix}.api.checkout.com/payments/search \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "query": "id:'pay_mbabizu24mvu3mela5njyhpit4'",
  "from": "2026-06-01T00:00:00Z",
  "to": "2026-06-02T00:00:00Z",
  "limit": 100
}
JSON

query 是必填字符串,最大 1024 字符;limit 范围为 1~1000。当前 Payment Search 请求体不支持 sort 字段。分页使用响应中的 _links.next.href,不要自行拼接下一页 URL。

6.2.2 补拉 actions

Checkout.com 的强匹配字段通常在 payment actions 中更完整,建议对候选交易调用 Get payment actions。

Ethoca 字段Checkout.com 字段
金额/币种payment/action amount、currency
交易时间requested_on、action processed_on
授权码action auth_code
ARNaction processing.acquirer_reference_number
卡尾号source/card last4,或客户侧保存
卡 BIN + 尾号source/card bin + last4;BIN 只有与尾号同时命中时才可使用
可退余额balances.available_to_refund、balances.total_refunded

reference、metadata、RRN、acquirer_transaction_id 和 payment ID 可以用于客户内部查询、退款执行和审计,但不得与 Ethoca transactionId 或客户订单号组合成 Ethoca 直接匹配规则。

6.2.3 发起退款

curl -X POST https://{prefix}.api.checkout.com/payments/pay_xxx/refunds \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Cko-Idempotency-Key: refund:checkout:pay_xxx:ethoca_123:1000" \
  -d '{
    "amount": 1000,
    "reference": "ethoca_1E7543HNEG001VOURNV96Q857",
    "metadata": {
      "ethoca_id": "1E7543HNEG001VOURNV96Q857"
    }
  }'

capture_action_id 目前仅适用于 Checkout.com 文档明确支持的 PayPal 和 Riverty 场景,不应作为普通卡支付多 capture 的通用退款参数。

6.2.4 Ethoca 反馈建议

Checkout.com 的 actions 中常能取得 auth_code 和 ARN;匹配仍须遵循第 4 节约束。退款成功后反馈:

  • Confirmed Fraud:outcome=stopped,refunded=refunded。
  • Customer Dispute:本次预警后退款用 outcome=resolved;仅在预警到达前已经退款时使用 outcome=previously_refunded。两者的 refunded 均按实际退款状态填写。
  • 若 payment 状态为 declined:matchTransactionResult=Payment declined,refunded=not refunded。

6.3 CyberSource

官方文档:

6.3.1 拉取交易

使用 Transaction Search API 按 submitTimeUtc 查询。查询接口支持多种 PSP 内部字段,但 Ethoca 匹配仅使用本文明确允许的金额、币种、时间、卡尾号、BIN+尾号、ARN 和授权码组合。

curl -X POST https://api.cybersource.com/tss/v2/searches \
  -H "v-c-merchant-id: your_merchant_id" \
  -H "Content-Type: application/json" \
  -H "Date: Mon, 06 Jul 2026 10:00:00 GMT" \
  -H "Digest: SHA-256=..." \
  -H "Signature: ..." \
  -d '{
    "query": "submitTimeUtc:[2026-06-01T00:00:00Z TO 2026-06-02T00:00:00Z]",
    "offset": 0,
    "limit": 100,
    "sort": "submitTimeUtc:asc"
  }'

分页递增 offset 并以账号实际允许的 limit 为准。不要未经验证直接使用超大页长;Transaction Search/Details 可能存在数据延迟,不应作为唯一实时交易状态来源。

批量对账可补充使用 Reporting API,例如 purchase/refund 明细报表。

6.3.2 用于 Ethoca 匹配的字段

Ethoca 字段CyberSource 字段
金额/币种orderInformation.amountDetails.totalAmount、currency
交易时间submitTimeUtc
卡尾号paymentInformation.card.suffix
卡 BIN + 尾号paymentInformation.card.prefix + paymentInformation.card.suffix;BIN 不得单独使用
授权码processorInformation.approvalCode
商户维度merchantId、merchantInformation.accountId

clientReferenceInformation.code、RRN、processorInformation.networkTransactionId 和 PSP id 可用于客户内部查询、退款执行和审计,但不参与 Ethoca transactionId/order ID 匹配。

6.3.3 发起退款

curl -X POST https://api.cybersource.com/pts/v2/payments/6281765770796275003009/refunds \
  -H "v-c-merchant-id: your_merchant_id" \
  -H "Content-Type: application/json" \
  -H "Date: Mon, 06 Jul 2026 10:00:00 GMT" \
  -H "Digest: SHA-256=..." \
  -H "Signature: ..." \
  -d '{
    "clientReferenceInformation": {
      "code": "ethoca_1E7543HNEG001VOURNV96Q857"
    },
    "orderInformation": {
      "amountDetails": {
        "totalAmount": "10.00",
        "currency": "USD"
      }
    }
  }'

注意:CyberSource 退款金额通常传 decimal 字符串,不是 minor unit。

6.3.4 Ethoca 反馈建议

  • ARN 完全一致时视为完全匹配。ARN 缺失时,必须按第 4.2 节组合 approvalCode、card prefix + suffix 或 suffix、UTC 时间窗口和金额容差;card prefix 不得单独使用。
  • 若 search 找不到,但客户后台有订单,可用订单侧 PSP id 补查 Transaction Details。
  • 退款成功后:Confirmed Fraud 使用 stopped + refunded,Customer Dispute 使用 resolved + refunded。找不到交易时,两类预警均使用 notfound + not refunded。

6.4 Worldpay

官方文档:

6.4.1 拉取交易

Worldpay Access Payment Queries 支持按日期范围查询卡支付,并返回交易、支付工具、事件和可执行操作链接。

curl "https://try.access.worldpay.com/paymentQueries/payments?startDate=2026-06-01T00:00:00Z&endDate=2026-06-02T00:00:00Z&pageSize=300" \
  -u "username:password" \
  -H "Accept: application/vnd.worldpay.payment-queries-v1.hal+json"

可用过滤包括 entityReferences、currency、minAmount、maxAmount、last4Digits、receivedEvents。该服务是数据聚合服务,通常会有短暂延迟,不应作为唯一实时来源。

6.4.2 用于 Ethoca 匹配的字段

Ethoca 字段Worldpay 字段
金额/币种payment value amount/currency
交易时间payment/event timestamp
卡尾号查询参数 last4Digits 和返回的 payment instrument
授权码issuer.authorizationCode;仅在返回该字段时使用
商户维度entityReferences
可退款动作_links.payments:refund、_links.payments:partialRefund

scheme.reference、transactionReference 和 Worldpay payment ID 可用于客户内部查询、退款执行和审计,但不得与 Ethoca transactionId 或客户 order ID/reference 直接匹配。

6.4.3 发起退款

Worldpay 不建议硬编码退款 URL。应使用 payment/sale/settlement 响应中的 action link。

全额退款:

curl -X POST "https://try.access.worldpay.com/payments/settlements/refunds/full/{linkData}" \
  -u "username:password" \
  -H "Accept: application/vnd.worldpay.payments-v5+json" \
  -H "Content-Type: application/vnd.worldpay.payments-v5+json"

部分退款:

curl -X POST "https://try.access.worldpay.com/payments/settlements/refunds/partials/{linkData}" \
  -u "username:password" \
  -H "Accept: application/vnd.worldpay.payments-v5+json" \
  -H "Content-Type: application/vnd.worldpay.payments-v5+json" \
  -d '{
    "value": {
      "amount": 1000,
      "currency": "USD"
    },
    "reference": "ethoca_1E7543HNEG001VOURNV96Q857"
  }'

6.4.4 Ethoca 反馈建议

  • 若 Payment Queries 返回 payments:refund 或 payments:partialRefund,说明 PSP 当前提供可执行退款动作。
  • 若交易尚未 settle,应优先 cancel/reversal,并反馈 not settled。
  • Worldpay 产品线较多,本方案以 Access API 为基线;老 Corporate Gateway/XML 需单独评估。

6.5 Adyen

官方文档:

6.5.1 拉取交易

Adyen 标准 Online Payments 没有一个面向普通商户的实时“按日期列出全部支付”API。推荐组合:

  1. Webhook 实时入库:AUTHORISATION、CAPTURE、REFUND、REFUND_FAILED、CHARGEBACK、NOTIFICATION_OF_CHARGEBACK 等。
  2. Received payment details report:补齐授权交易明细、授权码、卡尾号、收单参考、网络交易参考。
  3. Payment accounting report:做资金、退款、失败退款、冲正和结算对账。

6.5.2 用于 Ethoca 匹配的字段

Ethoca 字段Adyen 字段
金额/币种Amount、Currency
交易时间Creation Date
卡尾号Shopper PAN 或 Card Number
卡 BIN + 尾号Issuer Id 或 Original Card Bin 必须与卡尾号同时命中;BIN 不得单独使用
授权码Authorisation Code
ARN/收单参考Acquirer Reference
3DS 信息3D Directory Response、3D Authentication Response
商户维度Merchant Account

pspReference、merchantReference 和 Network Transaction Reference 可用于客户内部查询、退款执行和审计,但不得与 Ethoca transactionId 或客户 order ID/reference 直接匹配。

6.5.3 发起退款

curl -X POST "https://checkout-live.adyenpayments.com/checkout/v72/payments/PSP_REFERENCE/refunds" \
  -H "X-API-Key: ADYEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantAccount": "YourMerchantAccount",
    "amount": {
      "value": 1000,
      "currency": "USD"
    },
    "reference": "ethoca_1E7543HNEG001VOURNV96Q857",
    "merchantRefundReason": "FRAUD"
  }'

退款结果异步确认。收到 response 后记录退款 pspReference,最终以 REFUND、REFUND_FAILED、REFUNDED_REVERSED webhook 或 Payment accounting report 为准。

6.5.4 Ethoca 反馈建议

  • Adyen 报表字段对 Ethoca 匹配很友好,但报表不是实时。建议 webhook 入库 + 报表补偿。
  • 当 Acquirer Reference 已确认就是原交易 ARN 且完全一致时,视为完全匹配。ARN 缺失时,必须按第 4.2 节组合 Authorisation Code、前六后四或后四位、UTC 时间窗口和金额容差。
  • 若 Adyen 返回退款校验失败,例如金额超过余额、未 capture、币种不一致,应转人工并反馈实际状态。

7. 自动化退款策略

7.1 默认策略

以下反馈必须按预警类型分别生成,禁止把斜杠表达式直接写入请求。

场景系统动作Confirmed FraudCustomer Dispute
高置信唯一命中且通过全部退款校验按客户配置自动退款或审批退款确认后 stopped + refunded退款确认后 resolved + refunded
收到预警前已全额退款不重复退款选择符合实际情况的 Confirmed Fraud 合法组合,并传 matchTransactionResult=Refunded before alertpreviously_refunded + refunded,并传 matchTransactionResult=Refunded before alert
授权未 capture 且已成功 void/cancel/reversal不发起 refundpreviously_cancelled + not settledresolved + not settled
已正式拒付禁止自动退款,转争议流程按实际情况人工选择合法 outcomeunresolved_dispute + not refunded
找不到交易转人工复核notfound + not refundednotfound + not refunded
多笔候选转人工复核可暂报 in_progress,必须在 24 小时内转最终态不得使用 in_progress;人工确认后发送 Customer Dispute 合法 outcome
部分金额争议按客户金额策略处理使用合法 outcome,amountStopped 填实际阻止/退款金额使用 resolved/other 等合法 outcome,amountStopped 填实际部分退款金额

7.2 金额策略

Ethoca FAQ 建议:如果确认是正确交易,为了更好阻止拒付,通常应全额退款,让发卡行看到全额退款。系统可支持三种客户配置:

策略说明适用场景
全额退款按原交易可退余额退款默认推荐
预警金额退款按 chargebackAmount 或 amount 退款部分争议、订阅部分退款
人工确认金额系统只给出建议金额高客单价、复杂履约

8. 上线前确认清单

以下项目尚不能仅凭现有原始文档唯一确定,必须通过 TrustDecision 服务端说明或 Sandbox 联调确认:

  • 推送签名输出是十六进制还是 Base64,是否区分大小写。
  • timestamp 允许偏差、过期策略和重放保护规则。
  • 推送成功是否同时要求 HTTP 200 和响应体 code=200。
  • alertTimestamp 在两类预警中的真实类型,以及是否长期兼容毫秒时间戳和 ISO 8601。
  • ethocaMerchantId 的稳定 JSON 类型。
  • comments 是否接口必传,是否允许中文,以及 other/Other 时是否强制非空。
  • actionTimestamp 的必传条件。
  • 完整业务错误码、HTTP 状态码和可重试范围。
  • 重复推送的重试间隔、最大次数和批量上限。
  • Customer Dispute 对 Confirmed Fraud outcome 的兼容映射是否仍然有效。

上线前至少完成以下 Sandbox 用例:

  • 同一 ethocaId 重复推送,确认接收端幂等且不会重复退款。
  • 同一更新请求重复提交,确认客户端不会重复执行资金动作。
  • Confirmed Fraud 和 Customer Dispute 各覆盖所有计划使用的合法 outcome + refunded 组合。
  • 覆盖错误签名、过期时间戳、未知枚举、缺失必传字段和超长字段。
  • 覆盖顶层 code=200 但 alertUpdateResponses[].status=failed。
  • 覆盖 PSP 退款受理后失败、退款冲正和重复预警。

9. 参考资料