嵌入式集成

工作原理

后端集成

提示

确保对 IOTPay 端点的请求是在商户的服务器上执行的(而不是客户端浏览器上执行),以避免潜在的跨源资源共享(CORS)错误。

银行卡支付

在您的后端服务器上对 cc_purchase API 端点进行 POST 请求。

端点

https://ccapi.iotpaycloud.com/v3/cc_purchase

方法

POST

头部

Content-Type: application/json;charset=UTF-8

请求
名称必填类型示例描述
mchIdyString(30)10000701由 IOTPay 分配
mchOrderNoyString(30)1234567890abc由商户分配的订单号(不可重复)
amountyInt1500以分为单位
currencyyString(3)CAD目前仅支持 CAD
loginNameyString(12)jack123商户的登录名
subjectnString(64)
bodynString(250)
channelyStringPF_CCPF_CCUPI_EX
notifyUrlyString(200)支付成功时获取通知
returnUrlyString(200)https://example.com付款后重定向到此 URL
signyString(32)C380BEC2BFD727A4B6845133519F3AD6签名算法
响应
名称必填类型示例描述
retCodeyStringSUCCESS or FAIL
retMsgyString
retData.redirectUrlyString对于重定向支付,请忽略此字段,嵌入式集成请使用 retData.secureId 字段
retData.secureIdyString仅供嵌入式 SDK 集成使用

Info

确保将 secureId 提供给客户端。

银行卡令牌化

在您的后端服务器上对 cc_addCard API 端点进行 POST 请求。

端点 - 添加银行卡

https://ccapi.iotpaycloud.com/v3/cc_addCard

方法

POST

Content-Type: application/json;charset=UTF-8

请求
名称必填类型示例描述
mchIdyString(30)0000701由 IOTPay 分配
cardIdyString(30)604567999由商户分配,必须唯一
loginNameyString(12)jack123商户的登录名
channelyStringPF_CCPF_CCUPI_EX
returnUrlyString(200)添加卡后重定向到此 URL
signyString(32)C380BEC2BFD727A4B6845133519F3AD6签名算法

请注意

每个 cardId 只能绑定一张信用卡,如果一个用户需要绑定多张卡,请使用不同的 cardId

响应
名称必填类型示例描述
retCodeyStringSUCCESS or FAIL
retMsgyString
retData.redirectUrlyString对于重定向支付,请忽略此字段,嵌入式集成请使用 retData.secureId 字段
retData.secureIdyString仅供嵌入式 SDK 集成使用

Info

确保将 secureId 提供给客户端。

前端集成

Info

您将需要上面响应中的 secureId 来通过 JS SDK 创建 IOTPay iframe 实例。

添加一个占位符 div

<div id="iotpay_normal"></div>

添加一个 HTML script 标签

<script
  type="text/javascript"
  src="https://ccapi.iotpaycloud.com/cc/iotpaycc.js"
></script>
const script = document.createElement('script')
script.src = 'https://ccapi.iotpaycloud.com/cc/iotpaycc.js'
script.type = 'text/javascript'
script.async = true

从 API 调用中获取 secureId 后,将 iframe 挂载到占位符 div 中

注意

为了符合 PCI 合规性在新窗口打开, 您必须直接从 https://ccapi.iotpaycloud.com/cc/iotpaycc.js在新窗口打开 加载 IOTPay.js。请不要将其包含在捆绑包中或自行托管。

<script>
  let callback = function (event) {
    console.log(event)
    if (event.result == 'SUCCESS') {
      // 添加/支付成功
      // 返回的数据将包含在 event.detail 中
      // if (event.detail.retData && event.detail.retData.redirectUrl) {
      //     window.location.replace(event.detail.retData.redirectUrl);
      // }
    } else if (event.result == 'FAIL' && event.message == 'Timeout') {
      // 银联要求查询订单。在尝试 30 次后,我们将超时,商户需要查询订单。
      //
    } else if (event.result == 'FAIL') {
      // 添加/支付失败
      // 返回的数据将包含在 event.detail 中
      // if (event.detail.retData && event.detail.retData.redirectUrl) {
      //     window.location.replace(event.detail.retData.redirectUrl);
      // }
    }
    if (event.detail.retData && event.detail.retData.redirectUrl) {
      window.location.replace(event.detail.retData.redirectUrl)
    }
  }
  let secureId = '3abcd*******3abcd' // 从 addCard 或 Purchase 终点获取 secureId
  let iotpay_normal = Iotpay(secureId, 'Pay') // 第二个参数必须是 Add(添加卡)或 Pay
  iotpay_normal.mount('#iotpay_normal', callback)
</script>
async loadIOTLibrary() {
    const script = document.createElement('script');
    script.src = "https://ccapi.iotpaycloud.com/cc/iotpaycc.js";
    script.type = "text/javascript";
    script.async = true;

    return new Promise((resolve, reject) => {
        script.onload = () => {
            // 首先,我们需要调用 API 获取 secureId
            let reqBody = {
                mchUserId: "test",
                mchOrderNo: uuidV4(),
                amount: this.state.order.total * 100, // 确保单位为分
                channel: "PF_CC", // 或者 UPI_EX
                returnUrl: "https://test.merchant.com/payment/result",
                notifyUrl: "https://test.merchant.com/webhook/getNotify"
            }

            // 用商户的 API 密钥替换第二个参数
            reqBody = this.getSignedBody(reqBody, "==== merchantAPIKey ====");

            // 向商户的后端服务器发出请求,在那里会调用 'cc_purchase'
            axios.post('http://test.merchant.server/v1/iotpay/purchase', reqBody)
                .then(res => {
                    if (res.status === 200 && res.data.retCode === "SUCCESS" && res.data.retData.secureId) {
                        let order = this.state.order;
                        order.payment_id = res.data.retData.secureId;
                        this.setState({ order })

                        // iframe 选项,此字段不是强制性的
                        const options = {
                            "darkMode": true,
                            "theme": "card",
                            "button": {
                                "text": "立即支付!",
                                "color": "#fff",
                                "backgroundColor": "#f90",
                                "backgroundImage": "none",
                                "boxShadow": "none",
                                "height": "60px",
                                "borderRadius": '0px'
                            }
                        };

                        // 第二个参数必须是 Add(为将来的购买添加客户信用卡)或 Pay
                        let iotpay_normal = window.Iotpay(res.data.retData.secureId, 'Pay', options);

                        // IOTCallback 是处理支付结果回调的函数
                        iotpay_normal.mount('#iotpay_normal', this.IOTCallback);
                    } else {
                        // 处理失败的请求 - 例如:
                        reject(new Error(res.data.retMsg))
                    }
                })

            resolve();
        }
        script.onerror = () => {
            reject(new Error('加载 IOTPay 库失败。'));
        };

        document.body.appendChild(script);
    })
}

IOTCallback(event) {
    console.log(event);
    if (event.result === 'SUCCESS') {
        // 添加/支付成功
        // 返回的数据将包含在 event.detail 中
        // if (event.detail.retData && event.detail.retData.redirectUrl) {
        //     window.location.replace(event.detail.retData.redirectUrl);
        // }
    } else if (event.result === 'FAIL' && event.message === 'Timeout') {
        // 银联要求查询订单。在尝试 30 次后,我们将超时,商户需要查询订单。
        //
    } else if (event.result === 'FAIL') {
        // 添加/支付失败
        // 返回的数据将包含在 event.detail 中
        // if (event.detail.retData && event.detail.retData.redirectUrl) {
        //     window.location.replace(event.detail.retData.redirectUrl);
        // }
    }
    if (event.detail.retData && event.detail.retData.redirectUrl) {
        window.location.replace(event.detail.retData.redirectUrl);
    }
}

附加的 SDK 和文档

iOS 集成:iOS sdk在新窗口打开

Android 集成:Android sdk在新窗口打开

PHP 和 JS 集成:Php sdk在新窗口打开

上次更新: