当前位置:   article > 正文

【PHP+微信开发】之微信扫码支付_php微信扫码支付demo

php微信扫码支付demo

目录

1.下载官方DEMO

2.替换商户证书

3.修改商户配置信息

4.修改文件名称

5.引入官方支付类文件

6.使用模式二的支付代码

7.生成支付二维码

8.查看交易结果

9.验证回调信息

思路说明:


微信支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1  

1.下载官方DEMO

把微信官网下载的demo放在根目录/vendor/目录下,这里我的是/vendor/wxpay_pc目录(SDK下载 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1)

2.替换商户证书

把cert里面的文件替换成自己项目的证书(登陆微信商户平台,账户中心,API安全下载)

3.修改商户配置信息

把/wxpay_pc/lib目录下的WxPay.Config.php文件里的信息改成自己的信息,只需改以下四个就行:

4.修改文件名称

把example/目录下的notify.php改名为PayNotifyCallBack.php  不改也没事,我是为了和该文件里的类名保持一致

5.引入官方支付类文件

把里面require_once包含的文件都写成框架包含的形式,只要是用到的类里面的包含都改成框架包含的形式,如:

改成:注意,“ . ”用“ # ”表示,至于为什么,这里不是重点,你可以看看底层代码。

6.使用模式二的支付代码

把native.php  里面的模式二的php代码拿出来,封装起来放到控制器里,把里面的信息补充上去

 WX_LOG('wxpay','60','二维码加载完成'); 这里的WX_LOG()方法是我自己写的打印日志的函数,放在common.php文件下,怎么写的可以看上一篇ThinkPHP5自己写日志 ,使用日志排错还是在下面回调异步通知的方法里还是很有用的,当初在这里我踩了不少坑,毕竟是后台异步,用日志记录比较直观

  1. public function pay_pc()
  2. {
  3. error_reporting(E_ERROR);
  4. ini_set('date.timezone','Asia/Shanghai');
  5. vendor('wxpay_pc.lib.WxPay#Api');
  6. vendor('wxpay_pc.example.WxPay#NativePay');
  7. $notify = new \NativePay();
  8. $input = new \WxPayUnifiedOrder();
  9. // 必填项
  10. $out_trade_no = date('Ymd') . str_pad(mt_rand(1, 99999), 6, '0', STR_PAD_LEFT);; //订单号
  11. $input->SetBody("蜜蜂云"); //商品名称
  12. $input->SetOut_trade_no($out_trade_no); //订单号
  13. $input->SetTotal_fee("1"); //价格0.01 以分为单位1分
  14. $input->SetNotify_url('https://www.hulianweidu.com/index/wxpay/notify.html'); //异步回调通知地址
  15. $input->SetTrade_type("NATIVE"); //NATIVE 扫码支付
  16. $input->SetProduct_id("123456789"); //商品ID
  17. // 可填项
  18. $input->SetAttach("互联维度"); //附加数据
  19. $input->SetTime_start(date("YmdHis")); //订单生成时间
  20. $input->SetTime_expire(date("YmdHis", time() + 600)); //订单失效时间
  21. $input->SetGoods_tag("PC网页支付"); //订单优惠标记
  22. $result = $notify->GetPayUrl($input);
  23. WX_LOG('wxpay','60','二维码加载完成');
  24. $url2 = urlencode($result["code_url"]); //对url中文字字符编码
  25. $this->assign('url2',$url2);
  26. $this->assign('out_trade_no',$out_trade_no);
  27. return $this->fetch()
  28. }

需要注意的是$input->SetTotal_fee("1"); //价格0.01 以分为单位1分,我这里是为了方便测试,上线的时候别忘了乘以100,变成以元为单位

7.生成支付二维码

前端二维码:二维码$url2别忘了对中文字符编码,因为我在对应的方法里已经编码过了,所以在前端就没有再次编码操作。

<img alt="微信扫码支付" id="img" src="http://www.wxpay.com/example/qrcode.php?data={$url2}" style="width:150px;height:150px;"/>

8.查看交易结果

现在二维码生成了,现在不出意外应该能支付成功了,一种方法是可以在商户平台查看交易信息,一种是自己写个方法,查看交易结果,因为这个方法下面会用到,还是推荐用这种。因为当用户进入二维码页面之后,我们需要用户支付成功之后给出相应的提示,并跳转下一页面,所以我们需要ajax轮询请求刚刚说的这个方法,3秒查询一次,去判断用户有没有支付,如果支付则进入下一步操作,如果没有支付则继续轮询,直到支付结果改变。

首先是前端代码:

  1. <body>
  2. <input type="hidden" id="out_trade_no" value="{$out_trade_no}" >
  3. <img alt="微信扫码支付" id="img" src="http://www.wxpay.com/example/qrcode.php?data={$url2}" style="width:150px;height:150px;"/>
  4. </body>
  5. <script src="/public/index/index/vendor/bootstrap/jquery-3.2.1.min.js"></script>
  6. <script type="text/javascript">
  7. var time = setInterval("check()",3000); //3秒查询一次是否支付成功
  8. function check() {
  9. var url = "{:url('/index/Wxpay/orderstate')}";
  10. var out_trade_no = $("#out_trade_no").val();
  11. var param = {'out_trade_no':out_trade_no};
  12. $.post(url,param,function(data){
  13. data = JSON.parse(data);
  14. if (data['trade_state'] == 'SUCCESS') {
  15. time = window.clearInterval(time);
  16. // 支付成功把二维码替换成支付成功图标
  17. $("#img").attr('src','/public/index/pay/images/success.png');
  18. console.log(data);
  19. // window.location.href="{:url('/index/wxpay/notify')}";
  20. }else{
  21. console.log(data);
  22. }
  23. });
  24. }
  25. </script>

注意:别忘了在传二维码$url2的时候顺便把订单号也传过来,可以看上面的代码,并把订单号放在隐藏域,使用该订单号去查询该订单的支付结果

后端代码:

  1. //订单查询结果
  2. public function orderstate()
  3. {
  4. error_reporting(E_ERROR);
  5. ini_set('date.timezone','Asia/Shanghai');
  6. vendor('wxpay_pc.lib.WxPay#Api');
  7. if(isset($_REQUEST["transaction_id"]) && $_REQUEST["transaction_id"] != ""){
  8. $transaction_id = $_REQUEST["transaction_id"];
  9. $input = new \WxPayOrderQuery();
  10. $input->SetTransaction_id($transaction_id);
  11. echo json_encode(\WxPayApi::orderQuery($input));
  12. exit();
  13. }
  14. if(isset($_REQUEST["out_trade_no"]) && $_REQUEST["out_trade_no"] != ""){
  15. $out_trade_no = $_REQUEST["out_trade_no"];
  16. $input = new \WxPayOrderQuery();
  17. $input->SetOut_trade_no($out_trade_no);
  18. echo json_encode(\WxPayApi::orderQuery($input));
  19. exit();
  20. }
  21. }

为扫码支付的时候显示

扫码支付成功后,trade_state会改为SECCESS,成功的时候就可以进行后面的操作了(更改通知信息,跳转页面)

9.验证回调信息

支付成功后,微信服务器会异步返回你信息(xml格式数据),判断是否正确(包括签名),就是在最上面那段代码要填的异步通知地址,这个地址必须保证外网能访问,就是必须放在线上。关于异步回调当初可是坑了我不少啊!

关于异步通知的代码,其他不用改,就是把/example/PayNotifyCallBack.php(官网里notify.php)里的代码最后几行注释掉了,其他的没改:

  1. <?php
  2. ini_set('date.timezone','Asia/Shanghai');
  3. error_reporting(E_ERROR);
  4. vendor('wxpay_pc.lib.WxPay#Api');
  5. vendor('wxpay_pc.lib.WxPay#Notify');
  6. vendor('wxpay_pc.example.log');
  7. //初始化日志
  8. // $logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
  9. // $log = Log::Init($logHandler, 15);
  10. class PayNotifyCallBack extends WxPayNotify
  11. {
  12. //查询订单
  13. public function Queryorder($transaction_id)
  14. {
  15. $input = new \WxPayOrderQuery();
  16. $input->SetTransaction_id($transaction_id);
  17. $result = \WxPayApi::orderQuery($input);
  18. // Log::DEBUG("query:" . json_encode($result));
  19. if(array_key_exists("return_code", $result)
  20. && array_key_exists("result_code", $result)
  21. && $result["return_code"] == "SUCCESS"
  22. && $result["result_code"] == "SUCCESS")
  23. {
  24. return true;
  25. }
  26. return false;
  27. }
  28. //重写回调处理函数 通知地址
  29. public function NotifyProcess($data, &$msg)
  30. {
  31. // Log::DEBUG("call back:" . json_encode($data));
  32. $notfiyOutput = array();
  33. if(!array_key_exists("transaction_id", $data)){
  34. $msg = "输入参数不正确";
  35. return false;
  36. }
  37. //查询订单,判断订单真实性
  38. if(!$this->Queryorder($data["transaction_id"])){
  39. $msg = "订单查询失败";
  40. return false;
  41. }
  42. return true;
  43. }
  44. }
  45. // Log::DEBUG("begin notify");
  46. // $notify = new PayNotifyCallBack();
  47. // $notify->Handle(false);

这是异步返回的数据:

只需判断 return_code 是否等于SUCCESS

然后就是异步回调通知这个方法了:

  1. // 回调页面
  2. public function notify() {
  3. // 是否接收到了返回的xml数据
  4.  // $data = file_get_contents('php://input');
  5.  // WX_LOG('wxpay','95',$data);
  6. error_reporting(E_ERROR);
  7. ini_set('date.timezone', 'Asia/Shanghai');
  8. vendor('wxpay_pc.example.PayNotifyCallBack');
  9. $notify = new \PayNotifyCallBack();
  10. $notify->Handle(false);
  11.      
  12.   
  13.     //支付结果通知 根据结果通知,判断订单是否支付完成
  14. $result = $notify->GetValues(); //数组
  15. // ///更新支付状态//
  16. if ($result['return_code'] == 'SUCCESS') {
  17. //订单支付完成,修改订单状态,发货。
  18. $res = Db::table('test')->insert(['state'=>1]);
  19. if ($res) {
  20. WX_LOG('wxpay','114','支付成功');
  21. }else{
  22. WX_LOG('wxpay','116','支付失败');
  23. }
  24. }
  25. }

操作数据库等逻辑,只需要在这个方法写就行了!

对于这个方法,因为是后台异步操作的,前端看不到,所以建议打印日志,看看微信服务器有没有给这个方法传数据,方便排错!

 支付页面pay_pc,查询订单结果orderstate,异步回调notify,我都写在wxpay这个控制器里面了。

10.完成

到现在整个微信扫码支付整个流程就完成了!

思路说明:

1.准备:先下载微信官网的demo,并申请微信商户平台等信息(APPID,mchid等)

2.修改配置信息并引入相关文件

3.调用统一下单API,传入相关参数,并生成支付二维码

4.调用查询订单API,判断是否支付成功

5.在回调函数里写后续逻辑,包括数据库操作等

 这篇文章是在2018年写的,微信官方已经发布微信支付3.0了(产品介绍-Native支付 | 微信支付商户平台文档中心)

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
  

闽ICP备14008679号