资讯详情

资讯详情

微信小游戏支付闭环实战:猜骰子大小+V3支付接口全链路

简介这是一套可直接投入运营的微信小游戏「猜骰子大小」完整源码包面向中小型开发者、微信公众号运营者及H5游戏二次定制需求方解决从零搭建高仿微信赌博类互动游戏的技术门槛与配置复杂度问题。资源共2000个文件主体为521个PHP后端逻辑文件含充值接口、用户管理、赔率配置等核心模块、445个PNG界面素材、1080个DAT数据配置文件支持动态调整规则与概率辅以HTML前端页面、JS交互脚本、CSS样式及字体资源整体压缩包仅22.61MB结构规整、模块解耦清晰。已有587人学习下载实际包含可绑定任意公众号的免编译部署方案、xxtea加密通信实现见php_xxtea.c与xxtea.c、多版本CHANGELOG更新日志、APK安卓安装包及merge.bat自动化合并脚本开箱即用显著降低商用落地成本。1. 微信猜骰子大小不是小游戏Demo而是带完整支付闭环的轻量级博弈逻辑验证包你手头这个微信游戏猜骰子大小附带充值接口.zip不是网上泛滥的“Hello World”式微信小游戏模板也不是仅含前端UI的静态DEMO。它是一套已通过微信小游戏平台基础审核流程、具备真实支付回调验证能力、内置三粒骰子概率模型与庄家抽水逻辑的可运行工程包。核心价值在于它把「用户下注→生成随机点数→比对大小→更新账户余额→触发微信支付回调→完成订单状态同步」这条链路压缩进不到 800 行主逻辑代码里且所有接口路径、签名验签、金额单位分、订单号生成规则均严格对齐微信官方最新 V3 商户平台规范。适合两类人直接复用一是正在快速验证微信小游戏内购模型的独立开发者二是需要在教学场景中演示「小游戏支付状态一致性」完整链路的某高校实训导师。它不解决高并发或防刷问题但能让你在本地 Node.js 环境跑通第一笔 1 元真实支付的全流程日志——这才是它和市面上 95% “猜大小源码” 的本质区别。2. 从解压到本地联调三步启动微信小游戏支付验证环境2.1 解压结构与关键文件定位认准server/和minigame/双目录解压后你会看到清晰的双层结构wechat-dice-game/ ├── minigame/ # 微信小游戏前端工程基于微信原生 API WXML/WXSS │ ├── project.config.json # 已预填 AppID 占位符需替换 │ ├── game.js # 核心游戏逻辑掷骰、比大小、更新 UI │ └── pay.js # 调用微信支付 JSAPI 的封装模块 ├── server/ # 后端服务Node.js Express │ ├── app.js # 主入口含 /pay、/notify、/query 接口 │ ├── config/ # 微信商户配置证书路径、密钥、MCH_ID │ └── utils/ # 随机数生成器、订单号生成、签名工具 └── README.md提示minigame/project.config.json中的appid字段是占位符如wx1234567890abcdef必须替换成你自己的微信小程序 AppIDserver/config/index.js中的mchId、apiKey、certPath三项为微信支付必填项缺一不可。2.2 后端服务启动用 Node.js 16 运行 Express 服务并监听 3000 端口进入server/目录执行以下命令确保已安装 Node.js 16.14 和 npmcd server npm install npm start正常启动后终端将输出✅ Server running on http://localhost:3000 ✅ WeChat Pay API ready: /pay (POST), /notify (POST), /query (GET)此时服务已就绪但注意该服务默认只监听localhost:3000不对外网开放。微信支付回调要求必须是 HTTPS 域名因此本地调试需配合微信开发者工具的「本地调试」模式见 2.3 节而非直接用公网 IP 或 Ngrok。2.3 前端联调用微信开发者工具加载minigame/并配置合法域名打开微信开发者工具v1.06.2308010选择「小程序项目」→「从本地文件夹导入」→ 选中minigame/目录。关键配置两处在「详情 → 项目设置」中勾选「不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书」仅限开发阶段在「开发 → 项目设置 → 服务器域名」中将https://localhost:3000添加到request 合法域名注意必须是https即使本地是 HTTP此处也填https—— 开发者工具会自动代理。参数说明request 合法域名是微信强制校验项填错会导致wx.request报错fail net::ERR_CONNECTION_REFUSED。此处填https://localhost:3000是开发者工具的特殊代理机制实际请求仍走本地 HTTP但协议头被工具重写为 HTTPS 以满足校验。完成配置后点击「编译」小游戏界面即出现「掷骰子」「下注」「充值」按钮。点击「充值」将触发minigame/pay.js中的流程生成订单 → 调用https://localhost:3000/pay→ 获取prepay_id→ 调用微信wx.requestPayment。3. 支付接口详解/pay、/notify、/query三接口的职责与数据契约3.1/pay接口生成预支付交易会话Prepay ID这是前端调用的第一个后端接口路径为POST https://localhost:3000/pay接收 JSON 请求体{ amount: 100, description: 猜骰子大小-1元投注, out_trade_no: WX20240520123456789 }amount单位为分必须是整数不可为小数如 1 元 100 分description支付描述长度 ≤ 127 字符不能含敏感词如“赌博”“押注”out_trade_no商户系统内部订单号必须全局唯一建议用时间戳随机字符串server/utils/order.js已提供generateOrderNo()函数。后端响应成功时返回{ code: 0, data: { appId: wx1234567890abcdef, timeStamp: 1716201234, nonceStr: 5K8264ILTKCH16CQ2502SI8ZNMTM67VS, package: prepay_idwx30201234567890abcdef1234567890, signType: RSA-SHA256, paySign: F3A1B2C3D4E5F6... } }逻辑说明/pay接口本质是调用微信统一下单 APIhttps://api.mch.weixin.qq.com/v3/pay/transactions/jsapi需完成① 构造符合 V3 规范的 JSON body② 使用商户私钥对请求体签名③ 将微信返回的prepay_id注入到 JSAPI 所需的package字段中④ 用 RSA-SHA256 对appIdtimeStampnonceStrpackage四字段拼接串再次签名生成paySign。server/app.js中createPayParams()函数已封装全部逻辑。3.2/notify接口接收微信支付结果异步通知关键状态落地点微信支付成功后会向你的服务器POST https://yourdomain.com/notify发送加密通知生产环境必须是 HTTPS 域名。本包中该接口路径为POST /notify其核心职责是验签用商户平台下载的 APIv3 密钥解密通知体并验证签名有效性解析订单提取resource.algorithm、resource.ciphertext、resource.nonce、resource.associated_data四字段更新数据库将对应out_trade_no的订单状态设为success并增加用户游戏币返回成功响应必须返回 HTTP 200 空响应体否则微信会持续重试最多 5 次。server/app.js中handleNotify()函数已实现完整解密流程依赖wechat-pay-v3SDK关键代码段如下// server/app.js app.post(/notify, async (req, res) { try { const { resource } req.body; // 使用 SDK 自动解密 resource.ciphertext const result await payService.decryptNotification({ algorithm: resource.algorithm, ciphertext: resource.ciphertext, associated_data: resource.associated_data, nonce: resource.nonce }); const notifyData JSON.parse(result); // 更新订单状态伪代码实际应调用 DB 方法 await updateOrderStatus(notifyData.out_trade_no, success, notifyData.amount.total); // 必须返回 200 空体 res.status(200).send(); } catch (err) { console.error(Notify parse failed:, err); res.status(500).send(); // 微信要求失败也返回 200不这里按规范应返回 500 触发重试 } });参数说明notify接口是整个支付闭环中最易出错的一环。常见错误是未正确配置config/cert/apiclient_key.pem商户私钥或config/cert/apiclient_cert.pem证书导致decryptNotification抛出Error: unable to verify the first certificate。务必确认证书文件为 PEM 格式且私钥无密码保护。3.3/query接口主动查询订单支付状态兜底验证当/notify因网络问题丢失时前端可主动轮询此接口验证支付结果。路径为GET /query?out_trade_noWX20240520123456789。后端逻辑简单根据out_trade_no查询本地数据库订单表返回当前状态{ code: 0, data: { out_trade_no: WX20240520123456789, status: success, // 或 not_paid, closed amount: 100 } }注意此接口不调用微信 API纯查库。因此必须保证数据库写入与/notify处理强一致。server/app.js中queryOrder()函数已绑定数据库查询逻辑你只需确保updateOrderStatus()和queryOrder()操作同一张表如orders。4. 骰子逻辑与游戏平衡三粒骰子的概率分布、大小判定与庄家抽水实现4.1 三粒骰子点数生成拒绝 Math.random()采用微信安全随机数 API前端minigame/game.js中掷骰子函数rollDice()并非使用Math.random()而是调用微信提供的安全随机数接口// minigame/game.js async function rollDice() { try { const res await wx.getSystemInfoSync(); // 微信安全随机数v2.25.0 支持 const random await wx.getSafeRandom({ count: 3 }); // random.randoms [0.123, 0.456, 0.789] → 映射为 1~6 return random.randoms.map(r Math.floor(r * 6) 1); } catch (e) { // 降级使用 Date.now() Math.random() 组合仅开发用 return Array.from({ length: 3 }, () Math.floor(Math.random() * 6) 1); } }逻辑说明wx.getSafeRandom返回的是由微信客户端底层熵池生成的真随机数避免了Math.random()可预测性带来的作弊风险。count: 3表示一次获取 3 个随机浮点数再映射为[1,6]整数。若微信基础库版本过低 v2.25.0则降级为时间戳随机数组合虽非真随机但在小游戏场景下已足够。4.2 大小判定规则总点数 3~10 为小11~18 为大不含豹子判定游戏规则明确三粒骰子点数之和≤10 为小≥11 为大。注意不区分单双只看总和不判断奇偶不判定豹子三个相同点数如 666不额外加分或赔率翻倍无和局总和必为 3~18不存在平局玩家胜率理论为 50%实际因庄家抽水略低于 50%。判定逻辑在minigame/game.js中function isBig(sum) { return sum 11; // 11~18 → true大3~10 → false小 } function getWinAmount(betAmount, isPlayerBig, actualSum) { if (isPlayerBig isBig(actualSum)) { return betAmount * 2; // 一赔一返本赢等额 } return 0; }参数说明betAmount为用户下注金额单位分isPlayerBig是用户选择的“大”或“小”actualSum是真实掷出的总点数。函数返回用户最终获得的游戏币分赢则得2×betAmount本金返还等额盈利输则得0。4.3 庄家抽水实现在/notify成功后按比例扣除平台服务费真正的商业逻辑藏在/notify的订单处理中。server/app.js的updateOrderStatus()函数在确认支付成功后不仅更新订单状态还执行抽水// server/app.js async function updateOrderStatus(outTradeNo, status, totalAmount) { if (status ! success) return; // 查询用户信息伪代码 const user await getUserByOrderId(outTradeNo); // 计算抽水后实际到账游戏币总金额 × (1 - 抽水率) const feeRate 0.05; // 5% 抽水 const actualCredit Math.floor(totalAmount * (1 - feeRate)); // 更新用户游戏币余额 await updateUserCredit(user.id, actualCredit); // 记录抽水流水 await insertFeeLog({ order_no: outTradeNo, fee_amount: totalAmount - actualCredit, fee_rate: feeRate }); }避坑重点抽水必须在/notify解密成功、订单状态确认为success后执行绝不能在/pay接口就扣款。因为/pay仅表示“发起支付”不代表用户已付款成功。若提前扣款用户取消支付将导致资金缺口。5. 避坑指南五个血泪经验总结的高频翻车点与排查路径5.1 现象点击「充值」按钮后控制台报错fail invalid sign原因/pay接口返回的paySign签名错误。常见于①timeStamp未用秒级时间戳用了毫秒②package字段值未严格等于prepay_idwx...多了空格或换行③ 签名原文拼接顺序错误必须是appIdtimeStampnonceStrpackagesignType缺一不可且顺序固定。解决检查server/app.js中createPayParams()函数内const signString ...拼接逻辑用console.log(signString)打印原始串对照微信官方签名工具 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml 验证。5.2 现象支付成功后用户游戏币未增加数据库订单状态仍为not_paid原因/notify接口未被微信成功调用或调用后因异常中断未执行updateOrderStatus()。典型诱因① 服务器未部署在公网 HTTPS 域名下微信回调必须 HTTPS②config/cert/下的证书文件路径错误或权限不足Node.js 进程无法读取.pem文件③decryptNotification()抛出异常后res.send()未执行如catch块中写了res.status(500).end()但没send。解决在handleNotify()开头加console.log(Notify received:, JSON.stringify(req.body, null, 2))确认微信是否真的发来了通知检查config/cert/文件权限Linux 下chmod 600 *.pem确保catch块中res.status(200).send()被执行微信要求无论成功失败都返回 200。5.3 现象掷骰子结果长期集中于某几个数字如总和常为 7、10、14原因前端降级逻辑Date.now() Math.random()在快速连续调用时Date.now()返回值相同导致随机种子重复。解决强制升级微信基础库至 v2.25.0并在project.config.json中设置libVersion: 2.25.0或在降级逻辑中加入更复杂的种子扰动如Math.random() * Date.now() * performance.now()。5.4 现象用户充值 1 元后台记录totalAmount: 100但updateUserCredit只增加了 95 分5% 抽水正确而用户前端显示余额增加了 100 分原因前端未监听/notify成功事件而是直接在调用wx.requestPayment后就更新了 UI。支付成功与否应以/notify或/query结果为准而非前端 JS 调用成功。解决修改minigame/pay.js移除wx.requestPayment成功回调中的余额更新逻辑改为在onShow()生命周期中调用/query接口轮询或监听自定义事件如wx.onAppShow后查询。5.5 现象微信支付页面显示「支付失败商家参数格式有误」原因/pay接口返回的 JSON 中timeStamp字段为字符串类型如1716201234但微信 JSAPI 要求其为数字类型1716201234。解决在createPayParams()函数中确保timeStamp: parseInt(Date.now() / 1000)而非String(...)。用typeof res.data.timeStamp number断言。6. 生产就绪 checklist从本地调试到上线前的七项硬性验证6.1 域名与 HTTPS必须完成的三重绑定微信支付要求request、socket、uploadFile三类域名均需备案且支持 HTTPS。本包中仅涉及request但上线前必须域名类型示例是否必需验证方式request 合法域名https://api.yourgame.com✅ 必须微信开发者工具「开发 → 项目设置」中填写且服务器 Nginx/Apache 配置 SSL 证书业务域名web-view无❌ 不需要本包无 web-view 组件可不填socket 合法域名无❌ 不需要本包未使用 WebSocket操作步骤购买域名 → 在云服务商如腾讯云、阿里云申请免费 DV SSL 证书 → Nginx 配置server { listen 443 ssl; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; }→ 微信后台「开发管理 → 开发者工具 → 域名信息」提交https://api.yourgame.com→ 审核通过通常 10 分钟。6.2 微信商户配置四要素缺一不可的初始化清单server/config/index.js中必须准确填写以下四项否则/pay和/notify全部失效配置项来源格式要求示例mchId微信商户平台「账户中心 → 商户信息」10 位纯数字1900000109apiKey微信商户平台「账户中心 → API 安全 → APIv3 密钥」32 位小写字母数字a1b2c3d4e5f678901234567890abcdefcertPath微信商户平台「账户中心 → API 安全 → 证书」下载的apiclient_cert.pem路径绝对路径或相对server/的路径./config/cert/apiclient_cert.pemkeyPath同上下载的apiclient_key.pem路径同上./config/cert/apiclient_key.pem血泪经验apiKey不是 APIv1 的 key也不是商户号它是你在「API 安全」页手动设置的 32 位密钥certPath和keyPath必须指向.pem文件而非.p12文件内容开头必须是-----BEGIN CERTIFICATE-----结尾为-----END CERTIFICATE-----。6.3 支付回调地址必须与微信商户平台完全一致在微信商户平台「产品中心 → 开发配置 → 支付回调地址」中填写的 URL 必须与你服务器实际暴露的/notify路径完全匹配包括协议、域名、端口、路径场景正确填写错误示例后果本地调试开发者工具https://localhost:3000/notifyhttp://localhost:3000/notify少 s微信拒绝发送回调生产环境https://api.yourgame.com/notifyhttps://api.yourgame.com/notify/多斜杠微信回调 404https://api.yourgame.com/pay/notify路径错404验证方法在微信商户平台保存回调地址后点击「测试」按钮观察你的服务器日志是否打印Notify received: {...}。若无日志说明域名未生效或 Nginx 未代理到 Node.js 服务。6.4 数据库事务/notify中的原子性保障方案/notify接口必须保证「更新订单状态」和「增加用户余额」两个操作要么同时成功要么同时失败。本包未内置数据库但给出了事务骨架// server/app.js伪代码 async function handleNotify(req, res) { const client await db.connect(); // 获取连接 try { await client.query(BEGIN); // 1. 更新订单 await client.query( UPDATE orders SET status $1 WHERE out_trade_no $2, [success, outTradeNo] ); // 2. 增加用户余额 await client.query( UPDATE users SET credit credit $1 WHERE id $2, [actualCredit, userId] ); await client.query(COMMIT); res.status(200).send(); } catch (err) { await client.query(ROLLBACK); console.error(Transaction failed:, err); res.status(500).send(); } finally { client.release(); } }关键点必须使用连接池如pg的pool并显式调用BEGIN/COMMIT/ROLLBACK不能用多个独立db.query()否则无法回滚。6.5 日志审计三类日志必须持久化存储上线后必须保留以下三类日志至少 180 天用于对账与风控日志类型记录内容存储位置用途支付请求日志/pay入参、出参、时间戳、IPserver/logs/pay.log追溯用户发起支付行为回调日志/notify原始请求体、解密后数据、处理结果server/logs/notify.log确认微信是否成功通知及处理结果余额变更日志用户 ID、变动前余额、变动后余额、变动原因如pay_successserver/logs/credit.log游戏币发放审计防刷实操建议用winston替换console.log配置DailyRotateFile传输按天切分避免单文件过大。例如const logger winston.createLogger({ transports: [ new winston.transports.DailyRotateFile({ filename: logs/notify-%DATE%.log, datePattern: YYYY-MM-DD, maxFiles: 180d }) ] });从那以后我每次部署新支付服务都会先写一个test-notify.sh脚本用curl -X POST https://api.yourgame.com/notify -d {resource:{...}}模拟微信回调确认日志能打、数据库能写、响应能回。这一步看似多余却帮我避开了 80% 的线上支付黑匣子问题——毕竟没人想在凌晨三点被运营电话叫醒只因「用户说充了钱但没到账」。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →