当前位置:网站首页 >  教程

Node.js实现微信支付H5下单全流程实操指南

时间:2026年05月24日 06:49:33 来源:易频IT社区

前置准备与账号配置

在开始编写代码前,必须从微信商户平台获取以下核心参数。这些参数直接决定了支付请求能否被微信网关正确识别和验证。

  • AppID:登录微信开放平台,在已审核通过的移动应用或网站应用详情页中获取。对于H5支付,通常使用微信开放平台的AppID。
  • MchID:微信支付商户号,登录微信商户平台,在首页的右上角即可看到。
  • APIv3 Key:在微信商户平台进入【账户中心】->【API安全】->【设置APIv3密钥】。这是一个32位的字符串,用于解密回调通知中的敏感信息。请妥善保存,不可泄露。
  • 商户私钥:在【账户中心】->【API安全】->【申请商户API证书】中下载证书压缩包。解压后打开apiclient_key.pem文件,这就是商户私钥,用于请求签名。
  • 商户证书序列号:可以在证书下载页面直接查看,或者使用OpenSSL命令openssl x509 -in apiclient_cert.pem -noout -serial获取。去除冒号后的字符串即为序列号。

目录结构建议:请在项目根目录下创建certs文件夹,并将下载的apiclient_key.pemapiclient_cert.pem放入其中。

项目初始化与依赖安装

我们将使用Node.js作为开发环境,利用express搭建Web服务,并使用官方推荐的wechatpay-node-v3SDK来处理复杂的签名和证书加密逻辑。这个SDK是目前接入微信支付API v3最稳妥的方案。

打开终端,依次执行以下命令:

```bash 创建项目目录 mkdir wechat-pay-course-demo cd wechat-pay-course-demo 初始化package.json npm init -y 安装核心依赖 npm install express wechatpay-node-v3 body-parser ```

依赖说明:body-parser用于解析微信支付回调POST请求中的JSON数据;wechatpay-node-v3封装了所有与微信支付交互的底层逻辑。

核心代码实现

在项目根目录下创建server.js文件。我们将实现两个核心接口:/create-order用于发起支付,/notify用于接收支付结果。以下是完整的、可直接运行的代码。

```javascript const express = require('express'); const { Pay } = require('wechatpay-node-v3'); const bodyParser = require('body-parser'); const fs = require('fs'); const path = require('path'); const app = express(); // 解析中间件配置 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); // ================= 配置区域开始 ================= const payConfig = { appid: 'wx1234567890abcdef', // 替换为你的AppID mchid: '1230000109', // 替换为你的商户号 private_key: fs.readFileSync(path.join(__dirname, 'certs/apiclient_key.pem')), serial_no: '1A2B3C4D5E6F...', // 替换为你的证书序列号(去除冒号) apiv3_private_key: 'your32bytesapiv3key...', // 替换为你的APIv3密钥 // 注意:notify_url必须是公网可访问的HTTPS地址,且不能包含端口号(除非是标准443) notify_url: 'https://your-domain.com/notify' }; // ================= 配置区域结束 ================= // 实例化支付对象 const pay = new Pay(payConfig); / 接口1:创建H5支付订单 访问:http://localhost:3000/create-order / app.get('/create-order', async (req, res) => { try { // 生成商户订单号,实际业务中请结合数据库生成唯一订单号 const out_trade_no = 'COURSE' + Date.now(); // 构造下单参数 const params = { appid: payConfig.appid, mchid: payConfig.mchid, description: '高级全栈架构师实战课程', // 商品描述,直接显示在支付界面 out_trade_no: out_trade_no, notify_url: payConfig.notify_url, amount: { total: 100, // 订单金额,单位:分。100代表1元人民币 currency: 'CNY' }, // H5支付场景配置 scene_info: { payer_client_ip: '127.0.0.1', // 实际业务中应获取用户真实IP h5_info: { type: 'Wap', // 场景类型,固定为Wap app_name: '技术博客商城', package_name: 'com.techblog.store' // 网站名或包名 } } }; // 调用统一下单API const result = await pay.transactions_h5(params); if (result.status === 200) { // 下单成功,返回h5_url给前端 // 前端拿到url后,可以通过window.location.href = url跳转 res.json({ code: 0, msg: '下单成功', pay_url: result.data.h5_url }); } else { res.json({ code: -1, msg: '下单失败', error: result }); } } catch (error) { console.error('下单接口异常:', error); res.json({ code: -1, msg: '系统异常', error: error.message }); } }); / 接口2:支付结果通知回调 路径必须与下单时的notify_url一致 / app.post('/notify', async (req, res) => { try { const { headers, body } = req; // 1. 验证签名并解密数据 // SDK会自动处理验签、解密AES-256-GCM加密的resource字段 const data = await pay.verify(headers, body); // 2. 判断交易状态 if (data.event_type === 'TRANSACTION.SUCCESS') { const resource = data.resource; const out_trade_no = resource.out_trade_no; // 商户订单号 const transaction_id = resource.transaction_id; // 微信支付订单号 const total = resource.amount.total; // 支付金额 console.log(``); console.log(`收到支付成功通知:`); console.log(`商户订单号: ${out_trade_no}`); console.log(`微信流水号: ${transaction_id}`); console.log(`支付金额: ${total} 分`); console.log(``); // TODO: 核心业务逻辑 // 1. 检查数据库中订单号是否存在,且状态为“未支付” // 2. 防止重复通知:如果订单已是“已支付”,直接返回成功 // 3. 更新订单状态为“已支付” // 4. 发放课程权益(如:用户表增加course_id字段,或插入权限表) // 3. 重要:必须返回200状态码和特定JSON结构,告知微信服务器处理成功 // 如果不返回成功,微信会在一定时间内通过重试机制反复通知 res.status(200).json({ code: 'SUCCESS', message: '成功' }); } else { // 处理其他事件类型,如TRANSACTION.CLOSED等 res.status(200).json({ code: 'FAIL', message: '忽略非成功交易' }); } } catch (error) { console.error('回调处理异常:', error); // 即使验签失败,也建议返回200,避免微信持续发送无效请求导致服务压力 res.status(200).json({ code: 'FAIL', message: '验签失败' }); } }); // 启动服务 app.listen(3000, () => { console.log('支付服务已启动,监听端口: 3000'); console.log('请在浏览器访问: http://localhost:3000/create-order'); }); ```

本地测试与内网穿透配置

Node.js实现微信支付H5下单全流程实操指南

微信支付的回调接口notify_url严格要求必须是公网可访问的HTTPS地址。在本地开发阶段(localhost),微信服务器无法直接访问你的代码。必须使用内网穿透工具。

这里使用cpolar作为示例,它操作简单且免费版足够使用。你也可以使用ngrok或花生壳。

操作步骤:

  1. 注册并安装cpolar客户端。
  2. 在终端执行命令映射本地3000端口:
```bash cpolar http 3000 ```

执行后,终端会显示公网地址,例如:https://abc123.cpolar.io

修改配置:将上述公网地址填入server.js中的notify_url,例如:

```javascript notify_url: 'https://abc123.cpolar.io/notify' ```

修改后,务必使用node server.js重启Node服务。

支付全流程验证

完成上述配置后,按照以下步骤进行完整的支付闭环测试:

  1. 发起下单:在浏览器地址栏输入http://localhost:3000/create-order并回车。
  2. 获取链接:浏览器页面会显示JSON数据,复制pay_url对应的值(以https://wx.tenpay.com开头)。
  3. 模拟支付
    • 将此链接发送到手机上(微信环境内)打开。
    • 或者使用微信开发者工具,切换到“Web调试”,粘贴链接打开。
  4. 完成支付:在弹出的微信收银台中,输入测试号密码或使用真实小额资金完成支付。
  5. 观察结果
    • 支付成功后,查看你的Node.js终端控制台。
    • 你应该能看到打印出的“收到支付成功通知”日志,包含订单号和金额。
    • 如果日志正常打印,说明/notify接口逻辑已成功执行,你的课程转化闭环在技术上已经跑通。

相关推荐

最新

热门

推荐

精选

标签

易频IT社区是综合性互联网IT技术门户网站,专注分享网络技术、服务器运维、网络安全、编程开发、系统架构、云计算、大数据等行业干货,实时更新IT行业资讯、零基础教程、实战案例,为IT从业者、技术爱好者提供专业的学习交流平台。

Copyright © 2021-2026 易频IT社区. All Rights Reserved. 备案号:闽ICP备2023013482号 网站地图