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

swoole+PHP实现自动取消订单、恢复库存等操作

时间:2023-03-29 19:53:51 PHP

1、业务场景:如果客户下了订单,没有在规定的时间内付款,那么我们就需要取消订单。例如,一个好的处理方法是使用延迟取消。这里我们使用swoole,使用swoole的异步毫秒定时器,不会影响当前程序的运行。详情请参考:https://wiki.swoole.com/wiki/page/319.html2.说明,order_status为1时表示客户下单,为2时表示客户下单客户已付款,为0时表示订单已取消(由swoole完成),下面说明我没有使用框架,比较纯的PHP表示很容易理解和应用。库存数量为20,产品ID2的库存数量为40,然后客户下单产品ID1-10,产品ID2-20,所以库存表只够2个订单。示例中10秒后库存自动恢复,如下图:示意图:1.第一次下单后商品ID1的库存从20减少到10,商品ID2的库存从40减少到20;2、第二次下单后产品ID的库存为0,产品ID2的库存也为0。3、第三次下单时,程序提示缺货;4.10秒后(每次下单后10秒),客户下单两次,因为没有付款(csdn_order表的order_status为1),恢复了商品1和商品2的库存(csdn_order表的order_status变为0),客户可以继续下单。1.需要的sql数据库表DROPTABLEIFEXISTS`csdn_order`;CREATETABLE`csdn_order`(`order_id`int(10)unsignedNOTNULLAUTO_INCREMENT,`order_amount`float(10,2)unsignedNOTNULLDEFAULT'0.00',`user_name`varchar(64)CHARACTERSETlatin1NOTNULLDEFAULT'',`order_status`tinyint(2)unsignedNOTNULLDEFAULT'0',`date_created`datetimeNOTNULL,PRIMARYKEY(`order_id`))ENGINE=InnoDBAUTO_INCREMENT=0DEFAULTCHARSET=utf8;如果存在`csdn_order_detail`则删除表;创建表`csdn_order_detail`(`detail_id`int(10)unsignedNOTNULLAUTO_INCREMENT,`order_id`int(10)unsignedNOTNULL,`product_id`int(10)NOTNULL,`product_price`float(10,2)NOTNULL,`product_number`smallint(4)unsignedNOTNULLDEFAULT'0',`date_created`datetimeNOTNULL,PRIMARYKEY(`detail_id`),KEY`idx_order_id`(`order_id`))ENGINE=InnoDBAUTO_INCREMENT=0DEFAULTCHARSET=utf8;DROPTABLEIFEXISTS`csdn_product_stock`;CREATETABLE`csdn_product_stock`(`auto_id`int(10)unsignedNOTNULLAUTO_INCREMENT,`product_id`int(10)NOTNULL,`product_stock_number`int(10)unsignedNOTNULL,`date_modified`datetimeNOTNULL,PRIMARYKEY(`auto_id`),KEY`idx_product_id`(`product_id`))ENGINE=InnoDBAUTO_INCREMENT=3DEFAULTCHARSET=utf8;插入`csdn_product_stock`VALUES('1','1','20','2018-09-1319:36:19');插入`csdn_product_stock`VALUES('2','2','40','2018-09-1319:36:19');2、数据库配置信息:config.php3、order_submit.php,生成订单true));$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,1);$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$orderInfo=array('order_amount'=>10.92,'user_name'=>'yusan','order_status'=>1,'date_created'=>'now()','product_lit'=>array(0=>array('product_id'=>1,'product_price'=>5.00,'product_number'=>10,'date_created'=>'now()'),1=>array('product_id'=>2,'product_price'=>5.92,'product_number'=>20,'date_created'=>'now()')));try{$pdo->beginTransaction();//开始事务处理$sql='insertintocsdn_order(order_amount,user_name,order_status,date_created)values(:orderAmount,:userName,:orderStatus,now())';$stmt=$pdo->准备($sql);$affectedRows=$stmt->execute(array(':orderAmount'=>$orderInfo['order_amount'],':userName'=>$orderInfo['user_name'],':orderStatus'=>$orderInfo['order_status']));$orderId=$pdo->lastInsertId();if(!$affectedRows){thrownewPDOException("提交订单失败!");}foreach($orderInfo['product_lit']as$productInfo){$sqlProductDetail='insertintocsdn_order_detail(order_id,product_id,product_price,product_number,date_created)values(:orderId,:productId,:productPrice,:pr产品编号,现在())';$stmtProductDetail=$pdo->prepare($sqlProductDetail);$stmtProductDetail->execute(array(':orderId'=>$orderId,':productId'=>$productInfo['product_id'],':productPrice'=>$productInfo['product_price'],':productNumber'=>$productInfo['product_number']));$sqlCheck="selectproduct_stock_numberfromcsdn_product_stockwhereproduct_id=:productId";$stmtCheck=$pdo->准备($sqlCheck);$stmtCheck->execute(array(':productId'=>$productInfo['product_id']));$rowCheck=$stmtCheck->fetch(PDO::FETCH_ASSOC);if($rowCheck['product_stock_number']<$productInfo['product_number']){thrownewPDOException("缺货,提交订单失败!");}$sqlProductStock='更新csdn_product_stocksetproduct_stock_number=product_stock_number-:productNumber,date_modified=now()其中product_id=:productId';$stmtProductStock=$pdo->准备($sqlProductStock);$stmtProductStock->execute(array(':productNumber'=>$productInfo['product_number'],':productId'=>$productInfo['product_id']));$affectedRowsProductStock=$stmtProductStock->rowCount();//库存没有正常扣除,失败,inventory表中的product_stock_number设置为非负数//如果库存不足,sql异常:SQLSTATE[22003]:Numericvalueoutofrange:1690BIGINTUNSIGNED'(`test`.`csdn_product_stock`.`product_stock_number`-20)'if($affectedRowsProductStock<=0){thrownewPDOException("Outofstock,Failuretosubmitorder!");值超出范围}}echo"成功,订单号为:"。$orderId。”,订单金额为:“。$orderInfo['order_amount']。“。”;$pdo->commit();//提交事务//exec("phporder_cancel.php-a".$orderId."&");pclose(popen('phporder_cancel.php-A'。$订单号。'&','w'));//system("phporder_cancel.php-a".$orderId."&",$phpResult);//回显$phpResult;}catch(PDOException$e){echo$e->getMessage();$pdo->回滚();}$pdo=null;}catch(PDOException$e){echo$e->getMessage();}?>4、order_cancel.php,该方法主要是做自动取消订单恢复库存的业务流程true));$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT,0);$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);swoole_timer_after(10000,function($queryString){global$queryString,$pdo;try{$pdo->beginTransaction();//开始事务处理$orderId=$queryString['a'];$sql="selectorder_statusfromcsdn_orderwhereorder_id=:orderId";$stmt=$pdo->准备($sql);$stmt->execute(array(':orderId'=>$orderId));$row=$stmt->fetch(PDO::FETCH_ASSOC);//$row['order_status']==="1"代表已经下单,但未付款,我们还原始库保存只针对未付款的订单if(isset($row['order_status'])&&$row['order_status']==="1"){$sqlOrderDetail="selectproduct_id,product_numberfromcsdn_order_detailwhereorder_id=:orderId";$stmtOrderDetail=$pdo->准备($sqlOrderDetail);$stmtOrderDetail->execute(array(':orderId'=>$orderId));while($rowOrderDetail=$stmtOrderDetail->fetch(PDO::FETCH_ASSOC)){$sqlRestoreStock="更新csdn_product_stock设置product_stock_number=product_stock_number+:productNumber,date_modified=now()whereproduct_id=:productId";$stmtRestoreStock=$pdo->准备($sqlRestoreStock);$stmtRestoreStock->execute(array(':productNumber'=>$rowOrderDetail['product_number'],':productId'=>$rowOrderDetail['product_id']));}$sqlRestoreOrder="updatecsdn_ordersetorder_status=:orderStatuswhereorder_id=:orderId";$stmtRestoreOrder=$pdo->准备($sqlRestoreOrder);$stmtRestoreOrder->execute(array(':orderStatus'=>0,':orderId'=>$orderId));}$pdo->commit();//提交事务}catch(PDOException$e){echo$e->getMessage();$pdo->回滚();}$pdo=null;appendLog(date("Y-m-dH:i:s")."\t".$queryString['a']."\t"."end\t".json_encode($queryString));},$pdo);}catch(PDOException$e){echo$e->getMessage();}functionappendLog($str){$dir='log.txt';$fh=fopen($目录,“A”);fwrite($fh,$str."\n");fclose($fh);}?>

最新推荐
猜你喜欢