跳转到主要内容
阅读该接口文档前,务必先查看 接口说明
  • 针对信用卡交易,消费者有权在交易发生后180天内发起争议申请。当争议被提起时,每笔交易将产生20美元的争议处理费。
  • 在收到争议通知后,您有两种应对方式可供选择
    • 其一:您可以选择接受争议,即向发卡银行提交回复,确认您不对退款金额提出异议。
    • 其二:您可以选择对争议进行抗辩,通过完成一个引导式的提交流程,根据提示提供相关证据和支持性文件来阐述您的立场。
  • 若您选择对争议进行抗辩,将额外收取20美元的抗辩费。如果发卡银行不接受您提交的抗辩材料并判定消费者胜诉,抗辩费将被扣除,同时消费者的付款将被退还。
  • 关于费用退还政策,如果您成功赢得争议,Haipay将退还抗辩费。然而,除非您的Haipay合同中另有明确规定,否则最初收取的争议处理费在任何情况下均不予退还。
  1. PCI 合规性:直接违反 PCI DSS 要求
  2. 安全风险:WebView 和 iframe 可能无法提供足够的安全隔离
  3. 中间人攻击:恶意应用可能拦截或篡改支付数据
  4. 钓鱼风险:无法确保用户是在可信的环境中输入敏感信息

设备环境要求

如果您在支付页面中看不到您想要的钱包,则您的设备或浏览器可能不符合以下 Apple Pay 或 Google Pay 条件。
  • 钱包里必须至少有一张卡。
  • 您必须使用兼容的 Apple Pay 设备Google Pay 设备
  • 您必须使用 必须使用HTTPS支持的浏览器 来测试您正在测试的钱包。
  • 允许适用的浏览器访问您的钱包。
    • Chrome:设置 > 自动填充和密码 > 付款方式 > 允许网站检查您是否已保存付款方式
    • Safari:设置 > 高级 > 允许网站检查 Apple Pay 和 Apple 卡
  • 不要使用 Chrome 隐身窗口或 Safari 私人窗口。
  • 确认您在受支持的 Apple Pay 地区 和 Google Pay 地区 进行操作。
  • 对于 Apple Pay,请确认您的设备支持生物识别身份验证
桌面浏览器
  • Chrome 38+
  • Safari 10.1+
  • Firefox 29+
  • Edge 15+
  • Opera 25+
移动浏览器
  • iOS Safari 9+ 以及其他使用系统提供的 WebKit 引擎的浏览器和 Web 视图
  • Android Chrome 38+
  • 三星浏览器 7.1+
其他说明对于未明确支持的浏览器,我们限制支持如下:
  • 要求浏览器支持 TLS 1.2
  • 需要足够现代的浏览器来支持 JavaScript 中的 Promises
  • 我们会响应错误报告,但不会主动测试其他浏览器

地区限制

AD-安道尔AE-阿拉伯联合酋长国AF-阿富汗AG-安提瓜和巴布达AI-安圭拉AL-阿尔巴尼亚AM-亚美尼亚AO-安哥拉AQ-南极洲AR-阿根廷AS-美属萨摩亚AW-阿鲁巴AX-奥兰群岛BA-波斯尼亚和黑塞哥维那BB-巴巴多斯BD-孟加拉国BF-布基纳法索BH-巴林BI-布隆迪BJ-贝宁BL-圣巴泰勒米BM-百慕大BN-文莱BQ-博内尔、圣尤斯特歇斯和萨巴BS-巴哈马BT-不丹BV-布韦岛BW-博茨瓦纳BY-白俄罗斯BZ-伯利兹CC-科科斯(基林)群岛CD-刚果民主共和国CF-中非共和国CG-刚果共和国CI-科特迪瓦CK-库克群岛CM-喀麦隆CO-哥伦比亚CU-古巴CV-佛得角CW-库拉索CX-圣诞岛CY-塞浦路斯DJ-吉布提DM-多米尼克DO-多米尼加共和国DZ-阿尔及利亚EC-厄瓜多尔EE-爱沙尼亚EG-埃及EH-西撒哈拉ER-厄立特里亚ET-埃塞俄比亚FJ-斐济FK-福克兰群岛FM-密克罗尼西亚联邦FO-法罗群岛GA-加蓬GD-格林纳达GE-格鲁吉亚GF-法属圭亚那GG-根西岛GH-加纳GI-直布罗陀GL-格陵兰GM-冈比亚GN-几内亚GP-瓜德罗普GQ-赤道几内亚GS-南乔治亚和南桑威奇群岛GT-危地马拉GW-几内亚比绍HK-香港HM-赫德岛和麦克唐纳群岛HN-洪都拉斯HT-海地ID-印度尼西亚IL-以色列IM-马恩岛IN-印度IO-英属印度洋领地IQ-伊拉克IR-伊朗JM-牙买加JO-约旦JP-日本KE-肯尼亚KH-柬埔寨KI-基里巴斯KM-科摩罗KN-圣基茨和尼维斯KP-朝鲜KR-韩国KW-科威特KY-开曼群岛KZ-哈萨克斯坦LA-老挝LB-黎巴嫩LC-圣卢西亚LI-列支敦士登LK-斯里兰卡LR-利比里亚LS-莱索托LV-拉脱维亚LY-利比亚MD-摩尔多瓦ME-黑山MF-法属圣马丁MG-马达加斯加MH-马绍尔群岛MK-北马其顿ML-马里MM-缅甸MN-蒙古MP-北马里亚纳群岛MQ-马提尼克MR-毛里塔尼亚MS-蒙特塞拉特MU-毛里求斯MV-马尔代夫MW-马拉维MY-马来西亚MZ-莫桑比克NA-纳米比亚NC-新喀里多尼亚NE-尼日尔NF-诺福克岛NG-尼日利亚NI-尼加拉瓜NP-尼泊尔NR-瑙鲁NU-纽埃OM-阿曼PA-巴拿马PE-秘鲁PF-法属波利尼西亚PG-巴布亚新几内亚PH-菲律宾PK-巴基斯坦PM-圣皮埃尔和密克隆PN-皮特凯恩群岛PR-波多黎各PS-巴勒斯坦PW-帕劳RE-留尼汪RU-俄罗斯RW-卢旺达SA-沙特阿拉伯SB-所罗门群岛SC-塞舌尔SD-苏丹SH-圣赫勒拿SJ-斯瓦尔巴和扬马延SK-斯洛伐克SL-塞拉利昂SM-圣马力诺SN-塞内加尔SO-索马里SR-苏里南SS-南苏丹ST-圣多美和普林西比SV-萨尔瓦多SX-荷属圣马丁SY-叙利亚SZ-斯威士兰TC-特克斯和凯科斯群岛TD-乍得TF-法属南部领地TG-多哥TH-泰国TK-托克劳TL-东帝汶TM-土库曼斯坦TN-突尼斯TO-汤加TR-土耳其TT-特立尼达和多巴哥TV-图瓦卢TW-台湾TZ-坦桑尼亚UA-乌克兰UG-乌干达UM-美国本土外小岛屿UY-乌拉圭UZ-乌兹别克斯坦VA-梵蒂冈VC-圣文森特和格林纳丁斯VE-委内瑞拉VG-英属维尔京群岛VI-美属维尔京群岛VN-越南VU-瓦努阿图WF-瓦利斯和富图纳WS-萨摩亚YE-也门YT-马约特ZA-南非ZM-赞比亚ZW-津巴布韦

HaiPay.js 对接(Apple Pay & Google Pay)

HaiPay 提供了便捷的 Apple Pay 和 Google Pay 支付集成方案,通过简单配置即可在网页中快速集成支付功能。
<script src="https://cashier.haipay.top/js/applePayGooglePay_1.0.0.min.js"></script>

<div>
  <div id="applePay-googlePay"></div>
</div>

  // 创建实列
  const elements = applePayGooglePay.create('applePayGooglePay', {
      sandbox: true,
      clientToken: '6cgjnxvc6kdb',
      buttonType: 'buy',
      buttonTheme: 'black',
      buttonHeight: 50
  });

  // 挂载组件
  elements.mount('#applePay-googlePay');

  // 支付按钮渲染完成回调函数
  elements.on('ready', (data) => {
      console.log('Button rendered successfully:', data);
  });

 // 错误信息
  elements.on('error', (data) => {
      console.error('Payment error:', data);
  });


  • 参数说明
    • 1.初始化配置参数(HaiPay 构造函数参数)
参数名必选类型说明
sandboxBoolean环境类型,默认值 true,可选值 :
- true:测试环境(用于联调测试)
- false:生产环境(上线使用)
clientTokenString客户端令牌clientToken
buttonTypeString按钮文本类型,默认值 buy, 可选值:
- plain:“只显示支付徽标,无文字”
- add-money:“添加资金”
- book:“预定”
- buy:“购买”(默认)
- check-out:“结账”
- contribute:“捐款”
- order:“下单”
- reload:“重新加载”
- rent: “租赁”
-subscribe: “订阅”
-support: “支持”
-tip: “付小费”
-top-up: “充值”
buttonThemeString按钮主题样式,默认值 black,可选值:
- black:黑色背景
- white:白色背景
buttonHeightnumber按钮高度,默认值 50
  • 2.常见错误类型及解决方案
错误信息错误原因解决方案
Missing required parameters: env, orderNo缺少必需的初始化参数检查 clientToken 等参数是否传入
Unsupported region: CN生产环境下不支持中国地区

HaiPay.js 对接(creditCard)

HaiPay 提供了便捷的 creditCard 支付集成方案,通过简单配置即可在网页中快速集成支付功能。
<script src="https://cashier.haipay.top/js/creditCard_1.0.0.min.js"></script>

<div>
  <div id="creditCard"></div>
</div>

  // 创建实列
  const elements = creditCard.create('card', {
      sandbox: true,
      clientToken: '6cgjnxvc6kdb'
  });

  // 挂载组件
  elements.mount('#creditCard');

  // 信用卡页面渲染完成回调函数
  elements.on('ready', (data) => {
      console.log('Card rendered successfully:', data);
  });


 // 错误信息
  elements.on('error', (data) => {
      console.error('Payment error:', data);
  });

 // 提交表单信息
 elements.submit()


  • 参数说明
    • 1.初始化配置参数(HaiPay 构造函数参数)
参数名必选类型说明
sandboxBoolean环境类型,默认值 true,可选值 :
- true:测试环境(用于联调测试)
- false:生产环境(上线使用)
clientTokenString客户端令牌clientToken
cardThemeString主题样式,默认值 white,可选值:
- black:黑色背景
- white:白色背景
  • 2.常见错误类型及解决方案
错误信息错误原因解决方案
Missing required parameters: env, orderNo缺少必需的初始化参数检查 clientToken 等参数是否传入
Unsupported region: CN生产环境下不支持中国地区

限额

交易类型限额(单位:USD)
代收0.99-1000

代收API

1.代收申请

简要描述:
  • 创建代收订单
URL: 美元: /usd/collect/apply 说明:appId需使用美元对应的,用户支付成功后增加美元余额 参数:
参数名必选类型说明
appIdLong业务ID(后台获取,需要根据URL中的币种传递对应的业务ID)
orderIdString商户订单号(必须保证唯一性,长度不超过48)
nameString用户姓名,推荐使用真实姓名,格式:包含firstName和lastName,以空格分割的,示例:Donald John Trump
phoneString真实手机号(格式参考 电话号码格式
emailString真实电子邮件
amountString交易金额(精确到小数点后两位;禁止添加标点符号,例如:”,”)
payTypeString支付方式类型
inBankCodeString支付方式编码
clientIpString用户端ip
callBackUrlString用户支付成功后跳转地址
callBackFailUrlString用户支付失败后跳转地址
notifyUrlString回调地址
subjectString支付备注
bodyString备注详情
partnerUserIdString用户唯一标识(如用户ID userId),用于风控系统,必须真实有效,否则会影响交易。 格式要求:数字、大小写字母或常用符号-~!@#$%&*()_。
signString签名
请求示例
{
  "appId": 1054,
  "orderId": "M233323000059",
  "amount": "300",
  "phone": "09230219312",
  "email": "23423@qq.com",
  "name": "test",
  "inBankCode": "USA",
  "payType": "BANK_TRANSFER",
  "partnerUserId": "149597870",
  "sign": "af0gAHkUOyYHu9owQp8NJ4mPEeUW4vuJcjdxqLIzrVw8AvpLSjD1DXupReSG/CyuSkFRyiIvCp5u703AuGGmfgD2gKDH3Ywau41bAbG2jnHJ8mtjiSJ5iWUzanyd4Kr7d1+rETbzUl7/BkW3t0X8UUFdqpxwG8DPUjAwUKfplWDHV7koG51Ozexd80DCsmW6eWdouAZ1uNXGLYmV3ftE3BmfNRtuv1C5bfTJWrTEIOxbF6g2uYOFZTlIgrQgd7/2PsAYwQQXNz8Q8CYl4OxqCv4pXJxaLWPbR5tqZu9og5kn32C9aHW/NlU1y39vzz+4ef81yPAqUV9oHlSMSPrMmw=="
}
响应示例
{
  "status": "1",
  "error": "00000000",
  "msg": "",
  "data": {
    "orderId": "M233323000059",
    "orderNo": "6023071013539074",
    "payUrl": "",
    "clientToken": "",
    "sign": "YEoA8Y2JzQFGVzwJSqmemm1Kfv/bfyIfCqv2dp7RNzT5B72AQvdD+nt2nR4sL1HWscvmNHyVt5ovAi7MMhy3ziih/sMph+wPx4YjH3W1h5DyBvSlWvaKfKrK5ViomZ0pPYWydwRHnnRnicxToHK9S6qtSy7Q73O0hdz4hJ9p41Th3ycBl2Q9SeqSZYSY1ohcPDhdyRf2y0prb8rHgpBKzxZ5BKX/1bsE9OmsSEHAEYT8OGgko6aNe8XPAhr4G48cpWTftvnGQuzh0O65nuZRI/PF+Axt2zJCVbFHDDSREI9NlAT82ebDqhlVdxQzKE67D1nxgjb3dPmDUYHOBpmwxQ=="
  }
}
返回data参数说明
参数名类型说明
orderIdString商户订单号(必须保证唯一性)
orderNoString平台订单号
payUrlString支付链接
bankCodeString支付方式编码
clientTokenString在JavaScript Web SDK中使用的客户端令牌(见HaiPaySDK.js)
signString签名

2.代收申请 MIT模式

简要描述:
  • 创建MIT模式代收订单
URL: 美元: /usd/mit/apply 说明:appId需使用美元对应的,用户支付成功后增加美元余额 参数:
参数名必选类型说明
appIdLong业务ID(后台获取,需要根据URL中的币种传递对应的业务ID)
orderIdString商户订单号(必须保证唯一性,长度不超过48)
nameString用户姓名,推荐使用真实姓名,格式:包含firstName和lastName,以空格分割的,示例:Donald John Trump
phoneString真实手机号(格式参考 电话号码格式
emailString真实电子邮件
amountString交易金额(精确到小数点后两位;禁止添加标点符号,例如:”,”)
payTypeString支付方式类型
inBankCodeString支付方式编码
clientIpString用户端ip
callBackUrlString用户支付成功后跳转地址
callBackFailUrlString用户支付失败后跳转地址
notifyUrlString回调地址
subjectString支付备注
bodyString备注详情
partnerUserIdString用户唯一标识(如用户ID userId),用于风控系统,必须真实有效,否则会影响交易。 格式要求:数字、大小写字母或常用符号-~!@#$%&*()_。
tokenIDString支付令牌,首次交易不需要,后续主动扣款需要,通过回调获取
tokenStringApple Pay / Google Pay Token,自行获取传递或使用HaiPay页面,如何获取?
loadingTypeInteger0(默认) – 显示正常的支付结果页面; 1 – 显示加载中动画(loading 转圈),不展示订单信息。
cancelUrlString用户取消支付URL,如果传递,用户可在支付页面点击返回到此页面
signString签名
请求示例
{
  "appId": 1054,
  "orderId": "M233323000059",
  "amount": "300",
  "phone": "09230219312",
  "email": "23423@qq.com",
  "name": "test",
  "inBankCode": "USA",
  "payType": "BANK_TRANSFER",
  "partnerUserId": "149597870",
  "sign": "af0gAHkUOyYHu9owQp8NJ4mPEeUW4vuJcjdxqLIzrVw8AvpLSjD1DXupReSG/CyuSkFRyiIvCp5u703AuGGmfgD2gKDH3Ywau41bAbG2jnHJ8mtjiSJ5iWUzanyd4Kr7d1+rETbzUl7/BkW3t0X8UUFdqpxwG8DPUjAwUKfplWDHV7koG51Ozexd80DCsmW6eWdouAZ1uNXGLYmV3ftE3BmfNRtuv1C5bfTJWrTEIOxbF6g2uYOFZTlIgrQgd7/2PsAYwQQXNz8Q8CYl4OxqCv4pXJxaLWPbR5tqZu9og5kn32C9aHW/NlU1y39vzz+4ef81yPAqUV9oHlSMSPrMmw=="
}
响应示例
{
  "status": "1",
  "error": "00000000",
  "msg": "",
  "data": {
    "orderId": "M233323000059",
    "orderNo": "6023071013539074",
    "payUrl": "",
    "clientToken": "",
    "sign": "YEoA8Y2JzQFGVzwJSqmemm1Kfv/bfyIfCqv2dp7RNzT5B72AQvdD+nt2nR4sL1HWscvmNHyVt5ovAi7MMhy3ziih/sMph+wPx4YjH3W1h5DyBvSlWvaKfKrK5ViomZ0pPYWydwRHnnRnicxToHK9S6qtSy7Q73O0hdz4hJ9p41Th3ycBl2Q9SeqSZYSY1ohcPDhdyRf2y0prb8rHgpBKzxZ5BKX/1bsE9OmsSEHAEYT8OGgko6aNe8XPAhr4G48cpWTftvnGQuzh0O65nuZRI/PF+Axt2zJCVbFHDDSREI9NlAT82ebDqhlVdxQzKE67D1nxgjb3dPmDUYHOBpmwxQ=="
  }
}
返回data参数说明
参数名类型说明
orderIdString商户订单号(必须保证唯一性)
orderNoString平台订单号
payUrlString支付链接
clientTokenString在JavaScript Web SDK中使用的客户端令牌(见HaiPaySDK.js)
signString签名

3.代收查询

简要描述:
  • 查询代收订单
URL: 美元: /usd/collect/query 参数:
参数名必选类型说明
appIdLong业务ID(后台获取,需要根据URL中的币种传递对应的业务ID)
orderIdString商户订单号
orderNoString平台订单号(响应快)
signString签名
请求示例
{
  "appId": 1054,
  "orderId": "M22222000028",
  "sign": "EmyJGm3ELzG4FsOd0Krs9ncbSjo4oTGuXWML+7djYla3+VAwd9wS17z38p/7U2ZAjroO04XrE7YXcB1o76Dtyipj3h3bJzs7FYma1QNkMUdt9hh7m8U6hMsMQX7vIWHtXNwz4pbTSC75+kQWXaCew7KoE6LXECdJU8AISgNgeki2TK9R0pCfshr0Z2SZBPeuT6OvIH5LdmqgdZhuqnffGU2qnXk4KMkO848e6/WALLBR+LE1wyKHfPnYVcuKSMVYxkvKyyIL5JIPEgW0o5bh4RCbaUn3NZtyYwrU1uQ3ZDFRThm9j6XAQP+LBlmq3nOePqBtp/VDVarRaV+7FbQg3A=="
}
响应示例
{
  "status": "1",
  "error": "00000000",
  "msg": "",
  "data": {
    "orderId": "M22222000028",
    "orderNo": "6023042811314347",
    "amount": "50.00",
    "actualAmount": "0.00",
    "fee": "0.00",
    "status": 1,
    "sign": "fP433ygWVDLVGxYkVnIJj7riGq0U3vyVX+MbBAImxfGLZkZcEAHVEoVYuULZSmXAAXKRSyd67WlDNm+24pougM54ofAoH4HMtCL2tfCoBReFyz3z02AGKkrKE2xWhSpWoqfQoBvzwuN5iGMMu0s9Q1YvqiwJ8WDVIENnmiIyD8qDJN7caHTW2US14/faG+69AvnuIgJ/nu7/jogOlgEYdZdVYU7gcRDE+d47KjlFGswQkJ/h/uzV7cWtUqrtOO7ZnZ3/z33Xx8awokX36QoYcPSWAU0h+Ij9O9402HNhm1eTbYcLU0uI/z8xCAtyAI/tTyiFijpiNlxUKQj+zKsILw=="
  }
}
返回data参数说明
参数名类型说明
orderIdString商户订单号(必须保证唯一性)
orderNoString平台订单号
amountString交易金额
actualAmountString收到金额
feeString手续费
statusInteger状态(0未开始,1支付中,2成功(终态),3失败(终态), -1异常待确认)
payTimeString支付成功时间(当status=2时有值)(本地时间), 格式: yyyy-MM-dd HH:mm:ss
errorMsgString支付失败原因(当status=3时有值)
signString签名

4.退款申请

简要描述:
  • 发起原信用卡交易订单的退款操作,同步返回的退款状态请注意状态值,建议以查询接口为主。
URL: 美元: /usd/refund/apply 参数:
参数名必选类型说明
appIdLong业务ID(后台获取,需要根据URL中的币种传递对应的业务ID)
orderIdString商户申请退款订单号(商户新的订单号,不能使用原代收的商户订单号)
orderNoString平台订单号(原代收返回的平台单号)
signString签名
返回data参数说明
参数名类型说明
appIdString业务ID
orderNoString平台订单号 (原代收返回的平台单号)
orderIdString商户退款申请订单号
refundNoString本次退款平台单号
statusString退款状态,1表示退款申请成功,0表示处理中,2表示失败,正常下发起就是返回处理中,后续需要调用查询接口查询状态
errorMsgString错误信息,不一定有值
signString签名

5.退款查询

简要描述:
  • 发起退款的订单的结果查询。
URL: 美元: /usd/refund/refundQuery 参数:
参数名必选类型说明
appIdLong业务ID(后台获取,需要根据URL中的币种传递对应的业务ID)
orderIdString商户退款申请订单号
refundNoString平台退款单号(申请退款返回的平台单号,如果有值优先查询此字段)
signString签名
返回data参数说明
参数名类型说明
appIdString商户订单号(必须保证唯一性)
orderNoString平台订单号(原代收返回的平台单号)
orderIdString商户申请订单号
refundNoString平台退款单号
statusString退款状态,1表示退款申请成功,0表示处理中,2表示失败,退款结果以此状态为准
errorMsgString错误信息,不一定有值
signString签名

6.支付方式

币种支付类型(payType)支付编码(inBankCode)限额状态说明
USDBANK_TRANSFERCREDIT_CARD0.99-1000可用VISA
USDBANK_TRANSFERCREDIT_CARD0.99-1000可用MasterCard
USDBANK_TRANSFERCREDIT_CARD0.99-1000可用JCB
USDEWALLETGOOGLE_PAY0.99-1000可用Google Pay
USDEWALLETAPPLE_PAY0.99-1000可用Apple Pay

7.测试卡号

只能在测试环境使用

模拟成功支付

使用以下测试卡号,输入任意 CVC(3位数字)和有效期(未来日期)来模拟支付成功:
  • 卡号 1:4242424242424242

模拟支付失败

使用以下测试卡号、无效数据来模拟支付失败:
  • 卡号 1:4000000000009995
  • 无效月份:13
  • 无效 CVV:99

8.MIT(Merchant Initiated Transaction)模式说明

MIT(Merchant Initiated Transaction,商户发起交易)
指在用户完成一次性支付授权后,商户可在用户不在场的情况下主动发起的扣款。
该模式广泛应用于 订阅支付、分期付款、会员续费、延迟扣款 等业务场景。

基本流程

  1. 用户授权
    • 用户在首次支付时输入支付信息,并完成必要的身份验证。
    • 商户保存用户的支付凭证,用于后续的扣款请求。
  2. 商户发起扣款
    • 商户根据约定的周期或条件,直接使用已保存的支付凭证发起扣款请求。
    • 由于交易为 离线场景(off-session),即用户不参与交易,系统会依据用户授权和合规要求完成处理。
  3. 认证要求
    • 在大多数情况下,交易会直接完成。
    • 若发卡行或风控系统要求再次验证,交易可能进入待用户确认的状态,需要用户补充验证才能完成。

模式特点

  • 提升体验:用户无需每次手动输入支付信息。
  • 合规安全:符合国际支付法规和强客户认证(SCA)等要求。
  • 应用广泛:适用于订阅收费、自动续费、分期扣款、延迟结算等场景。

MIT流程图

9.Apple Pay / Google Pay Token 获取方式说明

对接流程

  • 无需申请Apple Pay/Google Pay开发者账号,由HaiPay完成
  • 引入 JavaScript 脚本([https://js.stripe.com/v3/])
  • 页面结构要求
    • 支付按钮容器:用于 Apple Pay/Google Pay 按钮的渲染。
  • 快速集成示例
<script src="https://js.stripe.com/v3"></script>

<div id="appId">
  <div id="applePay-googlePay"></div>
</div>

      initApplePayGooglePay() {
            const stripe = Stripe('需要一个密钥,请联系HaiPay获取'); //此密钥生产和测试不共用
            const paymentRequest = stripe.paymentRequest({
            country: "HK",
            currency: "usd",
            total: {
                label: "Haipay",
                amount: 0.99 * 100, // 单位是分
            },
            requestPayerName: true,
            requestPayerEmail: true,
            });

            // 用 paymentRequestButton 创建一个 Apple Pay / Goole Pay 按钮
            const elements = stripe.elements();
            const prButton = elements.create("paymentRequestButton", {
               paymentRequest: paymentRequest,
            });

            // 检查浏览器是否支持 Apple Pay Goole Pay
            paymentRequest.canMakePayment().then((result) => {
                if (result && (result.applePay || result.googlePay)) {
                    prButton.mount("#applePay-googlePay");
                } else {
                    document.getElementById("applePay-googlePay").style.display = "none";
                    document.getElementById("applePay-googlePay-not-supported").style.display = 'block';
                }
            });

            paymentRequest.on("paymentmethod", async (ev) => {
                //ev.paymentMethod.id 这个就是需要的token,用于调用/usd/mit/apply接口传参
            });
          }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"/>
    <meta name="description" content="You have a payment link that needs to be paid. Please click the link below to make the payment." />
    <title>Google Pay and Apple Pay Demo</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/8.0.20/jsrsasign-all-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.15.14/theme-chalk/index.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.15.14/index.js"></script>    
    <script src="https://js.stripe.com/v3/"></script>

    
    <style type="text/tailwindcss">
        @layer utilities {
            .apple-pay-button {
                background-color: black;
                color: white;
                border-radius: 9999px;
                padding: 12px 24px;
                font-size: 17px;
                font-weight: 500;
                cursor: pointer;
                transition: background-color 0.2s;
                display: inline-flex;
                align-items: center;
                justify-content: center;
            }
            .apple-pay-button:hover {
                background-color: #333;
            }
            .apple-pay-button img {
                margin-right: 8px;
                height: 20px;
            }
        }
      .content {
        width: 100%;
        max-width: 600px;
        background: #fff;
        box-sizing: border-box;
        box-shadow: 0 0 calc(8.53333vmin / 32 * 8) #ccc;
        padding:calc(8.53333vmin / 32 * 20) calc(8.53333vmin / 32 * 10) calc(8.53333vmin / 32 * 10);
        margin: 0 auto 20px;
        border-radius: calc(8.53333vmin / 32 * 6);
      }
    </style>
</head>
<body class="bg-gray-50 font-sans">
    <div id="app">
        <div class="container mx-auto px-4 py-12 max-w-4xl">
            <header class="mb-10 text-center">
                <h1 class="text-3xl font-bold text-gray-900 mb-2">Google Pay And Apple Pay Demo</h1>
                <p class="text-gray-600">体验安全快捷的支付方式</p>
            </header>

         <div class="content">
            <el-form ref="form" :rules="rules" :model="form">
                <el-form-item label="appId" prop="appId">
                  <el-input v-model="form.appId" placeholder="请输入业务ID" />
                </el-form-item>
                <el-form-item label="金额" prop="amount">
                  <el-input v-model="form.amount" placeholder="请输入金额" />
                </el-form-item>
                <el-form-item label="手机号" prop="phone">
                  <el-input v-model="form.phone" placeholder="请输入手机号码" />
                </el-form-item>
                <el-form-item label="邮箱" prop="email">
                  <el-input v-model="form.email" placeholder="请输入邮箱" />
                </el-form-item>
                <el-form-item label="加密字段" prop="key">
                  <el-input v-model="form.key" placeholder="请输入加密字段key" />
                </el-form-item>
                <el-form-item label="商户私钥" prop="privateKey">
                  <el-input v-model="form.privateKey" placeholder="请输入商户私钥privateKey"  type="textarea" resize="none" :autosize="{ minRows: 4, maxRows: 10 }"  />
                </el-form-item>
            </el-form>  
            </div>


            <div class="text-center">
                
                <div id="applePay-googlePay"></div>
                
                {/* 不支持Apple Pay时显示 */}
                <div id="applePay-googlePay-not-supported" class="text-gray-500 mb-6 hidden">
                    <p><i class="fa fa-info-circle mr-2"></i>此设备不支持googlePay 和 applePay</p>
                </div>
                
            </div>
        </div>
    </div>

  <script>
      // 初始化Vue实例
      new Vue({
        el: "#app",
        data() {
          return {
             form: {
                token: '',
                appId: ,
                orderId: Date.now(),
                amount: "0.99",
                phone: "18801234567",
                email: "test@haipay.tech",
                name: "Haipay",
                inBankCode: "APPLE_PAY",
                payType: "EWALLET",
                partnerUserId: Date.now(),
                key: '',
                privateKey: ''
            },
            rules: {
              appId: [
                { required: true, trigger: 'blur' }
              ],
              amount: [
                { required: true, trigger: 'blur' }
              ],
              phone: [
                { required: true, trigger: 'blur' }
              ],
              email: [
                { required: true, trigger: 'blur' }
              ],
              name: [
                { required: true, trigger: 'blur' }
              ],
              key: [
                { required: true, trigger: 'blur' }
              ],
              privateKey: [
                { required: true, trigger: 'blur' }
              ],
            },
            baseURL: 'https://uat-interface.haipay.asia',
            isH5: true,
            applePayButton: null,
          };
        },
        computed: {},
        created() {
          this.isMobileDevice()
          this.applePayButton = document.getElementById('applePay-googlePay');
          this.initApplePay()
        },
        methods: {
          isMobileDevice() { 
            let self = this
            if(typeof window.orientation !== 'undefined'){
              self.isH5 = true
            } else {
              self.isH5 = false
            }
          },
          initApplePay() {
            const self = this
            const stripe = Stripe('需要一个密钥,请联系HaiPay获取'); //此密钥生产和测试不共用
            const paymentRequest = stripe.paymentRequest({
            country: "HK",
            currency: "usd",
            total: {
                label: "Haipay",
                amount: Number(self.form.amount) * 100, // 单位是分
            },
            requestPayerName: true,
            requestPayerEmail: true,
            });

            // 用 paymentRequestButton 创建一个 Apple Pay 按钮
            const elements = stripe.elements();
            const prButton = elements.create("paymentRequestButton", {
               paymentRequest: paymentRequest,
            });

            // 检查浏览器是否支持 Apple Pay
            paymentRequest.canMakePayment().then((result) => {
                if (result && (result.applePay || result.googlePay)) {
                    prButton.mount("#applePay-googlePay");
                } else {
                    document.getElementById("applePay-googlePay").style.display = "none";
                    document.getElementById("applePay-googlePay-not-supported").style.display = 'block';
                }
            });

            paymentRequest.on("paymentmethod", async (ev) => {
                if(ev.walletName === 'googlePay') {
                  self.form.inBankCode = 'GOOGLE_PAY'
                } else if(ev.walletName === 'applePay') {
                  self.form.inBankCode = 'APPLE_PAY'
                }
                self.form.token = ev.paymentMethod.id //这个就是需要的token,用于调用/usd/mit/apply接口传参
                const requestData = {
                    headers: { 'content-type': 'application/json' },
                    body: self.form
                };
                    const signedBody = self.generateSign(requestData);
                    const response = await fetch(`${self.baseURL}/usd/mit/apply`,
                        {
                            method: 'POST',
                            headers: {
                            'Content-Type': 'application/json',
                            },
                            body: signedBody
                        });
                    const res = await response.json()
                    if(res.status === '1') {
                        self.orderNo = res.data.orderNo
                        if(self.isH5) {
                            window.location.href = res.data.payUrl
                        }else {
                            window.open(res.data.payUrl, "_blank");
                        }
                    }

                // 你可以选择立即支付或只是保存
                ev.complete("success");
            });
          },
         generateSign(requestData) {
            let param = {};

            // 处理Body参数
            if (requestData.body) {
                const contentType = requestData.headers['content-type'] || '';
                if (contentType.toLowerCase().includes('application/json')) {
                    try {
                        const jsonData = typeof requestData.body === 'string' 
                            ? JSON.parse(requestData.body) 
                            : requestData.body;
                        
                        // 收集非空参数
                        for (let key in jsonData) {
                            if (jsonData[key] !== '') {
                                param[key] = jsonData[key];
                            }
                        }
                    } catch (e) {
                        console.log('请求body不是JSON格式');
                    }
                }
            }

            // 排序参数(排除指定字段)
            const sortedKeys = Object.keys(param)
                .filter(key => !['privateKey', 'sign', 'key'].includes(key))
                .sort();
            const paramString = sortedKeys.map(key => `${key}=${param[key]}`).join('&');

            // 解析原始body数据
            let body = typeof requestData.body === 'string' 
                ? requestData.body 
                : JSON.stringify(requestData.body);
            let jsonData = JSON.parse(body);
            let key = jsonData.key;
            
            // 生成待签名字符串
            const stringSignTemp = `${paramString}&key=${key}`;
            console.log('待签名字符串:', stringSignTemp);

            // 处理私钥
            let privateKey = `
        -----BEGIN PRIVATE KEY-----
        ${jsonData.privateKey}
        -----END PRIVATE KEY-----
            `.trim();

            // 生成签名
            const sig = new KJUR.crypto.Signature({ alg: 'SHA256withRSA' });
            sig.init(privateKey);
            sig.updateString(stringSignTemp);
            const signatureHex = sig.sign();
            const sign = hextob64(signatureHex);

            // 添加签名到请求数据
            jsonData.sign = sign;
            return JSON.stringify(jsonData);
         },
        },
      });
    </script>
</body>
</html>

Last modified on April 17, 2026