微信支付在Yii中需通过easywechat v6+集成JSAPI支付,配置须分离公众号与支付参数,notify_url需公网HTTPS可访问且不在授权目录白名单中,prepay签名、回调验签与解密是关键难点。

easywechat)桥接,且关键环节——签名验证、回调处理、预支付参数生成——稍有疏漏就会卡在「支付失败」或「回调不触发」。直接硬套文档配置,90% 的人会在 notify 接口收不到数据或 prepay 签名过期。
用 easywechat v6+ 集成微信 JSAPI 支付(公众号内调起)
这是当前最稳妥的路径,v6 起弃用 Factory::payment(),改用服务容器式初始化,避免全局静态实例污染。
常见错误现象:Invalid signature、invalid appid、前端 requestPayment 报错「支付参数错误」。
- 安装时指定 v6 版本:
composer require "overtrue/wechat:~6.0",不要用easywechat/php-sdk(那是微信官方 SDK,不兼容 Yii 的依赖注入) - 配置必须拆成两份:公众号基础配置(
app_id、secret)和支付配置(mch_id、key、notify_url),不能混在一个数组里 -
notify_url必须是公网可访问、带 HTTPS、且**不在微信支付后台「支付授权目录」白名单中**——它走的是异步回调通道,和 JSAPI 的redirect_uri是两回事 - 在控制器里初始化时,要显式传入支付配置:
$payment = $app->getPayment($paymentConfig),不能直接调$app->payment
生成 prepay 参数并签名返回给前端
前端调 uni.requestPayment 或 WeixinJSBridge 时,需要后端提供完整签名后的 config 对象。Yii 本身不处理 JSAPI 签名逻辑,全由 easywechat 的 jssdk->sdkConfig() 完成。
使用场景:用户点击「微信支付」按钮,后端创建订单、调用微信统一下单接口、拿到 prepay_id 后生成签名参数。
- 统一下单必须传
openid,这个值不能从 session 猜,得从微信 OAuth2 授权回调里明确获取并绑定到用户模型 -
trade_type设为JSAPI,不是APP或NATIVE;否则返回的package字段格式不匹配前端调用 - 签名时间戳
timeStamp必须是字符串类型((string)time()),int 会触发前端「invalid timestamp」 - 返回给前端的字段必须严格包含:
appId、timeStamp、nonceStr、package、signType、paySign,缺一不可
处理 notify 回调时验证和解密是硬门槛
微信服务器发来的 POST 请求是原始 XML,php://input 可读,但直接 simplexml_load_string 会丢掉 CDATA 内容,导致 result_code 解析失败;V3 接口还强制要求验签+解密。
容易踩的坑:file_get_contents('php://input') 返回空、return_code == SUCCESS 但业务没更新、日志里全是乱码 XML。
- 务必在入口文件(如
web/index.php)顶部加ini_set('always_populate_raw_post_data', '-1');,否则 PHP 7.4+ 会丢原始 body - 不要用
$_POST读 notify 数据——微信不发表单,只发 XML 原文 - V2 接口只需校验
sign字段:把除sign外所有字段按字典序拼接 +key再 MD5,和原文sign对比 - V3 接口必须用商户证书解密响应体,且验签需调用
$wechat->verify()->validate($headers, $body),失败直接exit('success'),不能 render 页面
调试 notify 接口最有效的三件事
线上环境看不到报错,error_log 和 Yii::info() 往往被忽略,导致问题拖好几天。
性能影响:每次 notify 都要查库、更新状态、发消息,若没加事务或幂等判断,重复通知会导致订单状态错乱。
- 在
actionNotify()开头立即写日志:Yii::info(['raw_input' => file_get_contents('php://input')], 'wechat-notify') - 用
curl -X POST -d @test-notify.xml https://yoursite.com/wechat/notify模拟请求,test-notify.xml从微信文档抄,别信「测试号能自动回调」这种说法 - 所有数据库操作加
try/catch+Yii::$app->db->transaction,并在更新前查一次订单是否已成功,避免重复处理
notify_url 被微信服务器反复重试却静默失败、或是前端拿到的 paySign 和微信验签服务器算出的不一致。这两个点不打日志、不抓包、不模拟,光看文档永远找不到根因。



















