黄宽的blog

宁可十年不将军,不可一日不拱卒



laravel使用omnipay完成微信支付

        在laravel学院看到用omnipay-alipay支付完成这功能后,接着我开始做微信支付了,微信支付laravel学院也有写微信支付用的什么插件完成,不过使用的是overture,这应该叫项目名吧,官网和插件名好像是叫easywecha,对于做微信各方面功能来说都非常的强大,所以非常出名。不过在laravel学院中也提到了omnipay也提供了微信支付,因为没用过easywecha,只用过omnipay,所以我没有按照laravel学院使用overture,而是还是使用的omnipay里的插件omnipay-wechapay,在github找到了这个项目,发现支付宝的插件和微信插件的作者都是同一个人,因为使用过他做的支付宝插件,所以用微信的也还算得上有点经验,在做微信支付时得到了作者得热心帮助,在此深表感谢。如果有喜欢omnipay风格做微信或者支付宝支付的话可以去作者的github去看一下,有文档,链接地址附上:https://github.com/lokielse/omnipay-wechatpay

        具体配置可以参照laravel学院的支付宝支付章节,一个数组就是一个网关或者说是一种支付方式,要用微信支付的话,只需要在那配置文件中照着支付宝的做一个小数组就可以了。

        我做的是微信扫码支付模式二,在pc端页面显示出一个含有订单信息的二维码,就可以拿起手机打开微信客户端扫码支付了,微信的扫码支付和支付宝的扫码支付不同,支付宝扫码支付成功后会跳转到支付宝的页面去,再通过你传的回调地址跳转回你自己的页面,微信扫码你支付完成后,页面不会有任何变化,再次扫二维码会在微信客户端提示你订单已经失效。微信支付的流程基本和支付宝一致,首先是在自己的服务器发送一个下单请求,经过重重验证通过后会返回给你一串数据,你拿到这串地址数据后,你要借助第三方的二维码制作的库显示出这个二维码,如果用原生的sdk就很简单了,sdk有提供一个第三方库供我们使用。但是我们需要安全可靠,且符合laravel风格代码好维护,在我们的项目中使用的第三方二维码库,就是使用的原生sdk里面的库。在laravel这个框架里想显示出二维码有个小坑,下面附上github代码加以解释。忘了说了,如果create方法不能正常使用,请用gateway!

        当你成功获取到微信返回回来的地址后,怎么将二维码在页面上输出呢,这时我们需要把官方sdk下载下来,里面有一个第三方的库叫phpqrcode.php,调用里面的一个方法png即可输出,我们可以先将此库require进控制器,再将getCodeurl返回回来的参数输入进去即可出来,但这地方有个小坑,png方法返回的是一个二进制流,你如果单纯的将它获取到再赋到模版上,图片是出不来的,不知道你们会不会遇到这个坑,但是这个坑可把我给坑惨了,经过同事们和我一下午的调试,发现你请求这个图片,它的响应头的响应类型居然是text/html!!!!正常的应该是图片才对啊,最后折中给它解决掉了,如果你也遇到了这个问题,可以去看一下Laravel学院基础篇的http响应篇章。解决办法如下:

                   将getCodeurl丢进urlencode函数里加密,赋到模版上去,然后再在控制器里做一个方法,在路由器里做一条可以传参的路由可以使用post,我是用的any,对应这个方法。在模版里的img标签中的src属性中调用这条路由将,加密过后的参数丢到这路由里面去。这条路由对应的方法里面写return response(\QRcode::png(urldecode($pngcode)), 200)->header('Content-Type', "image/png")即可。经测试也可以用dd函数,dd函数似乎可以识别数据类型再以对应类型给予响应。到此微信的下单请求就结束了,比支付宝的操作还是麻烦些。下面来说回调。

        支付成功后支付宝会返回一段xml格式到你的服务器上,你要判断是否成功,然后给予微信想要的响应,官方的说法是会间隔一小段时间重复调用你的回调路由,所以,如果你有对订单进行状态改变的话,最好在回调方法开始时,就找到这一条订单查询状态如果状态已改变则直接返回成功,否则判定为第一次回调,完成自己的逻辑。

        我不知道omnipay-wechapay有没有可以直接让我们调用的解析xml转数组的方法,我找了一圈似乎没有,还好找了一圈,发现wechapay内部是有这个方法的,可惜是用在其他地方,幸好这个方法只有一句话,略加改造即可自己使用:$xml_array = json_decode(json_encode(simplexml_load_string($GLOBALS['HTTP_RAW_POST_DATA'], 'SimpleXMLElement', LIBXML_NOCDATA)), true);回调的调试方法最好是写日志。回调流程怎么做具体还是去看github的官方文档,会有大致流程,返回给微信服务器的也需要xml格式,可以去插件里面找array2xml,丢到自己控制器里面来直接调用就可以了。再次感谢laravel学院和插件作者。最后强调一点,composer最好不要update,哪个插件要更新就单独更新就好了。

  Laravel

作者  :  黄宽

不耻最后,即使慢,驰而不息,纵会落后,纵令失败



About ME

about me

黄宽

我不想成为一个庸俗的人。十年百年后,当我们死去,质疑我们的人同样死去,后人看到的是裹足不前、原地打转的你,还是一直奔跑、走到远方的我?

友情链接