仔细看了一遍官方的那幅流程图,我来简化理解一下
(注意:我这里针对的是扫码支付模式一,模式二没什么说的)
网站后台生成二维码,当然是跟据前台传来的参数有条件的生成
买家扫描二维码,扫描过程中,微信后台系统回调我们预先设定的url地址
(栗如:http://xx.com/a.php)
在回调php文件中设置商品价格,商品信息,支付结果异步通知地址(比如:http://xx.com/b.php)等,
然后发送给微信系统
微信系统根据我们发送的信息 返回一个预支付id给我们
我们将收到的数据原封不动返回去(这一步我真的无力吐槽了,完全是凭
感觉猜的,文档写的是返回预支付id,我试了只返回id提示错误)
此时买家扫描界面已经出现支付界面了,买家支付后,微信系统将把付款结果发送到上面我们设置的异步通知url上
然后我们就可以在异步url上完成我们自己的业务,比如会员充值成功,我们在数据库对应的添加金币
需要注意的是收到异步通知后一定要返回一个success回去,告诉微信系统我们已经收到通知,否则微信将多次发送异步通知
有时候由于网络原因可能你返回了成功但是也有可能收到多次通知,所以你在为会员添加金币的时候一定要根据订单号添加日志
在接收异步通知的时候首先去日志表看看订单号是否已经存

============================================================================

枯草的说明结束了 然后我们用代码来完整走一遍

首先我们来一个这样的前端页面,当然了,正式环境下怎么可能让用户来填写会员id呢,必须把id字段隐藏了,根据当前登陆的用户自动确定

代码如下:

本帖隐藏的内容



34 5 6 <script src="jquery.min.js" ></script>7 <script src="jquery.qrcode.min.js" ></script>8910
11 金额:

12 用户userid:

13支付14
15

16
171819 20 <script> 21 function getUrl() 22 { 23 var url = "http://xxxx.com/xxx/action.php"; 24 $.post(url,{'price' ("#price").val()*100,'userid' ("#userid").val()},function(re_url){ 25 createQR(re_url); 26 }) 27 } 28 function createQR(url) 29 { 30 $("#code").children().remove(); 31 $("#code").qrcode({ 32 // render: "table", 33 width: 200, //宽度 34 height:200, //高度 35 text: url 36 }); 37 } 38 </script>

当用户输入金额和会员id后,点击支付,然后用ajax去请求action.php这个文件,这个文件负责返回一个二维码的url地址

前台接到url后使用query.qrcode.min.js 这个库生成二维码,

下面看看action.php完整代码:

1 //接收两个参数  用addslashes过滤了一下数据
2 $p = addslashes($_POST['price']);   //充值金额
3 $u = addslashes($_POST['userid']);   //充值的用户(网站会员id)

5 $tmpArr = array(
6     'appid'=>'xxxxxxxxxxxxxxxxxx',   //不要填成了 公众号原始id
7     'mch_id'=>'xxxxxxxxxx',
8     'nonce_str'=>'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
9     'time_stamp'=>time(),
10     'product_id'=>$p."s".$u,   
11     );
12 // 生成签名需要上面五个参数,文档上没有,不要问我是怎么知道的,我只知道二维码格式是这样的:
13 // weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&
14 // product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
15 // 还有就是看一下他的sdk也能看到他是怎么生成签名的,用了那些参数。
16 // 有好几个坑我都是通过看sdk明白的,所以你有必要看一下他的sdk
17 
18 // 注意:上面五个参数是固定的  这个地方不可以自己加额外参数 否则报 原生url参数错误
19 // 但是如果不传参数我的业务逻辑怎么做呢  我这里用了一个比较巧妙的方法,没错,我们可以在产品编号product_id上
20 // 做文章,看我这里产品编号是 价格+当前网站用户userid组成的字符串,用
21 // 字符s分割,方便后面我们拆开,文档中说明了在用户扫描后只会返回openid和
22 // product_id给回调地址,再次证明你即便在上面新增额外参数也没有任何意义。我们完全可以
23 // 把需要的参数组装成字符串,然后用product_id来传递
24 
25 ksort($tmpArr);  //根据键值排序数组
26 // 把数组转换成这种格式:appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA
27 $buff = "";
28 foreach ($tmpArr as $k => $v)
29 {
30    $buff .= $k . "=" . $v . "&";
31 }
32 $buff = trim($buff, "&");
33 // 这个地方有的人可能会想到 http_build_query 函数直接了当,干净利索
34 // 我刚开始就是用的这个函数,坑了老半天。。。 意外发现生成的字符串里面居然有几个字节的乱码  
35 // 乍一看完全和上面生成的一样,各位可以尝试一下
36 // 这些步骤官方文档还是有的  不多说
37 $stringSignTemp=$buff."&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
38 $sign= strtoupper(MD5($stringSignTemp));
39 
40 // 生成的二维码url  到这里就可以返回给前台 前端使用 jquery.qrcode.min.js 这个库可以生成二维码了
41 // 我试了一下  url太长 生成的二维码太复杂  像素差的手机就悲哀了,接着往下看
42 $reurl = "weixin://wxpay/bizpayurl?appid=xxxxxxxxxxxxxxxxxx&mch_id=xxxxxxxxxx&nonce_str=".$tmpArr['nonce_str']."&
43 product_id=".$tmpArr['product_id']."&time_stamp=".$tmpArr['time_stamp']."&sign=".$sign;
44 
45 // 官方文档中介绍了有个长url转短url的API 写的还是很清楚的 没遇到坑
46 $posarr = array(
47     'appid'=>'xxxxxxxxxxxxxxxxxx',
48     'mch_id'=>'xxxxxxxxxx',
49     'nonce_str'=>'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
50     'long_url'=>urlencode($reurl)
51     // 这个地方文档中也说了 长url地址需要urlencode一下,不然你很可能得到签名错误
52     );
53 ksort($posarr);
54 $buff = "";
55 foreach ($posarr as $k => $v)
56 {
57    $buff .= $k . "=" . $v . "&";
58 }
59 $buff = trim($buff, "&");
60 
61 $stringSignTemp=$buff."&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
62 $sign= strtoupper(MD5($stringSignTemp));
63 
64 // 官方文档中说了 所有传输必须采用xml格式  post方式 https协议
65 
66 $xml = "
67            xxxxxxxxxxxxxxxxxx
68            xxxxxxxxxx
69            xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
70            ".$sign."
71            ".$posarr['long_url']."
72         ";
73 
74 // 短连接请求地址
75 $posturl = "https://api.mch.weixin.qq.com/tools/shorturl";
76 //下面使用curl来请求
77 $ch = curl_init($posturl);
78 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  //返回文件流
79 curl_setopt($ch, CURLOPT_POST, 1);  //使用post提交
80 curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);   //post数据
81 $response = curl_exec($ch);  
82 curl_close($ch);
83 
84 // simplexml_load_string php内置的解析简单xml文件的扩展
85 $xmlobj = simplexml_load_string ($response, 'SimpleXMLElement', LIBXML_NOCDATA ); 
86 // 这个地方我直接输出 $xml->short_url 居然是空的  非要经过下面几步才得行  难道是我php版本低了
87 $arr = array();
88 foreach ($xmlobj as $key => $value) {
89     // file_put_contents("mylog.php", $value."\n",FILE_APPEND);  
90     $arr[$key] = $value;
91 } 
92 //这个链接就很短了  生成的二维码很简单  像素超低的手机都可以扫
93 echo $arr['short_url'];
94 
95 // 最后,扫码支付只需要设置回调地址 ,至于支付授权目录 测试目录 白名单那些 都不用设置

各种解释各种坑已经在代码里面言尽了,请仔细看

然后用户可以拿起手机扫描二维码了,扫描过程中微信系统会发送一个xml数据到你预先设置的回调地址上

比如我这个地方就是 http://xxx.com/a.php

具体这个a.php要做些什么呢,官方文档有说明,文章开头也说了这个回调地址的任务是什么,所以我们直接看代码:

1 // file_get_contents("php://input")  接收原始输入流
2 $postObj = simplexml_load_string (file_get_contents("php://input"), 'SimpleXMLElement', LIBXML_NOCDATA ); 

4 $arr = array();
5 foreach ($postObj as $key => $value) { 
6     $arr[$key] = $value;
7 } 
8 $pos = explode("s",$arr['product_id']);
9 $price = $pos[0];
10 // $price = $pos[0]*0.01;
11 $userid = $pos[1];
12 // 这些参数可以到文档去看看  有的参数是必填 有的是选填
13 $tmparr = array(
14    'appid'=>'xxxxxxxxxxxxxxxxxx',
15    'mch_id'=>'xxxxxxxxxx',
16    'nonce_str'=>'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
17    'body'=>'情缘网现金充值',
18    'detail'=>'关注情缘网公众号,充值享8折优惠',
19    'product_id'=>$price,
20    'trade_type'=>'NATIVE',
21    'out_trade_no'=>time()."s".$userid.'s'.$price,
22    'spbill_create_ip'=>'211.149.241.155',
23    'notify_url'=>'http://xxx.com/b.php',
24    'total_fee'=>$price
25    );
26 // 注意这个地方我在订单号out_trade_no上做文章了,因为支付结果异步通知到另外一个url上,
27 // 而那个url上只能收到订单号而不是产品编号,所以我把运载在产品编号上的信息转移到了订单号上
28 // 我在异步url上才能处理我的业务
29 
30 // 当然你在这个页面处理业务也是可以的,比如你现在就把订单号,价格,会员信息等插入数据库,在异步url上在根据订单号查询出本次
31 // 订单信息,然后操作,两种放啊都是可取的
32 // 我这里业务简单,直接把数据寄托在订单号上了,最好是在这个页面处理一部分逻辑,在异步通知后完善逻辑
33 
34 ksort($tmparr);
35 $buff = "";
36 foreach ($tmparr as $k => $v)
37 {
38    $buff .= $k . "=" . $v . "&";
39 }
40 $buff = trim($buff, "&");
41 
42 $stringSignTemp=$buff."&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
43 $sign= strtoupper(md5($stringSignTemp));
44 $xml = "
45 
46    xxxxxxxxxxxxxxxxxx
47    xxxxxxxxxx
48    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
49    ".$sign."
50商品标题
51    商品描述
52    ".$price."
53    ".$tmparr['out_trade_no']."
54    ".$price."
55    xxx.xxx.xxx.xxx
56     http://xxx.com/b.php
57    NATIVE
58   
59 ";
60 // 调用统一下单 接口
61 $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; 
62 $ch = curl_init ($url);
63 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
64 curl_setopt($ch, CURLOPT_POST, 1);
65 curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
66 $response = curl_exec($ch);
67 // if(curl_errno($ch)){
68 //     print curl_error($ch);
69 // }
70 curl_close($ch);
71 // 将接收到的数据直接返回,这一步官方没说明,大坑
72 echo $response;

有了第一个php文件的详细说明,相信这个文件中的代码各位可以自行理解了,这里代码简单,没有使用类对象这些东西,

全是过程,一步步往下读就ok了

回调这一步完成过后用户应该已经支付成功了,接下来微信系统还会将支付成功的喜讯发送到我们统一下单中设置的回调地址上

我这里就是 http://xxx.com/b.php,直接看代码:

1 $postObj = simplexml_load_string     (file_get_contents("php://input"), 'SimpleXMLElement', LIBXML_NOCDATA );
2 $arr = array();
3 foreach ($postObj as $key => $value) {
4     $arr[$key] = $value;
5 } 
6 $status = $arr['result_code'];
7 $xml = "
8         
9            
10            
11         ";
12 echo $xml;
13 
14 // 下面就根据$status来处理业务逻辑
15 
16 //实例化数据库连接句柄
17 $mysqli = new mysqli("localhost", "username", "password", "dbname");
18 
19 $mysqli->query("set names 'utf8'");
20 
21 $danhao = $arr['out_trade_no'];   //订单号
22 $sql = " select * from wxpaylog where orderid = '".$danhao."' ";
23 $res = $mysqli->query($sql);
24 //如果已经处理过这个订单号了  就直接忽视
25 if($res->num_rows > 0 )
26 {
27     return false;    die;
28 }
29 
30 $pos = explode("s", $danhao);          
31 $userid = $pos[1];   //用户id
32 $price = round($pos[2]*0.01);  //充值金额
33 // $price = round($pos[2]*100);  //充值金额
34 $zengsong = 0;  //赠送额度
35 
36 //充值金额 和送金币 活动规则
37 if($price<50) $zengsong = round($price*0.2);
38 if($price>=50 && $price <100) $zengsong = round($price*0.25);
39 if($price>=100 && $price <200) $zengsong = round($price*0.35);
40 if($price>200) $zengsong = round($price*0.5);
41 
42 $sql = " select money from oepre_user where userid = '".$userid."'";
43 
44 $result = $mysqli->query($sql);
45 $row = $result->fetch_row();
46 $gold_num = $row[0];   //当前的金币
47 if($status == "SUCCESS")
48 {
49     //要设置的金币数量
50     $now_count = (int)$gold_num+(int)$price+(int)$zengsong;
51 }else
52 {
53     $now_count = (int)$gold_num;
54 }
55 
56 $sql = " update oepre_user set money = ".$now_count." where userid = '".$userid."'";
57 $result = $mysqli->query($sql);
58 //添加记录
59 $sql = " insert into wxpaylog (userid,money,zengsong,atime,orderid,remark)
60  values(".$userid.",".$price.",".$zengsong.",'".date("Y-m-d H:i:s")."','".$danhao."','".$arr['result_code']."') ";
61 $result = $mysqli->query($sql);

我试了多次充值,异步通知全都是成功支付的,如果支付到一班取消,或者其他原因,异步通知是不会到的,所以这个地方我处理的比较粗暴,无论他

来的是成功或者失败,我都是直接返回去,然后把日志写到数据库,如果充值出了问题我在到数据库里面去检查,我们网站一年也没几个充值的,所以,恕我偷懒咯。

正常情况下如果收到的不是success,那么需要继续调用查询订单api,看看具体情况在继续做处理。

微信扫码支付 php代码相关推荐

  1. java微信扫码支付_java 微信扫码支付 示例代码

    [实例简介] [实例截图] [核心代码] package main.java; import main.java.Utils.HttpClientUtil; import org.dom4j.Docu ...

  2. 企业实战, java、spingboot微信扫码支付,页面生成微信二维码,微信扫码付款,websocket通知,处理订单!复制粘贴代码直接开干

    一  功能描述:    前端选择商品后生成二维码,用户微信扫码支付 备注: 红色为后台给前端的接口 1.前端 选择确认商品 2.调后台生成订单接口 (状态未付款) 3.返回订单的详情(订单确认页面  ...

  3. ASP.NET Core Web 支付功能接入 微信-扫码支付篇

    // 随着版本更迭,新版本可能无法完全适用,请参考仓库内的示例. 这篇文章将介绍ASP.NET Core中使用 开源项目 Payment(https://github.com/Essensoft/Pa ...

  4. JAVA微信扫码支付模式二功能实现完整例子

    概述 本例子实现微信扫码支付模式二的支付功能,应用场景是,web网站微信扫码支付.实现从点击付费按钮.到弹出二维码.到用户用手机微信扫码支付.到手机上用户付费成功.web网页再自动调整到支付成功后的页 ...

  5. SpringBoot 2 集成微信扫码支付

    前言 该文主要是手把手教你如何在SpringBoot 中集成微信扫码支付,以及集成的过程需要注意的问题事项.另外需要感谢 vbirdbest 关于微信支付和支付宝支付相关包博客总结.因为文中很多地方参 ...

  6. 记录新人tp5微信扫码支付

    记录新人tp5微信扫码支付 1.开启商户平台相应的支付(最好填入回调地址,你的地址是可以直接访问的),下载sdk置于继承文件夹类比如tp5的extend 2.config文件中写入相应的参数,自己的或 ...

  7. 微信公众平台开发[5] —— 微信扫码支付介绍

    背景:因为微信占据众多的用户群,作为程序开发,自然而然也成了研究的重点.毕竟个人能力有限,很难想象设计的复杂性,多数时间接触起来,各种蒙圈,在此笔记自己的操作流程,仅做参考,欢迎指正. 一.微信扫码支 ...

  8. 微信扫码充值 php,PHP原生微信扫码支付

    素材火分享了多个微信支付源码,有用户需要一款PHP原生代码写的微信扫码支付,不基于任何框架,完全手写.需要其他支付源码的可找素材火管理员定制开发. 下载资源 下载积分: 800 积分 扫码支付只要授权 ...

  9. 微信扫码支付demo java_微信扫码支付JavaDemo

    [实例简介] 完全可用的微信扫码支付JavaDemo,如不能使用请站内联系本人 [实例截图] [核心代码] weChatpay_demo └── weChatpay_demo ├── src │   ...

最新文章

  1. configure: error: no acceptable C compiler found in $PATH
  2. java窗口坐标_如何在Java中获取窗口外部的鼠标单击坐标
  3. 【项目记录】用vue-h5写可前后端分离和控制计时的物联网移动端app
  4. SAP Spartacus Page Layout - 页面布局设计
  5. UEFI + GPT 启动 VHD
  6. c#读取solidworks文件_C#初学者教程系列20:Stream流读写
  7. bzoj5017 [Snoi2017]炸弹
  8. 关于安装AccessDatabaseEngine_x64.exe 的说明
  9. 使用kubeadm安装k8s集群故障处理三则
  10. Android Studio第一个NDK程序
  11. ant centos环境下 编译没有将配置文件加载_Linux 下的动态库、静态库与环境变量...
  12. 网站建设合同注意事项
  13. 国内外GIS基础软件对比分析优缺特性及实际工作生产应用和成功案例综合评价
  14. 四川为何紧急叫停某知名声乐演员计划在川23场次个人巡演活动?
  15. 在工作中历练思考力,行动力,表达力
  16. pytorch1.13启用caffe2
  17. autojs pro采用递归的方式,遍历所有子控件的源码分享
  18. 贾跃亭所持乐视网股权触及平仓线 部分面临被司法拍卖
  19. 《LSTM神经网络和双色球预测例子》
  20. linux樱桃树软件名字,名字带“樱”的3种水果,多数人最先想到樱桃,第3种最少见!...

热门文章

  1. 《C语言进阶》使用指针花式打印数组内容
  2. 最常用的中文停止词(stop word)列表
  3. ARM CMSIS DAP源码分析
  4. 读书笔记-专注于自己的目标不要为其他事情和人分心和浪费时间
  5. Python中列表的排序方法
  6. 基于Python实现的向量机SVM模型
  7. 2023 闲鱼二手数码项目
  8. 谈谈中间件开发,给想从事中间件开发的同学
  9. APISIX 助力中东社交软件,实现本地化部署
  10. 安卓项目中so库选择(ndk abiFilters设置,armeabi,armeabi-v7a,arm64-v8a)