news 2026/6/10 15:59:26

微信支付集成_JSAPI

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微信支付集成_JSAPI

微信支付集成_JSAPI

0.背景

产品接入微信支付,需要实现PC端扫码支付,移动端公众号支付,以及小程序支付.经过调研统一采用微信的JSAPI实现.主要过程分两个大步骤:

  • 下单接口(/v3/pay/transactions/jsapi),获取预付单号
  • 切换到微信环境(公众号,小程序)并结合预付单号,唤起支付界面,用户完成支付

需要实际在手机完成支付,本次测试代码全部通过前端实现.针对访问微信下单接口,通过ngin代理避免前端跨域问题.
有完整测试代码,若需要请关注公众号小满小慢回复wepay获取.获取代码后,你只需把src部署到你服务器,然后在微信中访问
即可.如果域名能映射到你本地开发机上,直接npm run server运行也是不错的选择.
这种方式运行,已经内置代理.不需要单独再配置nginx

1.集成前置准备

需要在微信支付平台申请商户号.申请好以后需要在商户号上关联对应的公众号,小程序等.涉及微信支付平台,需要提前准备一下信息

  • 微信支付地址: https://api.mch.weixin.qq.com
  • 商户号ID (mchid)
  • 商户API证书 (apiclient_key.pem)
  • 商户API证书序列号(merchant_serial_no)
  • 公众号或小程序的appid (appid)
  • 测试用户对应公众或小程序的openid (openid)

系统集成需要准备以下信息

  • 备案通过的域名
  • 微信支付回调地址 (notify_url)

商户平台配置

  • 产品中心/AppID账号管理 关联小程序或者公众号
  • 产品中心/开发配置 注册唤起支付url必须一样

2. 测试页面开发

测试页面方便不同的商户号测试,整体分两部分内容

  1. 全局配置,主要配置 mchid,apiclient_key.pem,merchant_serial_no,appid,openid,notify_url 配置好以后,信息存储在localStorage中
  2. 支付信息,主要设置 支付金额, 支付说明,是否分账.支付金额最多两位小数

整体测试页面如下

3. JSAPI下单接口

支付接口需要做签名处理,签名采用RAS算法,使用forge.js提供的算法

官方参考文档 https://pay.weixin.qq.com/doc/v3/merchant/4012791856

下单接口的签名串规则如下:

/* by 01022.hk - online tools website : 01022.hk/zh/areacode.html */ HTTP请求方法\n URL\n 请求时间戳\n 请求随机串\n 请求报文主体\n

实际代码体现如下:

/* by 01022.hk - online tools website : 01022.hk/zh/areacode.html */ const message = "POST\n" + "/v3/pay/transactions/jsapi\n" + timeStamp + "\n" + nonceStr +"\n" + JSON.stringify(payData) +"\n";

在前端针对timeStamp有些特殊处理

  • 参数要求到秒,前端通过new Date().getTime()是到毫秒的,需要除1000
  • 必须转换成字符串,否则微信接口会报错

生成签名的主要代码如下:

// 小游戏 地心侠士 function getSign(message, privateKeyStr) { const privateKey = forge.pki.privateKeyFromPem(privateKeyStr); const sha256 = forge.md.sha256.create(); sha256.update(forge.util.encodeUtf8(message)); const signature = forge.util.encode64(privateKey.sign(sha256)); return signature }

最终完整的认证信息如下:

WECHATPAY2-SHA256-RSA2048 mchid="${mchid}",serial_no="${serialNo}",nonce_str="${nonceStr}",timestamp="${timeStamp}",signature="${signature}"

前端完整下单代码如下:

async function processPayinfo(cfgInfo, payInfo) { const payData = { "appid": cfgInfo.appid, "mchid": cfgInfo.mchid, "description": payInfo.description, "out_trade_no": payInfo.out_trade_no || new Date().getTime() + "", "attach": payInfo.attach, "notify_url": cfgInfo.callback_url, "support_fapiao": false, "amount": { "total": Math.round(payInfo.amount * 100), "currency": "CNY" }, "payer": { "openid": cfgInfo.openid }, "settle_info": { "profit_sharing": payInfo.split_payment } }; const nonceStr = generateNonceStr(); const timeStamp = getTimeStamp(); const mchid = cfgInfo.mchid; const method = "POST"; const payUri = "/v3/pay/transactions/jsapi"; // 小游戏 地形侠士 签名原始串 const message =method +"\n" +payUri +"\n" +timeStamp + "\n" +nonceStr +"\n" +JSON.stringify(payData) +"\n"; // 小游戏 地心侠士 生成签名 const serialNo = cfgInfo.merchant_serial_no const privateKeyStr = cfgInfo.apiclient_key; const signature = getSign(message, privateKeyStr); // 小游戏 地心侠士 完整认证串 let auth = `WECHATPAY2-SHA256-RSA2048 mchid="${mchid}",serial_no="${serialNo}",nonce_str="${nonceStr}",timestamp="${timeStamp}",signature="${signature}` const response = await fetch(payUri, { method: method, mode: 'cors', headers: { 'Content-Type': 'application/json', 'Authorization': auth }, body: JSON.stringify(payData) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); console.log(result) return result; }

以上代码,执行成功就会返回预付订单号,类似如下的响应正文

{ "prepay_id": "wx132023572988633421178322a067e20000" }

4. 唤起微信支付

在上边拿到预付单号以后,就可以在微信环境唤起微信支付界面了.唤起微信支付通用涉及到签名,这里的签名方法一样,但是签名串规则略有变化.签名串规则如下:

appId\n 时间戳\n 随机字符串\n prepay_id=\n

这需要注意的是,package并不是下单接口返回的JSON串,需要转换成key=value的形式
完成唤起支付代码如下:

function onBridgeReady(cfgInfo, prepayinfo, cb) { const nonceStr = generateNonceStr(); const timeStamp = getTimeStamp(); // 小游戏 地心侠士 转换预付单号 const package = "prepay_id=" + prepayinfo.prepay_id; const message =cfgInfo.appid +"\n" +timeStamp +"\n" + nonceStr +"\n" + package +"\n"; // 小游戏 地心侠士 生成签名 const privateKeyStr = cfgInfo.apiclient_key; const signature = getSign(message, privateKeyStr); WeixinJSBridge.invoke('getBrandWCPayRequest', { "appId": cfgInfo.appid, "timeStamp": timeStamp, "nonceStr": nonceStr, "package": package, "signType": "RSA", "paySign": signature, }, function (res) { cb && cb(res); if (res.err_msg == "get_brand_wcpay_request:ok") { console.log("支付成功") } }); }

运行成功后,就会弹出微信支付的页面,测试界面显示如下

5. nginx跨域配置

整个测试代码完全通过前端JS实现,在访问微信下单接口时会有跨域限制,在实际服务器中,需要通过nginx对微信接口实现代理.关键配置如下

# === 小游戏 地心侠士 微信支付代理配置 === location ^~ /v3/pay/ { # 目标服务器地址(替换为实际地址) proxy_pass https://api.mch.weixin.qq.com; # 关键头设置 proxy_set_header Host api.mch.weixin.qq.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header User-Agent "WeChat-Pay-Proxy/1.0"; # 超时设置 proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; # 处理CORS add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' '*' always; add_header 'Access-Control-Allow-Headers' '*' always; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' '*'; add_header 'Access-Control-Allow-Headers' '*'; return 204; } }

6. 总结

微信交互常规的做法是通过后端发送请求到微信服务器,微信服务器返回数据,然后通过前端获取数据,再进行交互。在测试时,前端唤起支付,后端提供预定单接口.前后端都不方便测试支付情况.所有才结合微信提供POSTMAN中接口测试方法,完成这个纯前端的,通用的,微信支付测试页面.如需要完成源码,请在微信公众小满小慢回复wepay获取测试代码
原文地址:https://mp.weixin.qq.com/s/r8kAPXyuWZfN7wHXA7VZbw

转载请注明来源
作者:杨瀚博
QQ:464884492
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 14:15:30

27、Linux 系统打印与程序编译全攻略

Linux 系统打印与程序编译全攻略 在 Linux 系统中,打印和程序编译是两项重要的操作。下面将详细介绍如何在 Linux 系统中进行打印操作以及如何编译程序。 打印操作 在类 Unix 系统中,CUPS 打印套件支持两种历史上常用的打印方法,分别使用 lpr 和 lp 程序。 1. 使用 …

作者头像 李华
网站建设 2026/6/10 2:44:49

35、流量控制与字符串数字处理:for 循环及参数扩展详解

流量控制与字符串数字处理:for 循环及参数扩展详解 1. for 循环 在编程中,for 循环是一种强大的工具,用于处理序列。在现代版本的 bash 中,for 循环有两种形式。 1.1 传统 shell 形式 传统的 for 命令语法如下: for variable [in words]; docommands done其中, va…

作者头像 李华
网站建设 2026/6/10 14:15:16

21、正则表达式入门与元字符详解

正则表达式入门与元字符详解 1. 哈希表遍历 1.1 按预定义顺序遍历哈希表 若要按键插入哈希表的顺序遍历键,需维护一个单独的数组来存储这些键。每次向哈希表添加键时,也要将该键添加到数组中。示例代码如下: my @keys_in_order; my %hash; $hash{thing} = 1; push @key…

作者头像 李华
网站建设 2026/6/10 14:16:05

AutoGPT如何生成Word文档?python-docx调用指南

AutoGPT如何生成Word文档?python-docx调用指南 在当今AI驱动的自动化浪潮中,一个真正“能思考、会动手”的智能体已不再是科幻设想。设想这样一个场景:你只需告诉AI——“帮我写一份关于Python学习计划的报告”,几秒钟后&#xff…

作者头像 李华
网站建设 2026/6/10 13:02:53

鸿蒙PC UI控件库 - TextArea 多行文本输入详解

演示视频地址: https://www.bilibili.com/video/BV1jomdBBE4H/ 📋 目录 概述特性快速开始API 参考使用示例主题配置最佳实践常见问题总结 概述 TextArea 是控件库中的多行文本输入组件,支持字数统计、自动调整高度、验证等功能&#xff…

作者头像 李华
网站建设 2026/6/10 10:48:01

ES6新增的新特性以及用法

目录一、ES6介绍1.1 Let变量定义1.2 箭头函数1.2.1 基本语法1.2.2 this 绑定(重要区别!)1.3 模板字符串1.4 解构赋值1.4.1 数组解构1.4.2 对象解构1.5 扩展运算符1.5.1 数组扩展1.5.2 对象扩展1.6 默认参数1.7 剩余参数1.8 Symbol 类型1.10 S…

作者头像 李华