完成了基本调整调整
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -87,12 +87,31 @@ class NotifyQueue extends Command
|
||||
return false;
|
||||
}
|
||||
$partnersOil = new PartnersOil();
|
||||
$optType = (string)($data['optType'] ?? '');
|
||||
|
||||
// 加油:一单可多次加油,每笔单独通知。消息里带 consume_id 时推这一笔的占用金额和消费单号;
|
||||
// 老消息没有 consume_id(上线前入队的)则沿用旧口径推订单金额
|
||||
$consume = null;
|
||||
if ($optType == 'add_oil' && !empty($data['consume_id'])) {
|
||||
$consume = Db::name('qyt_consume')->where('id', (int)$data['consume_id'])->find();
|
||||
}
|
||||
if ($optType == 'refund') {
|
||||
$amount = $order['refund_amount'];
|
||||
} elseif ($consume) {
|
||||
$amount = number_format((int)$consume['consume_amount'] / 100, 2, '.', '');
|
||||
} else {
|
||||
$amount = $order['total_price'];
|
||||
}
|
||||
|
||||
$data = [
|
||||
'oilCardNo' => $order['oilCardNo'],
|
||||
'amount' => $order['total_price'],
|
||||
'shareNo' => $order['shareNo'],
|
||||
'type' => $data['optType'] == 'share_oil' ? 'add' : 'sub',
|
||||
'optType' => $data['optType'],
|
||||
// 分油:订单金额;加油:本次加油占用金额;退款:退款金额
|
||||
'amount' => $amount,
|
||||
// 订单实付金额(即分油金额),所有场景都带,方便对接方拿 amount 对照参考
|
||||
'orderAmount' => number_format((float)$order['total_price'], 2, '.', ''),
|
||||
'shareNo' => $consume && $consume['order_code'] !== '' ? $consume['order_code'] : $order['shareNo'],
|
||||
'type' => $optType == 'share_oil' ? 'add' : 'sub',
|
||||
'optType' => $optType,
|
||||
];
|
||||
$header['method'] = 'syb.notify.oilCard.change';
|
||||
$res = $partnersOil->sendRequest($partners, $partners['callback'], $data, $header);
|
||||
@@ -103,11 +122,16 @@ class NotifyQueue extends Command
|
||||
'oil_callback' => 1,
|
||||
'oil_callback_time' => time(),
|
||||
]);
|
||||
}else{
|
||||
}elseif($data['optType'] == 'add_oil'){
|
||||
// 退款通知成功不记 use_callback,避免把「加油已回调」标错
|
||||
$order->save([
|
||||
'use_callback' => 1,
|
||||
'use_callback_time' => time(),
|
||||
]);
|
||||
// 逐笔记录这一笔加油已通知
|
||||
if ($consume) {
|
||||
Db::name('qyt_consume')->where('id', $consume['id'])->update(['notify_status' => 1, 'notify_time' => time()]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user