讓我們來用php編寫一個搶購商品指令碼
主題列表:juejin, github, smartblue, cyanosis, channing-cyan
貢獻主題:https://github.com/xitu/juejin-markdown-themes
theme: juejin
highlight: juejin
專案原始碼
== 還沒上傳呢
https://juejin.im/editor/drafts/6894061101374734343
環境
- php7.2
- guzzle
- thinkphp5.1
說明
0. git clone xxxxxx
1. composer create-project topthink/think=5.1.* fxbox
2. cd fxbox
3. composer require guzzlehttp/guzzle:~6.0 安裝 guzzle
4. composer update
如何使用
如果是github那邊下載原始碼的話,看這裡
1. cd fxbox
2. php think fcbox:run
3. ....後面這裡就可以指令碼的安裝提示進行下一步驟了
效果圖
核心程式碼
<?php
namespace app\command;
use GuzzleHttp\Cookie\CookieJar;
use think\console\Command;
use think\console\Input;
use think\console\Output;
class Fcbox extends Command
{
private $userInfo = [];
private $cookies = '';
private $skus = '';
private $address = [];
//數量
private $count = 0;
// 使用者列表的下標
private $current_address = 0;
// sku列表的下標
private $current_sku = 0;
// 搶購開始時間
private $start_time = 0;
//生成訂單的token
private $orderToken = 0;
public $client = null;
public $jar = null;
public $output = null;
public function __construct($name = null)
{
parent::__construct($name);
$this->client = new \GuzzleHttp\Client(); //初始化客戶端
$this->jar = new CookieJar();
$this->output = new Output();
//獲取使用者資訊
$this->cookies = $this->inputCookie();
// 訂單結束
}
protected function configure()
{
// 指令配置
$this->setName('fcbox:run');
// 設定引數
}
protected function execute(Input $input, Output $output)
{
$this->output->writeln("-------------正在獲取個人資訊中-------------");
$this->userInfo = $this->getUserInfo(); // 使用者資訊
$this->address = $this->getUserAddress(); // 使用者地址
$this->output->writeln("----------------------------------------------------------------------");
// 獲取產品sku資訊 價格 描述 產品名稱
$this->skus = $this->getProduct(); // 產品資訊
$this->output->writeln("----------------------------------------------------------------------");
// 選擇sku資訊
$this->selectProductSku();
$this->output->writeln("----------------------------------------------------------------------");
// 選擇數量
$this->getInputCount();
$this->output->writeln("----------------------------------------------------------------------");
// 選擇地址
$this->selectUserAddress();
$this->output->writeln("----------------------------------------------------------------------");
// 搶購開始的時間
$this->getInputStartTime();
$this->output->writeln("----------------------------------------------------------------------");
/**
*
* 這裡需要迴圈進行下單
*
*
*/
// 提交訂單
while (true) {
sleep(5);
}
//生成提交訂單的資訊 認證token
$this->getConfirmToken();
$this->output->writeln("----------------------------------------------------------------------");
//提交訂單
$this->submitOrder();
$this->output->writeln("----------------------------------------------------------------------");
// 指令碼執行結束
$this->output->writeln("----------------------------------------------------------------------");
$this->output->writeln("------------------------------指令碼執行完成------------------------------");
$this->output->writeln("----------------------------------------------------------------------");
}
/**
* 對使用者輸入的cookie進行處理
* @return CookieJar
*/
private function inputCookie()
{
try {
fwrite(STDOUT, '請輸入你的Cookies:');
$cookies = trim(fgets(STDIN));
$cookies = explode(';', $cookies);
$base_url = 'mall.fcbox.com';
$data = [];
foreach ($cookies as $cookie) {
if ($cookie == '') continue;
[$name, $value] = explode('=', $cookie);
$data[trim($name)] = trim($value);
}
$resp = $this->jar->fromArray($data, $base_url);
return $resp;
} catch (\Exception $e) {
$this->output->writeln('驗證使用者Cookies發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 獲取產品的資訊
* @return array
*/
private function getProduct()
{
try {
fwrite(STDOUT, '請輸入你的產品的URL路徑:');
$url = trim(fgets(STDIN));
$args = explode('/', $url);
$product_id = array_pop($args);
$sku = $this->getProductSku($product_id);
$this->output->writeln("-------------獲取產品SKU資訊成功-------------");
return $sku;
} catch (\Exception $e) {
$this->output->writeln('獲取產品資訊發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 獲取產品的sku 列表
* @param $product_id
* @return array
*/
private function getProductSku($product_id)
{
try {
$skuInfoUrl = "https://mall.fcbox.com/item/skuInfo?itemCode={$product_id}&province=&city=&area=&latitude=&longitude=";
$response = $this->client->request('GET', $skuInfoUrl, [
'timeout' => 3.14,
'verify' => false,
]);
$content = $response->getBody()->getContents(); //獲取響應體,物件
$content = json_decode($content, JSON_UNESCAPED_UNICODE);
$skus = [];
foreach ($content['data']['skus'] as $sku) {
$item['skuCode'] = $sku['skuCode'];
$item['stock'] = $sku['stock'];
$item['salePrice'] = $sku['salePrice'];
$item['saleSiteId'] = $sku['saleSiteId'];
$item['saleSiteType'] = $sku['saleSiteType'];
$item['itemCode'] = $sku['itemCode'];
$item['description'] = $sku['saleAttributes'];
$item['activityPrice'] = $sku['activityPrice'];
$skus[] = $item;
}
return $skus;
} catch (\Exception $e) {
$this->output->writeln('獲取產品SKU發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 獲取cookies 的賬號資訊以及個人地址
* @param $cookies
* @return mixed
*/
public function getUserInfo()
{
try {
// 個人中心
$centerUrl = 'https://mall.fcbox.com/member/center?';
$response = $this->client->request('GET', $centerUrl, [
'timeout' => 3.14,
'verify' => false,
'cookies' => $this->cookies,
// 'debug' => true, //除錯
]);
$content = $response->getBody()->getContents(); //獲取響應體,物件
$content = json_decode($content, JSON_UNESCAPED_UNICODE);
$this->output->writeln("-------獲取使用者資訊成功-------");
return $content['data'];
} catch (\Exception $e) {
$this->output->writeln('獲取使用者資訊發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 獲取使用者地址
*/
private function getUserAddress()
{
try {
$url = 'https://mall.fcbox.com/addressBook/list';
$response = $this->client->request('POST', $url, [
'timeout' => 3.14,
'verify' => false,
'cookies' => $this->cookies,
// 'debug' => true, //除錯
]);
$content = $response->getBody()->getContents(); //獲取響應體,物件
$centerContent = json_decode($content, JSON_UNESCAPED_UNICODE);
$this->output->writeln("-------獲取使用者地址成功-------");
return $centerContent['data'];
} catch (\Exception $e) {
$this->output->writeln('獲取使用者地址列表發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 設定需要購買的數量
* @return int
*/
private function getInputCount()
{
try {
$result = false;
do {
fwrite(STDOUT, '請輸入你需要購買的數量:');
$count = trim(fgets(STDIN));
if (is_numeric($count) && $count != 0 && $count != '') {
$result = true;
$this->count = intval($count);
return intval($count);
}
$this->output->writeln('請輸入一個正確的數字');
} while ($result == false);
} catch (\Exception $e) {
$this->output->writeln('搶購數量發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 選擇使用者的地址
* @return int|string
*/
private function selectUserAddress()
{
try {
$this->output->writeln('-------------使用者地址列表-------------');
foreach ($this->address as $key => $address) {
$item = [];
if ($address['isDefault'] == 1) $item[] = '《預設地址》';
unset($address['id']);
unset($address['latitude']);
unset($address['longitude']);
unset($address['source']);
unset($address['uicUserId']);
unset($address['is_default']);
foreach ($address as $name => $value) {
$item[] = $value;
}
$item = implode(' ', $item);
$this->output->writeln("地址-序號:{$key} -> {$item}");
}
// 驗證輸入的序號是否合法
$result = false;
do {
fwrite(STDOUT, '請選擇使用者序號的地址:');
$input = trim(fgets(STDIN));
// 非法輸入
if ($input > count($this->address) || $input < 0) continue;
$result = true;
$this->current_address = $input;
return $this->current_address;
} while ($result == false);
} catch (\Exception $e) {
$this->output->writeln('選擇使用者地址發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 選擇產品的sku
* @return int|string
*/
private function selectProductSku()
{
try {
$this->output->writeln('-------------SKU列表-------------');
$lists[] = [
'序號', 'SKU', '庫存', '價格', '描述',
];
foreach ($this->skus as $key => $sku) {
$item = [];
$item['key'] = $key; //sku
$item['skuCode'] = $sku['skuCode']; //sku
$item['stock'] = $sku['stock']; // 庫存
$item['salePrice'] = $sku['salePrice'] / 100; // 價格
foreach ($sku['description'] as $description) {
$item['description'] = implode(',', [$description['key'], $description['value']]); // sku 描述
}
$lists[] = $item;
}
foreach ($lists as $rows) {
foreach ($rows as $row) {
$this->output->write($row . "\t\t");
}
$this->output->write("\n");
}
// 驗證輸入的序號是否合法
$result = false;
do {
fwrite(STDOUT, '請選擇產品SKU序號的序號:');
$input = trim(fgets(STDIN));
// 非法輸入
if ($input > count($this->address) || $input < 0) continue;
$result = true;
$this->current_sku = $input;
return $this->current_sku;
} while ($result == false);
} catch (\Exception $e) {
$this->output->writeln('發生錯誤,程式即將退出,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 設定開始搶購的時間
* @return false|int
*/
private function getInputStartTime()
{
try {
$result = false;
do {
fwrite(STDOUT, '請輸入開始搶購的時間:');
$time = trim(fgets(STDIN));
$time = strtotime($time);
if (time() < $time) {
$result = true;
$this->start_time = $time;
return $time;
}
$this->output->writeln('請輸入一個正確的時間範圍');
} while ($result == false);
} catch (\Exception $e) {
$this->output->writeln('搶購開始時間發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 生成提交訂單的order
* @return mixed
*/
private function getConfirmToken()
{
// addressId: 2891060
//itemReqStr: [{"count":1,"saleSiteId":403,"skuCode":"127025488939648"}]
try {
$this->output->writeln('-------------正在生成訂單Token中-------------');
$url = 'https://mall.fcbox.com/order/confirm';
$response = $this->client->request('POST', $url, [
'timeout' => 3.14,
'verify' => false,
'cookies' => $this->cookies,
'form_params' => [
'addressId' => $this->address[$this->current_address]['id'],
'itemReqStr' => json_encode([[
'count' => $this->count,
'saleSiteId' => $this->skus[$this->current_sku]['saleSiteId'],
'skuCode' => $this->skus[$this->current_sku]['skuCode'],
]]),
]
]);
$content = $response->getBody()->getContents();
$content = json_decode($content, JSON_UNESCAPED_UNICODE);
$token = $content['data']['orderToken'];
$this->orderToken = $token;
$this->output->writeln("-------------訂單Token生成成功,Token值為:{$token}-------------");
return $token;
} catch (\Exception $e) {
$this->output->writeln('生成訂單Token發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
/**
* 提交訂單資訊
*/
private function submitOrder()
{
try {
$this->output->writeln('-------------提交訂單中-------------');
$url = 'https://mall.fcbox.com/order/submit';
$data['token'] = $this->orderToken;
$data['addressId'] = $this->address[$this->current_address]['id'];
$data['deliveryRemark'] = $this->orderToken;
$data['coupons'] = [];
$data['orderFee'] = $this->skus[$this->current_sku]['activityPrice']; //價格
$data['orderFrom'] = 1;
$data['itemList'] = [
[
'skuCode' => $this->skus[$this->current_sku]['skuCode'],
'siteId' => $this->skus[$this->current_sku]['saleSiteId'],
'count' => $this->count,
'remark' => '[]',
]
];
$data['siteRemarks'] = [
[
'siteId' => 13,
'remark' => '',
]
];
$response = $this->client->request('POST', $url, [
'timeout' => 3.14,
'verify' => false,
'cookies' => $this->cookies,
'json' => $data,
]);
$content = $response->getBody()->getContents();
$content = json_decode($content, JSON_UNESCAPED_UNICODE);
$this->output->writeln("-------------提交訂單完成,當前訂單狀態:{$content['msg']}-------------");
} catch (\Exception $e) {
$this->output->writeln('提交訂單發生錯誤,錯誤原因:' . $e->getMessage());
exit;
}
}
}
相關文章
- 我讓chatGPT用PHP寫一個MVC框架,不僅寫出來,還能跑!ChatGPTPHPMVC框架
- 讓我們用gulp寫個前端腳手架前端
- 用php編寫我的第一段程式碼:hello worldPHP
- 讓我們寫一個 Win32 文字編輯器吧 - 1. 簡介Win32
- 使用PHP指令碼來寫Daemon程式PHP指令碼
- 編寫一個小指令碼來啟動和關閉sybase ASE指令碼
- 用Jmeter編寫一個較複雜的測試指令碼JMeter指令碼
- 【緊急情況】:回宿舍放下書包的我,花了20分鐘敲了一個搶購指令碼指令碼
- Blazor一個簡單的示例讓我們來起飛Blazor
- 從0到1編寫一個指令碼引擎指令碼
- 我們一起來玩轉 Grep 指令
- 商品搶購倒數計時效果程式碼例項
- 讓我們寫一個 Win32 文字編輯器吧 - 2. 計劃和顯示Win32
- 一個shell 指令碼用來同步表用的指令碼
- 從0到1編寫一個JS指令碼引擎JS指令碼
- 一次慘痛教訓讓我寫了個Windows定期備份檔案指令碼Windows指令碼
- 我們來動手編寫計算機模擬器計算機
- 讓我們構建一個Swift.ArraySwift
- 愛奇藝編碼團隊:我們讓AV1編碼速度提升5倍
- 讓我們來搞崩 Cocoa 吧(黑暗程式碼)
- gdb指令碼編寫指令碼
- Shell 指令碼編寫指令碼
- 學習Koa – 讓我們寫一箇中介軟體
- 學習Koa - 讓我們寫一箇中介軟體
- 面試官讓我5分鐘內寫一個搶紅包程式,我和他說了半小時原理!面試
- 在Linux中,如何編寫一個指令碼來自動執行日常任務?Linux指令碼
- 編寫 SQL 查詢:讓我們從基礎知識開始SQL
- 大家快來嚐嚐鮮 轉<用 curl 和 scsh 編寫 web 指令碼>(轉)Web指令碼
- 全都是外國人寫的防火牆指令碼,我也來寫一個,希望大家跟我一塊做好(轉)防火牆指令碼
- 讓我們來做一個屬於自己的瀏覽器主頁吧!瀏覽器
- [譯] 為什麼我用 JavaScript 來編寫 CSSJavaScriptCSS
- 油猴指令碼編寫指令碼
- 編寫git指令碼.shGit指令碼
- Python版中秋佳節月餅搶購指令碼Python指令碼
- [譯] 使用 Vue 編寫一個長按指令Vue
- 接上節我們來實戰操刀一個簡單的 PHP 守護程式!PHP
- 用指令碼來講一個技術生活的故事指令碼
- 讓我們來深入淺出block吧BloC