2022-08-06 15:25:13 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Services\Business\KuaiTuanTuan;
|
|
|
|
|
|
|
|
|
|
|
|
use App\Models\BusinessGoodsSku;
|
|
|
|
|
|
use App\Models\GoodsSku;
|
2022-10-24 09:44:43 +08:00
|
|
|
|
use App\Models\GroupGoods;
|
2023-07-15 18:18:22 +08:00
|
|
|
|
use App\Models\Shop;
|
|
|
|
|
|
use App\Models\ShopShip;
|
2022-08-06 15:25:13 +08:00
|
|
|
|
use App\Services\Business\BusinessClient;
|
2022-10-24 09:44:43 +08:00
|
|
|
|
use App\Models\Groups as GroupsModel;
|
2022-10-24 14:29:58 +08:00
|
|
|
|
use Illuminate\Support\Facades\Log;
|
2022-08-06 15:25:13 +08:00
|
|
|
|
|
|
|
|
|
|
class KuaiTuanTuan extends BusinessClient
|
|
|
|
|
|
{
|
|
|
|
|
|
// 所有的请求和响应数据编码皆为utf-8格式,url里的所有参数值请做urlencode编码。
|
|
|
|
|
|
// 如果请求的content-type是 application/x-www-form-urlencoded,所有参数值也做urlencode编码;
|
|
|
|
|
|
// 如果是multipart/form-data格式,每个表单字段的参数值无需编码,但每个表单字段的charset需要指定为utf-8
|
|
|
|
|
|
// 如果指定接口返回数据格式为JSON,请指明header头content-type: application/json
|
2022-08-08 13:27:13 +08:00
|
|
|
|
protected $clientId = '8d7ca13bc27247b6a04e08404b51dfd8';
|
2022-08-06 15:25:13 +08:00
|
|
|
|
|
2022-08-08 13:27:13 +08:00
|
|
|
|
protected $clientSecret = '4478bc82dc1e1f68fe06c9f2bc683f1dcb3e6d83';
|
2022-08-06 15:25:13 +08:00
|
|
|
|
|
|
|
|
|
|
protected $publicParams = [
|
|
|
|
|
|
'type' => '',
|
|
|
|
|
|
'client_id' => '',
|
|
|
|
|
|
'access_token' => '', // 非必填,通过code获取的access_token
|
|
|
|
|
|
'timestamp' => '',
|
|
|
|
|
|
'data_type' => '', // 非必填,响应格式,即返回数据的格式,JSON或者XML(二选一),默认JSON,注意是大写
|
|
|
|
|
|
'version' => '', // 非必填, API协议版本号,默认为V1,可不填
|
|
|
|
|
|
'sign' => ''
|
|
|
|
|
|
];
|
|
|
|
|
|
|
2023-08-22 15:26:34 +08:00
|
|
|
|
public function auth($type = 'ktt', $shipType = 'normal')
|
2022-08-06 15:25:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
$accessToken = $this->getAccessTokenWithCode();
|
2022-08-08 16:00:47 +08:00
|
|
|
|
$accessToken['scope'] = json_encode($accessToken['scope'], 256);
|
2023-07-15 18:18:22 +08:00
|
|
|
|
$accessToken['status'] = Shop::$STATUS_AUTHORIZED;
|
|
|
|
|
|
if ('ktt' === $type) {
|
|
|
|
|
|
$accessToken['pop_auth_token_create_response'] = json_encode($accessToken, 256);
|
|
|
|
|
|
$this->shop->update($accessToken);
|
|
|
|
|
|
}
|
|
|
|
|
|
if ('ship' === $type) {
|
2023-08-08 18:24:15 +08:00
|
|
|
|
unset($accessToken['r1_expires_at'], $accessToken['r1_expires_in'], $accessToken['r2_expires_at'], $accessToken['r2_expires_in'], $accessToken['w1_expires_at'], $accessToken['w1_expires_in'], $accessToken['w2_expires_at'], $accessToken['w2_expires_in'], $accessToken['request_id']);
|
2023-08-22 15:26:34 +08:00
|
|
|
|
$this->shop = ShopShip::query()->updateOrCreate(
|
|
|
|
|
|
['shop_id' => $this->shop->id, 'type' => $shipType],
|
2023-07-15 18:18:22 +08:00
|
|
|
|
$accessToken
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2022-08-06 15:25:13 +08:00
|
|
|
|
|
|
|
|
|
|
return $this->shop;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-29 14:03:58 +08:00
|
|
|
|
public function downloadGoodsListAndBind($activityNo, $title = '', $page = 1)
|
2022-08-06 15:25:13 +08:00
|
|
|
|
{
|
2023-01-29 11:29:48 +08:00
|
|
|
|
[$type, $appendParams] = Goods::downloadGoods($activityNo, $page);
|
2022-08-08 15:05:17 +08:00
|
|
|
|
$res = $this->doRequest($type, $appendParams);
|
2022-08-06 15:25:13 +08:00
|
|
|
|
$goods = $res['ktt_goods_query_list_response']['goods_list'];
|
2023-01-29 14:03:58 +08:00
|
|
|
|
$this->bindGoods($goods, $title);
|
2022-08-08 18:53:38 +08:00
|
|
|
|
$pageNum = ceil($res['ktt_goods_query_list_response']['total'] / $appendParams['size']);
|
2022-11-01 17:11:22 +08:00
|
|
|
|
if ($pageNum > $page && 60 >= $page) {
|
2023-01-29 14:03:58 +08:00
|
|
|
|
$this->downloadGoodsListAndBind($activityNo, $title, $page + 1);
|
2022-08-06 15:25:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-29 14:03:58 +08:00
|
|
|
|
public function bindGoods($goods, $title = '')
|
2022-08-06 16:38:04 +08:00
|
|
|
|
{
|
2023-01-29 14:03:58 +08:00
|
|
|
|
Goods::bindGoods($goods, $this->shop->id, $title);
|
2022-08-06 16:38:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-16 21:02:31 +08:00
|
|
|
|
public function incrQuantity($businessGoodsSku, $num, $incremental)
|
2022-08-06 15:25:13 +08:00
|
|
|
|
{
|
2022-08-17 20:50:03 +08:00
|
|
|
|
[$type, $appendParams] = Goods::incrQuantity($businessGoodsSku['goods_id'], $businessGoodsSku['sku_id'], $num, $incremental ? 1 : 2);
|
2022-08-08 15:05:17 +08:00
|
|
|
|
$this->doRequest($type, $appendParams);
|
2022-08-06 15:25:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-04 15:01:55 +08:00
|
|
|
|
public function batchIncrQuantity($businessGoodsSkus, $num, $incremental)
|
|
|
|
|
|
{
|
|
|
|
|
|
$batchAppendParams = [];
|
2024-03-23 15:13:24 +08:00
|
|
|
|
$logData = [];
|
2022-11-04 15:01:55 +08:00
|
|
|
|
foreach ($businessGoodsSkus as $businessGoodsSku) {
|
|
|
|
|
|
[$type, $appendParams] = Goods::incrQuantity($businessGoodsSku['goods_id'], $businessGoodsSku['sku_id'], $num, $incremental ? 1 : 2);
|
2024-03-23 15:13:24 +08:00
|
|
|
|
$logData[] = $appendParams;
|
2022-11-04 15:01:55 +08:00
|
|
|
|
$appendParams['type'] = $type;
|
|
|
|
|
|
$appendParams['client_id'] = $this->clientId;
|
|
|
|
|
|
$appendParams['timestamp'] = time();
|
|
|
|
|
|
$appendParams['access_token'] = $this->getShop()->access_token;
|
|
|
|
|
|
$appendParams['sign'] = $this->getSign($appendParams);
|
|
|
|
|
|
$batchAppendParams[] = $appendParams;
|
|
|
|
|
|
}
|
|
|
|
|
|
$this->batchAsyncPostRequest('https://gw-api.pinduoduo.com/api/router', $batchAppendParams);
|
2024-03-23 15:13:24 +08:00
|
|
|
|
if ($logData) {
|
|
|
|
|
|
Log::info('本次批量同步: ' . json_encode($logData, 256));
|
|
|
|
|
|
}
|
2022-11-04 15:01:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-09 10:34:36 +08:00
|
|
|
|
/**
|
2022-08-24 18:09:34 +08:00
|
|
|
|
* 下载订单
|
2022-08-09 10:34:36 +08:00
|
|
|
|
*
|
|
|
|
|
|
* @param $beginTime
|
|
|
|
|
|
* @param $endTime
|
2022-08-09 16:56:52 +08:00
|
|
|
|
* @param int $page
|
|
|
|
|
|
* @param string $downloadType
|
2022-08-11 02:13:19 +08:00
|
|
|
|
* @return void
|
2022-08-09 10:34:36 +08:00
|
|
|
|
*/
|
2022-08-11 02:13:19 +08:00
|
|
|
|
public function downloadOrdersAndSave($beginTime, $endTime, $downloadType = 'default', $page = 1)
|
2022-08-06 15:25:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
if ('increment' === $downloadType) {
|
2022-08-09 16:56:52 +08:00
|
|
|
|
[$type, $appendParams] = Order::downloadIncrementOrders($beginTime, $endTime, $page);
|
2022-08-10 16:39:25 +08:00
|
|
|
|
$responseName = 'ktt_increment_order_query_response';
|
2022-08-06 15:25:13 +08:00
|
|
|
|
} else {
|
2022-08-09 16:56:52 +08:00
|
|
|
|
[$type, $appendParams] = Order::downloadOrders($beginTime, $endTime, $page);
|
2022-08-10 16:39:25 +08:00
|
|
|
|
$responseName = 'ktt_order_list_response';
|
2022-08-06 15:25:13 +08:00
|
|
|
|
}
|
2022-08-08 15:05:17 +08:00
|
|
|
|
$res = $this->doRequest($type, $appendParams);
|
2023-04-05 18:59:46 +08:00
|
|
|
|
if (!isset($res[$responseName])) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-08-10 16:39:25 +08:00
|
|
|
|
$this->saveOrders($res[$responseName]['order_list']);
|
|
|
|
|
|
$pageNum = ceil($res[$responseName]['total_count'] / $appendParams['page_size']);
|
2022-08-24 18:09:34 +08:00
|
|
|
|
if ($pageNum > $page && 30 >= $page) {
|
|
|
|
|
|
$this->downloadOrdersAndSave($beginTime, $endTime, $downloadType, $page + 1);
|
2022-08-09 16:56:52 +08:00
|
|
|
|
}
|
2022-08-06 15:25:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-04-04 19:06:15 +08:00
|
|
|
|
public function getOrderInfo($orderSn)
|
|
|
|
|
|
{
|
|
|
|
|
|
[$type, $appendParams] = Order::getOrderInfo($orderSn);
|
|
|
|
|
|
|
|
|
|
|
|
return $this->doRequest($type, $appendParams);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-06 16:38:04 +08:00
|
|
|
|
protected function getAccessTokenWithCode()
|
|
|
|
|
|
{
|
|
|
|
|
|
$type = 'pdd.pop.auth.token.create';
|
|
|
|
|
|
$res = $this->doRequest($type, ['code' => $this->code]);
|
|
|
|
|
|
|
|
|
|
|
|
return $res['pop_auth_token_create_response'];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected function getSign($params)
|
|
|
|
|
|
{
|
2022-08-08 13:59:44 +08:00
|
|
|
|
ksort($params);
|
2022-08-06 16:38:04 +08:00
|
|
|
|
$str = '';
|
|
|
|
|
|
foreach ($params as $key => $val) {
|
|
|
|
|
|
$str .= $key . $val;
|
|
|
|
|
|
}
|
|
|
|
|
|
$str = $this->clientSecret . $str . $this->clientSecret;
|
|
|
|
|
|
|
|
|
|
|
|
return strtoupper(md5($str));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-08 14:20:54 +08:00
|
|
|
|
public function doRequest($type, $appendParams = [], $url = 'https://gw-api.pinduoduo.com/api/router')
|
2022-08-06 16:38:04 +08:00
|
|
|
|
{
|
|
|
|
|
|
$publicParams = [
|
|
|
|
|
|
'type' => $type,
|
|
|
|
|
|
'client_id' => $this->clientId,
|
|
|
|
|
|
'timestamp' => time()
|
|
|
|
|
|
];
|
|
|
|
|
|
if ('pdd.pop.auth.token.create' !== $type) {
|
2022-08-08 16:00:47 +08:00
|
|
|
|
$publicParams['access_token'] = $this->getShop()->access_token;
|
2022-08-06 16:38:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
$publicParams = array_merge($publicParams, $appendParams);
|
|
|
|
|
|
$publicParams['sign'] = $this->getSign($publicParams);
|
2022-09-01 09:56:08 +08:00
|
|
|
|
$res = $this->formDataPostRequest($url, $publicParams);
|
|
|
|
|
|
if (isset($res['error_response'])) {
|
2022-11-01 14:15:57 +08:00
|
|
|
|
// "error_msg":"业务服务错误","sub_msg":"该店铺下不存在该商品","sub_code":"11","error_code":50001
|
|
|
|
|
|
// "error_msg":"业务服务错误","sub_msg":"该SKU在快团团中设置的库存为无限库存,不支持修改库存","sub_code":"13","error_code":50001
|
|
|
|
|
|
if (50001 == $res['error_response']['error_code'] && in_array($res['error_response']['sub_code'], ['13', '11'])) {
|
|
|
|
|
|
BusinessGoodsSku::query()->where('goods_id', $appendParams['goods_id'])->where('sku_id', $appendParams['sku_id'])->update(['is_sync' => 0]);
|
|
|
|
|
|
}
|
2024-03-23 14:46:12 +08:00
|
|
|
|
Log::error(json_encode($res, 256) . $type);
|
2022-09-01 09:56:08 +08:00
|
|
|
|
}
|
2022-08-06 16:38:04 +08:00
|
|
|
|
|
2022-09-01 09:56:08 +08:00
|
|
|
|
return $res;
|
2022-08-06 16:38:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-08 18:53:38 +08:00
|
|
|
|
public function downloadGoods($skuId)
|
|
|
|
|
|
{
|
|
|
|
|
|
$goodsSku = GoodsSku::query()
|
|
|
|
|
|
->with(['goods:id,goods_code'])
|
|
|
|
|
|
->find($skuId);
|
|
|
|
|
|
$code = $goodsSku->goods->goods_code . '_' . $goodsSku->sku_code;
|
|
|
|
|
|
$business = BusinessGoodsSku::query()->where('shop_id', $this->shop->id)->where('external_sku_id', $code)->first(['goods_id', 'sku_id']);
|
|
|
|
|
|
[$type, $appendParams] = Goods::downloadSingle($business->goods_id);
|
|
|
|
|
|
$res = $this->doRequest($type, $appendParams);
|
|
|
|
|
|
$goods = $res['response']['result'];
|
|
|
|
|
|
$this->bindGoods([$goods]);
|
|
|
|
|
|
}
|
2022-08-11 02:13:19 +08:00
|
|
|
|
|
|
|
|
|
|
public function getAuthUrl($shopId, $platId)
|
|
|
|
|
|
{
|
|
|
|
|
|
$state = $shopId . '_' . $platId;
|
|
|
|
|
|
|
|
|
|
|
|
return "https://oauth.pinduoduo.com/authorize/ktt?client_id={$this->clientId}&redirect_uri={$this->redirectUri}&state={$state}";
|
|
|
|
|
|
}
|
2022-10-12 15:26:38 +08:00
|
|
|
|
|
|
|
|
|
|
public function createSku()
|
|
|
|
|
|
{
|
|
|
|
|
|
[$type, $appendParams] = Goods::createSpec();
|
|
|
|
|
|
|
|
|
|
|
|
return $this->doRequest($type, $appendParams);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-10-24 09:44:43 +08:00
|
|
|
|
public function createGroup($localGroupId)
|
2022-10-12 15:26:38 +08:00
|
|
|
|
{
|
2022-10-25 10:47:36 +08:00
|
|
|
|
[$type, $appendParams] = Groups::createGroup($localGroupId, $this->shop);
|
2022-10-24 09:44:43 +08:00
|
|
|
|
$res = $this->doRequest($type, $appendParams);
|
|
|
|
|
|
if (isset($res['response']['success'])) {
|
2022-10-25 13:57:57 +08:00
|
|
|
|
$group = GroupsModel::query()->where('parent_id', $localGroupId)->where('shop_id', $this->shop->id)->first();
|
2022-10-24 09:44:43 +08:00
|
|
|
|
$group->activity_no = $res['response']['activity_no'];
|
|
|
|
|
|
$group->save();
|
|
|
|
|
|
}
|
2022-10-12 15:26:38 +08:00
|
|
|
|
|
2022-10-24 09:44:43 +08:00
|
|
|
|
return $res;
|
2022-10-12 15:26:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-10-24 09:44:43 +08:00
|
|
|
|
public function queryGroupStatus($localGroupId)
|
2022-10-12 15:26:38 +08:00
|
|
|
|
{
|
2022-10-25 10:47:36 +08:00
|
|
|
|
[$type, $appendParams] = Groups::queryGroupStatus($localGroupId, $this->shop->id);
|
2022-10-24 09:44:43 +08:00
|
|
|
|
$res = $this->doRequest($type, $appendParams);
|
|
|
|
|
|
if (isset($res['response'])) {
|
2022-10-25 10:47:36 +08:00
|
|
|
|
$group = GroupsModel::query()->where('parent_id', $localGroupId)->where('shop_id', $this->shop->id)->first();
|
2022-10-24 21:30:23 +08:00
|
|
|
|
$group->create_status = $res['response']['status'];
|
|
|
|
|
|
if (1 === $res['response']['status']) {
|
|
|
|
|
|
$group->qr_code_url = $res['response']['qr_code_url'];
|
2022-10-25 10:47:36 +08:00
|
|
|
|
// foreach ($res['response']['goods_list'] as $goods) {
|
|
|
|
|
|
// $groupGoods = GroupGoods::query()
|
|
|
|
|
|
// ->where('group_id', $localGroupId)
|
|
|
|
|
|
// ->where('external_sku_id', $goods['sku_list'][0]['external_sku_id'])
|
|
|
|
|
|
// ->first();
|
|
|
|
|
|
// $groupGoods->ktt_goods_id = $goods['goods_id'];
|
|
|
|
|
|
// $groupGoods->ktt_sku_id = $goods['sku_list'][0]['sku_id'];
|
|
|
|
|
|
// $groupGoods->save();
|
|
|
|
|
|
// }
|
2022-10-24 21:30:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (2 === $res['response']['status']) {
|
|
|
|
|
|
$group->error_msg = $res['response']['error_msg'];
|
2022-10-24 09:44:43 +08:00
|
|
|
|
}
|
2022-10-24 21:30:23 +08:00
|
|
|
|
$group->save();
|
2022-10-24 09:44:43 +08:00
|
|
|
|
}
|
2022-10-12 15:26:38 +08:00
|
|
|
|
|
2022-10-24 09:44:43 +08:00
|
|
|
|
return $res;
|
2022-10-12 15:26:38 +08:00
|
|
|
|
}
|
2022-10-24 15:32:44 +08:00
|
|
|
|
|
|
|
|
|
|
public function queryGroup()
|
|
|
|
|
|
{
|
|
|
|
|
|
[$type, $appendParams] = Groups::queryGroup();
|
2022-10-24 21:30:23 +08:00
|
|
|
|
$res = $this->doRequest($type, $appendParams);
|
2023-01-29 11:29:48 +08:00
|
|
|
|
// if (isset($res['ktt_group_query_list_response'])) {
|
|
|
|
|
|
// foreach ($res['ktt_group_query_list_response']['activity_list'] as $activity) {
|
|
|
|
|
|
// $group = GroupsModel::query()->where('activity_no', $activity['activity_no'])->first();
|
|
|
|
|
|
// if ($group) {
|
|
|
|
|
|
// $group->is_help_sell = $activity[''];
|
|
|
|
|
|
// $group->status = $activity[''];
|
|
|
|
|
|
// $group->save();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
2022-10-24 15:32:44 +08:00
|
|
|
|
|
2022-10-24 21:30:23 +08:00
|
|
|
|
return $res;
|
2022-10-24 15:32:44 +08:00
|
|
|
|
}
|
2022-10-26 10:50:43 +08:00
|
|
|
|
|
|
|
|
|
|
public function uploadImage($url)
|
|
|
|
|
|
{
|
|
|
|
|
|
[$type, $appendParams] = Goods::uploadImage($url);
|
|
|
|
|
|
|
|
|
|
|
|
return $this->doRequest($type, $appendParams);
|
|
|
|
|
|
}
|
2023-08-28 13:42:27 +08:00
|
|
|
|
|
|
|
|
|
|
public function createLogistic($orderSn, $waybillNo)
|
|
|
|
|
|
{
|
2023-08-28 18:09:32 +08:00
|
|
|
|
[$type, $appendParams] = Order::createOrderLogistic($orderSn, $waybillNo);
|
|
|
|
|
|
|
|
|
|
|
|
return $this->doRequest($type, $appendParams);
|
2023-08-28 13:42:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function cancelLogistic($orderSn, $waybillNo)
|
|
|
|
|
|
{
|
2023-08-28 18:09:32 +08:00
|
|
|
|
[$type, $appendParams] = Order::deleteOrderLogistic($orderSn, $waybillNo);
|
|
|
|
|
|
|
|
|
|
|
|
return $this->doRequest($type, $appendParams);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function getLogisticsCompanies()
|
|
|
|
|
|
{
|
|
|
|
|
|
[$type, $appendParams] = Order::getLogisticsCompanies();
|
|
|
|
|
|
|
|
|
|
|
|
return $this->doRequest($type, $appendParams);
|
2023-08-28 13:42:27 +08:00
|
|
|
|
}
|
2022-08-06 15:25:13 +08:00
|
|
|
|
}
|