微信服务号 - 实际例子

通过一个完整的"在线商城服务号"例子,展示服务号开发的核心场景:用户授权、商品下单、微信支付、模板消息通知。

项目结构

├── server │ ├── app.js // Express入口 │ ├── routes │ │ ├── wechat.js // 微信消息/事件处理 │ │ ├── auth.js // OAuth网页授权 │ │ ├── order.js // 订单管理 │ │ └── pay.js // 微信支付 │ ├── services │ │ ├── token.js // access_token管理(Redis缓存) │ │ ├── template.js // 模板消息 │ │ └── user.js // 用户管理 │ └── utils │ └── wechat.js // 签名、XML解析等工具 ├── public │ ├── index.html // 商城首页 │ ├── order.html // 订单详情页 │ └── pay-success.html // 支付成功页 ├── package.json └── .env

server/app.js - 入口文件

const express = require('express') const session = require('express-session') const wechatRouter = require('./routes/wechat') const authRouter = require('./routes/auth') const orderRouter = require('./routes/order') const payRouter = require('./routes/pay') const app = express() app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false })) app.use(express.json()) app.use(express.static('public')) app.use('/wechat', wechatRouter) app.use('/auth', authRouter) app.use('/order', orderRouter) app.use('/pay', payRouter) app.listen(3000, () => console.log('商城服务启动于端口 3000'))

server/routes/order.js - 订单与支付

const router = require('express').Router() const crypto = require('crypto') const { unifiedOrder, generatePayParams } = require('../utils/wechat') const { sendTemplateMsg } = require('../services/template') const orders = new Map() router.post('/create', async (req, res) => { const { openid } = req.session.user const { productName, price } = req.body const orderId = 'ORD' + Date.now() const order = { id: orderId, openid: openid, productName: productName, price: price, status: 'pending', createTime: new Date().toISOString() } orders.set(orderId, order) const prepayResult = await unifiedOrder( openid, orderId, price * 100, productName ) const payParams = generatePayParams(prepayResult.prepay_id) res.json({ orderId: orderId, payParams: payParams }) }) router.get('/detail/:id', (req, res) => { const order = orders.get(req.params.id) if (!order) return res.status(404).json({ error: '订单不存在' }) res.json(order) }) module.exports = router

server/routes/pay.js - 支付回调

const router = require('express').Router() const xml2js = require('xml2js') const getRawBody = require('raw-body') const { verifySign } = require('../utils/wechat') const { sendTemplateMsg } = require('../services/template') router.post('/notify', async (req, res) => { const xmlData = await getRawBody(req, { encoding: 'utf-8' }) const { xml } = await xml2js.parseStringPromise(xmlData) const params = {} Object.keys(xml).forEach(k => { params[k] = xml[k][0] }) if (!verifySign(params)) { return res.send('<xml><return_code>FAIL</return_code></xml>') } if (params.result_code === 'SUCCESS') { const orderId = params.out_trade_no const order = orders.get(orderId) if (order) { order.status = 'paid' order.transactionId = params.transaction_id await sendTemplateMsg(order.openid, process.env.TPL_PAY_SUCCESS, { first: { value: '支付成功通知' }, keyword1: { value: order.productName }, keyword2: { value: `¥${(order.price).toFixed(2)}` }, keyword3: { value: orderId }, keyword4: { value: order.createTime }, remark: { value: '感谢购买,点击查看订单详情' } }, `https://example.com/order.html?id=${orderId}`) } } res.send('<xml><return_code>SUCCESS</return_code></xml>') }) module.exports = router

public/index.html - 商城首页

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>微信商城</title> </head> <body> <div id="app"> <div class="product-card"> <h3>精品课程</h3> <p class="price">¥99.00</p> <button onclick="buyNow('精品课程', 99)">立即购买</button> </div> </div> <script> async function buyNow(name, price) { const res = await fetch('/order/create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ productName: name, price: price }) }) const { payParams } = await res.json() WeixinJSBridge.invoke('getBrandWCPayRequest', payParams, function(res) { if (res.err_msg === 'get_brand_wcpay_request:ok') { location.href = '/pay-success.html' } }) } </script> </body> </html>

效果预览

微信商城
精品课程
¥99.00 立即购买
VIP会员
¥199.00 立即购买
模板消息通知
支付成功通知
商品名称:精品课程
支付金额:¥99.00
订单编号:ORD20250214001
支付时间:2025-02-14 10:30
感谢购买,点击查看订单详情
← Sa Oauth Frameworks →