<u dropzone='oo29x6'></u>
<datalist date-time='l82uoe5'></datalist>
          <code id='uy65ee'><dl draggable='4nqrejnb'></dl></code>

            <tr dir='vo4ytjw'></tr>

          1. <dt date-time='bviiaraz'><noframes dir='wb8o3f'>

            1. <kbd id='46chwmdw'></kbd>
              1. 文章熱詞:swoole,php,自動取消訂單

                日期:2019-06-21 08:52 by admin 1572 1 收藏
                我要分享

                摘要:當客戶下單在指定的時間内如果沒有付款,那我們需要将這筆訂單取消掉,比如好的處理方法是運用延時取消,這裏我們用到了swoole,運用swoole的異步毫秒定時器不會影響到當前程序的運行

                一、業務場景:當客戶下單在指定的時間内如果沒有付款,那我們需要将這筆訂單取消掉,比如好的處理方法是運用延時取消,這裏我們用到了swoole,運用swoole的異步毫秒定時器不會影響到當前程序的運行,具體參考:https://wiki.swoole.com/wiki/page/319.html

                二、說明,order_status爲1時代表客戶下單确定,爲2時代表客戶已付款,爲0時代表訂單已取消(正是swoole來做的),下面的代表我沒有用框架,比較純的PHP代表方便理解和應用

                三、舉例說明,庫存表csdn_product_stock産品ID爲1的産品庫存數量爲20,産品ID爲2的庫存數量爲40,然後客戶下單一筆産品ID1減10,産品ID2減20,所以庫存表隻夠2次下單,例子中10秒後自動還原庫存,如下圖:

                圖解:1、第一次下完單産品ID1庫存從20減到了10,産品ID2庫存從40減到了20;2、第二次下完單産品ID的庫存爲0了,産品ID2的庫存也爲0了,3、第三次下單時,程序提示Out of stock;4、過了10秒鍾(每個訂單下單後往後推10秒),客戶兩次下單,由于沒有付款(csdn_order表的order_status爲1),産品1和産品2的庫存被還原了(csdn_order表的order_status變爲0),客戶又可以繼續下單了

                640.gif

                1、所需要sql數據庫表

                DROP TABLE IF EXISTS `csdn_order`;
                CREATE TABLE `csdn_order` (
                  `order_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
                  `order_amount` float(10,2) unsigned NOT NULL DEFAULT '0.00',
                  `user_name` varchar(64) CHARACTER SET latin1 NOT NULL DEFAULT '',
                  `order_status` tinyint(2) unsigned NOT NULL DEFAULT '0',
                  `date_created` datetime NOT NULL,
                  PRIMARY KEY (`order_id`)
                ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
                DROP TABLE IF EXISTS `csdn_order_detail`;
                CREATE TABLE `csdn_order_detail` (
                  `detail_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
                  `order_id` int(10) unsigned NOT NULL,
                  `product_id` int(10) NOT NULL,
                  `product_price` float(10,2) NOT NULL,
                  `product_number` smallint(4) unsigned NOT NULL DEFAULT '0',
                  `date_created` datetime NOT NULL,
                  PRIMARY KEY (`detail_id`),
                  KEY `idx_order_id` (`order_id`)
                ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
                DROP TABLE IF EXISTS `csdn_product_stock`;
                CREATE TABLE `csdn_product_stock` (
                  `auto_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
                  `product_id` int(10) NOT NULL,
                  `product_stock_number` int(10) unsigned NOT NULL,
                  `date_modified` datetime NOT NULL,
                  PRIMARY KEY (`auto_id`),
                  KEY `idx_product_id` (`product_id`)
                ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
                INSERT INTO `csdn_product_stock` VALUES ('1', '1', '20', '2018-09-13 19:36:19');
                INSERT INTO `csdn_product_stock` VALUES ('2', '2', '40', '2018-09-13 19:36:19');

                2、數據庫配置信息:config.php

                <?php
                $dbHost = "192.168.0.110";
                $dbUser = "root";
                $dbPassword = "123456";
                $dbName = "test123";
                ?>

                3、order_submit.php,生成訂單

                <?php
                require("config.php");
                try {
                    $pdo = new PDO("mysql:host=" . $dbHost . ";dbname=" . $dbName, $dbUser, $dbPassword, array(PDO::ATTR_PERSISTENT => 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 = 'insert into csdn_order (order_amount, user_name, order_status, date_created) values (:orderAmount, :userName, :orderStatus, now())';
                        $stmt = $pdo->prepare($sql);  
                        $affectedRows = $stmt->execute(array(':orderAmount' => $orderInfo['order_amount'], ':userName' => $orderInfo['user_name'], ':orderStatus' => $orderInfo['order_status']));
                        $orderId = $pdo->lastInsertId();
                        if(!$affectedRows) {
                            throw new PDOException("Failure to submit order!");
                        }
                        foreach($orderInfo['product_lit'] as $productInfo) {
                            $sqlProductDetail = 'insert into csdn_order_detail (order_id, product_id, product_price, product_number, date_created) values (:orderId, :productId, :productPrice, :productNumber, now())';
                            $stmtProductDetail = $pdo->prepare($sqlProductDetail);  
                            $stmtProductDetail->execute(array(':orderId' => $orderId, ':productId' =>  $productInfo['product_id'], ':productPrice' => $productInfo['product_price'], ':productNumber' => $productInfo['product_number']));
                            $sqlCheck = "select product_stock_number from csdn_product_stock where product_id=:productId";  
                            $stmtCheck = $pdo->prepare($sqlCheck);  
                            $stmtCheck->execute(array(':productId' => $productInfo['product_id']));  
                            $rowCheck = $stmtCheck->fetch(PDO::FETCH_ASSOC);
                            if($rowCheck['product_stock_number'] < $productInfo['product_number']) {
                                throw new PDOException("Out of stock, Failure to submit order!");
                            }
                            $sqlProductStock = 'update csdn_product_stock set product_stock_number=product_stock_number-:productNumber, date_modified=now() where product_id=:productId';
                            $stmtProductStock = $pdo->prepare($sqlProductStock);  
                            $stmtProductStock->execute(array(':productNumber' => $productInfo['product_number'], ':productId' => $productInfo['product_id']));
                            $affectedRowsProductStock = $stmtProductStock->rowCount();
                            //庫存沒有正常扣除,失敗,庫存表裏的product_stock_number設置了爲非負數
                            //如果庫存不足時,sql異常:SQLSTATE[22003]: Numeric value out of range: 1690 BIGINT UNSIGNED value is out of range in '(`test`.`csdn_product_stock`.`product_stock_number` - 20)'
                            if($affectedRowsProductStock <= 0) {
                                throw new PDOException("Out of stock, Failure to submit order!");
                            }
                        }
                        echo "Successful, Order Id is:" . $orderId .",Order Amount is:" . $orderInfo['order_amount'] . "。";
                        $pdo->commit();//提交事務
                        //exec("php order_cancel.php -a" . $orderId . " &");
                        pclose(popen('php order_cancel.php -a ' . $orderId . ' &', 'w'));
                        //system("php order_cancel.php -a" . $orderId . " &", $phpResult);
                        //echo $phpResult;
                    }catch(PDOException $e){
                        echo $e->getMessage();
                        $pdo->rollback();
                    }
                    $pdo = null;
                } catch (PDOException $e) {
                    echo $e->getMessage();
                }
                ?>

                4、order_cancel.php,這個方法主要就是做訂單自動取消,并還原庫存的業務處理

                <?php
                require("config.php");
                $queryString = getopt('a:');
                $userParams = array($queryString);
                appendLog(date("Y-m-d H:i:s") . "\t" . $queryString['a'] . "\t" . "start");
                try {
                    $pdo = new PDO("mysql:host=" . $dbHost . ";dbname=" . $dbName, $dbUser, $dbPassword, array(PDO::ATTR_PERSISTENT => 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 = "select order_status from csdn_order where order_id=:orderId";  
                            $stmt = $pdo->prepare($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 = "select product_id, product_number from csdn_order_detail where order_id=:orderId";  
                                $stmtOrderDetail = $pdo->prepare($sqlOrderDetail);  
                                $stmtOrderDetail->execute(array(':orderId' => $orderId));  
                                while($rowOrderDetail = $stmtOrderDetail->fetch(PDO::FETCH_ASSOC)) {
                                    $sqlRestoreStock = "update csdn_product_stock set product_stock_number=product_stock_number + :productNumber, date_modified=now() where product_id=:productId";  
                                    $stmtRestoreStock = $pdo->prepare($sqlRestoreStock);
                                    $stmtRestoreStock->execute(array(':productNumber' => $rowOrderDetail['product_number'], ':productId' => $rowOrderDetail['product_id']));
                                }
                                $sqlRestoreOrder = "update csdn_order set order_status=:orderStatus where order_id=:orderId";  
                                $stmtRestoreOrder = $pdo->prepare($sqlRestoreOrder);
                                $stmtRestoreOrder->execute(array(':orderStatus' => 0, ':orderId' => $orderId));
                            }
                            $pdo->commit();//提交事務
                        }catch(PDOException $e){
                            echo $e->getMessage();
                            $pdo->rollback();
                        }
                        $pdo = null;
                        appendLog(date("Y-m-d H:i:s") . "\t" . $queryString['a'] . "\t" . "end\t" . json_encode($queryString));
                    }, $pdo);
                } catch (PDOException $e) {
                    echo $e->getMessage();
                }
                function appendLog($str) {
                    $dir = 'log.txt';
                    $fh = fopen($dir, "a");
                    fwrite($fh, $str . "\n");
                    fclose($fh);
                }
                ?>

                上一篇:git的4個階段的撤銷更改你必須要弄懂

                下一篇:php命名空間詳解


                評論

                -->