很多开发者,在搭建商城时,会头疼,在搭建需要在线支付的系统时,也会头疼,而最头疼的,就是微信支付这一关。
特别尤其是扫码支付的那种模式,它分别需要涉及到去调取 SDK,还要进行配置参数的操作,并且需处理异步通知,要是稍微没有给予注意的话,就特别容易出现卡住的状况。
今日,咱们不讲那些不实的事儿,直接从零点起始,运用实际能够运行的代码以及步骤,而将 PHP 达成微信扫码支付的完整流程走上一回。
所有配置和代码都基于官方 SDK,确保真实可靠。
一、下载 SDK 并引入项目
第一步当然是拿到官方的 SDK。
大量新手会四处寻觅资源,实际上径直前往微信支付官方文档或者 GitHub 仓库便能够寻得。
将要下载实现的 SDK 文件夹,全部放置到你的项目根目录那里,比如说将其命名为“wechatpay”。
接着,在那个需要进行支付功能调用的 PHP 文件当中,通过 require_once 去引入放置于 SDK 里的核心文件。
在这里进行一下提醒,千万不要仅仅引入一个文件,因为微信支付 SDK 所依赖的内容较多,所以最好是将 lib 目录下面的主要类库都进行加载,又或者直接采用官方所提供的入口文件方式来做。
二、配置商户核心参数
于 SDK 的 lib 目录之中寻觅到 wxpay.config.php,该文件即为整个配置的核心所在。
要进行修改的项目涵盖,APPID,这是公众号亦或是小程序的 AppId,MCHID,也就是商户号,KEY,此为商户支付密钥,它是要在商户平台去设置的,APPSECRET,是公众号密钥。
格外留意 NOTIFY_URL 这个异步通知的地址,它必然得是外网能够进行访问的 URL,不存在携带参数的情况,并且不要运用 localhost 或者内网 IP。
很多人在测试时收不到微信通知,问题就出在这个地址上。
除此之外,证书文件的路径同样需要仔细核对清楚,要是不存在需要退款之类功能的情况,那么能够暂且不进行证书的配置。
三、本地生成订单并调统一下单 API
一旦用户于网页之上施行点击“立即购买”这一动作,之后,后台先行创立一条订单记录之行为随即展开,且其状态被设置为“待支付”。
随后,进行必要参数的收集,其中包括:body,也就是商品描述;out_trade_no,此为商户系统内部订单号,且必须唯一;total_fee,这是金额,单位为分;spbill_create_ip,即客户端 IP。
把这些用来做参数的内容传递给软件开发工具包里的统一下单所对应的那接出接口部位,这接口也就是被称作 UnifiedOrder 方法的那一方法。
调用成功之后,微信服务器,会返回一个 code_url,这个字段,它就是预支付交易链接,而这预支付交易链接,也就是用户扫码之后所看到的那个二维码对应的内容。
要是返回呈现失败状态,依靠错误码去展开排查工作,常见情形包含签名出现错误,以及商户号尚未开通产品权限等等。
四、生成二维码并展示给用户

当获取到 code_url 之后,服务端会将这个链接,与订单信息一块儿,返回给前端页面。
前端能够借助 qrcode.js 这般的库,将链接转变为二维码图片,进而展示于页面之上。
需要同时将订单号显示出来,还要把金额显示出来,商品名称也得显示出来,并且要向用户进行提示,内容为“请打开微信扫码完成支付”。
将定时器设置于页面之目的系为提升体验,此定时器每隔二至三秒便会轮询后端接口一回,以查询订单状态是否已然支付。
支付成功啦,用户这样操作的益处在于,页面会自行实现跳转,直接进入成功页面,而并不需要用户手动去进行刷新操作哟。
五、处理微信异步通知结果
当用户通过扫码来进行确认支付这个动作之后,微信服务器就会朝着你于配置期间所填写的 NOTIFY_URL 去发送一个异步通知。
这个通知是以XML 格式发送的 POST 请求。
于 notify 所对应的文件当中,要借由 file_get_contents('php://input')去获取原始数据,接着运用 simplexml_load_string 将其转换成对象,或者借助官方所提供的 FromXml 方法把它转成数组。
去获取到结果之后,对签名开展验证,接着就要去检查 return_code 以及 result_code 是不是为 SUCCESS,最终按照 out_trade_no 把本地订单状态更新成“已支付”。
在将那种格式返回给微信的这件事情上,是必须要在处理完成之后才可去做的,不然的话,微信就会于 30 分钟的这个时间段里边,把通知重复去做 8 次。
六、解决重复通知和前端展示的难题
有些开发者明明返回了成功状态,微信还是一直发通知。
原因是微信要求严格的 XML 格式和正确的内容。
防止出现重复处理的情况,能够如同部分具备丰富经验的程序员那般,当订单处理达成成功状态之际,借助 Redis 或者 Memcached 去存储一个缓存,将键名设定成订单号,把有效期设置为 1 小时。
每次在收到通知之后,首先要去判断缓存是不是存在,要是存在的话,那就直接返回成功,之后便不再去执行业务逻辑。
关于前端在何时向用户提示支付成功这件事,能够在轮询接口当中对订单的状态展开查询,一旦经过检测发现状态转变成为“已支付”,便弹出成功的提示信息并且进行跳转。
// 示例:处理异步通知并防止重复处理
$xml = file_get_contents('php://input');
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
if ($data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS') {
$orderNo = $data['out_trade_no'];
// 检查缓存是否存在
$cacheKey = 'pay_success_' . $orderNo;
if (apcu_exists($cacheKey)) {
echo '';
return;
}
// 更新订单状态,加缓存
updateOrderStatus($orderNo, 'paid');
apcu_add($cacheKey, 1, 3600);
// 返回成功通知
echo '';
}
经历完整个流程,最为关键重要的,是配置要处于正确状态,异步通知的地址能够被访问,防重复方面的处理要做得完备完善。
按照这套方法,大部分情况下都能一次跑通。
要是在 notify 这个环节始终收不到结果,那就去检查一下服务器防火墙是不是屏蔽了微信的 IP 段,或者把 php.ini 里面的 allow_url_fopen 开启,然后再用 file_get_contents 对其进行测试一下。
支付操作结束之后,前端轮动询问接口能够去调用后端查询订单状况的接口,进而于页面之上实时呈现支付成果,给予用户一回顺畅的感受。

Comments NOTHING