当前位置:首页 > 热点

Thinkphp5在线支付

用ThinkPHP5做在线支付,线支最省事的线支路径是接微信和支付宝的官方SDK,别自己从头写签名逻辑。线支我见过一个团队花了三周自己封装微信支付V3的线支证书签名,结果上线第二天就因为平台证书轮换失效了。线支官方SDK虽然文档写得像天书,线支但至少签名、线支验签、线支回调这些坑它替你踩过了。线支

先聊微信支付。线支ThinkPHP5的线支composer里装wechatpay/wechatpay或者yansongda/pay都行。yansongda这个包对TP5友好些,线支配置直接扔在config/pay.php里。线支核心就三件事:统一下单、线支回调验签、线支退款。统一下单返回的prepay_id拿去前端调起JSAPI,这里注意TP5的json()方法默认会转义斜杠,微信那边有时候会抽风,加个JSON_UNESCAPED_SLASHES参数更稳。

回调地址别用url()助手函数生成,TP5的路由如果开了强制路由,回调路径带参数容易404。直接写死https://你的域名/pay/notify/wechat,然后在路由里单独注册一条Route::post('pay/notify/wechat', 'Pay/notifyWechat')。回调里验签通过后,先返回success的XML给微信,再去处理订单状态。顺序反了微信会重复通知,我吃过这个亏——用户付一次款,订单被加了三次积分。

支付宝这边相对简单,alipay-sdk-php直接composer拉下来。TP5的命名空间和支付宝SDK的自动加载偶尔打架,在extend目录下建个Alipay文件夹,把SDK丢进去,然后Loader::addNamespace('Alipay', EXTEND_PATH . 'Alipay')。电脑网站支付调pageExecute,手机网站调wapExecute,返回的是个表单HTML,直接echo到页面就跳转了。异步回调里verify()方法传$_POST,验签通过后记得检查trade_status是不是TRADE_SUCCESS,别只看total_amount对不对——有人会伪造金额相同的通知。

数据库设计上,订单表加个pay_status字段,0未支付1已支付2已退款。回调里用Db::name('order')->where('order_sn', $out_trade_no)->where('pay_status', 0)->update(['pay_status' => 1]),这个where('pay_status', 0)是防重复回调的关键。TP5的update返回影响行数,如果返回0说明已经被处理过了,直接忽略。

测试阶段用沙箱环境。微信沙箱要改sandbox配置,支付宝沙箱用alipaydev网关。有个细节:微信沙箱的total_fee必须传1,传真实金额会报签名错误。支付宝沙箱的买家账号在开放平台后台能查到,别傻乎乎用自己的支付宝去扫沙箱二维码。

最后说个真实案例。去年帮一个客户排查支付问题,回调一直收不到。查了三天,发现是Nginx配置里location ~ \.php$没包含path_info,微信的/pay/notify/wechat这种带路径的URL直接被当成静态文件404了。TP5的pathinfo模式在Nginx下需要单独配try_files,这个坑文档里从来不提。

分享到: