Medusa接入支付宝微信支付完整实战:从0到上线的四个小步与三次踩坑
【免费下载链接】medusaThe world's most flexible commerce platform for agents and developers项目地址: https://gitcode.com/GitHub_Trending/me/medusa
大促前夜,运营晓雯盯着后台的订单流失报表发愁:活动页曝光量翻了四倍,可结算页转化率纹丝不动。一查日志,问题出在支付环节——顾客选完商品,跳转到支付页就卡住,超过一半的人在这一步离开。她不懂代码,只知道一句话:"我们的商城,好像付不了款。"
这个商城跑在 Medusa 上。Medusa 自称"the world's most flexible commerce platform for agents and developers",它的支付系统是模块化的,Stripe 能跑,支付宝、微信支付理论上也能跑——只是没人接。接下来的一个月,我从零开始给这套开源电商平台接上了国内移动支付,全程记录了它真实的脾气。这篇实战记,就是那段时间的浓缩版。
两条路摆在面前:自己造轮子,还是站在轮子上
接手的第一件事不是写代码,而是开会。技术负责人抛出一个经典问题:支付这块,是自己写,还是接入现成的支付 SDK?
| 对比维度 | 自己造轮子 | 用 Medusa 支付模块扩展 |
|---|---|---|
| 开发量 | 要自己写订单状态机、对账、回调重试 | 只补支付网关的对接层 |
| 维护成本 | 每个接口变动都要跟进 | 核心逻辑随社区版本走 |
| 风险点 | 金额精度、回调乱序全靠自己兜 | 需要先吃透它的约定 |
| 时间 | 动辄数月 | 几天到一两周 |
结论很快出来:支付网关的 API 是"胳膊",订单与资金的流转逻辑才是"大腿"。Medusa 已经把大腿长好了,我们要做的,只是给胳膊装上去。
动手前先清点:四样东西缺一不可
- 一个能跑起来的 Medusa 项目(版本与官方仓库保持同步,避免 API 对不上)
- 支付宝开放平台 / 微信商户平台的沙箱测试账号,提前把 AppID、商户号、密钥申请下来
- 一台有公网地址的开发机,或者一个内网穿透工具——回调测试离不开它
- 一颗耐心:支付调试的报错信息,永远比你预想的更隐晦
第一小步:看懂 Medusa 支付模块的"插槽"结构
Medusa 的支付模块长这样:核心逻辑在packages/modules/payment/src/services/下,真正的插槽是payment-provider.ts里的PaymentProviderService,它负责把外部支付服务"取"出来调用;而每个支付服务要长什么样,由packages/core/types/src/payment/provider.ts里的IPaymentProvider接口规定。
这个接口像一份合同,列明了所有需要履约的方法:
| 接口方法 | 对应业务动作 |
|---|---|
initiatePayment | 创建支付会话 |
authorizePayment | 授权预扣款 |
capturePayment | 确认收款 |
refundPayment | 退款 |
retrievePayment/getPaymentStatus | 查询支付状态 |
cancelPayment | 取消支付 |
deletePayment | 清理支付数据 |
换句话说:你不需要关心订单怎么流转,只需要按这份合同,把支付宝和微信的 API 翻译成这些方法的实现。
第二小步:仿照 Stripe 写一个最小可跑的本地提供商
Medusa 自带了 Stripe 参考实现,路径在packages/modules/providers/payment-stripe/src/core/stripe-base.ts。它继承了一个抽象基类AbstractPaymentProvider,把 Stripe 的 PaymentIntent 封装成 Medusa 认得的支付会话。
我照葫芦画瓢,先写了一个"假装能支付"的本地提供商——收到initiatePayment就返回一个假支付链接,点开就是成功页。这一步不接任何真实网关,目的是验证插槽本身通不通。
class MockProviderService extends AbstractPaymentProvider<Options> { static identifier = "payment-mock" async initiatePayment({ amount }) { return { id: `mock_${Date.now()}`, data: { amount } } } async getPaymentStatus() { return PaymentSessionStatus.AUTHORIZED } }写完后记得看一个关键文件:packages/modules/payment/src/loaders/providers.ts。它规定每个提供商必须以pp_{identifier}的形式注册进容器,少一个static identifier都会在启动时直接报错。
预期结果:后台的支付设置里能看到
payment-mock这个选项,下单能走到"支付成功"。
第三小步:把支付宝和微信的官方 SDK 接进来
插槽验证通过后,真正的活才开始。这一步把官方 SDK 的调用填进刚才的骨架:initiatePayment里发预下单请求,拿到支付参数返回给前端拉起收银台;capturePayment里根据回调结果确认入账。
// medusa-config.js 中注册你的支付提供商 modules: { payment: { providers: [ { resolve: "./src/providers/payment-alipay", options: { appId: process.env.ALIPAY_APP_ID, privateKey: process.env.ALIPAY_PRIVATE_KEY, alipayPublicKey: process.env.ALIPAY_PUBLIC_KEY } } ] } }微信支付那边同理,只是多了 JSAPI、APP、小程序几种支付场景,实现上就多几个initiatePayment的分支。每一行配置背后都对应商户平台上的一个设置项,缺一个webhookSecret,启动时 Medusa 会不厌其烦地打警告。
第四小步:用 Webhook 把支付结果"签收"回来
支付回调,可以理解成快递签收通知:用户付完钱,支付宝/微信异步告诉你的服务器"这笔单子成了"。Medusa 只认它自己的状态机——PENDING → AUTHORIZED → CAPTURED,所以回调到达后要做两件事:验签,然后把它翻译成一次capturePayment。
沙箱里最容易忽略的是这件事:回调的地址必须公网可达。我第一次测试,回调静默丢失,订单永远停在"待付款",排查了半天才发现是内网地址根本收不到通知。
三次真实的踩坑记录
坑一:金额单位对不上
- 现象:下单 100 元,支付宝账单显示 1 元。
- 原因:支付宝以"元"为金额单位,而 Medusa 内部统一按最小货币单位(分)存储,我直接把
amount原样传了出去。 - 解决:参考 Stripe 提供商的
getSmallestUnit工具,入参前换算一次。这个坑赔了不止一杯奶茶。
坑二:回调验签一直失败
- 现象:Webhook 能收到,但验签 100% 报错。
- 原因:支付宝的验签参数是 URL 编码后的字符串,直接用原始 body 去验,顺序全乱了。
- 解决:严格按官方文档规定的参数拼接顺序组装验签串,先本地单测再联调。
坑三:沙箱用户扫码后无响应
- 现象:App 内拉起支付后,页面一直转圈。
- 原因:沙箱环境只支持沙箱版客户端,真机上用了正式版支付宝,自然查无此单。
- 解决:测试手机统一安装沙箱专用 App,所有测试账号走同一套环境。沙箱环境隔离是最容易被忽略的隐形坑。
上线前必查的五件事
- 金额精度:全链路核对一遍最小单位换算,尤其是退款路径,反向换算最容易出错。
- 回调幂等:支付宝/微信可能重复通知同一笔订单,
capturePayment必须对重复回调无副作用。 - 日志留痕:支付相关日志单独建文件,记录请求签名、原始回调报文,出问题能回溯。
- 密钥管理:私钥不进代码库,用环境变量或密钥管理服务;商户证书设置有效期提醒。
- 回滚预案:支付网关升级前,保留旧版本的容器镜像,约定好"观察 15 分钟,失败即回滚"。
还能怎么玩:两个进阶方向
接完基础支付只是开始。第一个方向是多提供商并存——给支付会话配一个优先级列表,支付宝挂了自动降级到微信,结算页的支付成功率报表会好看很多。第二个方向是把account_holder能力用起来,让用户绑定银行卡或开通免密支付,复购时一键扣款,把支付从"交易终点"变成"增长杠杆"。
给你的行动清单:五件小事
- 先跑通本地 Mock 提供商,确认插槽通畅,再碰真实网关
- 金额单位换算写成一个工具函数,从第一天就全局复用
- Webhook 回调地址用公网环境,沙箱手机装专用测试客户端
- 每笔支付的关键日志打全,包括验签原始报文
- 上线前完整走一遍"支付-回调-退款-重复回调"四连测
接入支付这件事,90% 的时间花在跟"约定"较劲上——跟 Medusa 的约定,跟支付平台的约定。把这层约定吃透了,剩下的只是翻译工作。而 Medusa 最值钱的地方,恰恰是它把那些约定固化成了清晰的接口合同,让翻译这件事,变成了照本宣科。
【免费下载链接】medusaThe world's most flexible commerce platform for agents and developers项目地址: https://gitcode.com/GitHub_Trending/me/medusa
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考