const fetch = require('node-fetch') const APPID = process.env.WECHAT_APPID const SECRET = process.env.WECHAT_SECRET let accessToken = null let tokenExpiresAt = 0 async function getAccessToken() { if (!APPID || !SECRET) { throw new Error('WECHAT_APPID and WECHAT_SECRET must be configured in .env') } if (accessToken && Date.now() < tokenExpiresAt) { return accessToken } const res = await fetch( `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${SECRET}` ) const data = await res.json() if (data.errcode) { throw new Error(`微信API错误: ${data.errmsg}`) } accessToken = data.access_token tokenExpiresAt = Date.now() + (data.expires_in - 300) * 1000 return accessToken } async function sendSubscribeMessage(openid, templateId, data, page = '') { const token = await getAccessToken() const body = { touser: openid, template_id: templateId, page, data, miniprogram_state: 'formal' } const res = await fetch( `https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=${token}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) } ) const result = await res.json() if (result.errcode && result.errcode !== 0) { console.error('发送订阅消息失败:', result) return { success: false, error: result.errmsg } } return { success: true } } async function sendOrderStatusNotification(openid, orderId, status, totalPrice) { const statusText = { paid: '已付款', completed: '已完成', cancelled: '已取消' } const templateId = process.env.WECHAT_ORDER_TEMPLATE_ID if (!templateId) { console.warn('WECHAT_ORDER_TEMPLATE_ID not configured, skipping notification') return { success: false, error: 'template not configured' } } return sendSubscribeMessage(openid, templateId, { thing1: { value: `订单 ${orderId}` }, phrase2: { value: statusText[status] || status }, amount3: { value: `¥${totalPrice}` }, date4: { value: new Date().toLocaleString('zh-CN') }, thing5: { value: '点击查看订单详情' } }, `/pages/customer-extra/order-detail/order-detail?id=${orderId}`) } module.exports = { getAccessToken, sendSubscribeMessage, sendOrderStatusNotification }