erp-backend/app/Services/OrderPullService.php
2026-04-01 17:07:04 +08:00

200 lines
7.3 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Services;
use App\Models\ShopAuth;
use App\Models\PlatformOrder;
use App\Models\Order;
use App\Models\OrderItem;
use App\Jobs\ProcessPlatformOrderJob;
use App\Services\Platform\TaobaoClient;
use App\Services\Platform\JdClient;
use App\Services\Platform\PddClient;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class OrderPullService
{
// 每批最大拉取数量
const BATCH_SIZE = 200;
// 两次拉取最小间隔(秒)
const PULL_INTERVAL = 60;
/**
* 生成内部短订单号
* 规则纯数字从1000开始每次+2四位数用完自动扩展五位数
*/
private function generateShortId(): string
{
$maxShortId = Order::where('short_id', 'REGEXP', '^[0-9]+$')
->orderByDesc('short_id')
->value('short_id');
if ($maxShortId) {
$nextId = intval($maxShortId) + 2;
} else {
$nextId = 1000;
}
return (string) $nextId;
}
/**
* 拉取订单(支持定量分批)
*
* @param string $platform
* @param string $shopId 店铺授权记录的 ID
* @param string|null $startTime
* @param string|null $endTime
* @param int $limit 最大拉取数量默认200
* @return array ['count' => 实际拉取数量, 'has_more' => 是否有更多, 'next_cursor' => 下一页cursor]
*/
public function pullOrders($platform, $shopId, $startTime = null, $endTime = null, int $limit = self::BATCH_SIZE)
{
// 限制单次最大拉取量
$limit = min($limit, self::BATCH_SIZE);
$shopAuth = ShopAuth::find($shopId);
if (!$shopAuth) {
throw new \Exception("店铺授权记录不存在ID: {$shopId}");
}
$client = $this->getPlatformClient($platform, $shopAuth);
$params = [
'start_time' => $startTime,
'end_time' => $endTime,
'limit' => $limit,
];
$result = $client->getOrders($params);
$orders = $result['orders'] ?? [];
$hasMore = $result['has_more'] ?? false;
$nextCursor = $result['next_cursor'] ?? null;
$queuedCount = 0;
foreach ($orders as $orderData) {
try {
// 每个订单放入队列异步处理
ProcessPlatformOrderJob::dispatch($platform, $shopAuth->id, $orderData);
$queuedCount++;
} catch (\Exception $e) {
Log::error('订单加入队列失败', [
'platform' => $platform,
'shop_id' => $shopAuth->id,
'order_no' => $orderData['platform_order_sn'] ?? 'unknown',
'error' => $e->getMessage(),
]);
}
}
return [
'count' => $queuedCount,
'has_more' => $hasMore,
'next_cursor' => $nextCursor,
'total_received' => count($orders),
];
}
/**
* 获取平台客户端
*/
private function getPlatformClient($platform, $shopAuth)
{
$config = [
'app_key' => $shopAuth->app_key,
'app_secret' => $shopAuth->app_secret,
'access_token' => $shopAuth->access_token,
];
return match ($platform) {
'taobao' => new TaobaoClient($config),
'jd' => new JdClient($config),
'pdd' => new PddClient($config),
default => throw new \Exception("不支持的平台: {$platform}"),
};
}
/**
* 处理单个订单(保存到数据库)
*/
public function processSingleOrder($platform, $shopAuthId, $orderData)
{
$platformOrderNo = $orderData['platform_order_sn'];
return DB::transaction(function () use ($platform, $shopAuthId, $orderData, $platformOrderNo) {
// 检查平台订单是否已存在
$exists = PlatformOrder::where([
'platform_type' => $platform,
'platform_shop_id' => $shopAuthId,
'platform_order_no' => $platformOrderNo,
])->lockForUpdate()->exists();
if ($exists) {
Log::info('订单已存在,跳过', ['order_no' => $platformOrderNo]);
return ['status' => 'skipped', 'reason' => '订单已存在'];
}
// 创建平台订单原始记录
$platformOrder = PlatformOrder::create([
'platform_type' => $platform,
'platform_shop_id' => $shopAuthId,
'platform_order_no'=> $platformOrderNo,
'order_status' => $orderData['platform_status'] ?? null,
'order_amount' => $orderData['total_amount'] ?? 0,
'buyer_name' => $orderData['buyer_nick'] ?? null,
'buyer_phone' => $orderData['receiver_phone'] ?? null,
'receiver_address' => $orderData['receiver_address'] ?? null,
'order_time' => $orderData['order_time'],
'payment_time' => $orderData['payment_time'] ?? null,
'raw_data' => json_encode($orderData),
]);
// 生成短订单号
$shortId = $this->generateShortId();
// 创建ERP主订单
$order = Order::create([
'short_id' => $shortId,
'platform_order_sn' => $platformOrderNo,
'platform' => $platform,
'shop_id' => $shopAuthId,
'shop_name' => $orderData['shop_name'] ?? '未知店铺',
'order_time' => $orderData['order_time'],
'payment_time' => $orderData['payment_time'] ?? null,
'buyer_nick' => $orderData['buyer_nick'] ?? null,
'receiver_name' => $orderData['receiver_name'] ?? null,
'receiver_phone' => $orderData['receiver_phone'] ?? null,
'receiver_address' => $orderData['receiver_address'] ?? null,
'goods_amount' => $orderData['goods_amount'] ?? 0,
'discount_amount' => $orderData['discount_amount'] ?? 0,
'freight' => $orderData['freight'] ?? 0,
'total_amount' => $orderData['total_amount'] ?? 0,
'order_status' => 'pending',
'platform_status' => $orderData['platform_status'] ?? null,
'items' => json_encode($orderData['items'] ?? []),
]);
// 创建订单商品明细
if (!empty($orderData['items'])) {
foreach ($orderData['items'] as $item) {
OrderItem::create([
'order_id' => $order->id,
'sku_id' => $item['sku_id'] ?? null,
'sku_code' => $item['sku_code'] ?? null,
'goods_name' => $item['goods_name'] ?? $item['title'] ?? null,
'quantity' => $item['num'] ?? $item['quantity'] ?? 1,
'price' => $item['price'] ?? 0,
'total' => $item['total'] ?? $item['amount'] ?? 0,
]);
}
}
return ['status' => 'success', 'order_id' => $order->id];
});
}
}