前端接入Paymax支付请求

材料指南

  1. 开发者平台 :配置开发必备信息(appid,商户号,公钥私钥),此处与请求参数appIdmerchantNo有关。

  2. PayerMax Apis:各支付接口信息,本文以收银台支付API为请求展开,请求url为orderAndPay,测试环境基础路径为:https://pay-gate-uat.payermax.com /aggregate-pay/api/gateway

  3. PayerMax接口说明:HTTPS传输 + POST方法提交 + 签名算法(SHA256WithRSA) + 接口结构 + 测试/生产环境地址 + 接口列表(收银台支付/纯API支付)

  4. 国家币种支持:不同国家支付渠道支持的币种,比如USD(美元)、IDR(印度尼西亚比盾)、PHP(菲律宾比索),此处与请求参数currencycountry有关。

  5. 各国支付方式处理:比如印度只支持Card类支付(Vsia、MasterCard),印尼支持APM方式支付,OTC、 BANK_TRANSFER(当地银行卡转账)、WALLET(钱包)等多种支付,此处与请求参数paymentDetail有关。

操作步骤

1.生成私钥(PrivateKey)和公钥(PublicKey)

通过加入开发者平台,点击左侧菜单栏-开发者工具-rsa密钥生成,点击按钮Generate Key Pair生成私钥匙PrivateKey和公钥publicKey,需要自己保存好,下一步需要用到。
在这里插入图片描述
在这里插入图片描述

2.上传公钥

点击菜单栏左侧-基础设置-开发信息,点击按钮公钥上传,将第一步的公钥复制到商户公钥内,点击确定按钮。
在这里插入图片描述
在这里插入图片描述
复制保留商户号,Appid,商户公钥信息,发起请求需要用到。

3.模拟请求

此处以收银台支付-下单api为例(orderAndPay)
在这里插入图片描述
请求参数基础配置,更多data内参数配置,查看顶部PayerMax Apis对应接口的参数配置和返回数据设置。

{"version": "1.1","keyVersion": "1","requestTime": "{{requestTime}}",//(*)请求时间:ISO 格式当前时间的时间戳"appId": "{{appId}}",//(*)appid"merchantNo": "{{merchantNo}}",//(*)商户号"data": {"integrate": "Hosted_Checkout", // (*)集成类型"outTradeNo": "{{orderNumber}}",//订单编号唯一,否则请求失败"subject": "111",//订单标题名称"totalAmount": "11",//金额"currency": "IDR",//金额单位(对应国家简称,比如国家为ID,支持金额为IDR,或USD)"country": "ID",//国家简称"userId": "167688058870154999",//用户编号唯一,否则请求失败"language": 'en', // 默认语言"paymentDetail": {"paymentMethod": "",//支付方式"targetOrg": ""//目标组织},"frontCallbackURL": "https://www.baidu.com",// 前端回调 URL"notifyUrl": "https://www.baidu.com"// 后端通知 URL}
}

完整模拟测试:
在这里插入图片描述

在这里插入图片描述
模拟请求(可以根据我的这个请求设置做相应修改):

{"version": "1.1","keyVersion": "1","requestTime": "{{requestTime}}","appId": "{{appId}}","merchantNo": "{{merchantNo}}","data": {"integrate": "Hosted_Checkout","outTradeNo": "ORD1542659689","subject": "测试支付","totalAmount": "11","currency": "USD","country": "BR","userId": "167688058870154999","paymentDetail": {"paymentMethod": "CARD",//CARD为visa和mastercard支付"targetOrg": ""//paymentMethod对应信息,其中paymentMethod为CARD,targetOrg为空。对应支付方式看顶部paymentDetail配置链接或文档},"frontCallbackURL": "https://www.baidu.com","notifyUrl": "https://www.baidu.com"}
}

响应数据内容(http结构输入框内的数据):

POST https://pay-gate-uat.payermax.com/aggregate-pay/api/gateway/orderAndPay
content-type: application/json
sign: X93Cp******超级长的字符串******ZweJ8y50Iw=={"version":"1.1","keyVersion":"1","requestTime":"2024-11-18T08:20:35.411Z","appId":"你的appid信息","merchantNo":"你的商户号","data":{"integrate":"Hosted_Checkout","outTradeNo":"ORD1542659689","subject":"测试支付","totalAmount":"11","currency":"USD","country":"BR","userId":"167688058870154999","paymentDetail":{"paymentMethod":"CARD","targetOrg":""},"frontCallbackURL":"https://www.baidu.com","notifyUrl":"https://www.baidu.com"}}content-type: application/json
sign: N+K3//5RSOnm******超级长的字符串******tUCTtXGQ=={"msg":"Success.","code":"APPLY_SUCCESS","data":{"redirectUrl":"https://cashier-n-uat.payermax.com/v2/index.html#/payments?merchantId=*********d&merchantAppId=*******&country=BR&tradeToken=T2********8&paymentMode=CARD&language=pt&token=63************8&amount=11&currency=USD&version=1.1&cashierId=T202411******&frontCallbackUrl=https%3A%2F%2Fwww.baidu.com&pmaxLinkV=1","outTradeNo":"ORD1542659689","tradeToken":"*********","status":"PENDING"}}

4. 前端请求实操

安装axios:

npm install axios

安装 jsrsasign 库,此处是对 privateKey 对请求数据进行 RSA 加签:

npm install jsrsasign

前端请求封装:
新建utils文件夹,目录下新建request.js

import axios from 'axios';// 配置基础请求的 URL
const BASE_URL = 'https://pay-gate-uat.payermax.com/aggregate-pay/api/gateway/';
import * as jsrsasign from 'jsrsasign';// 测试环境
const merchantNo = '**********';// 你的商户号
const appid = '***********';// 你的appidconst privateKey = `-----BEGIN PRIVATE KEY-----
*****你的超长私钥****
-----END PRIVATE KEY-----`;// 创建通用的 axios 请求函数
const sendPaymaxRequest = async (endpoint, paymaxParam) => {// 构造请求体const data = {version: '1.1',keyVersion: '1',requestTime: paymaxParam.requestTime, // 客户端传入的请求时间appId: appid, // 固定的 appIdmerchantNo: merchantNo, // 固定的 merchantNodata: {outTradeNo: paymaxParam.outTradeNo, // 唯一订单号subject: paymaxParam.subject, // 标题totalAmount: paymaxParam.totalAmount, // 总金额currency: paymaxParam.currency, // 货币单位country: paymaxParam.country, // 国家userId: paymaxParam.userId, // 用户 IDlanguage: 'en', // 默认语言reference: 'reference查询和回调返回', // 可自定义frontCallbackUrl: 'http://www.baidu.com', // 前端回调 URLnotifyUrl: 'http://www.notifyUrl.com', // 后端通知 URL integrate: 'Hosted_Checkout', // 集成类型expireTime: '1800', // 过期时间(单位:秒)paymentDetail: {paymentMethodType: paymaxParam.paymentMethod, // 支付方式targetOrg: paymaxParam.targetOrg, // 目标组织},},};// 对请求体进行签名const sign = generateSign(data);// 设置请求头const headers = {sign: sign, // 签名'Content-Type': 'application/json', // 设置请求头 Content-TypeAccept: 'application/json', // 接受返回 JSON 数据};try {// 使用 axios 发送请求,拼接不同的接口const response = await axios.post(`${BASE_URL}${endpoint}`, data, { headers });return response.data; // 返回接口响应数据} catch (error) {console.error('请求失败:', error);throw error; // 错误抛出}
};// 生成RSA签名的函数
const generateSign = (data) => {// 将请求体数据转换为JSON字符串const jsonString = JSON.stringify(data);// 创建 RSA 私钥对象const rsaKey = jsrsasign.KEYUTIL.getKey(privateKey);// 创建一个签名对象,指定使用的算法const signature = new jsrsasign.KJUR.crypto.Signature({ "alg": "SHA256withRSA" });signature.init(rsaKey);signature.updateString(jsonString);// 对请求体数据进行签名,返回 Base64 编码的签名const signed = signature.sign();console.log(jsrsasign.hextob64(signed))return jsrsasign.hextob64(signed); // 返回 Base64 编码的签名
};export default sendPaymaxRequest;

页面请求:

<script>import sendPaymaxRequest from '../../utils/request.js'export default {data() {return {paymaxParam:{requestTime:'',//当地时间搓outTradeNo:'',//唯一订单号subject:'',//标题名称totalAmount:'',currency:'',//货币单位,USDcountry:'',userId:'',paymentMethod:'',targetOrg:''}}},created(){},methods: {getRecharge(){// 获取当前时间的 Date 对象const now = new Date();// 转换为 ISO 格式字符串(包括时区信息)const isoString = now.toISOString();console.log("ISO String:", isoString);// 随机订单编号const generateOrderId = () => {const prefix = "ORD"; // 订单前缀,可自定义const timestamp = Date.now().toString(); // 时间戳const randomNumber = Math.floor(Math.random() * 10000); // 随机 4 位数return `${prefix}${timestamp}${randomNumber}`;}// 随机用户 IDconst generateUserId = () => {const prefix = "USER"; // 用户 ID 前缀const timestamp = Date.now().toString().slice(-5); // 时间戳后 5 位const randomNumber = Math.floor(Math.random() * 1000); // 随机 3 位数return `${prefix}${timestamp}${randomNumber}`;}// 随机订单编号const orderId = generateOrderId()// 随机用户idconst userId = generateUserId()const paymaxParam = {requestTime: isoString,outTradeNo: orderId,subject: this.paymaxParam.paymentMethod + this.paymaxParam.targetOrg +'支付',totalAmount: this.paymaxParam.totalAmount,currency: 'USD',country: this.paymaxParam.country,userId: userId,paymentMethod: this.paymaxParam.paymentMethod,  // 假设这是支付方式targetOrg: this.paymaxParam.targetOrg, // 目标组织};// 调用发送请求的函数sendPaymaxRequest('orderAndPay', paymaxParam).then(response => {console.log('OrderAndPay 请求成功:', response);const redirectUrl = response.data.redirectUrlconsole.log(redirectUrl);//确保每次提交的参数,orderId 每次都不一样,否则测试环境下即使请求成功,也不会返回response.data.redirectUrl(没有支付页面跳转)值为undefined.// 判断平台进行跳转if (process.env.UNI_PLATFORM === 'h5') {// 在H5环境下window.location.href = redirectUrl;} else if (process.env.UNI_PLATFORM === 'app-plus') {// 在 App 环境下if (typeof plus !== 'undefined' && plus.runtime) {plus.runtime.openURL(redirectUrl);} else {console.warn("当前环境不支持 openURL 跳转");}} else if (process.env.UNI_PLATFORM === 'mp-weixin') {// 在微信小程序环境下,外部链接需要用 web-view 组件打开uni.navigateTo({url: `/pages/webview/webview?redirectUrl=${encodeURIComponent(redirectUrl)}`});} else {console.error('不支持的运行平台');}}).catch(error => {console.error('请求失败:', error);});}}}
</script>

根据对应的redirectUrl跳转到不同的支付平台
在这里插入图片描述

5.订单信息查询

每一笔订单信息,即使请求成功或者失败,都会保存在
菜单栏-交易信息-订单列表中
在这里插入图片描述

注意点

1.sign签名的处理
  1. sign是通过私钥进行rsa加签生成,请求体同请求接口参数格式一样,请求体body的数据有无进行格式化,生成的sign是不一样的。要使完整请求成功,请求体格式应该相同。

详细看官方文档此处:PayerMax配置与签名
在这里插入图片描述

  1. 通过rsa加签私钥会把body的请求数据加入处理,所以请求要保持请求体body数据格式一致。
  2. sign正确格式尾部应为==结尾
  3. 前端js请求头部设置:
  // 设置请求头const headers = {sign: sign, // 签名'Content-Type': 'application/json', // 设置请求头 Content-TypeAccept: 'application/json', // 接受返回 JSON 数据};

2.国家和币种处理

  • 此处与请求参数currency(特价币种)country(国家代码)totalAmount(标价金额)相关。 比如:
    在这里插入图片描述
    巴西的国家代码为BR,支持的特价币种为BRL和USD俩种,支持方式为APM、CARD、APPLEPAY、GOOGLEPAY
    在这里插入图片描述
    使用对应支付,支付金额不能小于对应标准,比如选用USD作为特价币种,选择苹果支付时,totalAmount不能小于0.01,以此类推。
    在这里插入图片描述
  • 正常情况可以使用USD美元作为支持的特价币种,paymax可以自动转换当地支付方式的比例。

3.支付方式配置及注意事项

  • 前端配置数据参考(结合个人项目实际,这里仅作参考):
const data = [{ country:'BR',ename:'Brazil',cname:'巴西',methods:[{icon:'',way:'Card',rname:'Credit Card',paymentMethodType:'CARD',targetOrg:''},{icon:'',way:'APM',rname:'Bank Transfer',paymentMethodType:'BANK_TRANSFER',targetOrg:''},{icon:'',way:'APM',rname:'PIX',paymentMethodType:'REALTIME_PAYMENT',targetOrg:'PIX'},{icon:'',way:'APM',rname:'Boleto',paymentMethodType:'OTC',targetOrg:'BOLETO'},{icon:'',way:'APM',rname:'Boleto fast',paymentMethodType:'OTC',targetOrg:'BOLETO_FAST'},{icon:'',way:'APM',rname:'MercadoPago',paymentMethodType:'WALLET',targetOrg:'MERCADOPAGO'},{icon:'',way:'APM',rname:'PicPay',paymentMethodType:'WALLET',targetOrg:'PICPAY'},{icon:'',way:'GOOGLEPAY	',rname:'Google Pay',paymentMethodType:'GOOGLEPAY	',targetOrg:''},{icon:'',way:'APPLEPAY',rname:'Apple Pay',paymentMethodType:'APPLEPAY',targetOrg:''}],unit:['USD','BRL']},{..其他国家...}
]
  • 其中苹果支付(APPLEPAY)、谷歌支付(GOOGLEPAY)的paymentDetail参数设置,当支付方式类型为APPLEPAY时,目标对应机构为空。类似的还有CARD支付方式类型,还有此类卡(VISA、MasterCard)。参数设置为paymentMethodType:'APPLEPAY',targetOrg:'',其中苹果支付成功后跳转浏览器只支持safari浏览器上,其他设备或浏览器请求将无法显示ApplePay支付选项。在这里插入图片描述

  • 其他支付方式需上传对应的支付方式类型和目标机构,比如
    paymentMethodType:'WALLET',targetOrg:'NUPAY'在这里插入图片描述

4.虚拟Visa、MasterCard测试数据

虚拟账号,仅用于测试使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/474789.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jmeter的后置处理器(二)

5--JSR223 PostProcessor 功能特点 自定义后处理逻辑&#xff1a;使用脚本语言编写自定义的后处理逻辑。支持多种脚本语言&#xff1a;支持 Groovy、JavaScript、BeanShell 等脚本语言。动态参数传递&#xff1a;将提取的数据存储为变量&#xff0c;供后续请求使用。灵活性高…

CSS遮罩:mask

CSS属性 mask 允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。 // 一般用位图图片做遮罩 mask: url(~/assets/images/mask.png); mask-size: 100% 100%;// 使用 SVG 图形中的形状来做遮罩 mask: url(~/assets/images/mask.svg#star);…

Zmap+python脚本+burp实现自动化Fuzzing测试

声明 学习视频来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…

15. Python中的os.path模块/路径操作相关

这个专栏记录我学习/科研过程中遇到的一些小问题以及解决方案&#xff0c;一些问题可能比较蠢请见谅。自用&#xff0c;仅供参考。 ------------------------------------------------------------------------------------ Python中的os.path模块详解&#xff08;包括一些常…

鸿蒙实战:页面跳转传参

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙项目2.2 编写首页代码2.3 新建第二个页面 3. 测试效果4. 实战总结 1. 实战概述 本次实战&#xff0c;学习如何在HarmonyOS应用中实现页面间参数传递。首先创建项目&#xff0c;编写首页代码&#xff0c;实现按钮跳转至第二个页面并…

NLP论文速读(EMNLP 2024)|动态奖励与提示优化来帮助语言模型的进行自我对齐

论文速读|Dynamic Rewarding with Prompt Optimization Enables Tuning-free Self-Alignment of Language Models 论文信息&#xff1a; 简介: 本文讨论的背景是大型语言模型&#xff08;LLMs&#xff09;的自我对齐问题。传统的LLMs对齐方法依赖于昂贵的训练和人类偏好注释&am…

Label-studio-ml-backend 和YOLOV8 YOLO11自动化标注,目标检测,实例分割,图像分类,关键点估计,视频跟踪

这里写目录标题 1.目标检测 Detection2.实例分割 segment3.图像分类 classify4.关键点估计 Keypoint detection5.视频帧检测 video detect6.视频帧分类 video classify7.旋转目标检测 obb detect8.替换yolo11模型 给我点个赞吧&#xff0c;谢谢了附录coco80类名称 笔记本 华为m…

图像处理学习笔记-20241118

文章目录 霍夫变换基本原理霍夫变换的步骤使用 OpenCV 实现直线检测示例&#xff1a;标准霍夫变换 示例&#xff1a;概率霍夫变换参数解释霍夫变换检测圆 基于GAN的样本生成GAN的基本原理基于GAN的数据增广流程实现代码示例 同态滤波&#xff08;Homomorphic Filtering&#xf…

视频融合×室内定位×数字孪生

随着物联网技术的迅猛发展&#xff0c;室内定位与视频融合技术在各行各业中得到了广泛应用。不仅能够提供精确的位置信息&#xff0c;还能通过实时视频监控实现全方位数据的可视化。 与此同时&#xff0c;数字孪生等技术的兴起为智慧城市、智慧工厂等应用提供了强大支持&#…

当科技照进现实 机器人带着机器狗乘空轨

湖北日报讯&#xff08;记者魏铼、通讯员张璨龙&#xff09;11月14日&#xff0c;武汉东湖高新区空轨高新大道站&#xff0c;在光谷装上“智慧大脑”的人形机器人&#xff0c;乘空轨&#xff0c;看AI展&#xff0c;与小朋友在生态大走廊斗舞。 京天博特&#xff1a;光谷“智慧大…

freertos任务调度学习

首先创建任务&#xff0c;创建好任务后&#xff0c;开启任务调度器&#xff0c;任务才能执行 1.开启任务调度器 2.启动第一个任务 3.任务切换

蓝桥杯每日真题 - 第16天

题目&#xff1a;&#xff08;卡牌&#xff09; 题目描述&#xff08;13届 C&C B组C题&#xff09; 解题思路&#xff1a; 题目分析&#xff1a; 有 n 种卡牌&#xff0c;每种卡牌的现有数量为 a[i]&#xff0c;所需的最大数量为 b[i]&#xff0c;还有 m 张空白卡牌。 每…

MySQL系列之数据授权(privilege)

导览 前言Q&#xff1a;如何对MySQL数据库进行授权管理一、MySQL的“特权”1. 权限级别2. 权限清单 二、授权操作1. 查看权限2. 分配权限3. 回收权限 结语精彩回放 前言 看过博主上一篇的盆友&#xff0c;可以Get到一个知识点&#xff1a;数据授权&#xff08;eg&#xff1a;g…

C++为函数提供的型特性——缺省参数与函数重载

目录 一、缺省参数 二、函数重载 一、缺省参数 C为函数提供了一项新的特性——缺省参数。缺省参数指的是当前函数调用中省略了实参自动使用的一个值。这极大地提高了函数的灵活性 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值 。在调⽤该函数时&#xff0c;如果没有…

android 使用MediaPlayer实现音乐播放--权限请求

在Android应用中&#xff0c;获取本地音乐文件的权限是实现音乐扫描功能的关键步骤之一。随着Android版本的不断更新&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用需要动态请求权限&#xff0c;而到了android 13以上需要的权限又做了进一步…

go-zero(一) 介绍和使用

go-zero 介绍和使用 一、什么是 go-zero&#xff1f; go-zero 是一个基于 Go 语言的微服务框架&#xff0c;提供了高效、简单并易于扩展的 API 设计和开发模式。它主要目的是为开发者提供一种简单的方式来构建和管理云原生应用。 1.go-zero 的核心特性 高性能&#xff1a; g…

Orcad 输出有链接属性的PDF

安装adobe pdf安装Ghostscript修改C:\Cadence\SPB_16.6\tools\capture\tclscripts\capUtils\capPdfUtil.tcl ​ 设置默认打印机为 Adobe PDF ​ 将Ghostscript的路径修改正确 打开cadence Orcad &#xff0c;accessories->candece Tcl/Tk Utilities-> Utilities->PD…

.NET6 WebApi第1讲:VSCode开发.NET项目、区别.NET5框架【两个框架启动流程详解】

一、使用VSCode开发.NET项目 1、创建文件夹&#xff0c;使用VSCode打开 2、安装扩展工具 1>C# 2>安装NuGet包管理工具&#xff0c;外部dll包依靠它来加载 法1》&#xff1a;NuGet Gallery&#xff0c;注意要启动科学的工具 法2》NuGet Package Manager GUl&#xff0c…

#define定义宏(3)

大家好&#xff0c;今天来给大家介绍一下宏实现的原理以及缺点&#xff0c;还有宏和函数的一些区别&#xff08;下一期给大家详细介绍宏和函数的区别&#xff09;&#xff0c;那么话不多说&#xff0c;我们现在开始。 1.宏和参数不是计算之后传进去&#xff0c;而是替换进去的…

AJAX笔记 (速通精华版)

AJAX&#xff08;Asynchronous Javascript And Xml&#xff09; 此笔记来自于动力节点最美老杜 传统请求及缺点 传统的请求都有哪些&#xff1f; 直接在浏览器地址栏上输入URL。点击超链接提交 form 表单使用 JS 代码发送请求 window.open(url)document.location.href urlwi…