注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

早衰男的巢

大音希声 道隐无名

 
 
 

日志

 
 

PHP+jQuery:长连接PC+手机端交互场景应用实例——自动响应扫码支付结果  

2016-03-23 16:31:28|  分类: PHP |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

很早以前就想写个试试,直到最近有合适的任务把构想实现了一下。效果还比较满意

先来看看概述的流程图

这是一个(PC端)网页产生订单和微信支付用二维码;

然后用户使用手机微信扫描二维码支付;

支付成功后页面自动跳转到"支付成功"页面的这么一个流程。

 

这篇日志主要备忘怎样实现PHP下的"长连接"去响应一些外部的事件(或数据变化),除了支付外还可举一反三应用在扫码登录,扫码签到等等。

*如何创建订单、如何生成二维码、怎样部署微信扫码支付等都不是本文重点已略去,有时间我另外撰文。

 

入正题,根据这次的项目我们假设订单表的结构如下(省略掉了大部分与本文不相关的字段)

tab_orders

+----+-------------------+----------+----------+

| id | orderNum | totalFee | status |

+----+-------------------+----------+----------+

| 1 | 15121510498291750 | 100 | 1 |

+----+-------------------+----------+----------+

 

其中 tab_orders.orderNum 为订单号, 每张订单的唯一标识。

 

看看展示二维码,并在后台等待订单状态更新的

[qrPay.php]

<?php

$orderNum = "123456";// 订单号,生成和获取略

$qrfile = "/tmp/payqr_xxxx.png"; //这是根据订单信息(包含订单号)生成的二维码,创建过程略

 

?>

<body>

<div class="main">

<div style="text-align: center;"><img style="margin: 20px 0; " src="<?php echo $qrfile;?>" /></div>

<div style="text-align: center; color: #464646; font-size:.8em;">*扫描支付成功后页面会自动跳转</div>

</div>

<script>

//用长连接检查支付结果,循环无休,直到检查到已经支付成功,跳转去支付成功页

var ordernum = "<?php echo $orderNum;?>";

 

function loopchecker(){

$.get("chkPay.php?ordernum="+ordernum,function(data){ //长链

if(data.code==200){ //检测到支付成功,跳转去支付成功提示页

location.href='done.php';

}else{ //超时或返回的结果仍未支付成功,loop

loopchecker();

}

},"json");

}

 

loopchecker(); //页面加载即启动后台循环检查订单状态

</script>

 

</body>

</html>

 

关键在js函数 loopchecker() ,等待 chkpay.php 返回的结果,那么以下看看内容

[chkPay.php]

<?php

 

/**

* chkpay

*

* 伪长连接. 一个长心跳~每3秒检查一次支付结果,一共7次

* @author Flamen

* @copyright 2016

*/

 

set_time_limit(30); //让脚本执行时间允许长达最大30秒(以防触发php.ini的脚本时长限制)

 

$ordernum = $_GET["ordernum"];

if(!$ordernum) die("no ordernum");

 

$tik = 0; //检查次数计数,3秒*7次,大概每轮的总耗时21秒

 

while($tik<7){

//status: 1待支付, 2已支付 , 3(略)…

$sql = "SELECT * FROM `tab_orders` WHERE `orderNum`='{$ordernum}' AND `status` > 1 ;"; //

$rs = Util::postSqlApi($sql); //这是sql执行的方法,实现方法略,知道功能就行

if($rs){ //订单已经支付!

endjson(200,"pay ok!"); //输出json结果,终止执行脚本

}

//还没支付就等3秒,再查一次,一共查7次,见while()条件

$tik++;

sleep(3);

}

 

endjson(201,"timeout"); //查完7遍还没支付,输出【超时】结果让qrPay.Php再发起一次长链

 

 

 

/**

* endjson()

* 一个给json接口使用的标准化输出json的函数

* 使用后会直接中止脚本的后续输出,会die($json)

* @param integer $code

* @param string $desc

* @param array $extraArray

* @return void

*/

function endjson($code,$desc,$extraArray=null){

unset($json);

$json["code"]=$code;

$json["desc"]=$desc;

if(is_array($extraArray)){

foreach($extraArray as $k => $v){

$json[$k] = $v;

}

}

 

die(json_encode($json));

}

?>

 

 

可以看到chkpay.php 是个执行可能长达21秒左右的脚本,它会每隔3秒查询一次订单是不是已经被支付。如果发现订单状态改变了,立刻输出结果

所以只要订单被(腾讯的支付接口回调payok.php )更新为已支付,chkPay可能在延迟1-3秒内就能响应并反馈到 qrPay.php, js就能处理接下来的交互。

 

这个案例中并没有使用到真正意义的长链接,没有动用socks 因为这些在php上都不太好实现,而且对服务端有要求。

 

注意事项:

  1. Chkpay中,循环去查询数据库的频率和次数务必谨慎决定,视乎应用场景和用户量,数字设大了可能会flush了自己的数据库(特别是页面被多开的话效果拔群不亚于发起ddos攻击)
  2. Chkpay 本例中,估算完成7次查询耗时21秒是忽略了数据库的性能(假设db响应都很快),实际上此处应注意效能的优化,必要时采用数据库以外的其他高速缓存之类代替
  3. iquery 的$.get()没有超时参数,会默认依赖于浏览器的默认值(一般是30秒),如果想严谨一点,建议用$.ajax()代替
  4. 实际上订单的支付还存在用户打开页面就走开不了了之了,或者取消支付等其他情况,细致完善不要让qrpay傻傻一直循环下去空耗数据库资源。

 

 

  评论这张
 
阅读(247)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018