个人免签支付开发原理和示例源码分享
个人免签是什么?
官方支付接口比如支付宝、微信支付接口都需要营业执照才能申请,个人没有资质是无法申请的,想用官方支付是需要和商家签约的。
个人免签支付就是专门为没资质的个人使用的在线支付接口,无需签约,就可以使用。
个人免签原理
1、APP监听收款码的支付结果,然后修改页面的支付结果。
2、二次清算。款先到拥有官方支付接口的商户中,由商户给你结算。
3、Xposed微信插件实现全自动监听创建收款码、以及收款过程,容易封号。
方案其实有很多种,但是以上的方案都有不少的缺点,当然这些方案仍有不少人在用,没办法,确实是解决问题的一种办法。
实战示例分享
以下示例实现是用的第一种APP监听收款码的免签支付方式,整个过程很简单:访问URL -> 检查数据库2分钟内未支付的订单金额 -> 如果2分钟内未支付的订单金额中存在当前订单一样的金额,需要在当前金额基础上+0.01元用于区分订单的唯一性 -> 用户扫码支付 -> 安卓手机APP监听到这笔订单的收款 -> 将收款金额异步发送到服务器 -> 服务器修改数据库该笔订单金额的支付状态 -> 扫码页面一直在轮询订单的支付状态,发现已支付就修改页面的支付结果 -> 完成支付。
创建支付请求代码
index.php
<!DOCTYPEhtml><html><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0,viewport-fit=cover"><metacharset="utf-8"><scriptsrc="./js/jquery.min.js"></script><linkrel="stylesheet"href="./css/style.css"><title>微信赞赏码免签约支付实现原理Demo</title></head><body><?php//数据库配置include'./Db.php';//实例化类$db=newDB_API($config);//订单号$order_num=date('Ymd').time();//订单金额$order_price=0.01;//获取未支付订单列表$getOrderList=$db->set_table('mqpay_order')->findAll(['order_status'=>1]);//遍历订单$orderNoExpire=array();for($i=0;$i<count($getOrderList);$i++){//订单时间$order_time=json_decode(json_encode($getOrderList[$i]))->order_time;//订单金额$order_money=json_decode(json_encode($getOrderList[$i]))->order_money;//获取2分钟未支付的订单if(countTimes(time(),strtotime($order_time))<=2){//如果存在$orderNoExpire[]=$order_money;}}//判断是否有2分钟未支付的订单if(count($orderNoExpire)==0){$needPay=$order_price;}else{//获取2分钟未支付的订单的最大金额+0.01$needPay=max($orderNoExpire)+0.01;}//创建订单creatOrder($order_num,$order_price,$needPay,$db);//创建订单functioncreatOrder($order_num,$order_price,$needPay,$db){//订单参数$createOrder=['order_num'=>$order_num,'order_price'=>$order_price,'order_money'=>$needPay,];//创建$createOrderResult=$db->set_table('mqpay_order')->add($createOrder);if($createOrderResult){//成功echo'<divclass="payInfoCard"><divclass="header">里客云科技</div><divclass="moneyCard"><divclass="text">支付金额</div><divclass="money"><spanclass="rmb">¥</span>'.$needPay.'</div><!--二维码--><imgsrc="./img/zsm.jpg"id="zsmQrcode"class="zsmQrcode"/><pclass="payWarning">请识别上方赞赏码</p><pclass="payWarning">点击<spanclass="blueFont">其他金额</span>输入'.$needPay.'元</p><pclass="payWarningMini">输入的金额必须要完全一致</p><pid="orderExpireTime"></p><pid="orderNum"style="display:none;">'.$order_num.'</p><pid="needPay"style="display:none;">'.$needPay.'</p></div></div><!--提示--><pclass="payTips">我们通过机器人监测本次支付<br/>支付后会立刻显示支付结果<br/>支付后没显示支付结果请联系人工处理<br/>微信号:xxx</p>';}else{//失败echo'<divclass="payInfoCard"><divclass="header">里客云科技</div><divclass="moneyCard"style="padding:20px20px;">创建订单失败!</div></div>';}}//计算时间戳的差值functioncountTimes($begin,$end){$begintimes=$begin;$endtimes=$end;$timediff=abs($endtimes-$begintimes);$days=intval($timediff/86400);$remain=$timediff%86400;$hours=intval($remain/3600);$remain=$remain%3600;$mins=intval($remain/60);$secs=$remain%60;return$mins;}?><script>//每2秒获取一次支付结果varcheckPayInterval=setInterval('checkPay()',2000);//获取支付结果functioncheckPay(){//获取订单号和支付金额varorderNum=$("#orderNum").text();varneedPay=$("#needPay").text();$.ajax({type:"GET",url:"./checkPay.php?order_num="+orderNum+"&order_money="+needPay,success:function(res){//判断支付结果if(res.code==200){console.log('支付成功');$("#zsmQrcode").prop("src","./img/success.png");$('#orderExpireTime').css('display','none');clearInterval(checkPayInterval);}else{console.log(res.msg);}}});}//倒计时functionclock(times){//获取时分秒varh=parseInt(times/3600);varm=parseInt((times%3600)/60);vars=(times%3600)%60;//在页面中显示倒计时$('#orderExpireTime').html(m+"分"+s+"秒后过期");//倒计时if(times>0){times=times-1;setTimeout(function(){clock(times);},1000);}else{//显示订单过期$("#zsmQrcode").prop("src","./img/expire.png");$('#orderExpireTime').text('订单已过期,请刷新页面!');//结束轮询clearInterval(checkPayInterval);console.log('订单过期,停止监听');}}</script></body></html>
该页面是用于创建订单的,其中$order_price = 0.01;就是创建一笔0.01元的订单。
创建订单前,程序会查询数据库来确定当前金额是否存在未支付的订单,如果存在,需支付的金额会在当前订单金额基础上+0.01元。
为什么要这么做?因为APP监听只能监听到收到了多少钱,无法监听到订单号,所以无法区分这个金额是你支付的还是其他人支付的。 所以在当前订单有效期内,你需要注意两件事,第一,你这个程序的访问量一定不能太高,不允许高并发的情况出现,适合小众,小规模,小流量的业务使用,一旦人多了,短时间内订单量多了,很难做到精准的监听支付结果。
实时监听支付代码
checkPay.php
这个是用于订单页面实时监听支付结果的,每2秒就查一次数据库获取订单的支付结果,2分钟后未支付会停止查询。
<?php//页面编码header("Content-type:application/json");//数据库配置include'./Db.php';//实例化类$db=newDB_API($config);//获取订单号和支付金额$order_num=$_GET['order_num'];$order_money=$_GET['order_money'];//根据订单号和订单金额来查询支付结果$getOrderPayStatus=$db->set_table('mqpay_order')->find(['order_num'=>$order_num,'order_money'=>$order_money]);//判断支付结果if($getOrderPayStatus){//支付状态$order_status=json_decode(json_encode($getOrderPayStatus))->order_status;if($order_status==2){//支付成功$payResult=array('code'=>200,'msg'=>'支付成功');}else{//未支付$payResult=array('code'=>202,'msg'=>'未支付');}}else{//无结果$payResult=array('code'=>201,'msg'=>'未支付');}//返回JSONechojson_encode($payResult,JSON_UNESCAPED_UNICODE);?>
异步回调代码
notify.php
这个是异步回调,在APP监听软件需要配置这个文件的URL和传递的参数,将监听到的金额post给你的服务器然后修改数据库的支付结果,以实现支付回调的目的。
<?php//页面编码header("Content-type:application/json");//原文$orderMsg=$_GET['orderMsg'];//数据库配置include'./Db.php';//实例化类$db=newDB_API($config);//订单金额、需支付的金额、通知原文、db实例updateOrder($orderMsg,$db);//修改支付结果functionupdateOrder($orderMsg,$db){//截取//示例:二维码赞赏到账1.00元//截取【到账】后面的$money_1=substr($orderMsg,strripos($orderMsg,"到账")+6);//截取【元】前面的$money_2=substr($money_1,0,strrpos($money_1,"元"));//更新订单$updateOrderResult=$db->set_table('mqpay_order')->update(['order_status'=>1,'order_money'=>$money_2],['order_status'=>2,'order_paytime'=>time(),'order_msg'=>$orderMsg]);if($updateOrderResult){//成功$ret=array('code'=>200,'msg'=>'支付成功','order_num'=>$order_num,'order_money'=>$money_2,'order_msg'=>$orderMsg);}else{//失败$ret=array('code'=>200,'msg'=>'支付失败','order_num'=>$order_num);}}//返回JSONechojson_encode($ret,JSON_UNESCAPED_UNICODE);?>