2024-06-24 11:52:30 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace app\server;
|
|
|
|
|
|
|
|
|
|
use app\model\Orders;
|
|
|
|
|
use Exception;
|
|
|
|
|
use support\Log;
|
|
|
|
|
use support\Redis;
|
|
|
|
|
use think\db\exception\DataNotFoundException;
|
|
|
|
|
use think\db\exception\DbException;
|
|
|
|
|
use think\db\exception\ModelNotFoundException;
|
|
|
|
|
|
|
|
|
|
class Douyin
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
private $cookie = '';
|
|
|
|
|
private $id = '';
|
2024-08-19 20:20:17 +08:00
|
|
|
|
private $os = '';
|
2024-06-24 11:52:30 +08:00
|
|
|
|
private $token = '';
|
2024-09-20 10:39:29 +08:00
|
|
|
|
private $tryTimes = 0;
|
2024-06-24 11:52:30 +08:00
|
|
|
|
private $gate = 'https://life.douyin.com';
|
2024-07-28 16:50:38 +08:00
|
|
|
|
public $totalPage = 6;
|
2024-08-20 10:27:30 +08:00
|
|
|
|
private $keywords = ['泰国', '普吉岛', '西藏', 'S', 'G', 's', 'g'];
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
2024-08-16 21:12:33 +08:00
|
|
|
|
public function __construct($os = 3)
|
2024-06-24 11:52:30 +08:00
|
|
|
|
{
|
|
|
|
|
$this->cookie = $this->_cookie();
|
|
|
|
|
$this->id = $this->_id();
|
2024-08-19 20:20:17 +08:00
|
|
|
|
$this->os = $os;
|
2024-08-16 22:03:11 +08:00
|
|
|
|
$this->token = $this->_token('', $os);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function login()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function voucher($check_sn)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//https://lvyou.meituan.com/nib/trade/b/voucher/show?voucherCode=130949862550187&yodaReady=h5&csecplatform=4&csecversion=2.4.0
|
|
|
|
|
|
|
|
|
|
//https://lvyou.meituan.com/nib/trade/b/voucher/show?voucherCode=130949862550187&yodaReady=h5&csecplatform=4&csecversion=2.4.0
|
|
|
|
|
$res = $this->_curl('/nib/trade/b/voucher/show', [
|
|
|
|
|
'voucherCode' => $check_sn,
|
|
|
|
|
'yodaReady' => 'h5',
|
|
|
|
|
'csecplatform' => '4',
|
|
|
|
|
'csecversion' => '2.4.0'
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
return $res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*public function get($page, $start = null, $end = null, $orderId = '')
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (empty($start) || empty($end)) {
|
|
|
|
|
$start = date('Y-m-d 00:00:00');
|
|
|
|
|
$end = date('Y-m-d 23:59:59');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$start = strtotime($start) * 1000;
|
|
|
|
|
$end = strtotime($end) * 1000 + 999;
|
|
|
|
|
|
|
|
|
|
if ($start < strtotime('2024-05-23') * 1000) {
|
|
|
|
|
$this->totalPage = 1;
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$_list = [];
|
|
|
|
|
foreach (array_keys(Orders::DouyinStatus) as $status) {
|
|
|
|
|
|
|
|
|
|
$params = [
|
|
|
|
|
'page_index' => $page,
|
|
|
|
|
'page_size' => 20,
|
|
|
|
|
'status' => $status,
|
|
|
|
|
'order_id' => '',
|
|
|
|
|
'sku_name' => '',
|
|
|
|
|
'last_phone' => '',
|
|
|
|
|
'category' => [
|
|
|
|
|
"third_category_list" => []
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$list = $this->_curl('/life/trip/v2/travel_agency/book/search?root_life_account_id='.$this->_id(), $params, 'POST');
|
|
|
|
|
if (empty($list) || $list->status_code != 0) {
|
|
|
|
|
throw new \Exception("抖音拉单失败,Err:" . json_encode($list));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($list && $list->status_code == 0 && !empty($list->order_list)) {
|
|
|
|
|
foreach ($list->order_list as $order) {
|
|
|
|
|
if (empty($cert)) {
|
|
|
|
|
$cert = $this->_cert($order->order_info->order_id);
|
|
|
|
|
if (empty($cert)) {
|
|
|
|
|
throw new \Exception("抖音拉单{$order->order_info->order_id}详情获取失败");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$item = new Orders();
|
|
|
|
|
$item->os = 3;
|
|
|
|
|
$item->sn = $order->order_info->order_id;
|
|
|
|
|
$item->product_id = $order->order_info->product_id;
|
|
|
|
|
$item->product_name = $order->order_info->product_name;
|
|
|
|
|
$item->category_id = $order->order_info->product_sub_type;
|
|
|
|
|
$item->create_at = $order->order_info->pay_time * 1000;
|
|
|
|
|
$item->mobile = $order->order_info->buyer_phone;
|
|
|
|
|
$item->travel_date = $order->book_info->book_start_date ?? null;
|
|
|
|
|
$item->unit_price = $order->order_info->pay_amount;
|
|
|
|
|
$item->total_price = $order->order_info->pay_amount;
|
|
|
|
|
$item->actual_price = $order->order_info->pay_amount;
|
|
|
|
|
$item->quantity = $order->book_child_info->rec_person_num;
|
|
|
|
|
$item->order_status = $status;
|
|
|
|
|
$item->asset_status = $cert->status ?? 0;
|
|
|
|
|
$item->category_desc = $order->order_info->sku_category_name;
|
|
|
|
|
$item->asset_price = $cert->status == 2 || $cert->status == 5 ? $cert->amount->verify_amount : 0;
|
|
|
|
|
//抖音的核销金额需要查核销订单
|
|
|
|
|
|
|
|
|
|
if ($item->create_at < strtotime('2024-05-23') * 1000) {
|
|
|
|
|
$this->totalPage = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//if(mb_strrpos($item->product_name, "S") === false) continue;
|
|
|
|
|
if (!(mb_strrpos($item->product_name, "S") || mb_strrpos($item->product_name, "G"))) continue;
|
|
|
|
|
|
|
|
|
|
$_list[] = $item;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $_list; //返回半成品
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @throws ModelNotFoundException
|
|
|
|
|
* @throws DataNotFoundException
|
|
|
|
|
* @throws DbException
|
|
|
|
|
* @throws Exception
|
|
|
|
|
*/
|
2024-08-20 14:39:11 +08:00
|
|
|
|
public function get($page, $start = null, $end = null, $orderId = '')
|
2024-06-24 11:52:30 +08:00
|
|
|
|
{
|
|
|
|
|
if (empty($start) || empty($end)) {
|
|
|
|
|
$start = date('Y-m-d 00:00:00');
|
|
|
|
|
$end = date('Y-m-d 23:59:59');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$start = strtotime($start);
|
|
|
|
|
$end = strtotime($end);
|
|
|
|
|
|
2024-07-28 17:05:04 +08:00
|
|
|
|
// if ($start < strtotime('2024-05-22')) {
|
|
|
|
|
// $this->totalPage = 1;
|
|
|
|
|
// return [];
|
|
|
|
|
// }
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
|
|
|
|
if ($orderId) {
|
|
|
|
|
$start = $end = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$_list = [];
|
2024-08-20 14:39:11 +08:00
|
|
|
|
$list = $this->_certificateList($start, $end, $page, $orderId);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
if (empty($list->data->list) || $list->status_code !== 0) {
|
|
|
|
|
$this->totalPage = 1;
|
|
|
|
|
return $_list;
|
|
|
|
|
}
|
2024-09-05 10:55:45 +08:00
|
|
|
|
Log::info(date('Y-m-d', $start) . '--' . date('Y-m-d', $end) . " 抖音 page:{$page} total_count:" . $list->data->pagination->total_count . " page_count:" . $list->data->pagination->page_count );
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
|
|
|
|
foreach ($list->data->list as $order) {
|
2024-08-20 09:26:37 +08:00
|
|
|
|
Log::info("抖音 订单号:{$order->order_id} \n\n");
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
|
|
|
|
$orderDetail = $this->_orderDetail($order->order_id, $order->status);
|
|
|
|
|
if (empty($orderDetail)) {
|
2024-08-20 10:17:34 +08:00
|
|
|
|
Log::info("抖音 订单详情拉取失败:{$order->order_id}");
|
2024-06-24 11:52:30 +08:00
|
|
|
|
throw new Exception("抖音拉单{$order->order_id}详情获取失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$item = new Orders();
|
2024-08-20 14:39:11 +08:00
|
|
|
|
$item->os = $this->os;
|
2024-06-24 11:52:30 +08:00
|
|
|
|
$item->sn = $order->order_id;
|
|
|
|
|
$item->product_id = $order->sku->sku_id;
|
|
|
|
|
$item->product_name = $order->sku->title;
|
|
|
|
|
$item->category_id = $order->product_sub_type;
|
|
|
|
|
$item->create_at = $order->pay_time * 1000;
|
|
|
|
|
$item->mobile = $orderDetail->order_info->buyer_phone ?? null;
|
|
|
|
|
$item->travel_date = $orderDetail->book_info->book_start_date ?? null;
|
|
|
|
|
$item->unit_price = $order->amount->pay_amount;
|
|
|
|
|
$item->total_price = $order->amount->pay_amount;
|
|
|
|
|
$item->actual_price = $order->amount->pay_amount;
|
|
|
|
|
$item->quantity = $orderDetail->book_child_info->rec_person_num ?? null;
|
|
|
|
|
$item->order_status = $order->status;
|
|
|
|
|
$item->asset_status = $order->status ?? 0;
|
|
|
|
|
$item->category_desc = $order->sku->title;
|
|
|
|
|
$item->asset_price = $order->amount->verify_amount ?? 0;
|
2024-10-15 15:06:00 +08:00
|
|
|
|
$item->is_refunded = $item->order_status == 4 ? 1 : 0; // 是否已退款(1-已退款,0-未退款)
|
2024-06-24 11:52:30 +08:00
|
|
|
|
//抖音的核销金额需要查核销订单
|
|
|
|
|
if ($item->create_at < strtotime('2024-05-22') * 1000) {
|
|
|
|
|
$this->totalPage = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-28 17:12:34 +08:00
|
|
|
|
// $this->totalPage = intval($list->data->pagination->total_count / $list->data->pagination->page_count);
|
|
|
|
|
// if (($list->data->pagination->total_count % $list->data->pagination->page_count) > 0) {
|
|
|
|
|
// $this->totalPage += 1;
|
|
|
|
|
// }
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
|
|
|
|
//if(mb_strrpos($item->product_name, "S") === false) continue; G 达人 S 自己
|
2024-07-15 13:44:21 +08:00
|
|
|
|
// if (!(mb_strrpos($item->product_name, "S") || mb_strrpos($item->product_name, "G") || mb_strrpos($item->product_name, "甄"))) continue;
|
2024-08-16 21:12:33 +08:00
|
|
|
|
|
2024-07-15 13:44:21 +08:00
|
|
|
|
$kw_match = false;
|
|
|
|
|
|
|
|
|
|
foreach ($this->keywords as $kw) {
|
|
|
|
|
if (mb_strpos($item->product_name, $kw) !== false) {
|
|
|
|
|
$kw_match = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-20 10:27:30 +08:00
|
|
|
|
if ($this->os == 3 && !$kw_match) {
|
2024-07-15 13:44:21 +08:00
|
|
|
|
printf("skip order: %s %s\n", $item->sn, $item->product_name);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
|
|
|
|
$_list[] = $item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $_list; //返回半成品
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @throws Exception
|
|
|
|
|
*/
|
2024-08-20 14:39:11 +08:00
|
|
|
|
public function _certificateList($start, $end, $page, $orderId)
|
2024-06-24 11:52:30 +08:00
|
|
|
|
{
|
|
|
|
|
$params = [
|
|
|
|
|
"filter" => [
|
|
|
|
|
"start_time" => $start,//开始时间
|
|
|
|
|
"end_time" => $end,//结束时间 时间范围限定一个月
|
|
|
|
|
"is_market" => false,//必带
|
|
|
|
|
/*"status" => 1,//不传 全部,1未核销 2已核销 3申请退款中 4已退款 5部分核销
|
|
|
|
|
"product_option" => [],// 1团购/代金券 13预售券 15次卡 18通兑券/品 26有价券包 1303日历票 1305日历房 1306演出预订 1309日历品 2201团购|线上约
|
|
|
|
|
"is_combo_product" => true,//是否组合品
|
|
|
|
|
"order_id" => "1061241582949143669",//订单号
|
|
|
|
|
"sku_id" => "7379541565490675752" //产品ID*/
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
if ($orderId) {
|
|
|
|
|
$params['filter']['order_id'] = $orderId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Log::error('===_certificateList查询page='.$page.'时间:'.date('Y-m-d H:i:s',$start).'--'.date('Y-m-d H:i:s',$end).'====');
|
|
|
|
|
$this->_getRetriesLock();
|
|
|
|
|
|
2024-08-20 14:39:11 +08:00
|
|
|
|
$list = $this->_curl("/life/trip/fulfilment/v1/query/certificate_list?end_time={$end}&page_index={$page}&page_size=50&start_time={$start}&root_life_account_id=" . $this->_id(), $params, 'POST');
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
|
|
|
|
if (empty($list) || $list->status_code != 0) {
|
|
|
|
|
$this->_getRetriesLock();
|
2024-08-20 14:39:11 +08:00
|
|
|
|
$list = $this->_curl("/life/trip/fulfilment/v1/query/certificate_list?end_time={$end}&page_index={$page}&page_size=50&start_time={$start}&root_life_account_id=" . $this->_id(), $params, 'POST');
|
2024-06-24 11:52:30 +08:00
|
|
|
|
if (empty($list) || $list->status_code != 0) {
|
|
|
|
|
Log::error('===查询时间:' . $start . '--' . $end . '====certificate_list: ' . json_encode($list));
|
2024-11-05 14:42:06 +08:00
|
|
|
|
//throw new Exception("抖音拉单失败,Err:" . json_encode($list));
|
2024-06-24 11:52:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Log::warning('====list=====',['list'=>$list->data->pagination]);
|
|
|
|
|
return $list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function _getRetriesLock(): bool
|
|
|
|
|
{
|
2024-07-01 18:41:28 +08:00
|
|
|
|
$pattern = 'php webman spider:dy';
|
2024-07-02 16:15:03 +08:00
|
|
|
|
$maxProcesses = 8;
|
2024-06-29 13:40:15 +08:00
|
|
|
|
$this->_killMiddleProcesses($pattern, $maxProcesses);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
|
|
|
|
|
2024-07-01 19:21:53 +08:00
|
|
|
|
$maxRetries = 5;
|
2024-06-24 11:52:30 +08:00
|
|
|
|
$retries = 0;
|
|
|
|
|
while ($retries < $maxRetries) {
|
|
|
|
|
$back = Redis::set('SpiderMt:CertificateList:lock', time(), 'EX', 1, 'NX');
|
|
|
|
|
if ($back) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
$retries++;
|
|
|
|
|
sleep(1);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 09:55:32 +08:00
|
|
|
|
public function _killMiddleProcesses($pattern, $maxProcesses)
|
|
|
|
|
{
|
|
|
|
|
// 检查操作系统是否为 Linux
|
|
|
|
|
if (PHP_OS !== 'Linux') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取当前进程的 PID
|
|
|
|
|
$currentPid = getmypid();
|
|
|
|
|
|
|
|
|
|
// 获取进程列表
|
|
|
|
|
$command = "ps aux | grep '$pattern' | grep -v grep | grep -v '$currentPid' | awk '{print $2,$10}'";
|
|
|
|
|
$output = [];
|
|
|
|
|
exec($command, $output);
|
|
|
|
|
|
|
|
|
|
$processList = [];
|
|
|
|
|
foreach ($output as $line) {
|
|
|
|
|
list($pid, $runtime) = explode(' ', $line);
|
|
|
|
|
$runtimeParts = explode(':', $runtime);
|
|
|
|
|
$hours = intval($runtimeParts[0]);
|
|
|
|
|
$minutes = intval($runtimeParts[1]);
|
|
|
|
|
$totalMinutes = $hours * 60 + $minutes;
|
|
|
|
|
$processList[] = ['pid' => $pid, 'runtime' => $totalMinutes];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按运行时间排序
|
|
|
|
|
usort($processList, function ($a, $b) {
|
|
|
|
|
return $a['runtime'] <=> $b['runtime'];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 过滤掉当前 PID 和运行时间最短的 PID
|
|
|
|
|
if (!empty($processList)) {
|
|
|
|
|
array_shift($processList); // 移除运行时间最短的
|
|
|
|
|
}
|
|
|
|
|
$processList = array_filter($processList, function ($process) use ($currentPid) {
|
|
|
|
|
return $process['pid'] != $currentPid;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$processCount = count($processList);
|
|
|
|
|
|
|
|
|
|
// 如果进程数量超过最大值,则终止中间部分的进程
|
|
|
|
|
if ($processCount > $maxProcesses) {
|
|
|
|
|
$processesToKill = $processCount - $maxProcesses;
|
|
|
|
|
$processesKilled = 0;
|
|
|
|
|
|
|
|
|
|
// 杀死运行时间最短的进程
|
|
|
|
|
foreach ($processList as $process) {
|
|
|
|
|
if ($processesKilled >= $processesToKill) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exec("kill -9 {$process['pid']}");
|
|
|
|
|
$processesKilled++;
|
|
|
|
|
|
2024-09-05 10:55:45 +08:00
|
|
|
|
Log::info("Killed process with PID: {$process['pid']}\n");
|
2024-07-02 09:55:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($processesKilled === 0) {
|
2024-09-05 10:55:45 +08:00
|
|
|
|
Log::info( "No processes to kill.\n");
|
2024-07-02 09:55:32 +08:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2024-09-05 10:55:45 +08:00
|
|
|
|
Log::info( "Process count is not over the limit.\n");
|
2024-07-02 09:55:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 11:52:30 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 09:55:32 +08:00
|
|
|
|
|
2024-06-24 11:52:30 +08:00
|
|
|
|
public function _orderDetail($orderId = null, $status = null)
|
|
|
|
|
{
|
|
|
|
|
$orderDetail = $this->_curl("/life/trip/v2/travel_agency/book/detail", [
|
|
|
|
|
'order_id' => $orderId,
|
|
|
|
|
'book_order_id' => '',
|
|
|
|
|
'status' => $status,
|
2024-08-19 21:46:32 +08:00
|
|
|
|
'root_life_account_id' => $this->_id($this->os)
|
2024-06-24 11:52:30 +08:00
|
|
|
|
]);
|
|
|
|
|
return $orderDetail->data ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-08 09:56:28 +08:00
|
|
|
|
/**
|
|
|
|
|
* @param string $orderId
|
|
|
|
|
* @return array|null
|
|
|
|
|
*/
|
|
|
|
|
public function _orderMakeAppointmentStatus(string $orderId)
|
|
|
|
|
{
|
|
|
|
|
if (empty($orderId)) return [];
|
|
|
|
|
$params = [
|
|
|
|
|
'page_index' => 1,
|
|
|
|
|
'page_size' => 50,
|
|
|
|
|
'status' => 3,
|
|
|
|
|
'order_id' => $orderId,
|
|
|
|
|
'sku_name' => '',
|
|
|
|
|
'last_phone' => '',
|
|
|
|
|
'category' => [
|
|
|
|
|
"third_category_list" => []
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$orderBookingManagement = $this->_curl('/life/trade_view/v1/travel_agency/book/search?root_life_account_id=' . $this->_id(), $params, 'POST');
|
|
|
|
|
|
|
|
|
|
return $orderBookingManagement->order_list ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 11:52:30 +08:00
|
|
|
|
public function _orderBookingManagement(string $orderId)
|
|
|
|
|
{
|
|
|
|
|
if (empty($orderId)) return [];
|
|
|
|
|
foreach (array_keys(Orders::DouyinReservationStatus) as $status) {
|
|
|
|
|
$params = [
|
|
|
|
|
'page_index' => 1,
|
2024-07-08 19:06:29 +08:00
|
|
|
|
'page_size' => 50,
|
2024-06-24 11:52:30 +08:00
|
|
|
|
'status' => $status,
|
|
|
|
|
'order_id' => $orderId,
|
|
|
|
|
'sku_name' => '',
|
|
|
|
|
'last_phone' => '',
|
|
|
|
|
'category' => [
|
|
|
|
|
"third_category_list" => []
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$orderBookingManagement = $this->_curl('/life/trip/v2/travel_agency/book/search?root_life_account_id=' . $this->_id(), $params, 'POST');
|
|
|
|
|
if (!empty($orderBookingManagement->order_list)) break;
|
|
|
|
|
}
|
|
|
|
|
return $orderBookingManagement->order_list ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function _cert($order_id = null)
|
|
|
|
|
{
|
|
|
|
|
$info = $this->_curl('/life/trip/fulfilment/v1/query/certificate_list?root_life_account_id=' . $this->_id(), [
|
|
|
|
|
'filter' => [
|
|
|
|
|
"start_time" => strtotime(date('Y-m-d 00:00:00', time() - 5 * 24 * 3600)),
|
|
|
|
|
"end_time" => strtotime(date('Y-m-d 23:59:59')),
|
|
|
|
|
"is_market" => false,
|
|
|
|
|
"order_id" => $order_id
|
|
|
|
|
]
|
|
|
|
|
], 'POST');
|
|
|
|
|
|
|
|
|
|
if ($info->status_code != 0 || empty($info->data->list)) return [];
|
|
|
|
|
$i = $info->data->list[0];
|
|
|
|
|
if (empty($i)) return [];
|
|
|
|
|
|
|
|
|
|
$more = $this->_curl('/life/trip/fulfilment/v1/query/certificate_by_id/',
|
|
|
|
|
[
|
|
|
|
|
'certificate_id' => $i->certificate_id,
|
|
|
|
|
'root_life_account_id' => $this->_id()
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
if ($more->status_code == 0) return $more->data->certificate ?? [];
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function _cookie($data = '')
|
|
|
|
|
{
|
2024-08-19 20:47:34 +08:00
|
|
|
|
$key = 'Douyin:cookie';
|
|
|
|
|
if ($this->os == 5) {
|
|
|
|
|
$key = 'Douyin:cookie-' . $this->os;
|
|
|
|
|
}
|
|
|
|
|
if ($data) Redis::set($key, $data);
|
|
|
|
|
return Redis::get($key);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function _id($id = '')
|
|
|
|
|
{
|
2024-08-20 14:39:11 +08:00
|
|
|
|
if ($this->os == 5) {
|
2024-08-16 22:03:11 +08:00
|
|
|
|
return '7399206501845403686';
|
|
|
|
|
} else {
|
|
|
|
|
// return '7259680722519066679';
|
|
|
|
|
return Redis::get('Douyin:id');
|
|
|
|
|
}
|
2024-06-24 11:52:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected $_try = 0;
|
|
|
|
|
|
2024-08-20 14:39:11 +08:00
|
|
|
|
public function _token($token = '')
|
2024-06-24 11:52:30 +08:00
|
|
|
|
{
|
2024-08-20 14:39:11 +08:00
|
|
|
|
$dyKey = sprintf('Douyin:token-%s', $this->os);
|
2024-08-16 22:03:11 +08:00
|
|
|
|
if ($token) Redis::set($dyKey, $token, 'ex', 3600 * 24 - 50);
|
|
|
|
|
$token = Redis::get($dyKey);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
if (empty($token) && $this->_cookie()) {
|
|
|
|
|
if ($this->_try > 3) {
|
|
|
|
|
throw new Exception("cookie 失效");
|
|
|
|
|
}
|
|
|
|
|
$id = $this->_curl('/life/gate/v1/user/detail', null, 'HEAD');
|
|
|
|
|
$this->_try++;
|
|
|
|
|
if ($id) {
|
2024-08-16 22:03:11 +08:00
|
|
|
|
Redis::set($dyKey, $id, 'ex', 3600 * 24 - 50);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-16 22:03:11 +08:00
|
|
|
|
return Redis::get($dyKey);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function _curl($url, $params, $method = 'GET')
|
|
|
|
|
{
|
2024-07-11 17:16:04 +08:00
|
|
|
|
// 请求次数统计
|
|
|
|
|
$key = sprintf("Douyin:ReqiestCount:%s", date('Y-m-d'));
|
|
|
|
|
$requestCount = Redis::incrBy($key, 1);
|
|
|
|
|
if ($requestCount == 1) {
|
|
|
|
|
Redis::expire($key, 604800); // 7天
|
|
|
|
|
}
|
2024-08-19 20:20:17 +08:00
|
|
|
|
$cookiePath = sprintf(runtime_path() . '%s_dy_cookie.txt', $this->os);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
|
|
|
|
|
$http = $this->gate . $url;
|
|
|
|
|
if ($method == 'GET') {
|
|
|
|
|
$http = $http . '?' . http_build_query($params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ch = curl_init($http);
|
|
|
|
|
|
|
|
|
|
$header = [
|
|
|
|
|
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
|
|
|
|
|
'Sec-Ch-Ua-Platform: "Windows"',
|
|
|
|
|
'Host: life.douyin.com',
|
|
|
|
|
'Sec-Ch-Ua: "Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"',
|
|
|
|
|
'Accept-Language: zh-CN,zh;q=0.9',
|
|
|
|
|
'Content-type: application/json'
|
|
|
|
|
];
|
|
|
|
|
if ($method == 'GET' || $method == 'POST') {
|
2024-08-19 20:47:34 +08:00
|
|
|
|
$header[] = 'x-secsdk-csrf-token: ' . $this->_token('', $this->os);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
} else {
|
|
|
|
|
curl_setopt($ch, CURLOPT_HEADER, 1);
|
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
2024-08-19 20:20:17 +08:00
|
|
|
|
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiePath);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
$header[] = 'x-secsdk-csrf-request: 1';
|
|
|
|
|
}
|
|
|
|
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
2024-08-19 20:47:34 +08:00
|
|
|
|
curl_setopt($ch, CURLOPT_COOKIE, $this->_cookie(''));
|
2024-06-24 11:52:30 +08:00
|
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
2024-08-19 20:20:17 +08:00
|
|
|
|
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiePath);
|
2024-06-24 11:52:30 +08:00
|
|
|
|
if ($method == 'POST') {
|
|
|
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
|
|
|
|
|
}
|
|
|
|
|
$body = curl_exec($ch);
|
|
|
|
|
curl_close($ch);
|
|
|
|
|
if (!in_array($method, ['GET', 'POST'])) {
|
|
|
|
|
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
|
|
|
|
$header = substr($body, 0, $header_size);
|
|
|
|
|
$in = explode("\n", $body);
|
|
|
|
|
foreach ($in as $i) {
|
|
|
|
|
if (stripos($i, 'x-ware-csrf-token') !== false) {
|
|
|
|
|
$inn = explode(',', $i);
|
|
|
|
|
return $inn[1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2024-09-10 09:41:07 +08:00
|
|
|
|
|
|
|
|
|
$res = json_decode($body);
|
2024-09-10 09:43:28 +08:00
|
|
|
|
if (!isset($res->status_code) || $res->status_code != 0) {
|
2024-09-10 09:41:07 +08:00
|
|
|
|
Log::info("抖音 os:{$this->os} \n\n");
|
|
|
|
|
Log::info( "抖音 body:{$body} \n\n");
|
2024-11-05 14:42:06 +08:00
|
|
|
|
if ($this->tryTimes > 2) {
|
2024-09-20 10:39:29 +08:00
|
|
|
|
(new ThirdApiService())->weComNotice($this->os);
|
|
|
|
|
}
|
|
|
|
|
$this->tryTimes++;
|
2024-09-10 09:41:07 +08:00
|
|
|
|
}
|
|
|
|
|
return $res;
|
2024-06-24 11:52:30 +08:00
|
|
|
|
}
|
2024-11-05 14:42:06 +08:00
|
|
|
|
}
|