laravel项目接微信支付,能看到的方案都是用easywechat的5.x版本以下,几乎找不到6.x的例子。6.x放弃了对微信官方的接口封装,提供了更好的灵活性,但是文档真的是少的可怜,主要靠领悟,不像之前版本那样直接调就行了。
官方的集成方法就不啰嗦了,肯定都会。
一开始按我理解写的
$app = app('easywechat.pay');
$data = [ "description" => "xiaobu123", "out_trade_no" => "13323232323", "notify_url" => $config['notify_url'], "amount" => [ "total" => 100, "currency" => "CNY", ], "payer" => [ "openid" => "oQA2M60SiO8nZFlx9iBscG9jcMmY", ], ];$resp = $api->withAppId()->withMchid()->postJson('/v3/pay/transactions/jsapi', $data);dd($resp->getContent()); // 真实发起请求
直接报400
Symfony\Component\HttpClient\Exception\ClientException: HTTP/1.1 400 Bad Request returned for "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi". in file /var/www/lnmp/www/rent/vendor/symfony/http-client/Response/CommonResponseTrait.php on line 165
除了400什么错也看不到,更别提官方的接口错误了。
搜了下微信支付官方的论坛,看有人提示说同样的参数用postman试下,发现果然,官方的接口你有问题不会简单给你报个400出来的。比如像这样
{ "code": "SIGN_ERROR", "message": "Http头Authorization值格式错误,请参考《微信支付商户REST API签名规则》"}
反复看文档,检查参数,甚至去设置了jsapi的白名单目录(虽然我知道似乎没有必要,我之前只接过APP的微信支付,jsapi小程序支付还是第一次弄)
但始终只能看到返回400。
去翻symfony/http-client的源码,发现
public function getContent(bool $throw = true): string { if ($this->initializer) { self::initialize($this); } if ($throw) { $this->checkStatusCode(); }
getContent是可以接受一个是否抛出错误的参数,文档里也确实写了
代码修改为
$content = $resp->getContent(false);dd($content);
再调,这次终于把微信官方的api返回报给我了。很奇葩的错误,文档里从来没提到过。
纯数字的商户号在json里需要被双引号包起来!
不然你将收到一个这样的错误
{ "code": "PARAM_ERROR", "detail": { "location": "body", "value": 1659346105 }, "message": "无法将 JSON 输入源“/body/mchid”映射到目标字段“直连商户号”中,此字段需要一个 string 类型的 Json 值"}
不仅仅是微信接口需要注意,laravel-wechat的预置参数的传递也并不管用(查了composer.lock版本是6.8)
至此关键问题才算解决。
有效写法
$app = app('easywechat.pay');$api = $app->getClient();
$data = [ "appid" => "你的微信支付绑定的小程序appid", "mchid" => "商户号", "description" => "商品描述", "out_trade_no" => "13323232323", "notify_url" => $config['notify_url'], "amount" => [ "total" => 100, "currency" => "CNY", ], "payer" => [ "openid" => "oQA2M60**********jcMmY", ], ];$resp = $api->postJson('/v3/pay/transactions/jsapi', $data); $statusCode = $resp->getStatusCode();$content = $resp->getContent(false);dd($content);
成功以后你讲得到
"{"prepay_id":"wx0614422741974651715****36a0ae50000"}"
敏感数据用****代替了。