日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

php 订单过期处理,PHP实现处理过期或者超时订单,并还原库存

發(fā)布時間:2025/3/15 php 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php 订单过期处理,PHP实现处理过期或者超时订单,并还原库存 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

訂單是我們在日常開發(fā)中經(jīng)常會遇到的一個功能,最近在做一個訂單過期與超時的開發(fā)。訂單過期與超時就不用我解釋了吧,其實兩者都是同一個問題來著,就是訂單未支付的處理,我們要做的是對這些未支付的訂單到了一定時間就自動取消,好了,你第一反應(yīng)那肯定就是做一個定時任務(wù)了!是的,就是定時任務(wù),但是哪個才會是最佳方案呢,下面來看看:

一、前端到時間請求取消

你肯定不會想著在前端來做定時請求取消該訂單的,因為如果客戶禁用了該應(yīng)用或者沒聯(lián)網(wǎng),那到了一定時間時,還一直都是未處理狀態(tài)的。所以前端一般都是手動去觸發(fā)取消訂單的。

二、服務(wù)端定時查詢有沒有需要取消的訂單,然后批量處理。

這種方法我們用得最多的,不過存在準確度的問題,還有需要確認定時任務(wù)的周期,但是我們可以結(jié)合redis來實現(xiàn),我們可以在存redis時候順便存在mysql這樣的數(shù)據(jù)庫做長久存儲然后用服務(wù)端定時查詢,這里我用到了redis的訂閱功能。

首先先修改一下配置

vim?/etc/redis/redis.conf

notify-keyspace-events?“Ex”?#x 代表了過期事件。

然后再重啟redis

service?redis?restart

這里創(chuàng)建4個文件

index.php? 創(chuàng)建訂單,發(fā)布消息,10s后查詢訂單狀態(tài)并更新訂單

lRange('order',0,9999999);

$mysql??????=?new?\mysql();

$mysql->connect();

$data???????=?['ordersn'=>'SN'.time().'T'.rand(10000000,99999999),'status'=>0,'createtime'=>date('Y-m-d?H:i:s',time())];

$mysql->insert('order',$data);

$order_sn???=?$data['ordersn'];

$redis2->setex($order_sn,10,$order_sn);

psubscribe.php,發(fā)布redis訂閱的一些邏輯處理

setOption();

$redis->psubscribe(array('__keyevent@0__:expired'),?'keyCallback');

//?回調(diào)函數(shù),這里寫處理邏輯

function?keyCallback($redis,?$pattern,?$chan,?$msg)

{

$mysql?=?new?\mysql();

$mysql->connect();

$where?=?"ordersn?=?'".$msg."'";

$mysql->select('order','',$where);

$finds=$mysql->fetchAll();

if(isset($finds[0]['status'])?&&?$finds[0]['status']==0){

$data???=?array('status'?=>?3,'updatetime'=>date('Y-m-d?H:i:s',time()));

$where??=?"id?=?".$finds[0]['id'];

$mysql->update('order',$data,$where);

}

}

這里我把redis的一些操作和mysql的一些處理做了封裝處理,這個你們可以用到你們自己的項目當中的

Redis2.class.php

redis?=?new?Redis();

$this->redis->connect($host,?$port);

$this->redis->auth('123456');

}

public?function?setex($key,?$time,?$val)

{

return?$this->redis->setex($key,?$time,?$val);

}

public?function?set($key,?$val)

{

return?$this->redis->set($key,?$val);

}

public?function?get($key)

{

return?$this->redis->get($key);

}

public?function?expire($key?=?null,?$time?=?0)

{

return?$this->redis->expire($key,?$time);

}

public?function?psubscribe($patterns?=?array(),?$callback)

{

$this->redis->psubscribe($patterns,?$callback);

}

public?function?setOption()

{

$this->redis->setOption(\Redis::OPT_READ_TIMEOUT,?-1);

}

public?function?lRange($key,$start,$end)

{

return?$this->redis->lRange($key,$start,$end);

}

public?function?lPush($key,?$value1,?$value2?=?null,?$valueN?=?null?){

return?$this->redis->lPush($key,?$value1,?$value2?=?null,?$valueN?=?null?);

}

public?function?delete($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'];//數(shù)據(jù)庫

$port?=?$config['port'];????//端口號

$this->mysqli?=?new?mysqli($host,?$username,?$password,?$database,?$port);

}

/**

*?數(shù)據(jù)查詢

*?@param?$table?數(shù)據(jù)表

*?@param?null?$field?字段

*?@param?null?$where?條件

*?@return?mixed?查詢結(jié)果數(shù)目

*/

public?function?select($table,?$field?=?null,?$where?=?null)

{

$sql?=?"SELECT?*?FROM?`{$table}`";

//echo?$sql;exit;

if?(!empty($field))?{

$field?=?'`'?.?implode('`,`',?$field)?.?'`';

$sql?=?str_replace('*',?$field,?$sql);

}

if?(!empty($where))?{

$sql?=?$sql?.?'?WHERE?'?.?$where;

}

$this->result?=?$this->mysqli->query($sql);

return?$this->result;

}

/**

*?@return?mixed?獲取全部結(jié)果

*/

public?function?fetchAll()

{

return?$this->result->fetch_all(MYSQLI_ASSOC);

}

/**

*?插入數(shù)據(jù)

*?@param?$table?數(shù)據(jù)表

*?@param?$data?數(shù)據(jù)數(shù)組

*?@return?mixed?插入ID

*/

public?function?insert($table,?$data)

{

foreach?($data?as?$key?=>?$value)?{

$data[$key]?=?$this->mysqli->real_escape_string($value);

}

$keys?=?'`'?.?implode('`,`',?array_keys($data))?.?'`';

$values?=?'\''?.?implode("','",?array_values($data))?.?'\'';

$sql?=?"INSERT?INTO?`{$table}`(?{$keys}?)VALUES(?{$values}?)";

$this->mysqli->query($sql);

return?$this->mysqli->insert_id;

}

/**

*?更新數(shù)據(jù)

*?@param?$table?數(shù)據(jù)表

*?@param?$data?數(shù)據(jù)數(shù)組

*?@param?$where?過濾條件

*?@return?mixed?受影響記錄

*/

public?function?update($table,?$data,?$where)

{

foreach?($data?as?$key?=>?$value)?{

$data[$key]?=?$this->mysqli->real_escape_string($value);

}

$sets?=?array();

foreach?($data?as?$key?=>?$value)?{

$kstr?=?'`'?.?$key?.?'`';

$vstr?=?'\''?.?$value?.?'\'';

array_push($sets,?$kstr?.?'='?.?$vstr);

}

$kav?=?implode(',',?$sets);

$sql?=?"UPDATE?`{$table}`?SET?{$kav}?WHERE?{$where}";

$this->mysqli->query($sql);

return?$this->mysqli->affected_rows;

}

/**

*?刪除數(shù)據(jù)

*?@param?$table?數(shù)據(jù)表

*?@param?$where?過濾條件

*?@return?mixed?受影響記錄

*/

public?function?delete($table,?$where)

{

$sql?=?"DELETE?FROM?`{$table}`?WHERE?{$where}";

$this->mysqli->query($sql);

return?$this->mysqli->affected_rows;

}

}

對每一次訂單的訪問我們做了服務(wù)器監(jiān)聽任務(wù),如下:

cd?/var/www/html/redis

#即時監(jiān)聽,ctrl+c?退出監(jiān)聽??ctrl+z?暫停監(jiān)聽

nohup?php?psubscribe.php

#后臺監(jiān)聽

nohup?php?psubscribe.php?&

設(shè)置本地域名并訪問http://www.startphp.cn/index.php

此時,每訪問一次index.php,就會創(chuàng)建一個訂單,10s鐘后,如果該訂單依舊處于未支付狀態(tài),就設(shè)置訂單失效。

這里要注意一下:

在命令之前加上 nohup ,啟動的進程將會忽略linux的掛起信號 (SIGHUP)

這時候,當我們組合 nohup 和 &兩種方式時,啟動的進程不會占用控制臺,并且不依賴控制臺,控制臺關(guān)閉之后,進程被1號進程收養(yǎng),成為孤兒進程,這就和守護進程的機制非常類似了,并且nohup默認會把程序的輸出重定向到當前目錄下的nohup.out文件,如果沒有可寫權(quán)限,則寫入 $homepath/nohup.out

但是php的cli模式在服務(wù)器運行后,總是會掉線,處理這個問題的方法,寫一個腳本

1.編寫shell腳本,定時檢查進程是否存在,不存在的話就開啟服務(wù),并且將運行情況寫入日志

cd?/

mkdir?mytask

cd?mytask

touch?phprunning.sh

vi?phprunning.sh

腳本文件如下:

#!/bin/sh

PIDS=`pidof?php`

if?[?"$PIDS"?!=?""?];?then

echo?"在運行"

echo?-e?$(date?+%Y"."%m"."%d"?"%k":"%M":"%S)"?running....."?>>?/mytask/task.run.log

else

echo?"不在運行,開始啟動"

echo?-e?$(date?+%Y"."%m"."%d"?"%k":"%M":"%S)"?start?php?start....."?>>?/mytask/task.start.log

cd?/var/www/html/redis

php?psubscribe.php?&

echo?-e?$(date?+%Y"."%m"."%d"?"%k":"%M":"%S)"?start?php?success....."?>>?/mytask/task.start.log

fi

在crontab任務(wù)里創(chuàng)建任務(wù),這里設(shè)定的是每5s檢查一次,crontab -e

*?*?*?*?*?sleep?5;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?10;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?15;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?20;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?25;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?30;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?35;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?40;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?45;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?50;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

*?*?*?*?*?sleep?55;?sh?/mytask/phprunning.sh?>>?/mytask/crontab.log

效果你可以查看task.run.log

cat?/mytask/task.run.log

結(jié)果如下:

-e?2019.10.22?14:28:41?running.....

-e?2019.10.22?14:28:46?running.....

-e?2019.10.22?14:28:51?running.....

-e?2019.10.22?14:28:56?running.....

-e?2019.10.22?14:29:06?running.....

-e?2019.10.22?14:29:11?running.....

-e?2019.10.22?14:29:16?running.....

-e?2019.10.22?14:29:21?running.....

-e?2019.10.22?14:29:26?running.....

-e?2019.10.22?14:29:31?running.....

-e?2019.10.22?14:29:36?running.....

-e?2019.10.22?14:29:41?running.....

-e?2019.10.22?14:29:46?running.....

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的php 订单过期处理,PHP实现处理过期或者超时订单,并还原库存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。