MBE 微信支付集成指南
更新日期: 2026-02-02
版本: 1.0.0
目录
概述
MBE系统支持以下微信支付方式:
| 支付方式 | 场景 | API类型 |
|---|---|---|
| Native支付 | PC端扫码支付 | pay_type: native |
| H5支付 | 手机浏览器支付 | pay_type: h5 |
| JSAPI支付 | 微信内H5/小程序 | pay_type: jsapi |
架构图
┌─────────────────────────────────────────────────────────────┐
│ MBE 支付系统架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 前端应用 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ PC Web │ │ Mobile Web │ │ 微信内H5 │ │
│ │ (扫码支付) │ │ (H5支付) │ │ (JSAPI) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┬┴─────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MBE Payment API (/api/payment) │ │
│ │ │ │
│ │ POST /create 创建支付订单 │ │
│ │ GET /status/{id} 查询支付状态 │ │
│ │ POST /close/{id} 关闭订单 │ │
│ │ POST /refund 申请退款 │ │
│ │ GET /methods 获取支付方式 │ │
│ │ GET /plans 获取订阅计划 │ │
│ └──────────────────────────┬──────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ WeChatPayService │ │
│ │ (src/payments/wechat_pay.py) │ │
│ └──────────────────────────┬──────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 微信支付平台 API V3 │ │
│ │ api.mch.weixin.qq.com │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Webhook回调处理 │ │
│ │ POST /webhook/wechat/pay │ │
│ │ │ │
│ │ 1. 验证签名 │ │
│ │ 2. 解密数据 │ │
│ │ 3. 更新订阅状态 │ │
│ │ 4. 增加Token额度 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
前置准备
所需材料
| 材料 | 说明 |
|---|---|
| 营业执照 | 企业或个体工商户 |
| 法人身份证 | 正反面照片 |
| 对公银行账户 | 用于结算和验证 |
| 联系人手机号 | 接收验证码 |
| 已备案域名 | 用于H5支付和回调 |
依赖安装
# 安装微信支付SDK
pip install wechatpayv3
# 或者在 requirements.txt 中添加
echo "wechatpayv3>=1.2.0" >> requirements.txt
pip install -r requirements.txt
商户号申请
申请流程
访问商户平台
- 打开 https://pay.weixin.qq.com
- 点击"成为商户"
填写资料
- 选择主体类型(企业/个体工商户)
- 上传营业执照
- 填写法人信息
- 填写结算账户
账户验证
- 微信支付向结算账户打入随机验证款(0.01-1元)
- 登录商户平台填写验证金额
签署协议
- 在线签署《微信支付商户服务协议》
获取配置信息
配置项 获取位置 商户号(mch_id) 账户中心 → 账户信息 API V3密钥 账户中心 → API安全 → 设置API V3密钥 商户证书序列号 账户中心 → API安全 → 申请API证书 商户私钥 申请API证书时下载 apiclient_key.pem
开通支付产品
在商户平台 → 产品中心 开通:
- Native支付(默认开通)
- H5支付(需单独申请,设置H5支付域名)
- JSAPI支付(需绑定公众号/小程序AppID)
环境配置
配置文件
在 .env.development 或 .env.production 中添加:
# 支付环境
PAYMENT_ENV=sandbox # sandbox(测试)或 production(生产)
# 支付回调URL(需公网可访问)
PAYMENT_CALLBACK_URL=https://mbe.hi-maker.com
# 微信支付配置
WECHAT_PAY_APP_ID=wx1234567890abcdef
WECHAT_PAY_MCH_ID=1234567890
WECHAT_PAY_API_V3_KEY=your_32_chars_api_v3_key_here_xx
# 证书配置(二选一)
# 方式A: 文件路径
WECHAT_PAY_PRIVATE_KEY_PATH=/path/to/apiclient_key.pem
WECHAT_PAY_CERT_SERIAL=1234567890ABCDEF1234567890ABCDEF12345678
# 方式B: 直接配置内容(Docker/云环境推荐)
WECHAT_PAY_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nMIIEvg...
配置验证
# 测试配置是否正确
from src.payments.config import get_payment_config
config = get_payment_config()
print(f"WeChat configured: {config.is_wechat_enabled()}")
print(f"Environment: {config.environment}")
API接口说明
1. 创建支付订单
POST /api/payment/create
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| amount | float | 是 | 金额(元) |
| provider | string | 是 | 支付方式:wechat / alipay |
| pay_type | string | 否 | 支付类型:native / h5 / jsapi,默认native |
| plan | string | 否 | 订阅计划:personal / pro / enterprise |
| description | string | 否 | 商品描述 |
| openid | string | 条件 | JSAPI支付必填,用户OpenID |
| return_url | string | 否 | H5支付完成跳转URL |
请求示例
Native支付(PC扫码)
{
"amount": 29.00,
"provider": "wechat",
"pay_type": "native",
"plan": "personal",
"description": "MBE个人订阅-1个月"
}
H5支付(手机浏览器)
{
"amount": 29.00,
"provider": "wechat",
"pay_type": "h5",
"plan": "personal",
"return_url": "https://edu.hi-maker.com/payment/result"
}
JSAPI支付(微信内)
{
"amount": 29.00,
"provider": "wechat",
"pay_type": "jsapi",
"plan": "personal",
"openid": "oUpF8uN95-Ptaags6E_roPHg7AG0"
}
响应示例
Native支付响应
{
"success": true,
"order_id": "user123_personal_20260202120000_abc123",
"amount": 29.00,
"provider": "wechat",
"pay_type": "native",
"code_url": "weixin://wxpay/bizpayurl?pr=xxx",
"expire_time": "2026-02-02T14:00:00Z",
"sandbox": false
}
H5支付响应
{
"success": true,
"order_id": "user123_personal_20260202120000_abc123",
"amount": 29.00,
"provider": "wechat",
"pay_type": "h5",
"h5_url": "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=xxx",
"pay_url": "https://wx.tenpay.com/...",
"expire_time": "2026-02-02T12:05:00Z"
}
JSAPI支付响应
{
"success": true,
"order_id": "user123_personal_20260202120000_abc123",
"amount": 29.00,
"provider": "wechat",
"pay_type": "jsapi",
"pay_params": {
"appId": "wx1234567890",
"timeStamp": "1706860800",
"nonceStr": "abc123def456",
"package": "prepay_id=wx...",
"signType": "RSA",
"paySign": "xxxxx"
}
}
2. 查询支付状态
GET /api/payment/status/{order_id}
{
"success": true,
"order_id": "user123_personal_20260202120000_abc123",
"status": "paid", // pending / paid / failed / closed
"data": {
"transaction_id": "4200001234567890",
"amount": 2900,
"success_time": "2026-02-02T12:01:00Z"
}
}
3. 关闭订单
POST /api/payment/close/{order_id}
4. 申请退款
POST /api/payment/refund
{
"order_id": "user123_personal_20260202120000_abc123",
"refund_amount": 29.00,
"reason": "用户申请退款"
}
5. 获取支付方式
GET /api/payment/methods
6. 获取订阅计划
GET /api/payment/plans
前端集成
React/Next.js 示例
1. 支付组件
// components/PaymentButton.tsx
import { useState } from 'react';
import QRCode from 'qrcode.react';
interface PaymentButtonProps {
plan: string;
amount: number;
onSuccess?: () => void;
}
export function PaymentButton({ plan, amount, onSuccess }: PaymentButtonProps) {
const [loading, setLoading] = useState(false);
const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);
const [orderId, setOrderId] = useState<string | null>(null);
// 检测设备类型
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
const isWechat = /MicroMessenger/i.test(navigator.userAgent);
// 创建支付订单
const createPayment = async () => {
setLoading(true);
try {
// 根据环境选择支付类型
let payType = 'native';
if (isWechat) {
payType = 'jsapi';
} else if (isMobile) {
payType = 'h5';
}
const response = await fetch('/api/payment/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-User-ID': getUserId(), // 从登录状态获取
},
body: JSON.stringify({
amount,
provider: 'wechat',
pay_type: payType,
plan,
return_url: `${window.location.origin}/payment/result`,
}),
});
const data = await response.json();
if (data.success) {
setOrderId(data.order_id);
if (payType === 'native') {
// PC端显示二维码
setQrCodeUrl(data.code_url);
startPolling(data.order_id);
} else if (payType === 'h5') {
// H5支付跳转
window.location.href = data.h5_url;
} else if (payType === 'jsapi') {
// 微信内调起支付
invokeWechatPay(data.pay_params);
}
} else {
alert(data.error || '创建订单失败');
}
} catch (error) {
console.error('Payment error:', error);
alert('支付请求失败');
} finally {
setLoading(false);
}
};
// 轮询支付状态
const startPolling = (orderId: string) => {
const interval = setInterval(async () => {
const res = await fetch(`/api/payment/status/${orderId}`);
const data = await res.json();
if (data.status === 'paid') {
clearInterval(interval);
setQrCodeUrl(null);
onSuccess?.();
}
}, 2000);
// 5分钟后停止轮询
setTimeout(() => clearInterval(interval), 5 * 60 * 1000);
};
// 微信JSAPI支付
const invokeWechatPay = (params: any) => {
if (typeof WeixinJSBridge !== 'undefined') {
WeixinJSBridge.invoke('getBrandWCPayRequest', params, (res: any) => {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
onSuccess?.();
}
});
}
};
return (
<div>
<button
onClick={createPayment}
disabled={loading}
className="bg-green-500 text-white px-6 py-3 rounded-lg"
>
{loading ? '处理中...' : `微信支付 ¥${amount}`}
</button>
{/* 二维码弹窗 */}
{qrCodeUrl && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center">
<div className="bg-white p-8 rounded-xl text-center">
<h3 className="text-lg font-bold mb-4">微信扫码支付</h3>
<QRCode value={qrCodeUrl} size={200} />
<p className="mt-4 text-gray-500">请使用微信扫描二维码完成支付</p>
<button
onClick={() => setQrCodeUrl(null)}
className="mt-4 text-gray-400"
>
取消支付
</button>
</div>
</div>
)}
</div>
);
}
2. 支付结果页
// pages/payment/result.tsx
import { useEffect, useState } from 'react';
import { useSearchParams } from 'next/navigation';
export default function PaymentResult() {
const searchParams = useSearchParams();
const [status, setStatus] = useState<'loading' | 'success' | 'fail'>('loading');
useEffect(() => {
// H5支付返回后查询状态
const orderId = searchParams.get('order_id');
if (orderId) {
checkPaymentStatus(orderId);
}
}, [searchParams]);
const checkPaymentStatus = async (orderId: string) => {
try {
const res = await fetch(`/api/payment/status/${orderId}`);
const data = await res.json();
setStatus(data.status === 'paid' ? 'success' : 'fail');
} catch {
setStatus('fail');
}
};
return (
<div className="text-center py-20">
{status === 'loading' && <p>正在确认支付结果...</p>}
{status === 'success' && (
<div>
<h1 className="text-2xl text-green-500">支付成功!</h1>
<p className="mt-4">您的订阅已生效</p>
</div>
)}
{status === 'fail' && (
<div>
<h1 className="text-2xl text-red-500">支付未完成</h1>
<p className="mt-4">请重试或联系客服</p>
</div>
)}
</div>
);
}
支付流程
Native支付流程(PC扫码)
用户 前端 MBE API 微信支付
│ │ │ │
│─选择计划──▶│ │ │
│ │─创建订单────▶│ │
│ │ │─下单请求───▶│
│ │ │◀──code_url──│
│ │◀─返回code_url│ │
│◀─显示二维码│ │ │
│ │ │ │
│─扫码支付──────────────────────────────▶│
│ │ │ │
│ │◀──轮询状态───│ │
│ │ │◀──回调通知──│
│ │ │─验证签名 │
│ │ │─更新订阅 │
│ │◀──支付成功───│ │
│◀─显示成功─│ │ │
H5支付流程(手机浏览器)
用户 前端 MBE API 微信支付 微信APP
│ │ │ │ │
│─点击支付──▶│ │ │ │
│ │─创建订单────▶│ │ │
│ │ │─下单请求───▶│ │
│ │ │◀──h5_url────│ │
│ │◀─返回h5_url─│ │ │
│◀─跳转URL──│ │ │ │
│───────────────────────────────────────▶│ │
│ │ │ │◀──打开微信──│
│ │ │ │ │◀─支付
│◀────────────────────────────────return_url────────│
│─跳回结果页▶│ │ │ │
│ │─查询状态────▶│ │ │
回调处理
回调URL配置
在微信商户平台配置回调URL:
https://mbe.hi-maker.com/webhook/wechat/pay
回调处理逻辑
MBE系统会自动处理支付回调,执行以下操作:
- 验证签名 - 确保回调来自微信
- 解密数据 - 解密resource字段获取支付信息
- 更新订阅 - 根据订单类型更新用户订阅状态
- 增加Token - 根据计划增加Token额度
- 记录日志 - 记录支付日志
支付成功后自动处理
# 订单ID格式决定处理方式
# {user_id}_{plan}_{timestamp}_{random} -> 订阅购买
# {user_id}_token_{amount}_{timestamp}_{random} -> Token充值
# {user_id}_expert_{expert_id}_{timestamp}_{random} -> 专家购买
| 产品类型 | 处理逻辑 |
|---|---|
| personal/pro/enterprise | 升级订阅 + 增加Token额度 |
| token | 增加Token额度 |
| expert | 开通专家访问权限 |
退款处理
发起退款
# 通过API发起退款
POST /api/payment/refund
{
"order_id": "user123_personal_20260202120000_abc123",
"refund_amount": 29.00,
"reason": "用户申请退款"
}
退款注意事项
- 退款金额不能超过原订单金额
- 退款会原路退回用户支付账户
- 退款可能需要1-3个工作日到账
- 退款成功后需要相应扣除用户权益
常见问题
1. 沙箱模式如何测试?
# 设置环境变量
PAYMENT_ENV=sandbox
# 使用模拟支付接口
POST /webhook/payment/simulate/{order_id}?status=success
2. H5支付报"商户未配置域名"?
在微信商户平台 → 产品中心 → H5支付 → 设置H5支付域名
3. 回调收不到通知?
- 确保回调URL公网可访问
- 检查防火墙是否放行微信IP
- 查看服务器日志排查错误
4. 签名验证失败?
- 检查API V3密钥是否正确(32位)
- 检查商户证书序列号是否正确
- 检查私钥文件是否完整
5. 如何区分沙箱和生产环境?
from src.payments.config import get_payment_config
config = get_payment_config()
if config.is_sandbox:
print("当前是沙箱环境")
else:
print("当前是生产环境")
相关文档
文档版本: 1.0.0
更新时间: 2026-02-02