Medusa接入支付宝微信支付完整实战:从0到上线的四个小步与三次踩坑
2026/8/21 17:39:38 网站建设 项目流程

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能力用起来,让用户绑定银行卡或开通免密支付,复购时一键扣款,把支付从"交易终点"变成"增长杠杆"。

给你的行动清单:五件小事

  1. 先跑通本地 Mock 提供商,确认插槽通畅,再碰真实网关
  2. 金额单位换算写成一个工具函数,从第一天就全局复用
  3. Webhook 回调地址用公网环境,沙箱手机装专用测试客户端
  4. 每笔支付的关键日志打全,包括验签原始报文
  5. 上线前完整走一遍"支付-回调-退款-重复回调"四连测

接入支付这件事,90% 的时间花在跟"约定"较劲上——跟 Medusa 的约定,跟支付平台的约定。把这层约定吃透了,剩下的只是翻译工作。而 Medusa 最值钱的地方,恰恰是它把那些约定固化成了清晰的接口合同,让翻译这件事,变成了照本宣科。

【免费下载链接】medusaThe world's most flexible commerce platform for agents and developers项目地址: https://gitcode.com/GitHub_Trending/me/medusa

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询