完成了基本调整调整

This commit is contained in:
2026-09-18 20:55:21 +08:00
parent 864187e105
commit 57e0854a0e
56 changed files with 3122 additions and 105 deletions
@@ -340,58 +340,91 @@ class CallbackQueue extends Command
continue;
}
$payTime = !empty($c['pay_time']) ? (strtotime($c['pay_time']) ?: time()) : time();
// 落消费流水(uk_consume 去重:重复回调直接忽略)
// 一单可以分多次加油:每条推送是一次加油,consume_amount = 本次占用运单金额(分)
$consumeFen = (int)($c['consume_amount'] ?? 0);
$consumeYuan = number_format($consumeFen / 100, 2, '.', '');
$orderCode = trim((string)($c['order_code'] ?? ''));
// 去重键:文档里 order_code 是选填,缺失时用本笔消费的特征字段做指纹,
// 否则同一运单的第二笔加油会被唯一键误判为重复推送而丢掉(口径与迁移脚本回填一致)
$consumeKey = $orderCode !== '' ? $orderCode : 'FP' . md5(implode('|', [
$c['quota_id'] ?? '', $c['pay_time'] ?? '', $c['consume_amount'] ?? '',
$c['pay_fee'] ?? '', $c['station_code'] ?? '', $c['litter'] ?? '',
]));
$consumeId = 0;
try {
Db::name('qyt_consume')->insert([
'order_id' => $order['order_id'],
'waybill_no' => $c['waybill_no'] ?? '',
'waybill_no_code' => $code,
'order_code' => $c['order_code'] ?? '',
'station_code' => $c['station_code'] ?? '',
'station_name' => $c['station_name'] ?? '',
'oil_name' => $c['oil_name'] ?? '',
'litter' => $c['litter'] ?? '',
'oil_price' => (int)($c['oil_price'] ?? 0),
'actual_oil_price' => (int)($c['actual_oil_price'] ?? 0),
'pay_fee' => (int)($c['pay_fee'] ?? 0),
'consume_amount' => (int)($c['consume_amount'] ?? 0),
'pay_time' => $payTime,
'raw' => json_encode($c, 320),
'store_id' => $order['store_id'],
'create_time' => time(),
]);
// 流水落库与订单累计放在同一事务:唯一键挡住重推,重推既不重复累计也不重复通知
Db::transaction(function () use ($order, $c, $code, $orderCode, $consumeKey, $payTime, $consumeFen, $consumeYuan, &$consumeId) {
$consumeId = (int)Db::name('qyt_consume')->insertGetId([
'order_id' => $order['order_id'],
'waybill_no' => $c['waybill_no'] ?? '',
'waybill_no_code' => $code,
'order_code' => $orderCode,
'consume_key' => $consumeKey,
'station_code' => $c['station_code'] ?? '',
'station_name' => $c['station_name'] ?? '',
'oil_name' => $c['oil_name'] ?? '',
'litter' => $c['litter'] ?? '',
'oil_price' => (int)($c['oil_price'] ?? 0),
'actual_oil_price' => (int)($c['actual_oil_price'] ?? 0),
'pay_fee' => (int)($c['pay_fee'] ?? 0),
'consume_amount' => $consumeFen,
'pay_time' => $payTime,
'raw' => json_encode($c, 320),
'store_id' => $order['store_id'],
'create_time' => time(),
]);
// 累计已加油金额 / 次数,并记下最近一次加油信息(原子自增,不读后写)
Db::name('partners_order')->where('order_id', $order['order_id'])->update([
'used_amount' => Db::raw('`used_amount` + ' . $consumeYuan),
'used_num' => Db::raw('`used_num` + 1'),
'use_text' => '加油',
'qyt_order_code' => $orderCode,
'station_name' => $c['station_name'] ?? '',
'oil_name' => $c['oil_name'] ?? '',
'litter' => $c['litter'] ?? '',
'pay_fee' => (int)($c['pay_fee'] ?? 0),
'consume_time' => $payTime,
'update_time' => time(),
]);
// use_status 语义不变(0 未加油 / 1 有加油记录):只在第一笔加油时置 1 并记首次加油时间
Db::name('partners_order')->where('order_id', $order['order_id'])->where('use_status', 0)->update([
'use_status' => 1,
'use_time' => time(),
'shareNo' => $orderCode !== '' ? $orderCode : $order['shareNo'],
]);
});
} catch (\Exception $e) {
if (strpos($e->getMessage(), 'Duplicate') === false) {
throw $e;
}
$SybOil->saveLogStore('企油通消费回调重复,忽略流水:' . $code . '/' . ($c['order_code'] ?? ''));
$SybOil->saveLogStore('企油通消费回调重复,忽略(不重复累计、不重复通知):' . $code . '/' . $consumeKey);
continue;
}
// 条件跃迁 use_status 0 -> 1(要求已发放),仅胜出者通知下单平台
$affected = Db::name('partners_order')->where('order_id', $order['order_id'])
->where('use_status', 0)
->where('oil_status', 1)
->update([
'use_status' => 1,
'use_time' => time(),
'use_text' => '加油',
'qyt_order_code' => $c['order_code'] ?? '',
'shareNo' => $c['order_code'] ?: $order['shareNo'],
'station_name' => $c['station_name'] ?? '',
'oil_name' => $c['oil_name'] ?? '',
'litter' => $c['litter'] ?? '',
'pay_fee' => (int)($c['pay_fee'] ?? 0),
'consume_time' => $payTime,
'update_time' => time(),
]);
if ($affected) {
$queueService = new QueueService();
$queueService->push('notify_queue', json_encode([
'order_id' => $order['order_id'],
'optType' => 'add_oil',
'retry_count' => 0,
], 320));
$SybOil->saveLogStore('企油通消费回调处理成功:' . json_encode($c, 320));
// 超额告警:累计加油 + 已退款 > 订单金额。上游额度按司机凭证累计,
// 归属到本单的消费可能与本地可退金额算出的不一致,需要人工核对
$fresh = Db::name('partners_order')->where('order_id', $order['order_id'])
->field('total_price,used_amount,refund_amount,oil_status_zsy')->find();
if ($fresh && (float)$fresh['used_amount'] + (float)$fresh['refund_amount'] > (float)$fresh['total_price'] + 0.005) {
$SybOil->saveLogStore('【告警】订单已加油+已退款超出订单金额 order=' . $order['order_id']
. ' total=' . $fresh['total_price'] . ' used=' . $fresh['used_amount'] . ' refund=' . $fresh['refund_amount']);
}
// 每笔加油都通知下单平台(amount = 本次占用金额)
$notify = json_encode([
'order_id' => $order['order_id'],
'optType' => 'add_oil',
'consume_id' => $consumeId,
'retry_count' => 0,
], 320);
$queueService = new QueueService();
if ((int)($fresh['oil_status_zsy'] ?? 2) === 2) {
$queueService->push('notify_queue', $notify);
} else {
// 7.8 发放结果还没确认就先收到了加油:延后 60 秒再通知,尽量让「分油成功」通知先到下游
$queueService->laterPush('notify_queue', $notify, 60);
}
$SybOil->saveLogStore('企油通消费回调处理成功:' . json_encode($c, 320));
}
break;
default: