最近搞了个公众号,由于是新手,微信支付那一块其中就遇到了不少的坑,为此商家因为我的失误就丢了差不多1000块。。下面总结一下遇到的坑
图为微信支付的官方文档
图为实际文档的代码
如果你用过微信支付的sdk,就会发现支付的设置是在jsapi.php这个文件下面,其中上面的那段代码是微信支付js api的调用,如果有支付行为就会调用function里面的函数,如果是返回的信息是"get_brand_wcpay_request:ok",就会执行if里面你的写的代码,按道理来说if里面一般放置支付成功后的操作,但是这个是前端页面。。使用者可以去修改前端的页面,包括js。。这个是问题关键,我一开始以为是微信网页,在电脑打不开,就比较安全了,就没深思那么多,没想到上线之后还是有人可以修改前端页面,看来我还是太年轻了,直接跳过判断。。执行下一步操作,为此商家损失了几百块。由于那时候微信支付那一块我不懂,是找别人做这一块,我做另一块的,所以果断掉坑了,而那个人又不太负责任,据说那个人现在还去一个类似于慕课网的授课网站写微信支付的教程,我tm也是呵呵了,最后那个人想了一下给我建议,就是用微信的查询订单api功能去查询有没有该订单,如果没有该订单号,则证明他是跳过支付来执行下一段代码的。至于订单号,我是通过js的获取微秒级别的函数获取的时间戳作为商家的订单号的。
我想了一下大概可能出现的情况,做了个微信支付判断,如果有不法分子留意,有以下几种情况:
1.没有该微信订单号存在(通过修改前端支付判断的代码跳过支付直接进行下一步)
2.该订单号没有支付成功
3.该微信订单号为空
4.传过来的订单号是已经使用过的(旧的订单号,这样就可能会造成支付成功一次,以后买同样商品不用钱了)
5.传过来的订单支付的金额和你的商品价格不对(如果有人有心,买了个便宜商品,再把前端js代码改了一下,不把时间戳的微信单号传过来,下次买个贵的商品再把该单号传过来,你也gg了)
下面是我的判断代码
// 订单号不空, if(isset($_REQUEST["out_trade_no"]) && $_REQUEST["out_trade_no"] != "") { $out_trade_no = $_REQUEST["out_trade_no"]; $input = new WxPayOrderQuery(); $input->SetOut_trade_no($out_trade_no); $message =WxPayApi::orderQuery($input); /** 这里是一个数组 */ // 存在该微信订单号 if(!empty($message)) { // 该订单号支付成功 if($message['trade_state'] =="SUCCESS") { /** 支付成功 */ // 判断价格是否和商品对应 $a = $nowPrice*100; if($message['total_fee']!=$a) {// } } // 订单号没有不成功支付 else { echo "订单不存在."; mysql_query($sql); exit(0); /** 错误码 0*/ } } // 该订单号不存在 else { exit(-1); } } // 没有存过来单号 else { echo "呵呵,玩你妹"; exit(0); } // 记录微信单号 $sql = "select tradeid from OddNumber where tradeid = {$out_trade_no};"; $res = mysql_query($sql); $arr = mysql_fetch_assoc($res); //不空证明订单存在,就是已经用过了 if(!empty($arr) ){ echo "订单存在"; exit(-1); } // 下面是支付成功后的代码
好了。。这就是微信支付的坑。。我感觉还有更多的坑面对着我,昨晚又遇到一个坑。。微信支付文档本来写着$message['total_fee']是int,但是到了php又是string型,和数据库数据判断又出错了.
最后实验证明,还是用回调处理支付成功操作比较好...根据前端ajax发送来后台去判断,总会出现漏单,而且你需要去写逻辑去处理..