GLODIPAY iFrame 银行卡 API 规范
版本 2.0.0
目录
使用测试环境。不产生实际费用。
| 无 3DS | 4111 1111 1111 1111 | 01/30 | 029 | — |
| 无 3DS | 5555 5555 5555 4444 | 01/30 | 029 | — |
| 3DS 付款 | 4012 8888 8888 1881 | 01/30 | 029 | 成功:123456 / 失败:111111 |
| 3DS 付款 | 5111 1111 1111 1118 | 01/30 | 029 | 成功:123456 / 失败:111111 |
| 3DS 付款 | 4141 4141 4141 4141 | 12/30 | 123 | 成功:123456 / 失败:111111 |
介绍
本文档描述了 GLODIPAY iFrame 银行卡 API v2,它允许商户使用 HTML <iframe> 将 GLODIPAY 托管的银行卡输入表单嵌入到自己的网页中。
流程概述:
- 商户服务器发送 POST 请求到
/v2/card/iframe以创建银行卡会话。 - GLODIPAY 返回一个已签名的临时 URL,指向托管的银行卡输入表单。
- 商户在自己的结账页面上将此 URL 嵌入到
<iframe>中。 - 买家在 iframe 内的 GLODIPAY 托管表单上输入银行卡详情。
- GLODIPAY 处理付款,并通过 IPN 将结果发送到
notificationUrl,然后将买家重定向到callbackUrl或errorUrl。
商户页面可以保持其布局,而 GLODIPAY 则安全地处理银行卡数据。银行卡会话 URL 将在 expiresAt 指定的时间过期(默认:24 小时)。
接口地址 (Endpoints)
| 测试环境 | 将另 行提供 |
| 生产环境 | 从商户后台的 API Keys 页面获取 |
签名 (Signature)
所有发送给 GLODIPAY 的请求必须包含 signature 字段。所有来自 GLODIPAY 的响应和 IPN Payload 也包含 signature 字段以验证真实性。
签名使用 RSA with MD5 (md5WithRSAEncryption)。
生成签名 (商户 -> GLODIPAY)
使用您的 商户私钥(可从商户后台获取)。
步骤:
- 将除
signature以外的所有请求参数收集为扁平的键值对象。 - 仅按 自然升序 对 顶层键 进行排序(PHP 中的
SORT_NATURAL/ JavaScript 中带有{ numeric: true }的localeCompare)。不要对嵌套对象(如fees、paymentMethodDetails)内部的键进行排序。 - 递归修整所有字符串值的空格。
- 序列化为 JSON 字符串。
- 使用
openssl_sign(..., 'md5WithRSAEncryption')进行签名。 - 对二进制输出进行 Base64 编码。
验证签名 (GLODIPAY -> 商户)
使用 GLODIPAY 公钥(可在门户网站获取)。
步骤:
- 从 Payload 中移除
signature。 - 仅按自然升序对 顶层键 进行排序。不要对嵌套对象内部的键进行排序。
- 递归修整所有字符串值的空格。
- 序列化为 JSON 字符串。
- 使用
openssl_verify(..., base64_decode($signature), $publicKey, 'md5WithRSAEncryption')进行验证。 - 返回值
1= 有效。
注意 (Node.js):在排序/序列化之前将所有数字值转换为字符串。转义 JSON 字符串中的正斜杠:.replace(///g, '\/')。
POST PAYMENT
创建银行卡 iframe 会话。GLODIPAY 返回一个已签名的 URL,指向托管的银行卡输入表单,商户将其嵌入到 <iframe> 中。
接口地址: POST /v2/card/iframe
请求方法: POST
Content-Type: application/x-www-form-urlencoded
请求参数
| merchantId | String(1,50) | M | 商户 ID |
| orderRef | String(1,250) | M | 每个商户唯一的交易参考号 |
| amount | Float | M | 发票金额。最小值:1。最多 2 位小数 |
| currency | String(3) | M | ISO 4217 货币代码。例如:USD |
| cancelUrl | String(1,300) | M | 取消时重定向买家的 URL。必须为 https |
| callbackUrl | String(1,300) | M | 付款成功后重定向买家的 URL。必须为 https |
| notificationUrl | String(1,300) | M | 您的服务器接收 IPN Webhook 的接口。必须为 https |
| errorUrl | String(1,300) | M | 出错时重定向买家的 URL。必须为 https |
| orderDescription | String(max:3000) | M | 订单简短描述 |
| metadata | JSON | O | 附加到会话的键值对。在 IPN 和查询响应中返回 |
| transactionDocuments | JSON | O | 交易的辅助文档 |
| paymentMethod | String | M | 对于 iframe 银行卡会话,必须为 card |
| feeBySeller | Number(0-100) | O | 商户支付的手续费百分比。0 = 买家支付 100%。最多 2 位小数 |
| billingEmail | String(max:255) | O | 买家电子邮件地址 |
| billingCountry | String | O | ISO 3166-1 alpha-2 国家代码 |
| billingFirstName | String(max:255) | O | 账单名字 |
| billingLastName | String(max:255) | O | 账单姓氏 |
| billingStreet1 | String(max:255) | O | 账单街道 1 |
| billingStreet2 | String(max:255) | O | 账单街道 2 |
| billingCity | String(max:255) | O | 账单城市 |
| billingState | String(2,255) | O | 账单州/省 |
| billingPostalCode | String(max:25) | O | 邮政编码 |
| billingPhoneCountryCode | String(max:10) | O | 电话国家代码 |
| billingPhoneNumber | String(max:20) | O | 电话号码 |
| customerIp | String | O | 客户的 IP 地址 |
| websiteUrl | String(max:300) | O | 商户网站 URL |
| brandName | String(1,255) | O | 覆盖在银行卡表单上显示的品牌名称 |
| colorMode | String(1,255) | O | 最多 3 种颜色,用 --- 分隔。例如:#2e7d32---#e8f5e9---#81c784 |
| logoSource | String(1,255) | O | 覆盖在银行卡表单上显示的 Logo |
| signature | String(max:750) | M | RSA-MD5 签名。请参阅“签名”部分 |
| expiresAt | String | O | ISO 8601 格式的会话过期时间。例如:2025-09-14T14:03:42.102862Z。默认:24 小时 |
M = 必填,O = 可选
请求示例
{
"merchantId": "1100000123",
"orderRef": "ORDER-001",
"amount": "100.00",
"currency": "USD",
"paymentMethod": "card",
"callbackUrl": "https://yoursite.com/callback",
"notificationUrl": "https://yoursite.com/webhook",
"cancelUrl": "https://yoursite.com/cancel",
"errorUrl": "https://yoursite.com/error",
"orderDescription": "Test order",
"billingFirstName": "John",
"billingLastName": "Doe",
"billingStreet1": "123 Main St",
"billingStreet2": "",
"billingCity": "New York",
"billingEmail": "john@example.com",
"billingState": "NY",
"billingCountry": "US",
"billingPostalCode": "10001",
"billingPhoneCountryCode": "1",
"billingPhoneNumber": "5551234567",
"customerIp": "1.2.3.4",
"signature": "base64-encoded-signature"
}
响 应
Content-Type: application/json
| status | String | created |
| transactionId | String (ULID) | GLODIPAY 交易 ID |
| url | String | 已签名的托管银行卡输入表单 URL —— 将此嵌入到 <iframe/> 中 |
| message | String | 人类可读的消息 |
成功示例:
{
"status": "created",
"transactionId": "01jza90dy6w82dfrrqvadn5vs4",
"url": "https://payment.gpayprocessing.com/v2/card-iframe/01jza90dy6w82dfrrqvadn5vs4?...",
"message": "Iframe card created successfully"
}
错误示例:
{
"status": "error",
"transactionId": null,
"url": null,
"message": "No active payment service providers found. Please contact support."
}
嵌入 iFrame
收到 url 后,将其嵌入到您的页面中:
<iframe
src="{url}"
width="100%"
height="600"
frameborder="0"
scrolling="no"
allowtransparency="true">
</iframe>
该 URL 已签名并将在 expiresAt 到期。请勿在当前结账会话之外存储或共享它。买家必须在会话到期时间内完成付款。
交易查询 (TRANSACTION QUERY)
查询交易的当前状态和完整详情。
接口地址: POST /v2/checkout/query
请求方法: POST
Content-Type: application/json
请求 (Request)
| transactionId | String (ULID) | M | GLODIPAY 交易 ID |
| signature | String(max:750) | M | RSA-MD5 签名 |
响应 (Response)
Content-Type: application/json
| merchantId | String | 商户 ID |
| transactionId | String | GLODIPAY 交易 ID (ULID) |
| transactionNumber | String | GLODIPAY 人类可读的交易编号 |
| ref | String | 商户的 orderRef |
| currency | String | ISO 4217 货币代码 |
| amount | Float | 发票金额 |
| paidAmount | Float | 实际向买家收取的金额(包括买家费用) |
| settlementAmount | Float | 结算给商户的金额 |
| estimationSettlementAt | ISO 8601 datetime | 预计结算日期时间 |
| fees | JSON | 费用明细。请参阅 fees 对象 |
| status | String | 交易状态。请参阅“状态值”部分 |
| statusCode | Number | 数字状态码。请参阅“状态码”部分 |
| metadata | JSON | 原始会话中的键值对 |
| transactionDocuments | JSON | 辅助文档 |
| paymentMethodDetails | JSON | 所使用的付款方式。请参阅 paymentMethodDetails 对象 |
| message | String | 人类可读的状态消息 |
| descriptor | String | 交易描述符 |
| transactionCreatedAt | ISO 8601 datetime | GLODIPAY 系统中的交易创建时间 |
| originalTransactionCreatedAt | ISO 8601 datetime | 支付渠道侧的交易创建时间 |
| signature | String | RSA-MD5 签名 —— 使用 GLODIPAY 公钥验证 |
通知 (NOTIFICATION)
当交易达到终端状态时,GLODIPAY 会向您的 notificationUrl 发送 HTTP POST 请求。
请求方法: POST
Content-Type: application/json
重试策略: GLODIPAY 可能会重新发送尚未确认交易的 IPN。您的服务器应在收到通知后立即返回 {"returnCode":"100"}。
Payload
| merchantId | String | M | 商户 ID |
| transactionId | String | M | GLODIPAY 交易 ID (ULID) |
| transactionNumber | String | M | GLODIPAY 人类可读的交易编号 |
| ref | String | M | 商户的 orderRef |
| currency | String | M | ISO 4217 货币代码 |
| amount | Float | M | 发票金额 |
| paidAmount | Float | O | 实际向买家收取的金额(包括买家费用) |
| settlementAmount | Float | O | 结算给商户的金额 |
| estimationSettlementAt | ISO 8601 datetime | O | 预计结算日期时间 |
| fees | JSON | O | 费用明细。请参阅 fees 对象 |
| paymentMethodDetails | JSON | O | 所使用的付款方式。请参阅 paymentMethodDetails 对象 |
| status | String | M | 交易状态。请参阅“状态值”部分 |
| statusCode | Number | M | 数字状态码。请参阅“状态码”部分 |
| metadata | JSON | O | 原始会话中的键值对 |
| transactionDocuments | JSON | O | 辅助文档 |
| message | String | O | 人类可读的状态消息 |
| descriptor | String | O | 交易描述符 |
| transactionCreatedAt | ISO 8601 datetime | M | GLODIPAY 系统中的交易创建时间 |
| originalTransactionCreatedAt | ISO 8601 datetime | M | 支付渠道侧的交易创建时间 |
| signature | String | M | RSA-MD5 签名 —— 使用 GLODIPAY 公钥验证 |
fees 对象
| buyer | Float | 面向买家的费用金额 |
| seller | Float | 商户费用金额 |
| rolling | Float | 滚动保证金金额 |
| operate | Float | 总运营费用(渠道商 + GLODIPAY + 合作伙伴) |
| estimationRollingReleaseAt | ISO 8601 datetime | 预计滚动保证金释放日期时间 |
paymentMethodDetails 对象
| displayName | String | 付款方式标签 |
| group | String | 付款方式组类型 |
| family | String | 付款方式系列类型 |
| type | String | 付款方式类型 |
{type} | JSON | 可选。付款方式特定的详细信息。键名等于 type 的值(如 card)。仅在银行卡详细信息可用时出现在银行卡付款中。请参阅下面的 card 对象。 |
card 对象 (paymentMethodDetails.card)
| name | 持卡人姓名 |
| firstSixDigits | 卡号前 6 位 (BIN) |
| lastFourDigits | 卡号后 4 位 |
| expiryMonth | 过期月份 (MM) |
| expiryYear | 过期年份 (YY) |
| type | 银行卡品牌 (visa, mastercard, amex 等) |
| issuer | 发卡行名称 (取决于渠道) |
| issuerCountryCode | 发卡行国家代码 (ISO 3166-1 alpha-2) (取决于渠道) |
| funding | 银行卡资金类型 (credit, debit, prepaid) (取决于渠道) |
| authorizationCode | 发卡行授权码 (取决于渠道) |
| clientIP | 付款时的客户 IP 地址 (取决于渠道) |
| checks | AVS/CVC 验证结果 (取决于渠道) |
| threeDSecure | 3D Secure 认证详细信息 (取决于渠道) |
IPN Payload 示例:
{
"merchantId": "1100000123",
"transactionId": "01jza90dy6w82dfrrqvadn5vs4",
"transactionNumber": "2604-1713100800",
"ref": "ORDER-001",
"currency": "USD",
"amount": 100.00,
"paidAmount": 105.00,
"settlementAmount": 95.00,
"estimationSettlementAt": "2026-04-16T00:00:00+00:00",
"fees": {
"buyer": 5.00,
"seller": 5.00,
"rolling": 2.00,
"operate": 3.00,
"estimationRollingReleaseAt": "2026-05-14T00:00:00+00:00"
},
"status": "successful",
"statusCode": 6,
"paymentMethodDetails": {
"displayName": "Credit / Debit Card",
"group": "card",
"family": "card",
"type": "card"
},
"metadata": { "orderId": "12345" },
"transactionCreatedAt": "2026-04-14T10:00:00+00:00",
"originalTransactionCreatedAt": "2026-04-14T10:00:01+00:00",
"signature": "base64-encoded-rsa-signature"
}
响应 (商户 -> GLODIPAY)
您的服务器必须在 30 秒 内响应:
{
"returnCode": "100",
"description": "Received"
}
| returnCode | String | R | 必须为 "100" 以确认收到 |
| description | String(1,1500) | O | 可选描述 |
模拟付款
使用测试环境。不产生实际费用。
| 无 3DS | 4111 1111 1111 1111 | 01/30 | 029 | — |
| 无 3DS | 5555 5555 5555 4444 | 01/30 | 029 | — |
| 3DS 付款 | 4012 8888 8888 1881 | 01/30 | 029 | 成功:123456 / 失败:111111 |
| 3DS 付款 | 5111 1111 1111 1118 | 01/30 | 029 | 成功:123456 / 失败:111111 |
| 3DS 付款 | 4141 4141 4141 4141 | 12/30 | 123 | 成功:123456 / 失败:111111 |
附录
状态值
在 IPN Payload 和查询响应的 status 字段中返回的字符串值。
| incomplete | 交易已发起,等待操作 |
| pending | 等待付款确认 |
| under_review | 交易审核中 |
| successful | 付款成功完成 |
| failed | 付款失败 |
| error | 发生系统错误 |
| canceled | 交易已取消 |
| rejected | 交易被拒绝 |
| expired | 交易已过期 |
| released | 资金已释放 / 结算 |
| documents_uploaded | 辅助文档已上传 |
| refund_initiated | 退款请求已发起 |
| refund_under_review | 退款审核中 |
| refund_successful | 退款成功完成 |
| refund_failed | 退款失败 |
| refund_partially_successful | 部分退款完成 |
| refund_partially_failed | 部分退款失败 |
| void_initiated | 撤销已发起 |
| void_under_review | 撤销审核中 |
| void_successful | 撤销成功完成 |
| void_failed | 撤销失败 |
| void_partially_successful | 部分撤销 完成 |
| void_partially_failed | 部分撤销失败 |
| chargeback_alert | 收到拒付警报 |
| chargebacked | 交易已拒付 |
| dispute | 争议已开启 |
状态码
在 IPN Payload 和查询响应的 statusCode 字段中的数字代码。
| 1 | incomplete | 交易已发起 |
| 2 | pending | 等待确认 |
| 3 | error | 系统错误 |
| 4 | failed | 付款失败 |
| 5 | under_review | 审核中 |
| 6 | successful | 付款成功 |
| 7 | released | 已释放 / 结算 |
| 8 | refund_initiated | 退款已发起 |
| 9 | refund_failed | 退款失败 |
| 10 | refund_under_review | 退款审核中 |
| 11 | refund_successful | 退款成功 |
| 12 | refund_partially_failed | 部分退款失败 |
| 13 | refund_partially_successful | 部分退款成功 |
| 14 | canceled | 已取消 |
| 15 | rejected | 已拒绝 |
| 16 | expired | 已过期 |
| 17 | documents_uploaded | 文档已上传 |
| 18 | void_initiated | 撤销已发起 |
| 19 | void_under_review | 撤销审核中 |
| 20 | void_successful | 撤销成功 |
| 21 | void_failed | 撤销失败 |
| 22 | void_partially_successful | 部分撤销成功 |
| 23 | void_partially_failed | 部分撤销失败 |
| 24 | chargeback_alert | 拒付警报 |
| 25 | chargebacked | 已拒付 |
| 26 | dispute | 争议已开启 |
货币代码
GLODIPAY 遵循 ISO 4217 标准。此接口目前仅接受 USD。
| USD | 美元 |
国家代码
GLODIPAY 在 billingCountry 字段中使用 ISO 3166-1 alpha-2 两位字母代码。
| AD | 安道尔 |
| AE | 阿拉伯联合酋长国 |
| AF | 阿富汗 |
| AG | 安提瓜和巴布达 |
| AI | 安圭拉 |
| AL | 阿尔巴尼亚 |
| AM | 亚美尼亚 |
| AO | 安哥拉 |
| AQ | 南极洲 |
| AR | 阿根廷 |
| AS | 美属萨摩亚 |
| AT | 奥地利 |
| AU | 澳大利亚 |
| AW | 阿鲁巴 |
| AX | 奥兰群岛 |
| AZ | 阿塞拜疆 |
| BA | 波斯尼亚和黑塞哥维那 |
| BB | 巴巴多斯 |
| BD | 孟加拉国 |
| BE | 比利时 |
| BF | 布基纳法索 |
| BG | 保加利亚 |
| BH | 巴林 |
| BI | 布隆迪 |
| BJ | 贝宁 |
| BL | 圣巴泰勒米 |
| BM | 百慕大 |
| BN | 文莱达鲁萨兰国 |
| BO | 多民族玻利维亚国 |
| BQ | 博内尔、圣尤斯特歇斯和萨巴 |
| BR | 巴西 |
| BS | 巴哈马 |
| BT | 不丹 |
| BV | 布韦岛 |
| BW | 博茨瓦纳 |
| BY | 白俄罗斯 |
| BZ | 伯利兹 |
| CA | 加拿大 |
| CC | 科科斯(基林)群岛 |
| CD | 刚果民主共和国 |
| CF | 中非共和国 |
| CG | 刚果 |
| CH | 瑞士 |
| CI | 科特迪瓦 |
| CK | 库克群岛 |
| CL | 智利 |
| CM | 喀麦隆 |
| CN | 中国 |
| CO | 哥伦比亚 |
| CR | 哥斯达黎加 |
| CU | 古巴 |
| CV | 佛得角 |
| CW | 库拉索 |
| CX | 圣诞岛 |
| CY | 塞浦路斯 |
| CZ | 捷克 |
| DE | 德国 |
| DJ | 吉布提 |
| DK | 丹麦 |
| DM | 多米尼克 |
| DO | 多米尼加共和国 |
| DZ | 阿尔及利亚 |
| EC | 厄瓜多尔 |
| EE | 爱沙尼亚 |
| EG | 埃及 |
| EH | 西撒哈拉 |
| ER | 厄立特里亚 |
| ES | 西班牙 |
| ET | 埃塞俄比亚 |
| FI | 芬兰 |
| FJ | 斐济 |
| FK | 福克兰群岛 |
| FM | 密克罗尼西亚 |
| FO | 法罗群岛 |
| FR | 法国 |
| GA | 加蓬 |
| GB | 英国 |
| GD | 格林纳达 |
| GE | 格鲁吉亚 |
| GF | 法属圭亚那 |
| GG | 根西岛 |
| GH | 加纳 |
| GI | 直布罗陀 |
| GL | 格陵兰 |
| GM | 冈比亚 |
| GN | 几内亚 |
| GP | 瓜德罗普 |
| GQ | 赤道几内亚 |
| GR | 希腊 |
| GS | 南乔治亚岛和南桑威奇群岛 |
| GT | 危地马拉 |
| GU | 关岛 |
| GW | 几内亚比绍 |
| GY | 圭亚那 |
| HK | 香港 |
| HM | 赫德岛和麦克唐纳群岛 |
| HN | 洪都拉斯 |
| HR | 克罗地亚 |
| HT | 海地 |
| HU | 匈牙利 |
| ID | 印度尼西亚 |
| IE | 爱尔兰 |
| IL | 以色列 |
| IM | 马恩岛 |
| IN | 印度 |
| IO | 英属印度洋领地 |
| IQ | 伊拉克 |
| IR | 伊朗 |
| IS | 冰岛 |
| IT | 意大利 |
| JE | 泽西岛 |
| JM | 牙买加 |
| JO | 约旦 |
| JP | 日本 |
| KE | 肯尼亚 |
| KG | 吉尔吉斯斯坦 |
| KH | 柬埔寨 |
| KI | 基里巴斯 |
| KM | 科摩罗 |
| KN | 圣基茨和尼维斯 |
| KP | 朝鲜 |
| KR | 韩国 |
| KW | 科威特 |
| KY | 开曼群岛 |
| KZ | 哈萨克斯坦 |
| LA | 老挝 |
| LB | 黎巴嫩 |
| LC | 圣卢西亚 |
| LI | 列支敦士登 |
| LK | 斯里兰卡 |
| LR | 利比里亚 |
| LS | 莱索托 |
| LT | 立陶宛 |
| LU | 卢森堡 |
| LV | 拉脱维亚 |
| LY | 利比亚 |
| MA | 摩洛哥 |
| MC | 摩纳哥 |
| MD | 摩尔多瓦 |
| ME | 黑山 |
| MF | 圣马丁 (法属) |
| MG | 马达加斯加 |
| MH | 马绍尔群岛 |
| MK | 北马其顿 |
| ML | 马里 |
| MM | 缅甸 |
| MN | 蒙古 |
| MO | 澳门 |
| MP | 北马里亚纳群岛 |
| MQ | 马提尼克 |
| MR | 毛里塔尼亚 |
| MS | 蒙特塞拉特 |
| MT | 马耳他 |
| MU | 毛里求斯 |
| MV | 马尔代夫 |
| MW | 马拉维 |
| MX | 墨西哥 |
| MY | 马来西亚 |
| MZ | 莫桑比克 |
| NA | 纳米比亚 |
| NC | 新喀里多尼亚 |
| NE | 尼日尔 |
| NF | 诺福克岛 |
| NG | 尼日利亚 |
| NI | 尼加拉瓜 |
| NL | 荷兰 |
| NO | 挪威 |
| NP | 尼泊尔 |
| NR | 瑙鲁 |
| NU | 纽埃 |
| NZ | 新西兰 |
| OM | 阿曼 |
| PA | 巴拿马 |
| PE | 秘鲁 |
| PF | 法属波利尼西亚 |
| PG | 巴布亚新几内亚 |
| PH | 菲律宾 |
| PK | 巴基斯坦 |
| PL | 波兰 |
| PM | 圣皮埃尔和密克隆 |
| PN | 皮特凯恩 |
| PR | 波多黎各 |
| PS | 巴勒斯坦 |
| PT | 葡萄牙 |
| PW | 帕劳 |
| PY | 巴拉圭 |
| QA | 卡塔尔 |
| RE | 留尼汪 |
| RO | 罗马尼亚 |
| RS | 塞尔维亚 |
| RU | 俄罗斯 |
| RW | 卢旺达 |
| SA | 沙特阿拉伯 |
| SB | 所罗门群岛 |
| SC | 塞舌尔 |
| SD | 苏丹 |
| SE | 瑞典 |
| SG | 新加坡 |
| SH | 圣赫勒拿 |
| SI | 斯洛文尼亚 |
| SJ | 斯瓦尔巴和扬马延 |
| SK | 斯洛伐克 |
| SL | 塞拉利昂 |
| SM | 圣马力诺 |
| SN | 塞内加尔 |
| SO | 索马里 |
| SR | 苏里南 |
| SS | 南苏丹 |
| ST | 圣多美和普林西比 |
| SV | 萨尔瓦多 |
| SX | 圣马丁 (荷属) |
| SY | 叙利亚 |
| SZ | 斯威士兰 |
| TC | 特克斯和凯科斯群岛 |
| TD | 乍得 |
| TF | 法属南部领土 |
| TG | 多哥 |
| TH | 泰国 |
| TJ | 塔吉克斯坦 |
| TK | 托克劳 |
| TL | 东帝汶 |
| TM | 土库曼斯坦 |
| TN | 突尼斯 |
| TO | 汤加 |
| TR | 土耳其 |
| TT | 特立尼达和多巴哥 |
| TV | 图瓦卢 |
| TW | 台湾 |
| TZ | 坦桑尼亚 |
| UA | 乌克兰 |
| UG | 乌干达 |
| UM | 美国本土外小岛屿 |
| US | 美国 |
| UY | 乌拉圭 |
| UZ | 乌兹别克斯坦 |
| VA | 圣座 |
| VC | 圣文森特和格林纳丁斯 |
| VE | 委内瑞拉 |
| VG | 英属维尔京群岛 |
| VI | 美属维尔京群岛 |
| VN | 越南 |
| VU | 瓦努阿图 |
| WF | 瓦利斯和富图纳 |
| WS | 萨摩亚 |
| YE | 也门 |
| YT | 马约特 |
| ZA | 南非 |
| ZM | 赞比亚 |
| ZW | 津巴布韦 |
卡类型
| 1 | VISA | visa |
| 2 | MASTERCARD | mastercard |
| 3 | AMERICAN EXPRESS | amex |
| 4 | JCB | jcb |
| 5 | MAESTRO | maestro |
| 6 | DISCOVER | discover |
| 7 | UNION PAY | union-pay |
| 8 | DINERS | diners |
代码示例
PHP
<?php
function generateSignature(array $data): string
{
$privateKey = openssl_pkey_get_private("-----BEGIN PRIVATE KEY-----
YOUR_PRIVATE_KEY_HERE
-----END PRIVATE KEY-----
");
ksort($data, SORT_NATURAL);
array_walk_recursive(
$data,
static function (&$field) {
$field = trim($field);
}
);
openssl_sign(json_encode($data), $signature, $privateKey, 'md5WithRSAEncryption');
return base64_encode($signature);
}
// 示例:创建一个 v2 card iframe 会话
$payload = [
'merchantId' => '1100000123',
'orderRef' => 'ORDER-' . time(),
'amount' => '100.00',
'currency' => 'USD',
'paymentMethod' => 'card',
'callbackUrl' => 'https://yoursite.com/payment/callback',
'notificationUrl' => 'https://yoursite.com/payment/webhook',
'cancelUrl' => 'https://yoursite.com/payment/cancel',
'errorUrl' => 'https://yoursite.com/payment/error',
'orderDescription' => 'Test order',
'billingEmail' => 'customer@example.com',
];
$payload['signature'] = generateSignature($payload);
$ch = curl_init('https://payment-sandbox.gpayprocessing.com/v2/card/iframe');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
// 在您的结账页面上将 $result['url'] 嵌入到 iframe 中
echo '<iframe src="' . htmlspecialchars($result['url']) . '" width="100%" height="600" frameborder="0"></iframe>';
Node.js
// Save as script.mjs and run: node script.mjs
import { createSign } from 'crypto';
import https from 'https';
const PRIVATE_KEY = `-----BEGIN PRIVATE KEY-----
YOUR_PRIVATE_KEY_HERE
-----END PRIVATE KEY-----`;
function phpCast(v) {
if (typeof v === 'number') return String(v);
if (typeof v === 'boolean') return v ? '1' : '';
if (typeof v === 'string') return v.trim();
if (Array.isArray(v)) return v.map(phpCast);
if (v && typeof v === 'object') return Object.fromEntries(Object.entries(v).map(([k, val]) => [k, phpCast(val)]));
return v;
}
function generateSignature(data) {
const sorted = {};
Object.keys(data)
.filter(k => k !== 'signature')
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }))
.forEach(k => { sorted[k] = data[k]; });
const canonical = JSON.stringify(phpCast(sorted))
.replace(/\//g, '\\/')
.replace(/[\u0080-\uffff]/g, c => '\\u' + c.charCodeAt(0).toString(16).padStart(4, '0'));
const sign = createSign('md5WithRSAEncryption');
sign.update(canonical);
return sign.sign(PRIVATE_KEY, 'base64');
}
// 示例:创建一个 card iframe 会话
const payload = {
merchantId: '1100000123',
orderRef: 'ORDER-001',
amount: '100.00',
currency: 'USD',
paymentMethod: 'card',
callbackUrl: 'https://yoursite.com/payment/callback',
notificationUrl: 'https://yoursite.com/payment/webhook',
cancelUrl: 'https://yoursite.com/payment/cancel',
errorUrl: 'https://yoursite.com/payment/error',
orderDescription: 'Test order',
billingEmail: 'customer@example.com',
};
payload.signature = generateSignature(payload);
const postData = new URLSearchParams(payload).toString();
const options = {
hostname: 'payment-sandbox.gpayprocessing.com',
path: '/v2/card/iframe',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData),
},
};
const req = https.request(options, (res) => {
let body = '';
res.on('data', chunk => body += chunk);
res.on('end', () => {
const result = JSON.parse(body);
console.log('Iframe URL:', result.url);
});
});
req.on('error', console.error);
req.write(postData);
req.end();