Monnify 绑卡、放款、还款对接需求文档

版本:v0.3
日期:2026-06-25
范围:基于 Monnify API Reference、Direct Debit、Reserved Account、Disbursement、Webhook 文档整理。
约定:Monnify 等三方支付交互由 pmt 负责;短信等非支付三方能力仍按项目现状由对应服务承接。

1. 结论

本次贷款 MVP 采用 Card Tokenization 绑卡还款方案。业务上的“绑卡”定义为:客户通过 Monnify 完成一次卡支付验证,pmt 在支付成功后保存 Monnify 返回的 cardToken,后续按还款计划使用该 token 发起扣款。

  1. 绑卡主链路:Card Tokenization,首次卡支付成功后获取 cardToken
  2. 还款主链路:Charge Card Token,到期由 pmt 使用 token 发起扣款。
  3. 还款兜底链路:Reserved / Virtual Account,客户主动转账还款。
  4. 后置可选能力:Direct Debit / Mandate,后续如需银行账户直接扣款再接入。

放款使用 Disbursement Single Transfer。卡 token 扣款可能受卡过期、余额不足、发卡行风控、OTP/3DS 策略影响,因此必须保留主动还款入口和失败重试/提醒机制。

2. 基础接入

2.1 环境和认证

项目SandboxProduction
Base URLhttps://sandbox.monnify.comhttps://api.monnify.com
认证接口POST /api/v1/auth/login同左
认证方式Basic base64(apiKey:secretKey) 换 Bearer Token同左
后续接口Header: Authorization: Bearer <token>同左

测试凭据见 Monnify API Reference 的 Public Test Credentials:

字段
API KeyMK_TEST_GC3B8XG2XX
Secret KeyA663NRZA544DDPEM7KDN7Z8HRV6YXD8S
Contract Code5867418298

生产上线需要替换为 live API Key、Secret Key、Contract Code,并将 Base URL 切到生产域名。

2.2 通用接口清单

能力Method + Path用途
获取银行列表GET /api/v1/banks获取 Monnify 银行编码,供绑卡/绑账户、放款使用
校验银行账户GET /api/v1/disbursements/account/validate?accountNumber=&bankCode=校验账号户名,放款前和创建 mandate 前使用
获取交易状态GET /api/v2/merchant/transactions/query?transactionReference=&paymentReference=查询收款/卡支付交易状态
查询所有交易GET /api/v1/transactions/search按时间、金额、客户、状态分页对账

3. 绑卡/Card Tokenization

3.1 业务含义

客户在 App 中选择绑定还款银行卡,系统拉起 Monnify 卡支付能力,客户输入卡信息并完成银行侧验证。首次支付成功后,pmt 查询交易详情并保存 cardDetails.cardToken。后续还款日,pmt 使用该 token 进行自动扣款。

首次支付可以采用两种产品策略:

策略用户感知适用场景
小额验证支付扣一笔低金额用于验证银行卡只做绑卡,不在绑卡时还款
首期/当期还款支付支付本期还款并保存银行卡还款场景更自然,建议优先

MVP 建议采用“首期/当期还款支付并保存银行卡”。如果产品要求在放款前完成绑卡,则可采用小额验证支付。

小额验证支付需要按真实支付处理。Monnify Card Tokenization 文档说明 token 来自客户完成的首次成功卡支付,未说明该笔金额会自动退回。因此不能假设 Monnify 自动退款;如产品承诺退还小额验证金,需要通过退款能力或内部账务补偿另行处理,并确认 Refund API 已开通、费用、到账时效和失败处理策略。

https://developers.monnify.com/docs/collections/recurring-payments/card-tokenization

关键接口

步骤Method + Path说明
初始化交易POST /api/v1/merchant/transactions/init-transaction创建绑卡验证/首期还款交易,得到 transactionReference
卡支付POST /api/v1/merchant/cards/charge提交卡信息发起首次扣款
OTP 授权POST /api/v1/merchant/cards/otp/authorizeCharge a Card 返回 OTP_AUTHORIZATION_REQUIRED 时使用
3DS 授权POST /api/v1/sdk/cards/secure-3d/authorizeCharge a Card 返回 BANK_AUTHORIZATION_REQUIRED 时使用
查询交易GET /api/v2/merchant/transactions/query支付成功后读取 cardDetails.cardToken
Token 扣款POST /api/v1/merchant/cards/charge-card-token后续自动还款使用

3.2 用户操作交互

  1. 用户在 App 选择“绑定还款银行卡”。
  2. App 展示授权说明:绑定后将在还款日按贷款合同约定自动扣款,可更换或解绑银行卡。
  3. 用户点击确认,App 拉起 Monnify 卡支付页面或 SDK。
  4. 用户在 Monnify Checkout/SDK 或我方自建安全卡输入页中输入卡号、有效期、CVV、PIN 等卡信息。
  5. pmt 调用 Charge a Card
  6. 如果返回 SUCCESS,前端展示绑定处理中,后端查询交易并保存 token。
  7. 如果返回 OTP_AUTHORIZATION_REQUIRED,App 展示 OTP 输入框,用户输入 OTP 后 pmt 调用 OTP 授权接口。
  8. 如果返回 BANK_AUTHORIZATION_REQUIRED,App 跳转或打开 3DS 验证页,用户完成银行验证后回到 App。
  9. pmt 查询交易状态,确认支付成功且返回可复用 token。
  10. App 展示绑定成功,显示卡品牌和后四位。

推荐前端文案:

绑定后,我们将在还款日按贷款合同约定从该银行卡自动扣款。
你可以在还款设置中更换或解绑银行卡。

3.3 卡信息采集页面要求

卡信息采集有两种实现方式:

方案说明MVP 建议
Monnify Checkout/SDK用户在 Monnify 提供的页面或组件中输入卡号、有效期、CVV、PIN,pmt 不直接接触完整卡数据推荐
我方自建页面 + Charge a Card API用户在我方页面输入卡信息,pmt 服务端调用 Monnify Charge a Card仅在具备 PCI-DSS、安全审计和密钥管理能力后采用

如果采用我方自建页面,必须满足以下要求:

  1. 页面和接口全链路 HTTPS。
  2. 卡号、CVV、PIN 不落库、不写日志、不进入埋点和错误上报。
  3. 后端只在本次请求内转发给 Monnify,不做持久化。
  4. 前端禁止把卡信息传给除 pmt 支付接口以外的服务。
  5. 日志、APM、网关、风控、客服后台必须脱敏。
  6. 需要确认公司具备处理银行卡敏感信息所需的 PCI-DSS 合规能力。

因此,MVP 优先使用 Monnify Checkout/SDK 承接卡信息输入;只有在产品或技术上必须自建页面时,才走 Charge a Card API 直连模式。

3.4 OTP / 3DS 分流规则

OTP 还是 3DS 由 POST /api/v1/merchant/cards/charge 的响应决定,pmt 不预先判断。

Charge a Card 响应状态

Monnify 状态我方状态处理
SUCCESSBIND_PAID查询交易,读取并保存 cardToken
OTP_AUTHORIZATION_REQUIREDWAITING_OTP展示 OTP 输入框,调用 OTP 授权
BANK_AUTHORIZATION_REQUIREDWAITING_3DS跳转 3DS 验证,完成后查询交易
失败状态BIND_FAILED提示换卡或重试

OTP 授权字段映射:

字段取值
transactionReferenceCharge a Card 返回的 responseBody.transactionReference
tokenIdCharge a Card 返回的 responseBody.otpData.id
token用户输入的 OTP
collectionChannelAPI_NOTIFICATION

3DS 授权处理:

字段取值
transactionReferenceCharge a Card 返回的 responseBody.transactionReference
redirectUrl使用 responseBody.secure3dData.redirectUrl 引导用户验证
验证后动作回到 App 后调用交易查询接口确认最终支付状态

OTP 时效要求:

  1. Monnify API 文档未给出固定 OTP 有效时长,实际有效期通常由发卡行/银行侧控制。
  2. App 收到 OTP_AUTHORIZATION_REQUIRED 后应立即展示 OTP 输入框,不要让用户离开当前流程。
  3. 前端建议展示 3 分钟倒计时;倒计时只是产品提示,不代表 Monnify 官方有效期。
  4. 用户提交 OTP 后立即调用 POST /api/v1/merchant/cards/otp/authorize
  5. 如果 OTP 过期或授权失败,卡支付接口没有文档化的 card OTP resend 接口;MVP 按失败处理,提示用户重新发起绑卡/支付。
  6. 同一笔 transactionReference 不应反复无限尝试 OTP,建议限制 3 次以内,超过后重新创建交易。

3.5 Token 保存条件

只有同时满足以下条件,才能把支付方式置为 BOUND

  1. 交易状态为成功,例如 paymentStatus = PAID 或授权接口返回 SUCCESSFUL
  2. 交易详情返回 cardDetails.cardToken
  3. cardDetails.reusable = true
  4. cardDetails.supportsTokenization = true
  5. customerEmail 与后续 token 扣款使用的客户邮箱一致。

pmt 只保存 Monnify token、卡品牌、后四位、有效期、客户邮箱,不保存 PAN、CVV、OTP、PIN。

3.6 绑卡时序

sequenceDiagram
    participant App as 客户 App
    participant FCS as 贷款/FCS
    participant PMT as pmt
    participant Monnify as Monnify

    App->>FCS: 点击绑定还款银行卡
    FCS->>PMT: 创建绑卡验证/首期还款交易
    PMT->>Monnify: POST /api/v1/merchant/transactions/init-transaction
    Monnify-->>PMT: 返回 transactionReference
    App->>Monnify: 输入卡信息
    PMT->>Monnify: POST /api/v1/merchant/cards/charge
    Monnify-->>PMT: 返回 SUCCESS / OTP_REQUIRED / 3DS_REQUIRED
    alt 需要 OTP
        App->>FCS: 输入 OTP
        FCS->>PMT: 提交 OTP
        PMT->>Monnify: POST /api/v1/merchant/cards/otp/authorize
        Monnify-->>PMT: 返回支付结果
    else 需要 3DS
        App->>Monnify: 打开 redirectUrl 完成 3DS
        Monnify-->>App: 返回 App/H5
    end
    PMT->>Monnify: GET /api/v2/merchant/transactions/query
    Monnify-->>PMT: 返回 cardToken、maskedPan、reusable
    PMT-->>FCS: 更新支付方式为 BOUND
    FCS-->>App: 展示绑卡成功

4. 放款

https://developers.monnify.com/docs/disbursements/single-transfers

4.1 接口链路

步骤Method + Path说明
获取钱包余额GET /api/v2/disbursements/wallet-balance放款前确认 Monnify 钱包余额
获取/缓存银行列表GET /api/v1/banks获取目标银行编码
校验收款账户GET /api/v1/disbursements/account/validate校验借款人放款账户
发起单笔放款POST /api/v2/disbursements/single贷款放款主接口
OTP 授权POST /api/v2/disbursements/single/validate-otp若返回 PENDING_AUTHORIZATION 且 2FA 开启
重发 OTPPOST /api/v2/disbursements/single/resend-otpOTP 过期时使用
查询放款状态GET /api/v2/disbursements/single/summary?reference=主动查询
列表/搜索GET /api/v2/disbursements/single/transactions / GET /api/v2/disbursements/search-transactions对账和运营查询

生产使用 Transfer API 需要满足 Monnify 监管要求并开通权限。上线前还需要联系 Monnify 配置服务器静态 IP 白名单;如需关闭 API disbursement OTP,也需要向 Monnify 申请。

4.2 发起单笔放款请求字段

字段必填说明
amount放款金额
reference我方唯一放款引用,建议等于或包含 loanDisbursementId
narration银行流水备注
destinationBankCode借款人收款银行编码
destinationAccountNumber借款人收款账号
destinationAccountName借款人收款户名,应来自账户校验结果
currencyNGN
sourceAccountNumberMonnify 钱包账号
senderInfo代表付款方信息
async是否异步转账

4.3 放款状态映射

Monnify 状态我方状态处理
PENDING_AUTHORIZATIONWAITING_OTP等待运营/财务输入 OTP 或走免 OTP 配置
PENDING / PROCESSINGDISBURSING继续查询或等待回调
SUCCESSDISBURSED更新贷款为已放款,生成还款计划
FAILEDDISBURSE_FAILED可重试,必须使用新 reference 或按幂等策略处理
REVERSEDDISBURSE_REVERSED回滚贷款状态,进入人工处理

4.4 时序

sequenceDiagram
    participant Ops as 运营/系统任务
    participant FCS as 贷款/FCS
    participant PMT as pmt
    participant Monnify as Monnify

    FCS->>PMT: 请求放款 loanId、amount、客户收款账户
    PMT->>Monnify: GET /api/v2/disbursements/wallet-balance
    Monnify-->>PMT: 返回余额
    PMT->>Monnify: GET /api/v1/disbursements/account/validate
    Monnify-->>PMT: 返回户名
    PMT->>Monnify: POST /api/v2/disbursements/single
    Monnify-->>PMT: 返回 SUCCESS 或 PENDING_AUTHORIZATION
    alt 需要 OTP
        Ops->>PMT: 输入 OTP
        PMT->>Monnify: POST /api/v2/disbursements/single/validate-otp
        Monnify-->>PMT: 返回授权结果
    end
    PMT->>Monnify: GET /api/v2/disbursements/single/summary?reference=
    Monnify-->>PMT: 返回最终状态
    PMT-->>FCS: 通知放款成功/失败

5. 还款

5.1 主链路:Card Token 自动扣款

业务含义:账务系统到期生成应扣金额,pmt 使用已绑定银行卡的 cardToken 发起扣款,扣款成功后 FCS 入账并更新还款计划。

关键接口

步骤Method + Path说明
发起 token 扣款POST /api/v1/merchant/cards/charge-card-token使用 cardToken 从客户银行卡扣款
查询交易状态GET /api/v2/merchant/transactions/querypaymentReference 查询扣款结果
分页查询交易GET /api/v1/transactions/search日终对账

发起扣款请求字段

字段必填说明
cardToken绑卡成功后保存的 Monnify token
amount本次扣款金额,单位 NGN
customerName客户姓名
customerEmail客户邮箱,必须与首次卡交易对应客户一致
paymentReference我方唯一扣款引用,建议:RP-{repaymentPlanId}-{installmentNo}-{attemptNo}
paymentDescription扣款说明,例如 Loan repayment
currencyCodeNGN
contractCodeMonnify 合同号
apiKeyMonnify API Key
metaData可放 loanIdrepaymentPlanId,不要放敏感信息
incomeSplitConfig分账配置,MVP 不使用

还款状态映射

Monnify 状态我方状态处理
PENDING / PROCESSINGREPAY_PROCESSING等待回调或轮询
SUCCESS / PAID / SUCCESSFULREPAID入账,更新本金/利息/罚息/费用
FAILEDREPAY_FAILED记录失败原因,进入重试或提醒
REVERSEDREPAY_REVERSED冲正已入账金额,进入人工处理

时序

sequenceDiagram
    participant Job as 还款任务
    participant FCS as 贷款/FCS
    participant PMT as pmt
    participant Monnify as Monnify

    Job->>FCS: 到期生成应扣款项
    FCS->>PMT: 请求扣款 repaymentId、amount、paymentMethodId
    PMT->>PMT: 校验 cardToken 可用、生成 paymentReference
    PMT->>Monnify: POST /api/v1/merchant/cards/charge-card-token
    Monnify-->>PMT: 返回 transactionReference、paymentReference、扣款状态
    PMT->>Monnify: GET /api/v2/merchant/transactions/query?paymentReference=
    Monnify-->>PMT: 返回最终交易状态
    PMT-->>FCS: 通知还款成功/失败
    FCS->>FCS: 入账、更新还款计划、触发下一步提醒

5.2 兜底链路:Reserved / Virtual Account 主动还款

业务含义:为每个客户分配虚拟账户,客户主动转账还款。Monnify 通过交易回调通知入账;系统也可按 accountReference 查询交易。

关键接口

步骤Method + Path说明
创建虚拟账户POST /api/v2/bank-transfer/reserved-accounts为客户/贷款创建还款账户
查询虚拟账户GET /api/v2/bank-transfer/reserved-accounts/{accountReference}展示账户信息
查询账户交易GET /api/v1/bank-transfer/reserved-accounts/transactions?accountReference=对账和补偿
修改支付来源限制PUT /api/v1/bank-transfer/reserved-accounts/update-payment-source-filter/{accountReference}可限制付款来源
注销虚拟账户DELETE /api/v1/bank-transfer/reserved-accounts/reference/{accountReference}贷款结清后释放

创建虚拟账户请求字段

字段必填说明
accountReference我方唯一账户引用,建议:RA-{userId}RA-{loanId}
accountName银行转账展示户名
currencyCodeNGN
contractCodeMonnify 合同号
customerEmail客户邮箱
customerName客户姓名
bvn客户 BVN
getAllAvailableBanks是否返回所有可用银行
preferredBanks偏好银行,文档示例为 50515
restrictPaymentSource是否限制付款来源,降低误入账
allowedPaymentSources允许付款账号/BVN 等
nin客户 NIN

时序

sequenceDiagram
    participant App as 客户 App
    participant FCS as 贷款/FCS
    participant PMT as pmt
    participant Monnify as Monnify

    FCS->>PMT: 请求创建还款虚拟账户
    PMT->>Monnify: POST /api/v2/bank-transfer/reserved-accounts
    Monnify-->>PMT: 返回账户号、银行、accountReference
    PMT-->>FCS: 保存并展示给客户
    App->>Monnify: 客户转账还款
    Monnify-->>PMT: Transaction Completion Webhook
    PMT->>PMT: 校验签名、幂等检查
    PMT->>Monnify: GET /api/v2/merchant/transactions/query
    Monnify-->>PMT: 确认 PAID
    PMT-->>FCS: 通知入账
    FCS->>FCS: 分配本金/利息/罚息/费用

6. 回调、安全和对账

6.1 Webhook

Monnify Dashboard 需要配置以下 URL:

类型用途
Transaction Completion卡支付、转账收款、虚拟账户入账
Disbursement放款结果通知
Settlement结算对账
Refund退款结果,如后续启用

回调处理要求:

  1. 校验请求头 monnify-signature
  2. 按文档使用 Secret Key + 原始请求体计算 SHA-512 后比较签名。
  3. 回调只做轻量处理,先落库再异步处理,及时返回 HTTP 200。
  4. transactionReferencepaymentReferencereference 做幂等键,重复回调不能重复入账或重复推进状态。
  5. 回调后再调用查询接口确认状态,不只信任回调 payload。
  6. 如条件允许,按 Monnify Dashboard 或支持团队提供的信息限制回调来源 IP。

6.2 对账

场景对账接口频率
放款GET /api/v2/disbursements/search-transactionsGET /api/v2/disbursements/single/summaryT+0 每 15 分钟补偿,T+1 日终
卡 token 扣款GET /api/v2/merchant/transactions/queryGET /api/v1/transactions/searchT+0 每 15 分钟补偿,T+1 日终
虚拟账户还款GET /api/v1/bank-transfer/reserved-accounts/transactionsGET /api/v2/merchant/transactions/queryT+0 每 15 分钟补偿,T+1 日终

8. MVP 实施范围

8.1 必做

  1. Monnify 认证 token 获取和缓存。
  2. 银行列表同步与账户校验。
  3. Card Tokenization 绑卡、OTP/3DS 分流、交易查询、token 落库。
  4. 单笔放款、OTP 授权、放款状态查询。
  5. Card Token 自动还款扣款、扣款状态查询。
  6. Reserved Account 创建与交易查询,作为手动还款兜底。
  7. Webhook 接收、签名校验、幂等、异步处理。
  8. T+0 补偿任务和 T+1 对账任务。

9. 验收标准

  1. Sandbox 能完成 Card Tokenization 绑卡流程,覆盖 SUCCESS、OTP、3DS 分支,并正确保存 cardTokenmaskedPan、后四位、有效期和状态。
  2. Sandbox 能完成单笔放款发起、OTP 授权和状态查询,成功后 FCS 只推进一次放款状态。
  3. Sandbox 能完成 Charge Card Token 扣款发起和状态查询,成功后 FCS 只入账一次。
  4. Sandbox 能创建 Reserved Account,并通过交易查询或回调完成主动还款入账。
  5. Webhook 签名校验失败时拒绝处理;重复 webhook 不重复入账。
  6. 网络超时、Monnify 5xx、业务失败均进入可观测的补偿队列。

10. 参考资料