# Zeffra 代收 pay_type_code 接入说明

渠道标识：`zeffra`，国家/币种：`US / USD`。

| 平台 `payTypeCode` | Zeffra 产品码（平台内部） | 商户侧说明 |
| --- | --- | --- |
| `card` | `110` | 信用卡；卡信息、账单信息和设备风控信息必填。 |
| `apple_pay` | `111` | Apple Pay。 |
| `paypal` | `112` | PayPal。 |
| `cashapp` | `113` | Cash App。 |
| `google_pay` | `114` | Google Pay。 |
| `ach` | `115` | 美国 ACH。 |
| `debit_card` | `117` | 借记卡；卡信息、账单信息和设备风控信息必填。 |

商户只传平台标准 `payTypeCode`，不得传 Zeffra 产品码。代收金额使用平台分单位；平台仅在上游协议边界转换为 USD 元。

## 统一代收入参映射

Zeffra 要求真实用户标识、注册时间、账单信息、设备信息和终端 IP。除平台标准顶层字段外，渠道专用字段统一放在 `ext` 对象中；键名必须与下表完全一致。

### 收银台自动补齐规则

- `user_registered_at`：订单 `ext.zeffra.userRegisteredAt` 优先；收银台场景缺失时使用浏览器首次访问 AllOnePay 收银台的真实 Unix 秒时间。
- `user_id`：订单 `buyerId` 优先；收银台场景缺失时根据 `AppId + 本机稳定设备标识` 计算不可逆稳定标识，不使用订单号随机生成。
- `billing_info`：订单真实付款人及 `ext.zeffra.billing*` 优先；缺项时读取 Zeffra 渠道账号中预先配置的真实 `defaultBilling*`。
- `device_info.client_ip`：只由平台服务端按可信代理规则获取真实请求 IP；不信任客户端传入 IP。
- 其他 `device_info`：收银台浏览器自动采集并写入 `cashier.*`，显式 `ext.zeffra.device*` 仍具有更高优先级。
- `website`：`ext.zeffra.website` 优先，其次渠道账号 `defaultWebsite`，最后从已校验的 `returnUrl` 提取 HTTP/HTTPS Origin。

开放 API 直连 `/api/PayRequest/UnifiedPay` 且不经过 AllOnePay 收银台时，平台使用实际观察到的 API 请求 IP、User-Agent、Cookie 是否存在及首次观察时间生成稳定 API 上下文；无法观察的屏幕信息使用 `not_available`，不会伪装成浏览器值。商户显式传入的真实 `buyerId`、注册时间和 `ext.zeffra.device*` 始终优先。

| AllOnePay 字段 | 必填条件 | Zeffra 字段/说明 |
| --- | --- | --- |
| `buyerId` | 必填 | `user_id`，下游商户侧真实且稳定的付款用户标识。 |
| `payerEmail` | 必填 | `billing_info.email`。 |
| `payerPhone` | 必填 | `billing_info.phone`。 |
| `clientIp` | 必填 | `device_info.client_ip`，必须是真实付款终端公网 IP。 |
| `returnUrl` | 必填 | `auth_return_url`，必须是绝对 HTTP/HTTPS URL。 |
| `notifyUrl` | 必填 | Zeffra 原支付及被动退款共用的回调地址。 |
| `country` | 建议 | `billing_info.country` 的默认值；也可由 `ext.zeffra.billingCountry` 覆盖。 |
| `languageCode` | 建议 | `device_info.language` 的默认值；也可由 `ext.zeffra.deviceLanguage` 覆盖。 |
| `ext.zeffra.userRegisteredAt` | 必填 | `user_registered_at`，Unix 秒级时间戳。 |
| `ext.zeffra.enable3DSecure` | 否 | `enable_3d_secure`，字符串值 `"0"`/`"1"`；不传按 `0`，上游收到 JSON 整数。 |
| `ext.zeffra.website` | 必填 | 付款发起网站，必须是绝对 HTTP/HTTPS URL。 |
| `ext.zeffra.billingFirstName` | 必填 | `billing_info.first_name`。 |
| `ext.zeffra.billingLastName` | 必填 | `billing_info.last_name`。 |
| `ext.zeffra.billingAddress1` | 必填 | `billing_info.address1`。 |
| `ext.zeffra.billingAddress2` | 否 | `billing_info.address2`。 |
| `ext.zeffra.billingCity` | 必填 | `billing_info.city`。 |
| `ext.zeffra.billingState` | 必填 | `billing_info.state`。 |
| `ext.zeffra.billingPostalCode` | 必填 | `billing_info.postal_code`。 |
| `ext.zeffra.billingCountry` | 条件 | `billing_info.country`；未传时使用顶层 `country`。 |
| `ext.zeffra.deviceLanguage` | 条件 | `device_info.language`；未传时使用顶层 `languageCode`。 |
| `ext.zeffra.deviceOs` | 必填 | `device_info.os`。 |
| `ext.zeffra.deviceBrowser` | 必填 | `device_info.browser`。 |
| `ext.zeffra.deviceTimezone` | 必填 | `device_info.timezone`。 |
| `ext.zeffra.deviceScreenResolution` | 必填 | `device_info.screen_resolution`，例如 `1920x1080`。 |
| `ext.zeffra.deviceCardInputMethod` | 必填 | `device_info.card_input_method`，按上游约定传 `typed` 或 `pasted`。 |
| `ext.zeffra.deviceCookie` | 必填 | `device_info.cookie`。 |
| `ext.zeffra.cardNumber` | 卡/借记卡必填 | `card_info.card_number`。 |
| `ext.zeffra.expiryMonth` | 卡/借记卡必填 | `card_info.expiry_month`，格式 `MM`。 |
| `ext.zeffra.expiryYear` | 卡/借记卡必填 | `card_info.expiry_year`，按 Zeffra 要求填写。 |
| `ext.zeffra.securityCode` | 卡/借记卡必填 | `card_info.security_code`。 |

账单地址字段采用“订单优先、渠道配置兜底”：订单 `ext` 中的
`billingAddress1`、`billingAddress2`、`billingCity`、`billingState`、`billingPostalCode`、`billingCountry`
有非空值时直接使用；未传或仅为空白时，平台可读取运营人员在该商户 Zeffra 上游账号中维护的真实默认账单地址。
订单与渠道配置均缺少必填地址字段时，平台仍会拒绝下单。

## 商户请求示例

以下仅展示字段位置，卡号与安全码必须由合规的 PCI DSS 流程在单次请求中注入，不得替换为真实数据后保存到文档、日志或工单。

```json
{
  "appId": "<ALLONEPAY_MERCHANT_APP_ID>",
  "merchantOrderNo": "PAY-ZEFFRA-20260714-001",
  "amount": 1000,
  "currency": "USD",
  "country": "US",
  "payTypeCode": "card",
  "buyerId": "buyer-10001",
  "payerEmail": "payer@example.test",
  "payerPhone": "+12025550123",
  "clientIp": "203.0.113.10",
  "languageCode": "en-US",
  "returnUrl": "https://merchant.example.test/pay-return",
  "notifyUrl": "https://merchant.example.test/pay-notify",
  "ext": {
    "zeffra.userRegisteredAt": "1777996800",
    "zeffra.enable3DSecure": "1",
    "zeffra.website": "https://merchant.example.test",
    "zeffra.billingFirstName": "Test",
    "zeffra.billingLastName": "Buyer",
    "zeffra.billingAddress1": "123 Test Street",
    "zeffra.billingCity": "Los Angeles",
    "zeffra.billingState": "CA",
    "zeffra.billingPostalCode": "90001",
    "zeffra.billingCountry": "US",
    "zeffra.deviceLanguage": "en-US",
    "zeffra.deviceOs": "Windows 11",
    "zeffra.deviceBrowser": "Chrome",
    "zeffra.deviceTimezone": "America/Los_Angeles",
    "zeffra.deviceScreenResolution": "1920x1080",
    "zeffra.deviceCardInputMethod": "typed",
    "zeffra.deviceCookie": "<ONE_REQUEST_DEVICE_COOKIE>",
    "zeffra.cardNumber": "<ONE_REQUEST_CARD_NUMBER>",
    "zeffra.expiryMonth": "<MM>",
    "zeffra.expiryYear": "<YYYY>",
    "zeffra.securityCode": "<ONE_REQUEST_SECURITY_CODE>"
  },
  "timestamp": 1783958400,
  "nonce": "N1783958400001",
  "apiVersion": "v1.0",
  "sign": "<SIGNATURE>"
}
```

`ext` 是签名内容的一部分，按开放接口签名规则递归扁平化；商户不得在签名后修改任何扩展字段。

## 安全与回调

卡号、有效期、安全码只允许在受控 PCI 流程的本次请求生命周期中使用，不得落库、写日志或进入重试消息。若商户环境不具备相应合规能力，不得启用卡/借记卡直连产品。

上游 `merchant_order_no` 是我方当前代收尝试单号，可能带 `_A02`；`order_no` 才是 Zeffra 系统订单号。回调不得反向映射。

Zeffra 的被动退款回调仍发送到原 `notifyUrl`：`merchant_order_no`/`order_no` 分别对应原我方尝试单号/原 Zeffra 支付单号，`refund_no` 才是上游退款幂等号。平台只有在验签、原订单交叉校验、退款金额币种校验和退款资金存储过程全部成功后才返回 HTTP 200。
