Flutter 支付演示项目,覆盖 7 种支付方式的前后端完整接入:
| 支付方式 | 移动端 | Web / 桌面 | 后端 SDK |
|---|---|---|---|
| 微信支付 | App 支付(fluwx) | Native 扫码(二维码轮询) | wechatpay-node-v3 |
| 支付宝支付 | App 支付(alipay_kit) | 手机网站支付(WAP 跳转) | alipay-sdk |
| 云闪付 | App 支付(uppay:// 拉起) | 银联收银台跳转 | 自研 RSA2 签名对接 |
| Stripe | PaymentSheet 卡片支付 | PaymentSheet(web) | stripe SDK |
| Apple Pay | 经 Stripe 确认 | Safari | stripe SDK |
| Google Pay | 经 Stripe 确认 | Chrome | stripe SDK |
| 网页收银台 | 聚合收银台 | 微信扫码 / 支付宝 / Stripe 托管 | 自建聚合 |
技术文档见 docs/(含时序图、接口定义、安全、沙箱测试)。
flutter_paydemo/
lib/
main.dart # 入口:fluwx/Stripe 初始化 + 国际化 + ScreenUtil + EasyLoading
constants.dart # AppID / Universal Link / Stripe Key / 后端地址
models/ # 请求响应模型(fromJson/toJson)
service/
api_service.dart # dio 封装 + 各渠道创建/查询/收银台接口
pay_service.dart # 7 种支付编排(统一以后端状态为准)
platform/ # 渠道封装:wechat_flow / alipay_* / stripe_flow
pages/
home_page.dart # 商品 + 7 个支付入口
wechat_qr_dialog.dart # 微信 Native 扫码弹窗(含 Mock 模拟按钮)
utils/ # platform / toast / dialog / money / pay_result
server/ # Node.js 后端
src/
app.js # Express 装配(notify 在 json 之前挂载)
config/ # 环境变量(MOCK_MODE 开关)
controllers/ # payment / notify / checkout
services/ # order / wechat / alipay / unionpay / stripe / notify
mock/ # Mock 工厂(结构与真实渠道完全对齐)
.env.example # 全部环境变量模板
docs/ # 7 份支付技术文档
cd server
npm install
cp .env.example .env # 默认 MOCK_MODE=true,无需真实商户密钥
npm start # 监听 :3000
验证:
curl http://localhost:3000/health # {"ok":true,"mock":true}
curl http://localhost:3000/v1/products # 商品列表
flutter pub get
flutter run -d chrome # Web 端(微信 Native 扫码 / 支付宝 WAP / Stripe)
# 或
flutter run -d <设备> # Android/iOS App(App 支付)
后端地址通过 --dart-define=API_BASE_URL=http://localhost:3000 覆盖
(Android 模拟器访问宿主机用 http://10.0.2.2:3000)。
.env 中 MOCK_MODE=true 时,后端返回结构完全对齐真实渠道(sandbox:true、占位密钥):
code_url → 前端渲染二维码,弹窗内点「模拟支付成功(Mock)」走通tn: mock_tn_* → 前端判定 mock,直接模拟成功pk_test_mock 发布密钥 → 前端判定 mock,直接模拟成功下单默认停在 PENDING,POST /v1/payment/simulate/success {payment_id} 触发与真实回调
完全相同的 markPaid 幂等流程,随后 GET /v1/payment/{id} 返回 {success:true, note:'支付成功'}。
复制 server/.env.example → .env 并填写:
| 变量 | 说明 |
|---|---|
WECHAT_APPID / WECHAT_MCHID / WECHAT_KEY / WECHAT_CERT |
微信支付商户号 / API v3 密钥 / 证书 |
ALIPAY_APP_ID / ALIPAY_PRIVATE_KEY / ALIPAY_PUBLIC_KEY |
支付宝应用私钥 / 支付宝公钥(RSA2) |
UNIONPAY_MER_ID / UNIONPAY_PRIVATE_KEY_PATH / UNIONPAY_PUBLIC_KEY_PATH |
银联商户号 / 商户私钥 / 银联公钥(RSA2 签名验签,沙箱测试商户可用) |
STRIPE_SECRET_KEY / STRIPE_PUBLISHABLE_KEY / STRIPE_WEBHOOK_SECRET |
Stripe 密钥 / Webhook 签名密钥 |
前端对应替换:
lib/constants.dart:kWechatAppId(微信开放平台 AppID)、kWechatUniversalLink、kStripePublishableKeyapplicationId 与微信开放平台登记一致(fluwx activity-alias 由插件自带)LSApplicationQueriesSchemes(weixin/wechat)与 CFBundleURLTypes(wx{AppID}),
alipay_kit scheme 见 pubspec.yaml真实回调由 POST /v1/payment/notify/{channel} 验签处理(微信 AES-GCM 解密 / 支付宝 RSA2 验签 / 云闪付 RSA2 验签 / Stripe Webhook 校验)。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /v1/payment/:channel/ |
wechatpay/alipay/unionpay/stripe/apple/google 创建支付 |
| GET | /v1/payment/:payment_id |
支付状态查询(轮询 / 最终确认) |
| POST | /v1/payment/notify/:channel |
渠道异步回调(验签 + 幂等标记已支付) |
| POST | /v1/payment/simulate/:result |
仅 Mock:模拟支付结果 |
| POST | /v1/checkout/session |
收银台会话(wechat/alipay/stripe) |
| GET | /v1/checkout/session/:id |
收银台状态轮询 |
| GET | /v1/products |
商品列表 |
MainActivity 继承 FlutterFragmentActivity,
gradle.properties 已设 android.enableR8.fullMode=false;settings 已声明 Flutter 引擎 maven 仓库
(download.flutter.io)。注:老插件(如 alipay_kit_android、fluwx 5.3.1)在新版 AGP/Kotlin 下可能
需临时补 namespace 或升级版本,真机构建时按需处理IPHONEOS_DEPLOYMENT_TARGET 需 ≥ 13.0(flutter_stripe 要求),需 macOS 真机 pod installalipay_kit 底层依赖 dart:io,通过条件导出隔离(alipay_interface.dart),不影响 Web 构建MIT