Skip to content

🚀 快速开始(Quick Start)

IntPay 内嵌信用卡支付接入文档(Iframe 模式)

IntPay 提供基于 Iframe + Token 化机制 的信用卡支付解决方案。

该方案通过将卡信息完全托管在 IntPay SDK中,实现:

  • PCI DSS 合规(商户不接触卡数据)
  • 数据隔离(卡信息不经过商户服务器)
  • 灵活控制(支付流程由商户掌控)

核心理念:

卡信息在 iframe,交易控制在商户

架构说明

支付流程涉及两个核心角色:

组件职责
父页面(商户)订单创建、业务校验、发起支付
SDK(IntPay)卡信息采集、Token生成、3DS处理

通信方式:

js
window.postMessage()

支付流程

mermaid
sequenceDiagram
  participant 用户
  participant 父页面
  participant SDK
  participant IntPay

  用户->>SDK: 输入卡信息
  SDK->>父页面: PAY_CLICK
  父页面->>父页面: 校验 + 创建订单
  父页面->>SDK: PAY_READY
  SDK->>父页面: PAYMENT_TOKEN
  父页面->>IntPay: 调用支付接口
  IntPay-->>父页面: 返回结果 / 3DS
  父页面->>SDK: PAY_REDIRECT(如需要)

接入步骤

1. 初始化支付接口《iframe Url》

当持卡人选择支付方式时,商户后端 初始化支付接口,获取iframe html地址 alt text

请求参数:

json
{
    "channel": "iframeTest",
    "source": "shopyy",
    "website": "www.qq.com",
    "country": "US",
    "payMethodId": "1",
    "reference": "P1911",
    "amount": 10000,
    "currency": "USD"
}

返回参数:

json
{
    "requestId": "85b1f915-1c45-4ee0-8716-56d00c09dd28",
    "success": true,
    "data": {
        "channel": "iframeTest",
        "source": "shopyy",
        "url": "https://api.links-pay.com?token=37f88b34-537b-4774-8692-5e307d12f4d8",
        "expiresAt": "2025-10-14 17:32:38",
        "expiresIn": 86400,
        "iframeToken": "6861aa86-16c9-4721-8e9b-9bd69215e43b"
    },
    "timestamp": "2025-10-13T17:32:38.422+08:00"
}
  • iframeUrl 嵌入的html地址
  • iframeToken 用于支付接口《payments》的参数

前端渲染:

html
<iframe src="{{IFRAME_URL}}" name="iframe_pay" onload="iframeLoaded()"  id="iframe_pay" width="100%"></iframe>

2. 监听事件

alt text

父页面嵌入iframeUrl后(执行iframeLoaded方法),需要监听以下几个消息:

js
window.addEventListener('message', (event) => {
  const data = event.data;
  console.log('Listener:', data);



if (data.type === 'IFRAME_SIZE' && typeof data.height === 'number') {
  frameEl.style.height = data.height + 'px';
  console.log('[parent] child height:', data.height, 'px');
  return;
}
  
 
if (data.type === 'PAY_WINDOW') {
  if (data.action === 'LOADING') {
    // 页面加载loading动画
      createAjaxLoading();
  } else if (data.action === 'HIDELOADING') {
    // 页面删除loading动画
      removeAjaxLoading();
  } else if (data.action === 'ERROR') {
    // 页面删除loading动画,并渲染 失败提示给用户看
      removeAjaxLoading();
      moi.message({
        content: data.msg,
        type: 'error',
        timer:4000
      });
  }
}

if (data.type === 'PAY_CLICK' ) {
  // 进行表单校验以及订单创建等其他商户业务逻辑
  const payRes = await saveOrder();
  console.log('pay_submit');
  console.log(payRes);

  if (!payRes) {
    // 如果校验不通过,或逻辑走不通,则return,SDK就不会继续往下走支付流程
      return;
  }

  // 校验通过后,发送消息给SDK,告知SDK一切准备就绪
  frameEl.contentWindow.postMessage({ type: 'PAY_READY', ready: true }, '*');
  return;
}

// 监听支付token
if (data.type === 'PAYMENT_TOKEN' ) {
  // 判断卡号校验状态是否成功
    if (data.status === 'SUCCEEDED') {
      // 加载loading
      createAjaxLoading();
      console.log('Payment success:', data.payToken);
      // 通过后端接口 请求《payments》支付接口
    } else {
      // 如果失败,则告知客户
      console.warn(' Payment failed:', data.message);
      moi.message({
        content: data.message,
        type: 'error',
        timer:4000
      });
    }

  }
});

3. 用户点击支付

  1. 用户输入完卡信息后点击支付按钮
  2. SDK发送消息告知父页面
js
postMessage({ type: 'PAY_CLICK', ready: 'true' })

父页面需要:

  • 校验用户的账单和物流地址,比如有没有哪些字段没有填写的
  • 创建商城订单
  • 如您不需要做任何的预处理,可以直接发送PAY_READY消息

如下图所示:alt text


4. 通知SDK

当父页面一切就绪后,通过以下命令通知SDK,SDK会开始对卡信息进行加密

js
postMessage({ type: 'PAY_READY', ready: 'true' })

5. 获取 Token

当SDK完成卡信息校验及信息加密后,会告知父页面结果。如 加密结果,以及加密状态。

js
postMessage({
  type: 'PAYMENT_TOKEN',
  status: 'SUCCEEDED',
  payToken: 'xxx'
})

6. 接收Token

父页面收到PAYMENT_TOKEN后,判断status 结果(可参考上面的JS监听器代码):

  • 如 status = FAILED,则渲染失败告知用户且不进行下一步操作
  • 如 status = SUCCEEDED,则进行下一步支付请求操作

7. 请求支付接口

如status = SUCCEEDED后,则携带payToken,由商户后端请求《payments》接口 切记:payToken是卡号加密信息,iframeToken是第一步初始化的时候返回的,两者都要带入《payments》接口

请求参数:

json
{
    "iframeToken": "6861aa86-16c9-4721-8e9b-9bd69215e43b",
    "amount": 10000,
    "website": "www.links-pay.cc",
    "subject": "Women’s 3D Embroidered Bandeau Elegant Mini Dress",
    "channel": "iframeTest",
    "type": "iframe",
    "card": {
        "payToken": "a4a4575c-d144-4e7f-9fec-89c234f78d77"
    },
    "billing": {
        "country": "US",
        "firstName": "Melissa",
        "lastName": "Hughes",
        "address": "1225 Wilshire Blvd Apt 804",
        "city": "Los Angeles",
        "phone": "+14155527689",
        "postalCode": "90017",
        "state": "CA",
        "email": "melissa.hughes@example.com"
    },
    "reference": "R202512045",
    "shipping": {
        "country": "US",
        "firstName": "Melissa",
        "lastName": "Hughes",
        "address": "1225 Wilshire Blvd Apt 804",
        "city": "Los Angeles",
        "phone": "+14155527689",
        "postalCode": "90017",
        "state": "CA",
        "email": "melissa.hughes@example.com"
    },
    "notifyUrl": "https://www.links-pay.cc/notify",
    "currency": "USD",
    "returnUrl": "https://www.links-pay.cc/checkout.html",
    "items": [
        {
            "unitPrice": 10000,
            "name": "Women’s 3D Embroidered Bandeau Elegant Mini Dress",
            "currency": "USD",
            "quantity": "1",
            "category": "Women Clothing",
            "totalPrice": 10000
        }
    ],
    "browserInfo": {
        "screenWidth": 1920,
        "javaEnabled": false,
        "os": "Windows 10",
        "screenHeight": 1080,
        "ipAddress": "168.168.168.168",
        "browserName": "Chrome",
        "timeZone": -480,
        "javascriptEnabled": true,
        "language": "en-US",
        "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
        "colorDepth": 24
    },
    "utm":{
      "utmSource":"",
      "utmMedium":"",
      "utmTerm":"",
      "utmContent":""
    }
}

返回参数:

json
{
    "requestId": "b5cb20f9-6968-41ff-8e53-b1a9fc87a2b8",
    "success": true,
    "data": {
        "id": "P251011144163273295845",
        "reference": "R202512038",
        "status": "SUCCESS",
        "amount": 10000,
        "currency": "USD",
        "requiresAction": null,
        "nextAction": null,
        "failureMessage": null
    },
    "timestamp": "2025-10-11T14:41:23.406+08:00"
}

响应结果处理说明:

  • 当 success = false 时,表示本次接口调用失败,通常由于参数错误、签名错误、通道关闭或通道限额等原因。此时请直接读取并提示 error 字段中的错误信息。

  • 当 success = true 时,表示接口调用成功,此时应根据 data.status 进行判定支付结果,如果失败请展示 failureMessage 失败原因。

顶层结构字段说明

字段类型示例值说明
requestIdstring75daa341-66fd-4d87-949b-28f7f0ef6d64本次通知的唯一追踪 ID,由服务端生成,用于日志追踪、链路排查与问题定位。每次通知通常唯一。
successbooleantrue表示本次接口调用是否成功(接口层面)。true 表示通知调用成功并已返回业务结果;false 表示接口调用异常,如签名错误、参数缺失、权限拒绝、通道关闭等。
dataobject{...}支付结果详情对象。当 success = true 时,商户应重点解析该对象中的业务字段。
timestampstring (ISO 8601)2025-10-10T16:39:23.765+08:00通知生成时间,采用 ISO 8601 标准格式,包含毫秒与时区偏移。

data 对象字段说明(支付结果详情)

字段类型示例值说明
idstringP1231823IntPay 平台交易号。用于标识平台侧唯一交易,可用于对账、查询与问题排查。
referencestringSAIDF01239-1230商户订单号或交易参考号,由商户系统生成,用于关联商户内部订单。
requiresActionbooleanfalse是否仍需用户执行额外操作。通常用于表示是否需要完成额外验证步骤(如 3DS、OTP 等)。
amountnumber100支付金额,单位为最小货币单位。例如 USD 下 100 表示 1.00 USD
currencystringUSD支付币种,遵循 ISO 4217 三位字母代码标准。
failureMessagestringfail失败原因描述。当交易失败时返回;成功状态下通常为空、为 null 或被省略。
statusstringFAILED当前订单状态枚举值,商户应以此字段作为订单状态更新依据。

nextAction(当 requiresAction = true 时返回)

字段类型示例值说明
nextAction.typestringredirect操作类型
nextAction.urlstringhttps://3d.com跳转地址
nextAction.methodstringGET访问协议

状态枚举

状态值说明商户建议
PENDING待处理。支付请求已创建,正在等待用户操作、发卡行响应或通道处理。订单保持处理中,不要提前判定最终结果。
REQUIRES_ACTION需要下一步操作。通常表示用户需完成额外验证,如 3D Secure、OTP 或其他身份校验。引导用户继续完成验证流程,并等待后续结果通知。
SUCCEEDED支付成功。发卡行授权通过,交易已成功完成。将订单更新为成功,进入发货、入账或后续履约流程。
FAILED支付失败。可能由于发卡行拒付、风控拦截、余额不足、卡信息错误或其他原因导致。将订单更新为失败,并视业务需要记录失败原因。
CANCELED已取消。订单被商户、用户或系统主动取消,通常未完成实际扣款。将订单更新为已取消,结束本次支付流程。
REFUND_PENDING退款处理中。退款请求已提交,正在等待银行或通道处理。将订单更新为退款处理中,并等待后续通知。
REFUNDED已退款。原支付金额已成功退回持卡人账户。将订单更新为已退款,并同步售后或财务状态。
REFUND_FAILED退款失败。退款请求被通道或银行拒绝,未完成退款。保留原支付成功状态,并记录退款失败原因。
CHARGEBACK拒付。持卡人已发起争议,款项可能被强制退回。启动拒付处理流程,并同步风控、财务或客服系统。

不同支付产品或通道路由下,部分状态可能不会全部出现。
商户系统应至少完整兼容:PENDINGREQUIRES_ACTIONSUCCEEDEDFAILEDCANCELEDREFUNDED

支付处理

接口失败

success 字段:表示本次接口调用是否成功(逻辑层面)。

✅ true:接口调用正常,业务执行完成(即便支付失败,如 cvv 错误、卡号不存在、余额不足也会返回 true)。

❌ false:接口调用异常,如签名错误、参数缺失、权限拒绝等。

json
{
  "success": false,
  "message": "invalid signature"
}
  • 展示 error

接口成功

  • data.status = FAILED:代表持卡人付款失败,需要渲染错误信息(failureMessage

  • data.status = SUCCESS:代表持卡人付款成功

  • data.status = REQUIRES_ACTION:代表需要进行下一步操作,需要将 nextAction.url 发送给 SDK,由 SDK 完成后续处理

json
{
    "requestId": "b5cb20f9-6968-41ff-8e53-b1a9fc87a2b8",
    "success": true,
    "data": {
        "id": "P251011144163273295845",
        "reference": "R202512038",
        "status": "SUCCESS",
        "amount": 10000,
        "currency": "USD",
        "requiresAction": null,
        "nextAction": null,
        "failureMessage": null
    },
    "timestamp": "2025-10-11T14:41:23.406+08:00"
}

3DS 处理

您需要将nextAction.url 通过下面命令发送给SDK,由SDK自行完成后续操作

js
postMessage({
  type: 'PAY_REDIRECT',
  url: 'https://3ds-url'
})

父页面监听事件说明

PAY_CLICK 支付按钮事件

1、监听到该事件后,意味着 持卡人成功在SDK页面输入卡信息并点击支付按钮 2、SDK会来询问父页面是否需要校验物流和账单信息或创建订单

json
{ "type": "PAY_CLICK", "ready": "true" }

PAYMENT_TOKEN 支付TOKEN

父页面收到该事件后需立即请求《payments》支付接口

json
{
  "type": "PAYMENT_TOKEN",
  "status": "SUCCEEDED",
  "payToken": "xxx"
}

IFRAME_SIZE 宽高自适应

1、SDK初始化后以及页面宽高发生变动时会立即发送消息给父页面宽高度 2、父页面收到后需要立即设置iframe的width 和heigh ,给与客户更好的用户体验

js
postMessage({
  type: 'IFRAME_SIZE',
  height: '500px'
})

PAY_WINDOW 加载事件

父页面收到PAY_WINDOW事件,需判断action 状态:

  • 如果为LOADING 代表加载loading遮罩
  • HIDELOADING 代表关闭loading遮罩
  • ERROR 代表需要渲染错误信息给持卡人(但是不需要loading遮罩)
js
postMessage({
  type: 'PAY_WINDOW',
  action: 'LOADING/HIDELOADING/ERROR'
})