文件
xionggeshop/addons/shopro_wechat_trade/library/WxShippingService.php

164 行
5.2 KiB
PHP

<?php
namespace addons\shopro_wechat_trade\library;
use addons\shopro\model\Order;
use addons\shopro\model\OrderItem;
use think\Db;
use think\Log;
class WxShippingService
{
protected $client;
public function __construct()
{
$this->client = new WxTradeClient();
}
public function syncOrderShipping($orderId, $triggerItemId = 0)
{
if (!Bridge::isEnabled()) {
return false;
}
$order = Order::with('item')->where('id', $orderId)->find();
if (!$order || !Bridge::shouldHandleOrder($order)) {
return false;
}
$items = [];
if (!empty($order->item)) {
foreach ($order->item as $item) {
$items[] = is_object($item) && method_exists($item, 'toArray') ? $item->toArray() : (array) $item;
}
}
$triggerItem = null;
if ($triggerItemId) {
foreach ($items as $item) {
$itemArr = is_object($item) ? $item->toArray() : $item;
if (intval($itemArr['id']) === intval($triggerItemId)) {
$triggerItem = $itemArr;
break;
}
}
}
$built = WxShippingPayload::buildUploadPayload($order, $items, $triggerItem);
$payload = $built['payload'];
$logId = SyncLogger::create($order, 'shipping', $payload, $triggerItemId, $built['meta']['delivery_mode']);
try {
$response = $this->client->postJson('/wxa/sec/order/upload_shipping_info', $payload);
$this->client->callOrThrow($response, '上传发货信息');
SyncLogger::markSuccess($logId, $response, $payload);
return true;
} catch (\Exception $e) {
$response = isset($response) && is_array($response) ? $response : [];
SyncLogger::markFailed($logId, $e, $response, $payload);
Log::error('[shopro_wechat_trade] shipping sync fail order#' . $orderId . ': ' . $e->getMessage());
throw $e;
}
}
public function syncOrderConfirm($orderId)
{
if (!Bridge::isEnabled()) {
return false;
}
if (SyncLogger::hasSuccessfulConfirm($orderId)) {
return true;
}
$order = Order::with('item')->where('id', $orderId)->find();
if (!$order || !Bridge::shouldHandleOrder($order)) {
return false;
}
$pending = OrderItem::where('order_id', $orderId)
->where('dispatch_status', '<>', OrderItem::DISPATCH_STATUS_GETED)
->count();
if ($pending > 0) {
return false;
}
$payload = WxShippingPayload::buildConfirmPayload($order);
$logId = SyncLogger::create($order, 'confirm', $payload);
try {
$response = $this->client->postJson('/wxa/sec/order/notify_confirm_receive', $payload);
$this->client->callOrThrow($response, '同步确认收货');
SyncLogger::markSuccess($logId, $response, $payload);
return true;
} catch (\Exception $e) {
$response = isset($response) && is_array($response) ? $response : [];
SyncLogger::markFailed($logId, $e, $response, $payload);
Log::error('[shopro_wechat_trade] confirm sync fail order#' . $orderId . ': ' . $e->getMessage());
throw $e;
}
}
public function backfillShippedOrders($limit = 50)
{
$rows = Db::name('shopro_order')
->alias('o')
->join('shopro_order_item oi', 'oi.order_id = o.id')
->where('o.platform', 'wxMiniProgram')
->where('o.pay_type', 'in', ['wechat', 'huifu_wechat'])
->where('o.status', '>', 0)
->where('oi.dispatch_status', '>=', OrderItem::DISPATCH_STATUS_SENDED)
->group('o.id')
->order('o.id', 'desc')
->limit($limit)
->column('o.id');
$count = 0;
foreach ($rows as $orderId) {
$hasSuccess = Db::name('shopro_wechat_trade_sync')
->where('order_id', $orderId)
->where('sync_type', 'shipping')
->where('status', 'success')
->find();
if ($hasSuccess) {
continue;
}
try {
$this->syncOrderShipping($orderId);
$count++;
} catch (\Exception $e) {
// logged
}
}
return $count;
}
public function retryFailed($limit = 50)
{
$now = time();
$rows = Db::name('shopro_wechat_trade_sync')
->where('status', 'pending')
->where('retry_count', '>', 0)
->where('next_retry_time', '<=', $now)
->order('id', 'asc')
->limit($limit)
->select();
$count = 0;
foreach ($rows as $row) {
try {
if ($row['sync_type'] === 'confirm') {
$this->syncOrderConfirm($row['order_id']);
} else {
$this->syncOrderShipping($row['order_id'], $row['order_item_id']);
}
$count++;
} catch (\Exception $e) {
// logged
}
}
return $count;
}
}