自学内容网 自学内容网

前端接入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 = '***********';// 你的appid

const 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, // 固定的 appId
    merchantNo: merchantNo, // 固定的 merchantNo
    data: {
      outTradeNo: paymaxParam.outTradeNo, // 唯一订单号
      subject: paymaxParam.subject, // 标题
      totalAmount: paymaxParam.totalAmount, // 总金额
      currency: paymaxParam.currency, // 货币单位
      country: paymaxParam.country, // 国家
      userId: paymaxParam.userId, // 用户 ID
      language: 'en', // 默认语言
      reference: 'reference查询和回调返回', // 可自定义
      frontCallbackUrl: 'http://www.baidu.com', // 前端回调 URL
      notifyUrl: '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-Type
    Accept: '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:'',//货币单位,USD
 country:'',
 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}`;
}

// 随机用户 ID
const 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()
// 随机用户id
const 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.redirectUrl
console.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-Type
    Accept: '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测试数据

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


原文地址:https://blog.csdn.net/m0_47814717/article/details/143858507

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!