当前位置: 首页 > 后端技术 > PHP

PHP如何处理过期或超时的订单以及恢复库存

时间:2023-03-29 23:53:38 PHP

订单是我们在日常开发中经常遇到的一个功能。最近在做一个订单过期和超时的开发。我不需要解释订单到期和超时。其实这两个都是同一个问题,就是未付款订单的处理。我们需要做的是在一定时间后自动取消这些未支付的订单。好了,你的第一反应肯定是做定时任务吧!是的,这是一个计划任务,但哪个是最好的解决方案呢?下面我们来看一下:1.当前端请求取消订单的时候,你肯定不会想着在前端做一个预定的请求取消订单,因为如果客户禁用了如果你已经打开了该应用程序或未连接到Internet,在一定时间后仍将未处理。因此,前端一般会手动触发取消订单。2、服务器定时检查是否有需要取消的订单,然后批量处理。这种方式我们用的最多,但是存在精度问题,需要确认定时任务的周期,但是可以结合redis来实现。我们可以将redis存储在mysql等数据库中进行长期存储,然后使用服务器定时查询,这里我使用的是redis的订阅功能。先修改配置再重启redis创建4个文件index.php创建订单,发布消息,查询订单状态,10s后更新订单lRange('order',0,9999999);$mysql=new\mysql();$mysql->connect();$data=['ordersn'=>'SN'.time().'T'.rand(10000000,99999999),'status'=>0,'createtime'=>date('Y-m-dH:i:s',time())];$mysql->insert('order',$data);$order_sn=$data['ordersn'];$redis2->setex($order_sn,10,$order_sn);psubscribe.php,发布redissubscription一些逻辑处理这里我封装了redis的一些操作和mysql的一些处理,大家可以在自己的项目中使用Redis2.class.phpredis=newRedis();$this->redis->connect($host,$port);$this->redis->auth('123456');}publicfunctionsetex($key,$time,$val){返回$this->redis->setex($key,$time,$val);}公共函数集($key,$val){return$this->redis->set($key,$val);}publicfunctionget($key){return$this->redis->get($key);}publicfunctionexpire($key=null,$time=0){return$this->redis->expire($key,$time);}publicfunctionpsubscribe($patterns=array(),$callback){$this->redis->psubscribe($patterns,$callback);}publicfunctionsetOption(){$this->redis->setOption(\Redis::OPT_READ_TIMEOUT,-1);}publicfunctionlRange($key,$start,$end){return$this->redis->lRange($key,$start,$end);}publicfunctionlPush($key,$value1,$value2=null,$valueN=null){return$this->redis->lPush($key,$value1,$value2=null,$valueN=null);}publicfunctiondelete($key1,$key2=null,$key3=null){return$this->redis->delete($key1,$key2=null,$key3=null);}}db.class.php,sql处理的一些包`'127.0.0.1','username'=>'root','password'=>'123456qwerty','database'=>'marhal','port'=>3306,);$host=$config\['host'\];//主机地址$username=$config\['username'\];//用户名$password=$config\['password'\];//密码$database=$config\['database'\];//数据库$port=$config\['port'\];//端口号$this->mysqli=newmysqli($host,$username,$password,$database,$port);}/\*\*\*数据查询\*@param$table数据表\*@paramnull$field字段\*@paramnull$where条件\*@return混合查询结果数\*/publicfunctionselect($table,$field=null,$where=null){$sql="SELECT\*FROM\`{$表}\`";//echo$sql;退出;如果(!empty($field)){$field='\`'.内爆('\`,\`',$field)。'\`';$sql=str\_replace('\*',$field,$sql);}if(!empty($where)){$sql=$sql.'在哪里'。$在哪里;}$this->result=$this->mysqli->query($sql);return$this->result;}/\*\*\*@returnmixed获取所有结果\*/publicfunctionfetchAll(){return$this->result->fetch\_all(MYSQLI\_ASSOC);}/\*\*\*插入数据\*@param$table数据表\*@param$data数据数组\*@return混合插入ID\*/publicfunctioninsert($table,$data){foreach($dataas$key=>$value){$data\[$key\]=$this->mysqli->real\_escape\_string($value);}$keys='\`'。内爆('\`,\`',array\_keys($data))。'\`';$值='\\''。内爆(“','”,阵列\_值($数据))。'\\'';$sql="INSERTINTO\`{$table}\`({$keys})VALUES({$values})";$this->mysqli->query($sql);return$this->mysqli->insert\_id;}/\*\*\*更新数据\*@param$table数据表\*@param$data数据数组\*@param$where过滤条件\*@return混合主题影响记录\*/publicfunctionupdate($table,$data,$where){foreach($dataas$key=>$value){$data\[$key\]=$this->mysqli->real\_escape\_string($value);}$sets=数组();foreach($dataas$key=>$value){$kstr='\`'.$键。'\`';$vstr='\\''.$价值。'\\'';array\_push($sets,$kstr.'='.$vstr);}$kav=implode(',',$sets);$sql="UPDATE\`{$table}\`SET{$kav}WHERE{$where}";$this->mysqli->query($sql);return$this->mysqli->affected\_rows;}/\*\*\*删除数据\*@param$table数据表\*@param$where过滤条件\*@return混合影响记录\*/publicfunctiondelete($table,$where){$sql="DELETEFROM\`{$table}\`WHERE{$where}";$this->mysqli->query($sql);return$this->mysqli->affected\_rows;}}`对于每次订单访问,我们都做了服务器监控任务,如下:设置本地域名,访问http://www.sixstaredu.com/ind...p此时,每次访问index.php,都会创建一个订单。10秒后,若订单仍未支付,则订单作废但是php的cli方式在服务器运行后会一直断开。为了解决这个问题,我们不妨写一个脚本1.写一个shell脚本,定时检查进程是否存在。如果不存在,则启动服务并记录运行状态写入日志脚本文件如下:#!/bin/shPIDS=`pidofphp`if["$PIDS"!=""];thenecho"running"echo-e$(date+%Y"."%m"."%d""%k":"%M":"%S)"running.....">>/mytask/task.run.logelseecho"没有运行,开始"echo-e$(date+%Y"."%m"."%d""%k":"%M":"%S)"startphpstart.....">>/mytask/task.start.logcd/var/www/html/redisphppsubscribe.php&echo-e$(date+%Y"."%m"."%d""%k":"%M":"%S)"startphpsuccess.....">>/mytask/task.start.logfi在crontab任务中创建一个任务,这里设置为每5s检查一次,crontab-e效果可以查看task.run.log结果如下: