1、合作商余额查询
2、分油账户司机可用额度
This commit is contained in:
@@ -2,8 +2,13 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | 企油通 · 回调接收
|
||||
// +----------------------------------------------------------------------
|
||||
// | 入口:public/qytconsume.php -> /qytNotify/consume
|
||||
// | 对应企油通 7.10「运单加油明细推送(异步)」,我方须返回 {"code":"100","msg":"Success"}
|
||||
// | 入口:
|
||||
// | public/qytconsume.php -> /qytNotify/consume 企油通 7.10「运单加油明细推送」
|
||||
// | public/qytwaybill.php -> /qytNotify/waybill 企油通 3.10「发放结果通知」
|
||||
// |
|
||||
// | 两个回调都是 multipart/form-data,业务参数在表单字段里(JSON 字符串):
|
||||
// | 7.10 -> params 我方须返回 {"code":"100","msg":"Success"}
|
||||
// | 3.10 -> data + sign 我方只要返回 HTTP 2xx 即算成功,响应体不做要求
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
@@ -70,4 +75,78 @@ class QytNotify extends Controller
|
||||
|
||||
return json(['code' => '100', 'msg' => 'Success']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 3.10 发放结果通知(运单油费 / 企业福利)
|
||||
*
|
||||
* 企油通把 7.7 提交的批次处理完后(全部成功 / 部分成功 / 处理失败)主动推过来,
|
||||
* 一个批次一条,内容与 7.8 查询结果一致。接上之后就不必再靠轮询等结果。
|
||||
*
|
||||
* 约定(见文档 3.10):
|
||||
* · form-data,字段 data(JSON 字符串)+ sign
|
||||
* · scene 区分场景:oil=运单油费下发(7.7),welfare=员工福利下发(9.3)
|
||||
* · 接收端返回 HTTP 2xx 即视为成功;非 2xx 或 5 秒内无响应会重试,最多 5 次
|
||||
* · 同一批次可能收到多次(重试 / 批次重新提交),必须幂等
|
||||
* · 明细最多约 1 万条,报文可能很大
|
||||
*
|
||||
* 所以这里只做「尽快收下、丢进队列、立刻回 200」,真正的状态跃迁交给
|
||||
* callback:queue 异步做,避免大报文处理超过上游 5 秒超时导致无谓重试。
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function waybill()
|
||||
{
|
||||
$request = Request::instance();
|
||||
// ⚠️ 必须直接读 $_POST:cores\Request 给所有入参挂了全局过滤器
|
||||
// ['my_trim','my_htmlspecialchars','filter_emoji'],走 $request->post() 取到的
|
||||
// JSON 引号会被转义成 ",json_decode 必然失败(通知会被静默丢掉)
|
||||
$formData = isset($_POST['data']) ? trim((string) $_POST['data']) : '';
|
||||
$sign = isset($_POST['sign']) ? trim((string) $_POST['sign']) : '';
|
||||
$raw = $request->getContent();
|
||||
|
||||
$payload = $formData !== '' ? $formData : $raw;
|
||||
$qyt = new QytOil();
|
||||
// 明细可能上万条,日志只留头部,完整报文靠 batch_no 去企油通后台对
|
||||
$qyt->saveLog('3.10 发放结果通知原文[' . $request->contentType() . '](截断):'
|
||||
. mb_substr($payload, 0, 4000) . (mb_strlen($payload) > 4000 ? ' …(已截断)' : ''));
|
||||
|
||||
$data = json_decode($payload, true);
|
||||
// 兜底:若上游或中间层做过 HTML 转义,反转义后再解析一次
|
||||
if (!is_array($data) && strpos($payload, '"') !== false) {
|
||||
$data = json_decode(htmlspecialchars_decode($payload, ENT_QUOTES), true);
|
||||
}
|
||||
// 兼容:直接推 JSON body 且外层包了一层 {data: ..., sign: ...}
|
||||
if (is_array($data) && isset($data['data'])) {
|
||||
$sign === '' && $sign = (string) ($data['sign'] ?? '');
|
||||
$data = is_string($data['data']) ? json_decode($data['data'], true) : $data['data'];
|
||||
}
|
||||
|
||||
if (!is_array($data) || empty($data['batch_no'])) {
|
||||
$qyt->saveLog('3.10 发放结果通知解析失败或缺少 batch_no,已忽略');
|
||||
// 仍然回 2xx:报文我方解析不了,让上游重试 5 次也没有意义,
|
||||
// 这类单由 7.8 轮询兜底(轮询并没有下线)
|
||||
return json(['code' => '100', 'msg' => 'Success']);
|
||||
}
|
||||
|
||||
// TODO 验签(对 data 原串签名,规则见开发指南 2.5,待对接人给到平台公钥与算法确认)
|
||||
// if ($sign !== '' && !(new QytCrypto())->verifyNotify($payload, $sign)) {
|
||||
// $qyt->saveLog('3.10 发放结果通知验签失败 batch_no=' . $data['batch_no']);
|
||||
// return json(['code' => '99', 'msg' => 'sign error']);
|
||||
// }
|
||||
|
||||
// 只处理运单油费(7.7)。员工福利(9.3)我方没有对接,收下回 2xx 即可,
|
||||
// 否则上游会按失败重试 5 次。
|
||||
$scene = (string) ($data['scene'] ?? 'oil');
|
||||
if ($scene !== 'oil') {
|
||||
$qyt->saveLog('3.10 发放结果通知 scene=' . $scene . '(非运单油费),已忽略 batch_no=' . $data['batch_no']);
|
||||
return json(['code' => '100', 'msg' => 'Success']);
|
||||
}
|
||||
|
||||
(new QueueService())->push('callback_queue', json_encode([
|
||||
'header' => ['method' => 'qyt_waybill_result'],
|
||||
'res' => $data,
|
||||
], 320));
|
||||
|
||||
return json(['code' => '100', 'msg' => 'Success']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user