PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC] ); } catch (Throwable $e) { echo "提示:连不上数据库({$e->getMessage()}),只发送推送、不做前后对比\n"; } /** 按 waybill_no_code 取订单快照 */ function snap(?PDO $pdo, string $code): ?array { if (!$pdo) { return null; } $st = $pdo->prepare('SELECT order_id, oilCardNo, total_price, used_amount, used_num, use_status FROM yoshop_partners_order WHERE waybill_no_code = ? LIMIT 1'); $st->execute([$code]); return $st->fetch() ?: null; } echo "回调地址:{$url}\n"; echo "待补推:" . count($payloads) . " 条\n"; echo str_repeat('=', 66) . "\n\n"; $okCount = $failCount = 0; foreach ($payloads as $i => $params) { $no = $i + 1; $item = json_decode($params, true)['order_list'][0]; $code = $item['waybill_no_code']; $yuan = number_format($item['consume_amount'] / 100, 2); echo "【{$no}/" . count($payloads) . "】运单流水 {$code}\n"; echo " 加油站:{$item['station_name']} 金额:{$yuan} 元 消费单号:{$item['order_code']}\n"; $before = snap($pdo, $code); if ($pdo && !$before) { echo " ⚠️ 本地找不到该运单流水对应的订单,推过去也会被判为「未匹配订单」,跳过\n\n"; $failCount++; continue; } if ($before) { printf(" 订单:order_id=%s 油卡号=%s 金额=%s 已加油=%s(%s 次)\n", $before['order_id'], $before['oilCardNo'], $before['total_price'], $before['used_amount'], $before['used_num']); } // 与企油通一致:multipart/form-data,params 放表单字段(cURL 传数组即为 multipart) $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_POST => true, CURLOPT_POSTFIELDS => ['params' => $params], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, ]); $resp = curl_exec($ch); $http = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); $err = curl_error($ch); curl_close($ch); if ($resp === false) { echo " ❌ cURL 失败:{$err}\n\n"; $failCount++; continue; } echo " HTTP {$http} 响应:{$resp}\n"; if (strpos($resp, '"100"') === false) { echo " ⚠️ 未返回 code=100,查 runtime/storelog 下当天的 qyt_*.txt\n\n"; $failCount++; continue; } // 等 callback:queue 落库 if (!$before) { echo " 已受理(无数据库连接,未做入账校验)\n\n"; $okCount++; continue; } echo ' 等待 callback:queue 处理'; $after = null; for ($t = 0; $t < 10; $t++) { sleep(1); echo '.'; $after = snap($pdo, $code); if ($after && (float) $after['used_amount'] > (float) $before['used_amount']) { break; } } echo "\n"; if ($after && (float) $after['used_amount'] > (float) $before['used_amount']) { printf(" ✅ 已入账:已加油 %s -> %s,次数 %s -> %s,剩余未加油 %s 元\n\n", $before['used_amount'], $after['used_amount'], $before['used_num'], $after['used_num'], number_format(max(0, (float) $after['total_price'] - (float) $after['used_amount']), 2)); $okCount++; } else { echo " ⚠️ 10 秒内订单没变化。可能原因:\n" . " 1) callback:queue 进程没在跑(supervisorctl status)\n" . " 2) 这条之前已经入账过,被唯一键判为重复推送(正常,不会重复累计)\n" . " 3) 处理异常,查 runtime/storelog 下当天的 " . date('YmdH') . ".txt\n\n"; $failCount++; } } echo str_repeat('=', 66) . "\n"; echo "完成:成功入账 {$okCount} 条,需关注 {$failCount} 条\n"; if ($pdo) { echo "\n各订单当前状态:\n"; foreach ($payloads as $params) { $code = json_decode($params, true)['order_list'][0]['waybill_no_code']; $row = snap($pdo, $code); if ($row) { printf(" %s order_id=%s 金额=%s 已加油=%s(%s 次)加油状态=%s\n", $code, $row['order_id'], $row['total_price'], $row['used_amount'], $row['used_num'], (int) $row['use_status'] === 1 ? '已加油' : '未加油'); } else { printf(" %s 本地无对应订单\n", $code); } } }