927 lines
83 KiB
Markdown
927 lines
83 KiB
Markdown
# 企油通对接现状分析报告(第一阶段:项目理解与代码调研)
|
||
|
||
> 版本:v1 ・ 生成时间:2026-09-01
|
||
> 范围:仅调研,未修改任何代码 / 数据库 / 配置。
|
||
> 结论中凡无法从代码确证的,均标注 **【待确认】**。
|
||
|
||
---
|
||
|
||
## 0. 术语与角色对照(先统一叫法)
|
||
|
||
| 报告用词 | 含义 | 代码 / 数据中的体现 |
|
||
|---|---|---|
|
||
| **用户** | 终端加油司机 / 消费者 | 小程序用户、下单平台的 `mobile` |
|
||
| **下单平台** | 调用我们接口的外部对接公司 | `yoshop_partners` 表;样例数据只有 1 家「华集云慧」(`orgNo=S99535450`),回调地址 `https://api.chenan.vip/hmb/oilCardChange` |
|
||
| **我们的系统** | 本项目 server-tp6 | 对外品牌名「**慧明宝**」(见 `慧明宝供应链平台接口文档V1.0.16.docx`),主体「广西慧明石化有限公司」 |
|
||
| **上游油品平台 / 四方平台** | 真正出油券、管油站、管核销的上游 | `yoshop_company` 表;目前有两代对接实现,见第 3、4 节 |
|
||
| **企油通** | 本次要接入的新上游平台 | `企油通接口对接文档.md`,域名 `worknoya.vip` |
|
||
| 智慧油客 | 上一代上游(`suoyoubao.com.cn`) | `SybOil` / `Crypto`;企油通文档里就是「passageway=3 已停用」的那个通道 |
|
||
| 定聚 | 当前在用上游(`idingju.com`,中石油 BP `/api/cnpcbp/*`) | `IdingjuOil` / `Idingju` |
|
||
|
||
**关键判断:** 业务链路 `用户 → 下单平台 → 我们的系统 → 企油通` 中,
|
||
- 「用户 → 下单平台 → 我们的系统」这一段 = **慧明宝入站 API**(`app/api/controller/OilCard.php`),是我们对下单平台的对外契约,**本次仅做最小扩展(新增 `name` 字段),其余 method/URL/字段/加密不变**。
|
||
- 「我们的系统 → 上游」这一段 = 用**企油通**整体替换(智慧油客 + 定聚 全部废弃)。
|
||
|
||
---
|
||
|
||
## 0.5 决策记录(2026-09-01 与需求方确认)
|
||
|
||
| # | 议题 | 决策 |
|
||
|---|---|---|
|
||
| 1 | 废弃范围 | **智慧油客(`SybOil`) + 定聚(`IdingjuOil`) 两套上游全部废弃**,统一换成企油通;不需要与定聚灰度并存 |
|
||
| 2 | 企油通企业 | 我们侧**只有一个企业**,`business_license` 为单一配置值;**线下已开通账户**(不需要在系统里做 7.2 创建 / 7.4 开户回调流程) |
|
||
| 3 | 订单映射粒度 | **一张订单 ↔ 一次 `createAndSendQuota`(7.7)**,其中 1 个 batch → 1 条 waybill → 1 个 employee(该订单的司机) |
|
||
| 4 | 分油用户来源 | **`yoshop_account` 用户池不保留**;司机信息由**下单平台提供** |
|
||
| 5 | 小程序油品链路 | **停用**:mobile-uniapp 代码不动,但后端支付成功后**不再触发**任何油品发放/分油/核销逻辑(`PaySuccess::shareOil`、小程序 `order/qrCode(Img)`、`Station.php` 等油品分支停用或摘除) |
|
||
| 6 | 入站契约变更 | `syb.oil.oilCard.share` **新增 `name`(司机姓名)入参**;**不新增 `id_card`**。其余字段与加密不变 |
|
||
| 7 | 支付通道 | **默认 = 支付宝企业码(`passageway=1`)**,需配置 `institution_id`;通道值做成**后台/配置可切换** |
|
||
| 8 | 范围外 | `app/admin` 模块、`yoshop_merchant` 支付聚合链路(`submitOrder`/`Notify`/乐刷)**不在本次范围**,不动 |
|
||
|
||
**由决策派生的新约束(需在方案中处理):**
|
||
- 决策 6 + 7:`passageway=1` 时 `employee_list` 可不传 `id_card`,只需 `mobile + name + quota_amount + voucher_name + institution_id`,与「下单平台只加传 `name`」正好吻合。
|
||
- **但 7.16 司机额度调整 / 7.17 获取支付凭证 均要求 `id_card`(必填)** → 在没有 `id_card` 的前提下,「**撤销分油 / 额度回收**」能力受限(见风险 R-07)。
|
||
- 决策 5:小程序历史油券订单(`yoshop_order_goods` 中大量 `zsy_ticket` 数据)后续只读展示,不再有新增。
|
||
|
||
---
|
||
|
||
## 1. 项目架构
|
||
|
||
### 1.1 server-tp6(后端,ThinkPHP 6)
|
||
|
||
多应用结构(`app/` 下按模块分目录):
|
||
|
||
| 模块 | 作用 | 与本次相关度 |
|
||
|---|---|---|
|
||
| `app/api` | 对外 HTTP 接口:小程序端 + 下单平台入站 API + 上游回调接收 | ★★★ 核心 |
|
||
| `app/store` | 后台管理端接口(admin-vue 实际对接的是这里,`renderSuccess` 风格) | ★★★ |
|
||
| `app/admin` | yoshop 原生后台模块,仅 `controller/{admin,setting,store}`,**疑似未启用** 【待确认】 | ★ |
|
||
| `app/console` | 命令行 / 队列消费者 / 定时任务 | ★★★ |
|
||
| `app/common` | 公共 model / service / crypto / enum | ★★★ |
|
||
|
||
- **路由**:`route/app.php` 基本为空,全部走 TP6 默认「模块/控制器/操作」约定路由。
|
||
- **多入口文件**(`public/*.php`):除 `index.php` 外,为特定回调 / 场景硬编码了 `PATH_INFO`:
|
||
| 入口文件 | 绑定路由 | 用途 |
|
||
|---|---|---|
|
||
| `public/partners.php` | 透传到 `api` 应用 | 下单平台调用慧明宝 API 的入口(`/partners.php/oilCard/share` 等) |
|
||
| `public/oil.php` | `/sybNotify/notify` | 上游「分油/发放结果」回调(小程序链路) |
|
||
| `public/oiluse.php` | `/sybNotify/use` | 上游「加油/核销结果」回调(小程序链路) |
|
||
| `public/partnersoil.php` | `/sybNotify/partnersNotify` | 上游「分油结果」回调(下单平台链路) |
|
||
| `public/partnersoiluse.php` | `/sybNotify/partnersUse` | 上游「核销结果」回调(下单平台链路) |
|
||
| `public/leshua.php` / `public/notice.php` / `public/ocp.php` | — | 乐刷支付 / 通知 / opcache 面板(与油品无关) |
|
||
- **队列**:Redis(Predis),`app/common/service/QueueService.php`,支持普通队列 + ZSET 延迟队列。消费者在 `config/console.php` 注册:
|
||
| 命令 | 队列 | 作用 |
|
||
|---|---|---|
|
||
| `callback:queue` | `callback_queue` | 处理上游回调(method: `oil` / `use` / `oil_partners` / `use_partners`) |
|
||
| `partners:queue` | `partners_queue` | 下单平台订单入队后 → 调用上游发放 |
|
||
| `notify:queue` | `notify_queue` | 我们 → 下单平台的结果回调(带 3 次退避重试 60/300/1800s) |
|
||
| `card:queue` / `process:queue` / `timer` | — | 兑换卡 / 其他 / 定时任务(与油品无关或次要) |
|
||
- **其他**:GatewayWorker(WebSocket 推送,`Gateway::sendToUid`);`app/common/lock/RedisLock`(分油抢占锁)。
|
||
- **日志**:上游相关日志统一写 `runtime/storelog/{Ym}/{Ymd}/{YmdH}.txt`(`saveLogStore()`)。
|
||
|
||
### 1.2 admin-vue(后台管理前端)
|
||
|
||
- 技术栈:Vue 2 + Ant Design Vue(vue-antd-pro 脚手架),`src/config/router.config.js` 静态菜单 + `src/router/generator-routers.js`。
|
||
- API 层:`src/api/**`,`axios` 封装(`src/utils/request`),基地址指向 server-tp6 的 `store` 应用。
|
||
- 与本次相关的菜单 / 页面见第 6 节。
|
||
|
||
### 1.3 mobile-uniapp(小程序端,**本次禁止修改**)
|
||
|
||
- 技术栈:uni-app + uView UI。
|
||
- `config.js`:`apiUrl = https://www.hmzkw.com/index.php?s=/api/`,指向 server-tp6 `api` 应用。
|
||
- 标准 yoshop 商城客户端(商品 / 购物车 / 结算 / 订单 / 微信支付 / 售后)。
|
||
- **仅两处直接触达「油品」语义**(其余全部是服务端在支付成功后自动处理):
|
||
| api 文件 | 接口 | 服务端 | 依赖上游? |
|
||
|---|---|---|---|
|
||
| `api/station.js` | `station/list` | `api/controller/Station.php` → `SybOil::baseGasStationList` | 是(且当前已坏,见风险) |
|
||
| `api/order.js` | `order/qrCode`、`order/qrCodeImg` | `api/controller/Order.php` → `IdingjuOil::payQrCodeRequest` | 是(核销码/图) |
|
||
| `api/order.js` | `order/list`、`order/detail`、`order/cancel`、`order/pay` … | 标准商城订单 | 否(间接) |
|
||
|
||
> `order/qrCodeImg` 出参是 `{ base64: "data:image/png;base64,..." }`,服务端通过 `shell_exec("node public/myscript.js <url>")` 把上游返回的二维码链接转成图片。**这是企油通改造的强约束点**(企油通给的是 H5 免登 URL,不是二维码字符串)。
|
||
|
||
---
|
||
|
||
## 2. 当前订单相关业务流程
|
||
|
||
### 2.1 流程 A:小程序商城消费链路(`yoshop_order` + `yoshop_order_goods`)
|
||
|
||
```
|
||
小程序 goods/list,detail
|
||
→ checkout/submit ── 创建 yoshop_order + yoshop_order_goods(order_type='zsy_ticket',oilCardType='zsy_ticket')
|
||
→ order/pay(微信支付)
|
||
→ 支付回调 → app\api\service\order\PaySuccess::onPaySuccess
|
||
├─ updatePayStatus → shareOil($detail) ★ 触发「分油」
|
||
│ · getCompany($goods_no) 硬编码 goods_no→orgNo,取 yoshop_company(status=10)
|
||
│ · processUserOrders($company_id) RedisLock 抢一个「空闲」分油用户(yoshop_account,state=0 且 last_called_at<今天)
|
||
│ · IdingjuOil::oilOilCardShare(...) → 定聚 /api/cnpcbp/order
|
||
│ 入参 mobile / out_order_id=oilCardNo / shortname=goods_no / notify_url=oil.php / use_notify_url=oiluse.php
|
||
│ 出参 code==1,data.trade_no(=shareNo)、data.state(2=已发券)、data.useUrl
|
||
│ · 回写 order_goods:account_id / company_id / shareNo / oil_status_zsy / oil_status
|
||
└─ Event 'OrderPaySuccess'
|
||
→ 上游异步回调 public/oil.php (/sybNotify/notify) → 塞 callback_queue(method='oil')
|
||
→ CallbackQueue case 'oil':按 shareNo 命中 order_goods,useStatus==1 → oil_status=1、qrCode=useUrl
|
||
→ 用户点核销 → order/qrCode | order/qrCodeImg
|
||
→ IdingjuOil::payQrCodeRequest(/api/cnpcbp/getUseCode)→ 写 yoshop_order_qrcode → 返回二维码 URL / base64 图
|
||
→ 加油完成 → 上游回调 public/oiluse.php (/sybNotify/use) → callback_queue(method='use')
|
||
→ CallbackQueue case 'use':写 yoshop_order_record,useStatus==2 → order_goods.use_status=1、use_time
|
||
若该 order 下所有 order_goods 都 use_status=1 → yoshop_order.order_status=30(已完成)
|
||
释放 yoshop_account(state=0)
|
||
```
|
||
|
||
订单状态枚举(`app/common/enum/order/`):
|
||
- `OrderStatus`:10 进行中 / 20 已取消 / 21 待取消 / 30 已完成
|
||
- `PayStatus`:10 待支付 / 20 成功 / 30 超时
|
||
- `PayType`:10 余额 / 20 微信 / 30 转账
|
||
- 油品自定义(在 `order_goods` / `partners_order` 字段上,非枚举类):
|
||
- `oil_status`:0 未分油 / 1 已分油
|
||
- `oil_status_zsy`:1 待处理 / 2 已发券 / 3 发券失败 / 5 已退单(注释写「中石油下单状态」)
|
||
- `use_status`:0 未核销 / 1 已核销
|
||
- `oil_callback` / `use_callback`:是否已回调下单平台
|
||
|
||
**取消 / 退款**:`app/api/model/Order.php::cancel()` 仅改订单状态(已付款→21 待取消,待后台审核)。`app/common/service/order/Refund.php`、`order/Complete.php` **均不触达上游**——即小程序订单退款/取消**不会**撤销已发放的油券。属流程缺口(见风险 14)。
|
||
|
||
### 2.2 流程 B:下单平台对接链路(`yoshop_partners_order`)
|
||
|
||
**入站(下单平台 → 我们,"慧明宝" API,全部 RSA+AES 信封)**,控制器 `app/api/controller/OilCard.php`,鉴权 `app/common/crypto/RsaUtil.php`(平台私钥签名下发 + 合作商公钥验签):
|
||
|
||
| method 头 | 请求 URL | 动作 |
|
||
|---|---|---|
|
||
| `syb.oil.oilCard.stockList` | `/oilCard/stock` | 查合作商可下单数量 / 已用 / 未用(读 `yoshop_partners_goods` + `yoshop_partners_order` 计数) |
|
||
| `syb.oil.oilCard.share` | `/oilCard/share` | 下单:校验 appKey→`yoshop_partners`、`requestId` 幂等(`yoshop_request_log` 唯一索引)、商品/库存/合作商库存校验 → 创建 `yoshop_partners_order`(order_status=10) → 扣 `goods_sku` 库存 → **push `partners_queue`** → 返回 `oilCardNo` + `amount` |
|
||
| `syb.pay.qrCode.request` | `/oilCard/getPayQrCode` | 申请核销码:`IdingjuOil::payQrCodeRequest` → 写 `yoshop_order_qrcode` |
|
||
| `syb.oil.oilCard.shareList` | `/oilCard/shareList` | 分油记录分页查询 |
|
||
| `syb.oil.oilCard.orderStatus` | `/oilCard/orderStatus` | 单笔订单状态查询 |
|
||
|
||
**中段(我们 → 上游)**:`app/console/command/PartnersQueue.php` 消费 `partners_queue`:
|
||
- 取 `yoshop_partners_order`,`order_status==10 && oil_status==0 && oilCardType=='zsy_ticket'`
|
||
- `getCompany($goods_no)` 硬编码取 `yoshop_company`
|
||
- `IdingjuOil::oilOilCardShare(...)`,`notify_url=partnersoil.php`、`use_notify_url=partnersoiluse.php`
|
||
- 回写 `shareNo / qrCode / oil_status_zsy / oil_status`;若 `state==2` → push `notify_queue`(optType=`share_oil`)
|
||
|
||
**上游回调(上游 → 我们)**:
|
||
- `public/partnersoil.php` → `/sybNotify/partnersNotify`(method 置为 `oil_partners`)→ `callback_queue`
|
||
- `public/partnersoiluse.php` → `/sybNotify/partnersUse`(method 置为 `use_partners`)→ `callback_queue`
|
||
- `CallbackQueue` case `oil_partners`:按 `shareNo` 命中 `yoshop_partners_order`,`useStatus=='1'` → `oil_status=1 / qrCode`,push `notify_queue`(share_oil)
|
||
- `CallbackQueue` case `use_partners`:写 `yoshop_order_record`,`useStatus=='2'` → `use_status=1 / use_time`,push `notify_queue`(add_oil)
|
||
|
||
**出站回调(我们 → 下单平台)**:`app/console/command/NotifyQueue.php` 消费 `notify_queue`:
|
||
- 取 `yoshop_partners_order` + `yoshop_partners`
|
||
- `PartnersOil::sendRequest($partners['callback'], ...)`,header `method='syb.notify.oilCard.change'`,body `{oilCardNo, amount, shareNo, type(add/sub), optType}`
|
||
- 期望响应 `code=='00'`;成功回写 `oil_callback / use_callback`;失败按 1/3 次退避重试(延迟队列)
|
||
|
||
### 2.3 流程 C:后台手动运维(admin-vue → app/store)
|
||
|
||
见第 6 节。核心:手动分油 / 撤销分油 / 补单回调 / 核销码 / 合作商与公司管理 / 分油用户池管理 / 库存同步。
|
||
|
||
### 2.4 【待确认】另一条支付聚合链路
|
||
|
||
`app/api/controller/Order.php::submitOrder / searchOrder`、`app/api/controller/Notify.php`、`yoshop_merchant`(+balance_log+order)、`public/leshua.php`、`config` 中的 `patformKey.php` 等,构成一条「商户 / 代理商 + passageway(WX) + notifyUrl + 乐刷」的**第四方支付聚合**链路,与油券链路数据表有交叉(`order_goods.merchant_id`、`Company::processUserOrders`)。它与本次「企油通油品对接」的关系**未确认**——可能是历史遗留、可能仍在跑。**建议本次不动,单独确认。**
|
||
|
||
---
|
||
|
||
## 3. 当前上游(四方平台)对接流程
|
||
|
||
### 3.1 第一代:智慧油客 `SybOil`(`suoyoubao.com.cn`)—— **基本已废弃**
|
||
|
||
- 代码:`app/common/service/SybOil.php`(+ 早期 `app/api/controller/syb/Syb*.php` 一组「透传壳」控制器)
|
||
- 加密:`app/common/crypto/Crypto.php`——RSA(平台公钥加密 AES key) + AES-256-ECB 加密 body + SHA256withRSA 签名,method 头 `syb.*`,接口路径 `/api/1.0.0/...`
|
||
- 配置:`config/crypto.php`(单租户默认参数)**或** 按 `yoshop_company` 行(`orgNo/appKey/privateKey/publicKey/platformPublicKey`)
|
||
- 现状:
|
||
- `CallbackQueue` 里整段 `syb.notify.*` 处理逻辑**全部被注释**,替换为 `oil` / `use` / `*_partners`
|
||
- `PaySuccess::shareOil` 的 `SybOil` 版本**被注释**,改用 `IdingjuOil`
|
||
- `yoshop_company` 里 `suoyoubao` / `124.70.136.175` 两行 `status=20`(停用)
|
||
- **仍在引用但实际已不可用**:`app/api/controller/Station.php`(油站列表,`CompanyModel::detail('2')` 指向停用公司)、`app/store/controller/Goods.php`(库存同步)
|
||
- 结论:**这是「已废弃的四方平台」最贴切的候选**。
|
||
|
||
### 3.2 第二代:定聚 `IdingjuOil`(`idingju.com`,中石油 BP `/api/cnpcbp/*`)—— **当前在用**
|
||
|
||
- 代码:`app/common/service/IdingjuOil.php` + `app/common/crypto/Idingju.php`
|
||
- 鉴权:`/api/open/getToken`(appid=orgNo, appsecret=appKey)拿 `access_token`,本地缓存到 `public/temp/{orgNo}.txt`(含 `expires_time`);业务请求把 `access_token / timestamp / signature` 拼到 **URL query**,body 为明文 JSON(**不加密**)
|
||
- 签名:`signature = sha1(api + token + implode(sort(params+token)) + timestamp)`
|
||
- 多租户:按 `yoshop_company` 行(`status=10` 的 3 行都是 `idingju.com` 域名)
|
||
- 已实现的接口:
|
||
| 方法 | 定聚接口 | 用途 |
|
||
|---|---|---|
|
||
| `baseGasStationList` | `/api/cnpcbp/stations` | 油站列表(**当前 Station.php 用的是 SybOil,未切到这里**) |
|
||
| `stockList` | `/api/cnpcbp/queryStock` | 库存(`data.quantity`) |
|
||
| `oilOilCardSelect` | `/api/cnpcbp/detail` | 订单详情(`out_order_id` 空,形同占位) |
|
||
| `oilOilCardShare` | `/api/cnpcbp/order` | **下单 / 分油**(`data.trade_no / state / useUrl`) |
|
||
| `payQrCodeRequest` | `/api/cnpcbp/getUseCode` | **核销二维码**(`data.useQrCodeUrl`) |
|
||
- 回调:上游 GET/POST 到 `partnersoil.php` / `partnersoiluse.php` / `oil.php` / `oiluse.php`(**当前回调体未验签**,`sybNotify` 里验签代码被注释,直接原样塞队列);回调关键字段 `trade_no`(=shareNo)、`useStatus`('1' 分油成功 / '2' 核销成功)、`useUrl`
|
||
- 说明:定聚没有「分油成功」的独立推送语义——`oilOilCardShare` 同步返回 `state`,或靠 `partnersoil.php` 回调补。
|
||
|
||
### 3.3 出站客户端:`PartnersOil`(不是油品上游,是「回调下单平台」)
|
||
|
||
- `app/common/service/PartnersOil.php`:方法名沿用 `syb.*` 风格,但实际是 POST 到 `yoshop_partners.callback`
|
||
- 加密:`RsaUtil`(`config/rsa.php` 的平台私钥 + 合作商公钥),与入站 API 同一套信封
|
||
|
||
### 3.4 加密类总览
|
||
|
||
| 类 | 用途 | 算法 | 密钥来源 |
|
||
|---|---|---|---|
|
||
| `crypto/Crypto.php` | 智慧油客 SybOil | RSA + AES-256-ECB + SHA256withRSA | `config/crypto.php` 或 `yoshop_company` |
|
||
| `crypto/Idingju.php` | 定聚 IdingjuOil | token + sha1 签名,body 明文 | `yoshop_company` |
|
||
| `crypto/RsaUtil.php` | 慧明宝入站 API + 回调下单平台 | RSA(加密 AES key) + AES-256-ECB + SHA256withRSA | `config/rsa.php`(平台私钥文件)+ `yoshop_partners`(合作商公钥) |
|
||
| (企油通需新建) | — | appId+timestamp+sign(RSA),`params` 为 JSON 字符串;7.15 特殊 MD5→SHA1withRSA;7.16/7.17 强制 RSA 验签 | 线下索取 |
|
||
|
||
---
|
||
|
||
## 4. 旧四方平台代码位置(清单)
|
||
|
||
### 4.1 智慧油客 `SybOil`(第一代,基本死代码)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `app/common/service/SybOil.php` | 上游客户端(油站/库存/分油/撤销/核销/发票/用户/优惠券等一整套 `syb.*`) |
|
||
| `app/common/crypto/Crypto.php` | 配套加密 |
|
||
| `config/crypto.php` | 配套配置(含**明文私钥**) |
|
||
| `app/api/controller/syb/SybBase.php` `SybOil.php` `SybOrder.php` `SybPay.php` `SybUser.php` `SybVoucher.php` `SybNotify.php` | 早期一组透传壳控制器(`sendRequest` 依赖 `config('crypto.*')`) |
|
||
| `app/api/controller/SybNotify.php` | **仍在用**(回调入口路由到这里),含 `notify/use/partnersNotify/partnersUse` + 被注释的 `notifyOld` |
|
||
| `app/api/controller/Station.php` | 油站列表,`SybOil` + 停用公司,实际已坏 |
|
||
| `app/store/controller/Goods.php`(`stock`/`all` 附近,~L155-211) | 库存同步用 `SybOil::stockList` |
|
||
| `app/console/command/CallbackQueue.php` | 顶部大段注释的 `syb.notify.*` 处理逻辑(历史实现) |
|
||
| `app/api/service/order/PaySuccess.php`(~L182-221 注释块) | `SybOil` 版 `shareOil` |
|
||
|
||
### 4.2 定聚 `IdingjuOil`(第二代,当前在用)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `app/common/service/IdingjuOil.php` | 上游客户端 |
|
||
| `app/common/crypto/Idingju.php` | token + sha1 |
|
||
| `app/console/command/PartnersQueue.php` | 下单平台链路:消费 `partners_queue` → `IdingjuOil::oilOilCardShare` |
|
||
| `app/api/service/order/PaySuccess.php`(`shareOil()`,~L253-318) | 小程序链路:`IdingjuOil::oilOilCardShare` |
|
||
| `app/api/controller/Order.php`(`qrCode` L310 / `qrCodeImg` L349) | 小程序核销:`IdingjuOil::payQrCodeRequest` |
|
||
| `app/api/controller/OilCard.php`(`getPayQrCode`) | 下单平台核销:`IdingjuOil::payQrCodeRequest` |
|
||
| `app/store/controller/Order.php`(`qrCode` / `share`) | 后台手动核销 / 分油 |
|
||
| `app/store/controller/partners/Order.php`(`qrCode` / `share`) | 后台合作商订单手动核销 / 分油 |
|
||
| `app/store/controller/Company.php`(`stock()`) | 后台库存同步 `IdingjuOil::stockList` |
|
||
| `app/console/command/CallbackQueue.php`(case `oil` / `use` / `oil_partners` / `use_partners`) | 回调处理(当前生效实现) |
|
||
|
||
### 4.3 出站回调下单平台(本次不改)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `app/common/service/PartnersOil.php` + `app/console/command/NotifyQueue.php` + `config/rsa.php` + `crypto/RsaUtil.php` | 我们 → 下单平台的结果回调 |
|
||
|
||
### 4.4 硬编码映射(迁移时必须统一收敛,现散落 7 处)
|
||
|
||
`getCompany($goodsNo)`(`goods_no → orgNo`)与 `getGoodsNo($orgNo)` / `getGoodsNo` 反向映射,重复出现在:
|
||
`app/api/controller/OilCard.php`、`app/api/controller/Order.php`、`app/api/service/order/PaySuccess.php`、`app/store/controller/Order.php`、`app/store/controller/partners/Order.php`、`app/store/controller/Company.php`、`app/console/command/PartnersQueue.php`。
|
||
|
||
---
|
||
|
||
## 5. 订单创建 / 提交 / 支付 / 取消 / 退款 / 状态同步 / 回调 代码定位
|
||
|
||
| 环节 | 小程序链路 | 下单平台链路 | 后台 |
|
||
|---|---|---|---|
|
||
| 创建 / 提交 | `api/service/order/Checkout.php`、`api/service/order/source/**`、`api/model/Order.php::putInto` | `api/controller/OilCard.php::share` → `api/model/partners/Order.php::saveOrder` | — |
|
||
| 支付 | `api/controller/Order.php::pay` → `api/model/Order.php::onPay` → 微信支付回调 → `api/service/order/PaySuccess.php::onPaySuccess` | 无「支付」概念(下单即扣合作商库存 / 余额) | — |
|
||
| **发放 / 分油(触上游)** | `PaySuccess::shareOil()` → `IdingjuOil::oilOilCardShare` | `console/command/PartnersQueue.php` → `IdingjuOil::oilOilCardShare` | `store/controller/Order.php::share`、`store/controller/partners/Order.php::share` |
|
||
| 核销 / 二维码(触上游) | `api/controller/Order.php::qrCode` / `qrCodeImg` | `api/controller/OilCard.php::getPayQrCode` | `store/controller/Order.php::qrCode`、`store/controller/partners/Order.php::qrCode` |
|
||
| 取消 | `api/controller/Order.php::cancel` → `api/model/Order.php::cancel`(仅改状态,不触上游) | 无 | `store/controller/Order.php::updatestatus` |
|
||
| **撤销分油** | `store/controller/Order.php::cancelShare` —— **调用未定义方法 `$this->oilOilCardCancelShare()`,当前会致命错误 / 功能已损坏** | — | admin-vue `CancelShareForm.vue` → `/order/cancelShare` |
|
||
| 退款 | `common/service/order/Refund.php`(**不触上游**) | 无 | — |
|
||
| 状态同步(我方←上游) | 回调 `oil.php` / `oiluse.php` → `SybNotify::notify/use` → `callback_queue` → `CallbackQueue` case `oil`/`use` | 回调 `partnersoil.php` / `partnersoiluse.php` → `SybNotify::partnersNotify/partnersUse` → `callback_queue` case `oil_partners`/`use_partners` | 补单:`store/controller/Order.php::callback` / `partners/Order.php::oilCallback` / `useCallback` |
|
||
| 结果回调(我方→下单平台) | — | `console/command/NotifyQueue.php` → `PartnersOil::sendRequest($partners.callback)` | 手动触发同 `oilCallback` / `useCallback` |
|
||
| 完成 | `api/model/Order.php::receipt` / `CallbackQueue` 使所有券核销后置 `order_status=30` | `CallbackQueue` 更新 `partners_order` | — |
|
||
|
||
---
|
||
|
||
## 6. admin-vue 相关页面
|
||
|
||
菜单定义:`admin-vue/src/config/router.config.js`
|
||
|
||
| 菜单 | 路由 | 页面文件 | 对接 store 接口 | 与油品对接关系 |
|
||
|---|---|---|---|---|
|
||
| 分油公司 › 公司列表 | `/company/index` | `views/company/Index.vue` | `/company/index` `/company/all` `/company/detail` | **上游平台账号管理**(url/orgNo/appKey/privateKey/publicKey/platformPublicKey) |
|
||
| 分油公司 › 创建 / 编辑 | `/company/create` `/company/update` | `views/company/Create.vue` `Update.vue` | `/company/add` `/company/edit` | 同上;表单字段 = `url, orgNo, appKey, privateKey, publicKey, platformPublicKey` + 公司资料 |
|
||
| — | modal | `views/company/modules/ApiParaForm.vue` | — | 只读展示对接参数 |
|
||
| — | modal | `views/company/modules/AccountForm.vue` | `/company/addAccount` | 批量生成随机身份「分油用户」写入 `yoshop_account` |
|
||
| — | modal | `views/company/modules/RechargeForm.vue` | `/company/recharge` | 公司余额充值(`yoshop_company_balance_log`) |
|
||
| 分油公司 › 余额明细 | `/company/balance/index` | `views/company/balance/Index.vue` | `/company.balance/*` | 公司余额流水 |
|
||
| 分油公司 › 分油用户 | `/account/index` | `views/account/Index.vue` | `/account/*` | `yoshop_account` 用户池(小程序分油借用的身份) |
|
||
| 合作商管理 › 列表 | `/partners/index` | `views/partners/Index.vue` | `/partners/index` `/partners/all` | **下单平台账号管理**(orgNo/appKey/privateKey/publicKey/callback/balance) |
|
||
| 合作商管理 › 创建 / 编辑 | `/partners/create` `/partners/update` | `views/partners/Create.vue` `Update.vue` | `/partners/add` `/partners/edit` | 含勾选可售商品 + 库存分配(`yoshop_partners_goods`) |
|
||
| — | modal | `views/partners/modules/ApiParaForm.vue` | — | 只读展示对接参数(含回调地址) |
|
||
| 合作商管理 › 订单列表 | `/partners/order/index` | `views/partners/order/Index.vue` | `/partners.order/list` `share` `qrCode` `oilCallback` `useCallback` | `yoshop_partners_order` 运维:手动分油 / 核销码 / 重推回调 |
|
||
| — | modal | `views/partners/order/modules/{OilForm,UseForm,ShareForm,PayForm}.vue` | 同上 | |
|
||
| 合作商管理 › 余额明细 | `/partners/balance/index` | `views/partners/balance/Index.vue` | `/partners.balance/*` | |
|
||
| 订单管理 › 全部 / 油券 / 优惠券 | `/order/list/all` `/oil` `/coupon` | `views/order/Index.vue` | `/order/list` `/order/detail` | `yoshop_order` + `order_goods` 运维 |
|
||
| — | modals | `views/order/modules/{ShareForm,CancelShareForm,FillUpForm,PayForm,CancelForm,DeliveryForm,PriceForm,UpdateStatusForm}.vue` | `/order/share` `/order/cancelShare` `/order/callback` `/order/qrCode` `/order.event/*` | **手动分油 / 撤销分油(当前坏) / 补单 / 付款码** |
|
||
| 订单管理 › 售后 | (路由已注释,页面文件仍在) | `views/order/refund/**` | — | 当前未启用 |
|
||
|
||
企油通改造时预计需要动的 admin-vue 页面:**`views/company/**`(改造为企业管理:营业执照 / 通道 / 企业状态 / 开户流程)、`views/order/**` 与 `views/partners/order/**`(补企油通字段、查发放结果、回单下载)**。其余尽量不动。
|
||
|
||
---
|
||
|
||
## 7. 数据库相关表(`oil.sql`,表前缀 `yoshop_`)
|
||
|
||
### 7.1 下单平台侧
|
||
|
||
| 表 | 关键字段 | 说明 |
|
||
|---|---|---|
|
||
| `yoshop_partners` | `orgNo, appKey, privateKey, publicKey, callback, balance` | 下单平台(对接公司)账号 & 回调地址 & 余额。样例仅 1 条「华集云慧」 |
|
||
| `yoshop_partners_goods` | `partners_id, goods_id, stock_num, use_num` | 分配给下单平台的可售商品与库存 |
|
||
| `yoshop_partners_order` | `province, mobile, oilCardType, oilCardNo, shareNo, partners_order_no, partners_id, goods_id/name/no, goods_price, total_price, order_status(10/20/30), qrCode, oil_status, oil_status_zsy, oil_time, oil_text, oil_callback(+time), use_status, use_time, use_text, use_callback(+time), expiration_time` | 下单平台订单主表。**无 user_id**(`user_id=0`)。样例数据 `oil_status_zsy` 多为 3(发券失败,测试环境 `face003`) |
|
||
| `yoshop_partners_balance_log` / `yoshop_partners_stock_log` | `scene, money / goods_id, num` | 余额 / 库存变动明细 |
|
||
|
||
### 7.2 上游平台侧
|
||
|
||
| 表 | 关键字段 | 说明 |
|
||
|---|---|---|
|
||
| `yoshop_company` | `url, orgNo, appKey, privateKey, publicKey, platformPublicKey, canOrderNum, unUseNum, useNum, balance, status(10启用/20停用)` | 上游平台账号。样例:row 2/6 = 智慧油客(`suoyoubao` / `124.70...`),`status=20`;row 7/8/9 = 定聚(`idingju.com`),`status=10`,`privateKey/publicKey/platformPublicKey` 存 `'1'`(定聚不用 RSA) |
|
||
| `yoshop_company_balance_log` | `scene(10充值/20消费/30管理员/40退款), money` | 公司余额流水 |
|
||
| `yoshop_account` | `userNo, mobile, userName, userIdCard, userType, company_id, state(0空闲/1占用), last_called_at, is_delete` | **分油用户池**——小程序订单分油时「借」一个身份去调上游 |
|
||
|
||
### 7.3 小程序商城订单侧
|
||
|
||
| 表 | 关键字段(仅列油品相关) | 说明 |
|
||
|---|---|---|
|
||
| `yoshop_order` | `order_no, order_type, order_status(10/20/21/30), total_price, pay_price, pay_type, pay_status, merchant_id, user_id, order_source, platform` | 商城订单主表(yoshop 标准 + `merchant_id` 代理) |
|
||
| `yoshop_order_goods` | `account_id, userNo, mobile, province, oilCardType, oilCardNo, shareNo, company_id, merchant_id, goods_id/name/no, goods_price, total_price, total_pay_price, qrCode, oil_status, oil_status_zsy, oil_time, oil_text, use_status, use_time, use_text, expiration_time` | **油品状态实际承载在这张表**(一单可多券) |
|
||
| `yoshop_order_qrcode` | `oilCardNo, qrCode, amount, order_id, order_goods_id, user_id` | 每次申请核销码留痕(样例可见 URL 形态:`https://t-h5.einrkv.com/...`) |
|
||
| `yoshop_order_record` | `oilCardNo, shareNo, amount, type(add/sub), optType(share_oil/add_oil/cancel_share), order_id, order_goods_id, user_id` | 油卡变动通知落库 |
|
||
| `yoshop_request_log` | `request_id(唯一), app_key, create_time` | 入站 API `requestId` 幂等去重 |
|
||
|
||
### 7.4 其他相关
|
||
|
||
| 表 | 说明 |
|
||
|---|---|
|
||
| `yoshop_goods` / `yoshop_goods_sku` | 商品(`goods_no, oilCardType, province, stock_total`)/ SKU(`stock_num`)。库存被「下单减」与「上游库存同步」两套逻辑写 |
|
||
| `yoshop_merchant` / `yoshop_merchant_balance_log` / `yoshop_merchant_order` | 「商户 / 代理商」体系 + 发券订单,与支付聚合链路相关,**与企油通关系待确认** |
|
||
| `yoshop_order_refund` 系列 | 售后单(当前后台未启用该菜单) |
|
||
|
||
> 表结构注释在 `oil.sql` 中为 UTF-8;用 `sed`/编辑器读取正常,用 Windows PowerShell `Get-Content` 会乱码。
|
||
|
||
---
|
||
|
||
## 8. 企油通接口清单(据 `企油通接口对接文档.md` 第 7 章,共 23 个)
|
||
|
||
公共约定:
|
||
- 全部 `POST`,路径 `/enterprise/api/...`,域名测试/正式不同,**线下索取**。
|
||
- 外层信封:`{ appId, timestamp, sign, params }`,其中 **`params` 必须是 JSON 字符串(转义),不是对象**。
|
||
- 响应:`{ status: ok|error, data, message, serialNo, sign }`。
|
||
- 业务接口**不需要登录态 token**(`appId + business_license` 即可)。
|
||
- 金额单位不统一:**分** → 7.7/7.8/7.9/7.10/7.11/7.12/7.13/7.14;**元** → 7.16/7.17/7.19/7.20/7.21/7.23。
|
||
- `passageway`:1 支付宝企业码 / 2 平安银行 / 3 智慧油客(🚫停用,勿传) / 4 企油通(仅出现在返回值)。
|
||
- `7.16 / 7.17` **必须真实 RSA 验签**,否则 403。
|
||
- `batch_no / waybill_no / waybill_no_code` 当前**全平台唯一**,需加企业前缀。
|
||
|
||
| 编号 | 名称 | 路径 | 用途 / 备注 |
|
||
|---|---|---|---|
|
||
| 7.1 | 企业登录(可选) | `/enterprise/api/auth/login` | 业务接口不需要,一般不用 |
|
||
| 7.2 | 企业申请创建 | `/enterprise/api/zhyk/openAnAccount` | 提交营业执照等,返回待审核;之后线下开户 |
|
||
| 7.3 | 企业账户信息推送(智慧油客) | 回调 | 🚫 已停用 |
|
||
| 7.4 | 企业账户信息推送(平安银行) | 回调 `.../callback/ygzf/enterpriseAccountCallback` | 平台→我方,开户完成后推送银行账户 |
|
||
| 7.5 | 企业账户信息查询 | `/enterprise/api/zhyk/accountQuery` | 查企业账户号/开户行/状态 |
|
||
| 7.6 | 企业信息查询 | `/enterprise/api/zhyk/getEnterpriseInfo` | `is_new / can_pay / password` |
|
||
| 7.7 | **运单油费下发** | `/enterprise/api/zhyk/createAndSendQuota` | **核心:给司机按运单发额度**,单批≤100 人,**异步**,`quota_amount` 单位分,平安通道 `id_card` 必填 |
|
||
| 7.8 | 运单发放结果查询 | `/enterprise/api/zhyk/waybillBatch` | 按 `batch_no` 查发放明细与 `handle_status` |
|
||
| 7.9 | 运单加油明细查询 | `/enterprise/api/zhyk/waybillQuotaDetail` | 返回 `order_code`(→7.19 回单入参)、加油站、升数、油品、实付 |
|
||
| 7.10 | **运单加油明细推送(异步)** | 回调 `.../callback/ygzf/waybillConsumeCallback` | 平台→我方,消费推送;**我方须返回 `{"code":"100","msg":"Success"}`** |
|
||
| 7.11 | 获取企业账户余额 | `/enterprise/api/zhyk/distributable` | 平安实时余额(勿高频轮询);支付宝通道不支持 |
|
||
| 7.12 | 司机钱包金额查询 | `/enterprise/api/zhyk/driverBalanceQuery` | 司机可用余额(分) |
|
||
| 7.13 | 司机钱包明细查询 | `/enterprise/api/zhyk/driverWalletQuery` | 流水,默认只回溯近 1 个月 |
|
||
| 7.14 | 企业发票下载 | `/enterprise/api/zhyk/invoice` | 按月,返回发票地址集 + 加油明细 |
|
||
| 7.15 | **H5 跳转地址(司机免登加油)** | H5 URL | 替代「核销二维码」;签名:`ksort → http_build_query → urldecode → 大写MD5 → SHA1withRSA → base64`;带 `creditcode` 时须一并入签且企业须 `approved` |
|
||
| 7.16 | 司机额度调整 | `/enterprise/api/quota/adjustVoucher` | `change_type` 02 增 / 03 减(≈撤销分油),金额**元**,**须 RSA 验签** |
|
||
| 7.17 | 获取支付凭证 | `/enterprise/api/quota/getVoucherList` | 返回 `quota_id`(→7.16 入参),金额**元**,**须 RSA 验签** |
|
||
| 7.18 | 司机三证信息保存 | `/enterprise/api/zhyk/saveDriverDoc` | 身份证/驾照/行驶证,含 OCR + 实名二要素;仅更新已存在司机 |
|
||
| 7.19 | 支付回单获取(平安) | `/enterprise/api/receipt/getPaymentReceipt` | 按 `order_code` 取银行电子回单 PDF;`generating` 需重试(可能 T+1) |
|
||
| 7.20 | 司机提现到银行卡(平安) | `/enterprise/api/driver-withdraw/withdrawToBank` | 异步,`out_trade_no` 幂等,金额**元** |
|
||
| 7.21 | 提现结果查询(平安) | `/enterprise/api/driver-withdraw/queryWithdraw` | 轮询至 `success/failed` |
|
||
| 7.22 | 企业列表查询 | `/enterprise/api/enterprise/list` | 枚举本 appId 名下企业与 `business_license`、已绑定 `passageway`;**需开通权限** |
|
||
| 7.23 | 平安消费回调测试接口 | `/enterprise/api/zhyk/testPinganConsume` | 🚫 仅测试环境,模拟一笔消费联调 7.10 |
|
||
|
||
**四阶段流程**:① 企业创建(7.2→线下开户→7.4/7.5)② 发放油费(7.7→7.8;额度调整 7.17→7.16)③ 司机加油(7.15→7.9/7.10→7.19)④ 获取发票(7.14)。
|
||
|
||
---
|
||
|
||
## 9. 旧平台接口 ↔ 企油通接口 对应关系
|
||
|
||
> ⚠️ **前提:两者业务模型不同**(详见风险 1)。下表是「功能意图」层面的映射,不是字段级等价。
|
||
|
||
| 现有能力(慧明宝入站 method / 上游调用) | 现实现(定聚 / 智慧油客) | 企油通对应 | 差异要点 |
|
||
|---|---|---|---|
|
||
| 下单 / 分油 `syb.oil.oilCard.share` → `oilOilCardShare` | 定聚 `/api/cnpcbp/order`,同步返回 `trade_no/state` | **7.7 `createAndSendQuota`**(+ 7.8 查结果) | 由「给手机号发一张固定面值油券」变为「按 `waybill_list.employee_list` 给司机发额度」;**异步**,需 7.8 轮询;平安通道 `id_card` 必填;金额单位分;`batch_no/waybill_no/waybill_no_code` 需加企业前缀 |
|
||
| 库存查询 `syb.oil.oilCard.stockList` → `stockList` | 定聚 `/api/cnpcbp/queryStock`(`quantity`) | **7.11 `distributable`**(企业资金余额,平安) | 企油通无「油券库存」概念,是**企业账户可发放资金上限**;支付宝通道不支持;勿高频轮询 |
|
||
| 分油记录查询 `syb.oil.oilCard.shareList` → — | — | **7.9 `waybillQuotaDetail`** / **7.17 `getVoucherList`** | 7.17 须 RSA 验签;返回结构差异大(凭证 / 运单明细) |
|
||
| 订单状态查询 `syb.oil.oilCard.orderStatus` → — | 读本地 `partners_order` | **7.8 `waybillBatch`**(发放态)/ **7.9**(消费态)/ **7.12**(余额态) | 状态分散在多个接口,无「单笔订单聚合状态」 |
|
||
| 核销二维码 `syb.pay.qrCode.request` → `payQrCodeRequest` | 定聚 `/api/cnpcbp/getUseCode`(`useQrCodeUrl` 二维码链接) | **7.15 H5 跳转地址(免登)** | **不再是二维码字符串,是 H5 URL**;签名算法完全不同(大写 MD5 → SHA1withRSA);带 `creditcode` 时须企业 `approved`。**小程序 `order/qrCodeImg` 出参 base64 图不能变** → 服务端需把 H5 URL 转二维码图 |
|
||
| 撤销分油(后台 `cancelShare`,当前坏) | 曾经 `SybOil::oilOilCardCancelShare` | **7.16 `adjustVoucher`**(`change_type=03` 减额度) | 须 RSA 验签;金额单位元;先 7.17 拿 `quota_id` |
|
||
| 分油结果回调 `partnersoil.php` / `oil.php`(method `oil`/`oil_partners`,`trade_no`+`useStatus=1`) | 定聚主动推 | **无对应推送** → 改为主动查 **7.8** | 企油通发放无「成功推送」,须轮询 |
|
||
| 加油/核销结果回调 `partnersoiluse.php` / `oiluse.php`(method `use`/`use_partners`,`useStatus=2`) | 定聚主动推 | **7.10 `waybillConsumeCallback`** | 回调地址由我方提供并配置;**我方须返回 `{"code":"100","msg":"Success"}`**(现有返回 `OK` / `{"code":"00"}`,不匹配) |
|
||
| 油站列表 `syb.base.gasStation.list` → `baseGasStationList` | 定聚 `/api/cnpcbp/stations`(Station.php 却用 SybOil,已坏) | **文档无公开油站接口**(H5 内自带选站) | 小程序 `station/list` 需重新评估:或保留定聚、或去掉、或改为静态/其它源 **【待确认】** |
|
||
| 发票(SybOil 有 `payInvoiceRequest/Status`) | 未接入下单平台链路 | **7.14 `invoice`** | 按月企业维度 |
|
||
| 我方 → 下单平台回调 `syb.notify.oilCard.change`(`PartnersOil`) | 生效 | **保持不变**,内部把企油通字段翻译回该结构 | 契约层,不改 |
|
||
| 企业开户 / 账户 | **旧系统无此概念**(`yoshop_company` 直接填 orgNo/appKey) | **7.2 / 7.4 / 7.5 / 7.6 / 7.22** | 全新流程:企业创建须审核 + 线下开户 + 异步回调 |
|
||
| 司机建档 / 三证 | 旧系统「借」`yoshop_account` 池身份 | **7.18 `saveDriverDoc`** + 7.7 `employee_list` 建档 | 实名二要素核验;司机须属于企业 |
|
||
| 提现 | 无 | **7.20 / 7.21**(新增能力,平安) | 可选 |
|
||
|
||
---
|
||
|
||
## 10. 当前发现的问题与风险(已按 0.5 决策收敛)
|
||
|
||
> 图例:✅ 决策已消解 ・ 🔴 待处理阻塞项(需你拍板 / 需对接人补料) ・ 🟡 施工注意项
|
||
|
||
| # | 风险 | 级别 | 结论 / 处理方向 |
|
||
|---|---|---|---|
|
||
| R-01 | 业务模型差异(油券库存 vs 企业运单额度) | ✅ | 决策 2/3/4:单企业 + 一张订单一次 `createAndSendQuota`(1 batch / 1 waybill / 1 employee);「商品面值」= `quota_amount`(元→分);不再有「平台油券库存」概念 |
|
||
| R-02 | 「废弃四方平台」范围 | ✅ | 决策 1:`SybOil` + `IdingjuOil` 全部废弃,不灰度并存 |
|
||
| R-03 | 企业开户不可即时(7.2→7.4) | ✅ | 决策 2:线下已开户,系统内**不实现** 7.2/7.4,`business_license` 直接配置;7.5/7.6/7.22 作可选核对 |
|
||
| R-04 | 发放异步两段式(7.7 受理 → 7.8 轮询) | 🟡 | 新增 `qyt_poll_queue` 延迟队列轮询 7.8;`partners_order` 增发放态字段 |
|
||
| R-05 | 无「发放成功」推送 | 🟡 | 同 R-04,靠轮询 7.8 `handle_status` 驱动 `notify_queue` |
|
||
| R-06 | 核销形态:二维码字符串 → H5 免登 URL(7.15) | 🟡 | 下单平台链路 `getPayQrCode` 出参 `qrCode` 直接放 H5 URL(本就是链接,下单平台侧生成二维码逻辑不受影响);7.15 特殊签名需新写。小程序 `order/qrCodeImg` 因链路停用(决策 5)不涉及 |
|
||
| R-07 | 7.16/7.17 需 `id_card`,但下单平台不传(决策 6) | 🟡→🔴 | 决策 9:**撤销/退款做**(企油通有 7.16)。但 7.16 的 `quota_id` 来自 7.17,而 7.17 需 `id_card`。落地方案:先尝试从 7.7 受理响应 / 7.8 结果 / 7.9 明细里拿到可用的凭证标识并落库(`quota_id`);若均拿不到 → 撤销请求要求下单平台补传 `id_card`。**具体以联调时对接人确认的「7.16 定位方式」为准(R-19)** |
|
||
| R-08 | 金额单位混用(分/元) | 🟡 | 新增单位换算 helper,`QytOil` 内部统一 |
|
||
| R-09 | 全平台唯一编号需企业前缀 | 🟡 | 定义前缀规则(如 `HM` + 环境标识),`batch_no/waybill_no/waybill_no_code` 由 `saleOrderNo`/`order_id` 派生并落库 |
|
||
| R-10 | 库存查询语义(`syb.oil.oilCard.stockList` → `/oilCard/stock`) | ✅ | 决策:企油通没有就不接。接口壳保留(防下单平台报错),数据来源改为我方 `yoshop_partners_goods.stock_num`(后台仍可分配),不再调用上游;`Company::stock` / `store/Goods.php` 的上游库存同步移除。**【待确认下单平台是否仍调用该接口】**,如不调用后续可直接下线 |
|
||
| R-11 | 签名/加密体系全新 | 🟡 | 新建 `app/common/crypto/Qyt.php`(业务信封 RSA 签名 + 7.15 H5 特殊签名 + 7.16/7.17 RSA 验签) |
|
||
| R-12 | 7.10 回调需返回 `{"code":"100","msg":"Success"}` 且需验签 | 🟡 | 新回调入口独立实现,不复用 `SybNotify` 的 `OK` 返回 |
|
||
| R-13 | `store/controller/Order.php::cancelShare` 调用未定义方法(已坏) | 🟡 | 属小程序链路(决策 5 停用);本次移除该分支或改指向「按订单 7.16 撤销」(受 R-07 约束) |
|
||
| R-14 | `goods_no ↔ orgNo` 硬编码散落 7 处 | 🟡 | 单企业后 `orgNo` 概念消失,`goods_no → voucher_name/面值` 收敛为 `config/qyt.php` 映射或读 `yoshop_goods` |
|
||
| R-15 | 退款/取消无上游回收 | 🟡 | 决策 9:做。新增入站 method `syb.oil.oilCard.cancelShare`(.docx 未定义,属慧明宝契约小扩展)→ 我方查凭证 → 7.16 `change_type=03` 减额度 → 回写 + 回调下单平台(optType=cancel_share, type=sub) |
|
||
| R-16 | `Station.php` / `store/Goods.php` 依赖已停用 SybOil | 🟡 | 决策 5:一并停用/摘除;`store/Goods.php` 库存同步改为不依赖上游 |
|
||
| R-17 | `app/admin`、`yoshop_merchant` 支付聚合 | ✅ | 决策 8:范围外,不动 |
|
||
| R-18 | 敏感信息明文(config/DB 私钥) | 🟡 | 企油通密钥放 `config/qyt.php` + `.env`,不写进 `yoshop_*` 表 |
|
||
| R-19 | 环境参数需线下索取 | 🔴 | 需对接人给:测试/正式域名、`appId`、业务密钥/公私钥、`institution_id`、7.10 回调地址配置方式、7.15 落地页 appId |
|
||
| R-20 | 文档只覆盖第 7 章 | 🔴 | 7.15 落地页参数、`institution_id` 分配、拼签字段明细需补 |
|
||
| R-21 | 小程序历史油券订单数据 | 🟡 | `yoshop_order_goods` 大量 `zsy_ticket` 旧数据只读保留;后台订单页兼容旧/新字段展示 |
|
||
|
||
### 决策补充(2026-09-01 第二轮)
|
||
|
||
| # | 议题 | 决策 |
|
||
|---|---|---|
|
||
| 9 | 撤销 / 退款 | **做**(企油通有 7.16 `adjustVoucher`)。新增入站 method `syb.oil.oilCard.cancelShare` → 我方定位凭证 → 7.16 `change_type=03` 减额度 → 回写 + 回调下单平台。凭证定位方式(是否需 `id_card`)以联调时对接人确认为准 |
|
||
| 10 | `/oilCard/stock` 库存 | 企油通没有就不接。接口壳保留、数据取我方 `yoshop_partners_goods`,不再同步上游 |
|
||
| 11 | 回调下单平台字段 | **不硬凑**。所有字段严格按企油通实际返回来填,企油通没有的(如旧 `shareNo`)就填空 / 不下发。发放阶段 `shareNo` 可留空或填 `waybill_no_code`;消费阶段填企油通 `order_code` |
|
||
| 12 | 后台范围 | 「满足接口 + 满足运营」——凡企油通有、运营用得上的都进后台:发放结果查询(7.8)、加油明细(7.9)、H5 加油链接(7.15)、消费流水、企业余额(7.11)、企业信息(7.5/7.6)、发票下载(7.14) |
|
||
|
||
### 决策补充(2026-09-01 第三轮 · 施工细节)
|
||
|
||
| # | 议题 | 决策 |
|
||
|---|---|---|
|
||
| 13 | 企油通订单字段落库 | 直接加到 `yoshop_partners_order` 主表(不建关联表);发放态复用 `oil_status_zsy` |
|
||
| 14 | `name` 缺失 | 兜底占位(`"司机"+手机尾4位`),不阻断下单 |
|
||
| 15 | `qrCode` 返回 | 直接把 7.15 H5 URL 放进 `qrCode` 字段,不转二维码图 |
|
||
| 16 | 发放结果获取 | 延迟队列退避轮询 7.8(新增 `qyt_poll_queue` + `qyt:poll` 命令) |
|
||
| 17 | 7.10 消费回调入口 | 新建独立入口 `public/qytconsume.php` |
|
||
| 18 | 小程序油品链路 | 后端停止触发,相关代码**保留不删** |
|
||
| 19 | 旧上游代码(SybOil/IdingjuOil/…) | 本期保留不删、只停止调用;全链路联调通过后在收尾阶段统一删除 |
|
||
| 20 | 后台「企业管理」 | 改造现有「分油公司」菜单为「企业管理」页(复用菜单/路由/权限) |
|
||
| 21 | 施工节奏 | 先出 DB 迁移 + `config/qyt.php` + `Qyt.php` / `QytOil.php` 骨架审核,确认后再动队列/控制器 |
|
||
|
||
### 仍需对接人提供(R-19/R-20,阻塞联调,不阻塞脚手架开发)
|
||
|
||
测试 + 正式域名、`appId`、业务 RSA 公私钥与**业务接口拼签字段顺序**、`institution_id`(支付宝企业码通道必填)、7.10 回调地址如何配置、7.15 H5 落地页 `appId` 与签名字段清单、7.16 凭证定位方式。
|
||
|
||
---
|
||
|
||
## 附 B. 第二阶段 A-1 交付物(骨架,待审)
|
||
|
||
| 文件 | 状态 | 说明 |
|
||
|---|---|---|
|
||
| `server-tp6/qyt_migration.sql` | 新增 | `yoshop_partners_order` 加 14 字段 + 2 索引;新建 `yoshop_qyt_consume`;含回滚脚本。**执行前请审字段** |
|
||
| `server-tp6/config/qyt.php` | 新增 | 配置骨架;标 ★ 的值待对接人给(用 `.env` 覆盖) |
|
||
| `server-tp6/app/common/crypto/Qyt.php` | 新增 | 业务信封 / 7.15 H5 签名 / 验签;`bizSign()` 的拼签规则标 **TODO 待对接人确认**(默认走 7.15 同族算法) |
|
||
| `server-tp6/app/common/service/QytOil.php` | 新增 | 企油通客户端:7.7/7.8/7.9/7.11/7.14/7.15/7.16/7.17;元↔分、编号生成、日志工具 |
|
||
|
||
> 均为**新增文件,未触碰任何现有文件**。审核通过后再进入 A-2(改 `PartnersQueue` / 新增 `QytPollQueue` / `QytNotify` / 改 `OilCard.php` / 改 `CallbackQueue`)。
|
||
|
||
---
|
||
|
||
## 附 C. 第二阶段 A-2 交付物(下单平台链路打通,待审)
|
||
|
||
> ⚠️ **部署前必须先执行 `qyt_migration.sql`**(`yoshop_partners_order` 会用到新列)。
|
||
|
||
### 新增文件
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `app/console/command/QytPollQueue.php` | `qyt:poll` 命令:退避轮询 7.8 拿发放结果,成功→写订单+投 `notify_queue`;超次数标记人工核对 |
|
||
| `app/api/controller/QytNotify.php` | `/qytNotify/consume`:接收 7.10,验签(TODO),落 `callback_queue`(method `qyt_consume`),返回 `{"code":"100","msg":"Success"}` |
|
||
| `public/qytconsume.php` | 7.10 回调入口(配到企油通后台的地址) |
|
||
|
||
### 改动文件(现有)
|
||
|
||
| 文件 | 改动 |
|
||
|---|---|
|
||
| `config/console.php` | 注册 `qyt:poll` |
|
||
| `app/console/command/PartnersQueue.php` | 整个 `processMessage` 重写:`IdingjuOil::oilOilCardShare` → 生成企业前缀编号 + `QytOil::createAndSendQuota`(7.7 受理) → 受理成功投 `qyt_poll_queue`。删除硬编码 `getCompany()` |
|
||
| `app/console/command/CallbackQueue.php` | **仅新增** `case "qyt_consume"`(写 `yoshop_qyt_consume` + 更新订单核销 + 投 `notify_queue`);旧 `oil/use/oil_partners/use_partners` 分支保留不动 |
|
||
| `app/api/controller/OilCard.php` | ①`use QytOil` ②`share()` 加 `name` 入参 + 兜底占位 + `saveOrder` 增 `driver_name/passageway` ③`getPayQrCode()` 改 `QytOil::h5Url`(出参 `qrCode` 结构不变)④**新增 `cancelShare()`**(method `syb.oil.oilCard.cancelShare` → 7.17 定位 `quota_id` → 7.16 减额度 → 投 `notify_queue` optType=`cancel_share`)。`getCompany()`/`IdingjuOil` import 保留(死代码,收尾清) |
|
||
| `app/api/service/order/PaySuccess.php` | `shareOil()` 的 `zsy_ticket` 分支加 `continue` —— 小程序支付成功后不再触发上游(优惠券分支保留) |
|
||
|
||
### A-2 新增待确认
|
||
|
||
- **`optType=cancel_share`**:`NotifyQueue` 把撤销通知发给下单平台时 `type=sub / optType=cancel_share`(`.docx` 回调 optType 枚举只有 share_volume/share_oil/add_oil)。需与下单平台确认能否识别,或改用其约定值。
|
||
- **7.7 响应 `data.status`**:文档写 `1 成功 / 2 失败`,此处「成功」按「受理成功」处理;如企油通实际语义不同需调 `PartnersQueue`。
|
||
- **7.8 `list[].handle_status`**:按 `1待处理/2成功/3失败` 匹配;如字段名/取值不同需调 `QytPollQueue`。
|
||
|
||
### 未动(留给 A-3)
|
||
|
||
小程序核销 `app/api/controller/Order.php::qrCode/qrCodeImg`、`Station.php`、`store/controller/Order.php`(小程序订单后台)、`store/controller/Company.php::stock`、`store/controller/Goods.php`、`store/controller/partners/Order.php`(下单平台订单后台运维)、admin-vue 页面。
|
||
|
||
---
|
||
|
||
## 附 D. 并发 / 原子性加固(A-2 补丁,已并入 A-2 交付物)
|
||
|
||
### 状态机(`yoshop_partners_order`)
|
||
|
||
| `oil_status_zsy` | 含义 | 迁入方 | 迁入条件 |
|
||
|---|---|---|---|
|
||
| 0 | 未提交 | 建单默认 | — |
|
||
| 1 | 已受理待发放 | `PartnersQueue` | `WHERE oil_status_zsy=0`(7.7 受理成功后) |
|
||
| 2 | 发放成功 | `QytPollQueue` | `WHERE oil_status=0 AND oil_status_zsy=1`(7.8 handle_status=2) |
|
||
| 3 | 发放失败 | `PartnersQueue` / `QytPollQueue` | `WHERE oil_status_zsy IN (0,1)`(7.7 拒绝 / 7.8=3 / 轮询超时) |
|
||
| 5 | 已撤销 | `OilCard::cancelShare` | `WHERE oil_status=1 AND oil_status_zsy=2 AND use_status=0`(7.16 成功) |
|
||
|
||
`use_status` 0→1:`CallbackQueue` `WHERE use_status=0 AND oil_status=1`(7.10 消费)。
|
||
|
||
**每个状态迁移都是条件 `UPDATE ... WHERE 期望值`,`affected_rows=1` 的进程才推送下游队列** → 天然幂等,可多进程 / 重复消息安全。
|
||
|
||
### 具体措施
|
||
|
||
| 场景 | 风险 | 措施 |
|
||
|---|---|---|
|
||
| `OilCard::share` 同一 `saleOrderNo` 并发 | 先查后插竞态 → 重复建单 / 库存超扣 | DB 唯一键 `uk_partner_saleorder(partners_id, partners_order_no)`;命中已存在订单 → **幂等返回原结果**;`saveOrder` 捕获 Duplicate 再幂等返回 |
|
||
| `PartnersQueue` 同一 order 被多 worker / 重复消息处理 | 重复调 7.7 | `RedisLock('qyt:send:{order_id}', 60s)` 串行 + 锁内重读状态;`batch_no` 确定性派生,重试用同一值,依赖企油通按 `batch_no` 幂等(`dup_batch_hints` 命中即按已受理处理) |
|
||
| 7.7 成功但 worker 崩溃(未及入轮询队列) | 订单卡在「已受理」永不发放 | `oil_status_zsy` 只在 7.7 结果确定后离开 0;`QytPollQueue::reconcile()`(空闲每 60s)补投:`oil_status_zsy=0` 超 2min → 重投 `partners_queue`;`oil_status_zsy=1` 且 15min 无进展 → 重投 `qyt_poll_queue` |
|
||
| `QytPollQueue` 多 worker / 延迟队列并发迁移 | 同一 order 重复 7.8 → 重复回调下单平台 | `QueueService::migrateDelayedToReady` 改为**先 `zrem` 抢占再入队**;发放成功用条件 UPDATE 1→2,仅胜出者推 `notify_queue` |
|
||
| 企油通重推 7.10 | 重复消费流水 / 重复回调 | `yoshop_qyt_consume` 唯一键 `uk_consume(waybill_no_code, order_code)` + 插入捕获 Duplicate;`use_status` 条件跃迁 0→1,仅胜出者推 `notify_queue` |
|
||
| `cancelShare` 并发 / 与 7.10 消费竞争 | 重复调 7.16 减额度 / 撤销与加油冲突 | `RedisLock('qyt:cancel:{order_id}', 60s)` + 条件占位 `WHERE oil_status_zsy=2 AND use_status=0`;7.16 失败回滚 `oil_text`;成功再条件跃迁 2→5(仍要求未核销),冲突则返回人工核对 |
|
||
| `callback_queue` / `notify_queue` 单消费者假设 | 与旧代码一致 | 建议单进程;即使多进程,因全链路条件跃迁,最坏只是日志重复 |
|
||
|
||
### 遗留(联调时与对接人确认)
|
||
|
||
- **7.7 幂等键**:确认企油通是否严格按 `batch_no` 去重,重复提交返回什么(用于 `dup_batch_hints` 精确匹配)。
|
||
- **7.16 幂等**:文档无幂等键;当前靠 `RedisLock` + 条件占位防重,但跨进程锁过期(60s)后仍有极小窗口。若企油通提供幂等键(如 `out_trade_no`)应接入。
|
||
- **`RedisLock`** 用 `config('redis')`,`QueueService` 用硬编码 `127.0.0.1:6379` —— 生产需统一(本次未动 `QueueService` 连接配置)。
|
||
|
||
---
|
||
|
||
## 附 E. 对下单平台接口文档更新(`慧明宝供应链平台接口文档V1.0.17.docx`)
|
||
|
||
在原 `V1.0.16.docx` 基础上做增量修改,保留原文件为历史。改动:
|
||
|
||
| # | 章节 | 变更 |
|
||
|---|---|---|
|
||
| 1 | 3.2.1 用户分油 请求体 | 新增 `name`(司机姓名,可选,String V50,缺失平台兜底) |
|
||
| 2 | 3.5.1 油卡变动通知 `optType` | 新增取值 `cancel_share`(撤销分油,配 `type=sub`) |
|
||
| 3 | 文末新增《附录:V1.0.17 变更说明》 | ①`share` 增 `name` + 异步发放语义 + `saleOrderNo` 幂等;②**新增接口 `syb.oil.oilCard.cancelShare`**(撤销分油,`/oilCard/cancelShare`,入参 `orgNo` / `oilCardNo` 或 `saleOrderNo` / `id_card`,出参 `oilCardNo` `amount`);③`qrCode.request` 返回值由二维码串改为 H5 免登地址;④`stockList` 返回值改为平台内部额度统计;⑤`notify` 空值兼容说明;⑥修订记录 |
|
||
|
||
制作方式:`unpack → merge_runs.py → 编辑 document.xml → 重新打包`,`validate.py` XSD 校验通过。
|
||
**注意**:①本机无 LibreOffice,未能渲染 PDF 目视核对,建议用 Word 打开确认排版;②新增《附录》为普通标题,不在目录中,Word 打开时可「更新域」重建目录;③`merge_runs` 合并了冗余样式标签(内容与渲染不变),故 `.docx` 体积小于原文件属正常。
|
||
|
||
---
|
||
|
||
## 附 F. 范围收敛(2026-09-03 · 最终版)—— 支付宝企业码通道,仅 3 个上游接口
|
||
|
||
> 需求方最终确认:**只对接支付宝企业码通道**,上游实际只用 3 个接口:
|
||
> **7.7 运单油费下发 / 7.15 H5 跳转地址 / 7.10 运单加油明细推送(异步回调)**。
|
||
> 司机姓名 + 手机号由下单平台必传。不做撤销(企油通仅 7.16 调整额度,本期不用)。
|
||
> 本节内容**取代**前文附 B / C / D / E 中与轮询、撤销、平安通道、7.8/7.9/7.11/7.14/7.16/7.17 相关的描述。
|
||
|
||
### 与之前版本的差异
|
||
|
||
| 项 | 之前(附 B/C/D) | 现在(最终) |
|
||
|---|---|---|
|
||
| 上游接口 | 7.7 + 7.8 轮询 + 7.15 + 7.10 + 7.16/7.17 撤销 + 可选 7.9/7.11/7.14 | **仅 7.7 + 7.15 + 7.10** |
|
||
| 发放结果 | 7.7 受理 → `qyt_poll_queue` 退避轮询 7.8 | **7.7 受理成功即视为发放成功**(支付宝企业码通道),直接回调下单平台。删除 `QytPollQueue` / `qyt:poll` / `qyt_poll_queue` |
|
||
| 通道 | 1/2 可切换 + `institution_id` | **固定 `passageway=1`**(支付宝企业码)+ `institution_id` 必填 |
|
||
| 司机姓名 `name` | 可选,缺失兜底占位 | **必填**,下单平台不传 → 返回 `0001 缺少必填请求参数 name`。(`mobile` 本就必填) |
|
||
| 撤销分油 | 新增入站 `syb.oil.oilCard.cancelShare` → 7.17/7.16 | **不做**。移除该 method、`RedisLock('qyt:cancel:…')`、`QytOil::getVoucherList/adjustVoucher` |
|
||
| 7.7 入参 | 含 `id_card`、`effective_*`、`institution_config`、`passageway` 动态 | 精简为:`batch_no` / `business_license` / `passageway="1"` / `institution_id` / `waybill_list:[{waybill_no, employee_list:[{mobile, name, quota_amount(分), voucher_name, effective_start:"", effective_end:"", waybill_no_code}]}]` |
|
||
| DB 字段 | 含 `passageway` / `quota_id` / `poll_times` / `last_poll_time` | 移除以上 4 个;保留 `driver_name` / `batch_no` / `waybill_no` / `waybill_no_code` / `qyt_order_code` / 消费明细 5 项 |
|
||
| `oil_status_zsy` 取值 | 0/1/2/3/5 | **0 未提交 / 2 发放成功 / 3 发放失败**(无 1 待处理、无 5 撤销) |
|
||
| `yoshop_qyt_consume` | 含 `quota_id` / `passageway` 列 | 移除该 2 列 |
|
||
|
||
### 最终文件清单
|
||
|
||
| 文件 | 状态 |
|
||
|---|---|
|
||
| `config/qyt.php` | 精简(去通道切换 / 轮询配置) |
|
||
| `app/common/crypto/Qyt.php` | 不变(信封 + 7.15 签名 + 验签) |
|
||
| `app/common/service/QytOil.php` | **精简为 `createAndSendQuota`(7.7) + `h5Url`(7.15)** + `post/curlPost` + 工具 |
|
||
| `app/console/command/PartnersQueue.php` | 7.7 受理成功=发放成功 → 条件跃迁 0→2 → 回调;含 `reconcile()` 兜底补投 |
|
||
| `app/console/command/QytPollQueue.php` | **已删除** |
|
||
| `config/console.php` | 移除 `qyt:poll` 注册 |
|
||
| `app/api/controller/QytNotify.php` + `public/qytconsume.php` | 不变(7.10 入口,返回 `{"code":"100","msg":"Success"}`) |
|
||
| `app/console/command/CallbackQueue.php` | `qyt_consume` 分支:`use_status` 条件跃迁 0→1 + `yoshop_qyt_consume` 去重;旧定聚分支保留 |
|
||
| `app/api/controller/OilCard.php` | `share` 加必填 `name`;`getPayQrCode` → `QytOil::h5Url`;**移除 `cancelShare`**;`saveOrder` 幂等 |
|
||
| `app/api/service/order/PaySuccess.php` | `shareOil()` 的 `zsy_ticket` 分支 `continue`(小程序停用) |
|
||
| `app/common/service/QueueService.php` | `migrateDelayedToReady` 改 zrem-first(仅 `notify_queue` 用到延迟队列) |
|
||
| `qyt_migration.sql` | 精简字段 + 保留 2 个唯一键 |
|
||
| `慧明宝供应链平台接口文档V1.0.17.docx` | `name` 必填;移除 cancelShare;发放语义改「受理即成功」;无 cancel_share |
|
||
|
||
### 并发/原子性(最终,简化后)
|
||
|
||
- **`share`**:`uk_partner_saleorder(partners_id, partners_order_no)` 唯一键 + 幂等返回原结果 + `saveOrder` 捕获 Duplicate。
|
||
- **`PartnersQueue`**:`RedisLock('qyt:send:{order_id}', 60s)` 串行 + 锁内重读;发放态跃迁 `UPDATE ... WHERE oil_status_zsy=0`,`affected=1` 才回调下单平台;`batch_no` 确定性派生,重试用同一值,靠企油通按 `batch_no` 幂等(`dup_batch_hints` 命中即按已发放);空闲 `reconcile()` 每 60s 补投丢失的 `partners_queue` 消息。
|
||
- **`CallbackQueue` 7.10**:`yoshop_qyt_consume` 唯一键去重 + `use_status` 跃迁 `WHERE use_status=0 AND oil_status=1`,`affected=1` 才回调;企油通重推安全。
|
||
- **`NotifyQueue`**:原有 3 次退避重试不变;报文结构 `syb.notify.oilCard.change` 不变。
|
||
|
||
### 联调前仍需对接人提供
|
||
|
||
测试/正式域名、`appId`、业务接口 **RSA 拼签字段顺序**、`institution_id`、7.10 回调地址配置方式、7.15 H5 落地页 `appId`;确认 **7.7 支付宝企业码通道响应 `data.status` 语义**(是否 1=受理即发放成功)与 **batch_no 重复提交的返回文案**(校准 `dup_batch_hints`)。
|
||
|
||
## 11. 改造方案(基于 0.5 决策,待你对 §10「🔴 待拍板」项给结论后即可开工)
|
||
|
||
### 11.1 边界原则
|
||
|
||
- **完全不动**:`mobile-uniapp` 全部;`NotifyQueue` + `PartnersOil` 对下单平台回调的**报文结构**(`syb.notify.oilCard.change`);`yoshop_partners` / `yoshop_partners_goods` 表结构;`app/admin`;`yoshop_merchant` 相关。
|
||
- **最小扩展**:`app/api/controller/OilCard.php` 的 `syb.oil.oilCard.share` 仅新增可选入参 `name`。其余入站 method / URL / 加密不变。
|
||
- **整体替换**:「我们 → 上游」这一层——删除 `SybOil` / `IdingjuOil` 调用,换 `QytOil`。
|
||
- **停用**:小程序油品发放链路(`PaySuccess::shareOil` 油券分支、`Order::qrCode / qrCodeImg`、`Station`)。
|
||
|
||
### 11.2 新增 / 改动文件清单(预估)
|
||
|
||
| 类型 | 文件 | 说明 |
|
||
|---|---|---|
|
||
| 新增 | `config/qyt.php` | 域名、`appId`、公私钥、`business_license`、`passageway` 默认值、`institution_id`、编号前缀、7.10 回调地址、7.15 落地页地址 |
|
||
| 新增 | `app/common/crypto/Qyt.php` | 三种签名/验签:①业务信封 ②7.15 H5 签名 ③7.16/7.17 RSA 验签 |
|
||
| 新增 | `app/common/service/QytOil.php` | `createAndSendQuota(7.7)` / `waybillBatch(7.8)` / `waybillQuotaDetail(7.9)` / `h5Url(7.15)` / `getVoucherList(7.17)` / `adjustVoucher(7.16)` / (可选)`distributable / invoice / enterpriseList` |
|
||
| 新增 | `public/qytconsume.php` + `app/api/controller/QytNotify.php` | 7.10 消费回调入口,验签,返回 `{"code":"100","msg":"Success"}`,落 `callback_queue`(method `qyt_consume`) |
|
||
| 新增 | `app/console/command/QytPollQueue.php`(注册 `qyt:poll`) | 退避轮询 7.8 发放结果 |
|
||
| 新增 | `app/common/library/Amount.php`(或并入 helper) | 元↔分 |
|
||
| 改 | `app/console/command/PartnersQueue.php` | 换 `QytOil::createAndSendQuota`;受理成功入 `qyt_poll_queue` |
|
||
| 改 | `app/console/command/CallbackQueue.php` | 删定聚 `oil/use/oil_partners/use_partners` 分支,加 `qyt_consume` 分支 |
|
||
| 改 | `app/api/controller/OilCard.php` | `share` 加 `name`;`getPayQrCode` → `QytOil::h5Url`;`stock` 数据源改我方 `partners_goods`;**新增 `cancelShare` method**(7.16 减额度) |
|
||
| 改 | `app/api/service/order/PaySuccess.php` | 移除 `shareOil()` 油券分支(保留优惠券分支) |
|
||
| 改 | `app/store/controller/partners/Order.php` | `share` 改为「查发放结果(7.8)」;`qrCode` → h5Url;回调按钮走新队列 |
|
||
| 改 | `app/store/controller/Order.php` | 移除/改造小程序链路 `cancelShare / qrCode / share` |
|
||
| 改 | `app/api/controller/Station.php`、`app/store/controller/Goods.php` | 停用/摘除上游依赖 |
|
||
| 删/弃 | `SybOil.php`、`IdingjuOil.php`、`crypto/{Crypto,Idingju}.php`、`config/crypto.php`、`app/api/controller/syb/*`、`public/{oil,oiluse,partnersoil,partnersoiluse}.php` | 确认无引用后移除(可先保留一版做回滚) |
|
||
| 改 | admin-vue `src/views/partners/order/**`、`src/views/company/**` | 见 11.6 |
|
||
|
||
### 11.3 数据库改动(全部增量加字段,不改现有字段 / 类型)
|
||
|
||
`yoshop_partners_order` 增加:`driver_name`(司机姓名)、`passageway`(本单通道)、`batch_no`、`waybill_no`、`waybill_no_code`(唯一索引,回调匹配)、`quota_id`(7.17 凭证 ID)、`qyt_order_code`(7.9/7.19 订单号)、`handle_status`(7.8 单条发放态 1/2/3)、`poll_times` / `last_poll_time`、以及消费明细 `station_name / litter / oil_name / pay_fee(分) / consume_time`。
|
||
|
||
新增表(建议):`yoshop_qyt_consume`(7.10 每笔消费流水)。
|
||
|
||
> `yoshop_company` / `yoshop_account`:单企业 + 取消用户池后闲置。**不删表**(保历史数据),改为不再写入;`business_license` 等改放 `config/qyt.php`。
|
||
|
||
### 11.4 下单平台链路 端到端流程(改造后)
|
||
|
||
```
|
||
下单平台 POST /partners.php/oilCard/share (method=syb.oil.oilCard.share, RSA信封)
|
||
body: orgNo, goodsNo, mobile, name(新增), saleOrderNo, oilCardType=zsy_ticket
|
||
↓ OilCard.php::share
|
||
· 校验 appKey→yoshop_partners、requestId 幂等、库存(R-10)
|
||
· 建 yoshop_partners_order(order_status=10, driver_name=name)
|
||
· 生成 batch_no / waybill_no / waybill_no_code(企业前缀 + saleOrderNo/order_id)
|
||
· push partners_queue → 返回 { oilCardNo, amount }(结构不变)
|
||
↓ PartnersQueue → QytOil::createAndSendQuota(7.7)
|
||
params = { batch_no, business_license(配置), passageway(配置, 默认1),
|
||
institution_id(配置, 通道1必填),
|
||
waybill_list:[{ waybill_no, waybill_no_code,
|
||
employee_list:[{ mobile, name, quota_amount(元→分),
|
||
voucher_name, effective_start:"", effective_end:"" }] }] }
|
||
· status=1 受理成功 → 记 batch_no, handle_status=1 → push qyt_poll_queue(延迟)
|
||
· status=2 → oil_status_zsy=3, oil_text=msg
|
||
↓ QytPollQueue → QytOil::waybillBatch(7.8) by batch_no(退避轮询)
|
||
· list[0].handle_status==2 → oil_status=1, oil_status_zsy=2, quota_id → push notify_queue(share_oil)
|
||
· ==3 → oil_status_zsy=3, oil_text=error_msg
|
||
· ==1 且未超次数 → 再次延迟入队
|
||
↓ 核销:下单平台 POST /oilCard/getPayQrCode → QytOil::h5Url(7.15)
|
||
· 返回 { qrCode: <H5免登URL> }(结构不变;下单平台侧原有「拿字符串生成二维码」逻辑不受影响)
|
||
↓ 司机加油后:企油通 POST public/qytconsume.php (7.10)
|
||
· QytNotify 验签 → 按 waybill_no_code / order_code 命中 order
|
||
· 写 yoshop_qyt_consume;use_status=1, use_time;返回 {"code":"100","msg":"Success"}
|
||
· push notify_queue(add_oil)
|
||
↓ NotifyQueue(报文结构不变)→ PartnersOil::sendRequest($partners.callback,
|
||
method=syb.notify.oilCard.change, body={ oilCardNo, amount, shareNo, type, optType })
|
||
```
|
||
|
||
**`name` 缺失兜底**:下单平台未传时用 `"司机"+mobile后4位` 占位(企业码通道不做姓名实名核验)—— **待你确认是否可接受**。
|
||
|
||
### 11.5 对下单平台回调(`syb.notify.oilCard.change`)字段映射(决策 11:不硬凑,按企油通实际返回填)
|
||
|
||
| 回调字段 | 旧值(定聚) | 新值(企油通) |
|
||
|---|---|---|
|
||
| `oilCardNo` | `partners_order.oilCardNo` | 不变(我方自生成) |
|
||
| `amount` | `total_price` | 不变 |
|
||
| `shareNo` | 定聚 `trade_no` | 发放阶段:留空或填 `waybill_no_code`;消费阶段:填企油通回调的 `order_code`。企油通无对应值时**填空字符串**,不硬造 |
|
||
| `type` / `optType` | add/sub、share_oil/add_oil/cancel_share | 不变;新增撤销场景 `type=sub, optType=cancel_share` |
|
||
|
||
> 保持报文**结构**与字段名不变(下单平台既有解析不受影响),只是个别字段值可能为空。
|
||
|
||
### 11.6 admin-vue 改动(决策 12:满足接口 + 满足运营)
|
||
|
||
- `views/partners/order/Index.vue`:列表增列「批次号 / 运单号 / 发放态 / 通道」;「手动分油」→「查询发放结果(7.8)」;「核销码」→「获取加油链接(7.15)」;增「撤销分油(7.16)」「加油明细(7.9)」。
|
||
- 新增「企业管理」页:企业对接参数 + 通道切换(1/2) + `institution_id` + 企业信息(7.5/7.6) + 企业余额(7.11) + 发票下载(7.14) + 消费流水查询。
|
||
- 订单详情页兼容「旧定聚字段 + 新企油通字段」两种展示。
|
||
- 旧「分油公司 / 分油用户」菜单:保留只读(历史数据),不再新增。
|
||
|
||
### 11.7 建议实施顺序
|
||
|
||
**A. 不依赖对接人环境料,可先做(脚手架 + 内部改造):**
|
||
1. DB 迁移脚本(`yoshop_partners_order` 加字段 + 新建 `yoshop_qyt_consume`)。
|
||
2. `config/qyt.php`(占位)+ `app/common/library` 单位/编号 helper。
|
||
3. `app/common/crypto/Qyt.php`(信封结构 + 7.15 算法已文档化可实现;业务接口拼签字段顺序留 TODO 待确认)。
|
||
4. `app/common/service/QytOil.php`(各接口入参组装 + 调用骨架)。
|
||
5. 改 `app/api/controller/OilCard.php`:`share` 加 `name`;新增 `cancelShare` method;`stock` 改内部数据源。
|
||
6. 改 `PartnersQueue` + 新增 `QytPollQueue`(`qyt:poll`) + `QytNotify` + `public/qytconsume.php` + 改 `CallbackQueue`。
|
||
7. 停用小程序油品链路(`PaySuccess::shareOil` 油券分支、`Order::qrCode/qrCodeImg`、`Station`、`store/Goods::stock`)。
|
||
8. admin-vue:`views/partners/order/**` + 新增「企业管理」页。
|
||
|
||
**B. 拿到对接人环境料后(R-19/R-20):**
|
||
9. 填 `config/qyt.php` 真值 + 补 `Qyt.php` 拼签字段顺序 + 7.16 凭证定位方式。
|
||
10. 测试环境联调:7.7 → 7.8 → 7.15 → 7.10(用 7.23 模拟消费)→ 7.16 撤销。
|
||
11. 全链路回归(下单→发放→轮询→核销→消费回调→回调下单平台→撤销)+ 旧数据展示。
|
||
|
||
**C. 收尾:**
|
||
12. 确认无引用后清理 `SybOil` / `IdingjuOil` / `crypto/{Crypto,Idingju}` / `config/crypto.php` / `app/api/controller/syb/*` / 旧入口文件。
|
||
|
||
---
|
||
|
||
## 附:本阶段已核查的关键文件清单
|
||
|
||
- 后端上游对接:`app/common/service/{SybOil,IdingjuOil,PartnersOil}.php`、`app/common/crypto/{Crypto,Idingju,RsaUtil}.php`、`config/{crypto,rsa}.php`
|
||
- 入站 API:`app/api/controller/OilCard.php`、`app/api/controller/SybNotify.php`、`app/api/controller/syb/*`、`app/api/controller/Station.php`
|
||
- 队列:`app/console/command/{CallbackQueue,PartnersQueue,NotifyQueue}.php`、`config/console.php`、`app/common/service/QueueService.php`
|
||
- 订单:`app/api/controller/Order.php`、`app/api/service/order/PaySuccess.php`、`app/api/service/main/order/PaySuccess.php`、`app/api/model/Order.php`、`app/api/model/partners/Order.php`、`app/common/model/partners/Order.php`
|
||
- 后台:`app/store/controller/{Order,Company,Partners}.php`、`app/store/controller/partners/Order.php`、`app/store/model/{Company,Partners}.php`、`app/common/enum/order/*`
|
||
- 入口:`public/{partners,partnersoil,partnersoiluse,oil,oiluse}.php`
|
||
- admin-vue:`src/config/router.config.js`、`src/api/{partners,company,order}/*`、`src/views/{company,partners,order,account}/**`
|
||
- mobile-uniapp:`config.js`、`api/{station,order,card,goods,checkout}.js`
|
||
- 数据库:`oil.sql` 中 `yoshop_{account,company,company_balance_log,partners,partners_goods,partners_order,order,order_goods,order_qrcode,order_record,request_log,merchant}` 建表与样例数据
|
||
- 文档:`企油通接口对接文档.md`(第 7 章 23 接口)、`慧明宝供应链平台接口文档V1.0.16.docx`(= 我们对下单平台的入站契约)
|
||
|
||
---
|
||
|
||
## 附 G. 后台功能适配 + 接口文档就地修订(2026-09-04)
|
||
|
||
### G1. 后台(app/store + admin-vue)适配
|
||
|
||
**下单平台订单管理**(运营日常用的「查看订单 / 处理订单」)
|
||
|
||
| 层 | 文件 | 改动 |
|
||
|---|---|---|
|
||
| 后端 | `app/store/controller/partners/Order.php` | **整体重写**。移除 `IdingjuOil` / `CompanyModel` / `getCompany()` 硬编码;`qrCode()` 改调 `QytOil::h5Url`(7.15);`share()` 改为「重新发放」——仅允许 `oil_status_zsy=3(发放失败)` 条件重置为 0 后重投 `partners_queue`(避免与在途单冲突);新增 `detail()` 返回订单 + `yoshop_qyt_consume` 加油流水;`oilCallback()/useCallback()` 保留为「重推结果给下单平台」并加状态前置校验 |
|
||
| 后端 | `app/store/model/partners/Order.php` | `getFilter()` 新增检索:司机姓名 `driver_name`、单号 `orderNo`(油卡编号/销售单号/批次号/运单号 模糊)、企油通发放态 `oil_status_zsy` |
|
||
| 前端 | `views/partners/order/Index.vue` | 搜索区加「司机姓名 / 单号 / 企油通发放态」,「用户电话」改「司机手机号」;列表新增「企油通单号(批次/运单)」「司机(姓名+手机)」「加油信息(油站/油品/升数/实付)」列,去掉旧「分油记录编号」列;状态列增加企油通发放态标签 + `oil_text` 失败原因;按钮文案改为 重新发放 / 加油链接 / 重推发放结果 / 重推加油结果 |
|
||
| 前端 | `views/partners/order/modules/PayForm.vue` | **重写**:原来把二维码串塞 `<iframe>`,现改为用 `vue-qr` 渲染 7.15 H5 免登地址二维码 + 只读链接框 + 一键复制(运营可直接把链接发给司机) |
|
||
| 前端 | `modules/{ShareForm,OilForm,UseForm}.vue`、`api/partners/order.js` | 标题与注释文案同步 |
|
||
|
||
> `views/partners/**`(合作商列表/新增/编辑/对接参数/余额)维护的是**下游接口账户**(orgNo / appKey / RSA 公私钥 / 回调地址 / 可售商品与额度),与上游换成企油通无关,**无需改动**;其中「商品额度」正是 `/oilCard/stock` 现在的数据来源。
|
||
|
||
**停用旧上游依赖的后台/小程序端点**(上游定聚、智慧油客已下线,这些接口再调只会超时或报错,统一改为明确提示,页面仍可查历史数据)
|
||
|
||
| 文件 | 方法 | 处理 |
|
||
|---|---|---|
|
||
| `app/api/controller/Order.php` | `qrCode()` / `qrCodeImg()` | 返回「该功能已停用」(小程序不改代码,只是拿到提示) |
|
||
| `app/api/controller/Station.php` | `list()` | 返回空列表(企油通无油站查询能力),小程序页面不报错 |
|
||
| `app/store/controller/Order.php` | `share()` / `cancelShare()` / `qrCode()` | 返回「小程序油品链路已停用」(顺带修掉了原先调用未定义方法的致命错误) |
|
||
| `app/store/controller/Company.php` | `stock()` | 返回「上游库存同步已停用」 |
|
||
| `app/store/controller/Goods.php` | `onReloadStock()` | 同上 |
|
||
| `app/store/controller/User.php` | `add()` / `oil()` | 分油用户池已停用,不再向上游注册用户 / 手动分油 |
|
||
|
||
> 其余 `new SybOil()` 残留经核对**均只用于写日志**(`saveLogStore`),无业务副作用;`PaySuccess::shareOil` 内的 `IdingjuOil` 调用位于已 `continue` 的分支,不可达。
|
||
|
||
### G2. 接口文档就地修订(不加变更说明章节)
|
||
|
||
`慧明宝供应链平台接口文档V1.0.17.docx` **直接在原文覆盖修改**,未新增任何「变更说明 / 附录」章节,并删除本期无用的接口与参数。
|
||
|
||
**版本 / 接口层面**
|
||
|
||
| # | 位置 | 改动 |
|
||
|---|---|---|
|
||
| 1 | 1.2 版本号 | V1.0.16 → **V1.0.17** |
|
||
| 2 | **3.4 基础数据查询 / 油站列表查询** | **整章删除**(企油通无油站查询能力;含请求应答表与报文示例,约 277KB) |
|
||
| 3 | 2.7 接口清单列表 | 删「油站查询」行;序号 5→4;付款码申请用途改为「获取司机免登加油地址(H5)」 |
|
||
| 4 | 目录 | 删除对应两条 TOC 条目 |
|
||
|
||
最终对外接口收敛为 4 个:`syb.oil.oilCard.share` / `syb.oil.oilCard.shareList` / `syb.pay.qrCode.request` / `syb.notify.oilCard.change`(另有正文中的 `stockList`、`orderStatus` 两个查询接口)。
|
||
|
||
**参数层面(去掉本期无用的传参)**
|
||
|
||
| 接口 | 删除 / 修改 |
|
||
|---|---|
|
||
| `syb.oil.oilCard.share` | **删请求体 `amount`**(金额由 `goodsNo` 面额决定,本期不传);**新增必填 `name`**(司机姓名 V50);`goodsNo` 约束 `?`→`1`;使用场景⑵ 改为「同步返回受理结果,发放结果由油卡变动通知推送(optType=share_oil)或用订单状态查询主动查」;请求报文示例同步删 `amount` 与注释行、补 `"name"` |
|
||
| `syb.pay.qrCode.request` | **删请求体 `longitude` / `latitude` / `oilCardType`** 三个参数(企油通 H5 免登不需要);API 描述改为「获取司机免登加油地址(H5)」;使用场景改写;返回值 `qrCode` 描述由「二维码链接」改为「**H5免登加油地址**」并去掉「2分钟有效/扫一次失效」旧口径;请求与应答报文示例同步更新(应答示例换成企油通 H5 地址样例) |
|
||
| `syb.oil.oilCard.stockList` | 使用场景改为「查询自身可下单额度与用量统计(平台内部额度,非上游实时库存)」 |
|
||
| `syb.oil.oilCard.shareList` | 返回字段 `num` 口径由「分油数量(升)」修正为「**购买数量(张)**」,与实现一致 |
|
||
| `syb.notify.oilCard.change` | `optType` 删除未使用的 `发券:share_volume`,仅保留 `share_oil` / `add_oil` |
|
||
|
||
**校验**:XML 良构 ✓、XSD `validate.py` 全部通过 ✓、段落 1717 → 1392、残留检查 `gasStation`/`油站`/`share_volume`/`二维码链接`/`longitude`/`latitude`/「变更说明」均为 **0**。
|
||
**仍未做**:本机无 LibreOffice,无法渲染 PDF 目视核对排版;删章后小节序号由 Word 样式自动重排,打开时建议「更新域」刷新目录。
|
||
|
||
---
|
||
|
||
## 附 H. 下单改为按金额直传(2026-09-06)
|
||
|
||
下单平台不再传 `goodsNo`(商品编码),改为**直接传 `amount`(金额,元)**。商品/面额概念从下单链路整体移除。
|
||
|
||
### 后端
|
||
|
||
| 文件 | 改动 |
|
||
|---|---|
|
||
| `app/api/controller/OilCard.php` | `share()` 入参 `goodsNo` → **`amount`**(必填,正则校验:元、≤2 位小数、>0);**删除**商品查找、`goods_sku` 平台库存校验、`partners_goods` 合作商额度校验、下单扣库存;落单金额三字段(`goods_price`/`total_price`/`total_pay_price`)统一取 `amount`;返回 `amount` 用传入值 |
|
||
| 同上 | **删除整个 `stock()` 方法**(`syb.oil.oilCard.stockList` 完全建立在 `goodsNo` 之上,已无意义);删除已失效的 `updateGoodsStockNum()`、`getCompany()`;清理 6 个不再使用的 `use` |
|
||
| 同上 | `shareList` 响应去 `productName`;`orderStatus` 响应去 `province` / `goods_name` / `goods_no`(这些字段现在恒为空) |
|
||
| `app/api/model/partners/Order.php` | `saveOrder()` 去掉 `PartnersGoods` 的 `setIncUseNum` / `setDecStockNum`,事务包装随之取消(单条写入无需事务) |
|
||
| `app/store/model/partners/Order.php` | 列表查询去掉 `goods.images.file` 关联与 `goods_no` 检索项 |
|
||
|
||
### 前端 admin-vue
|
||
|
||
`views/partners/order/Index.vue`:删除「商品编码」搜索项、「商品信息」列与 `GoodsItem` 组件引用;列名「油卡数量/油卡金额」→「数量/发放金额」,汇总文案→「发放总金额」。eslint **0 error**(warning 数与改动前一致)。
|
||
|
||
### 接口文档(就地修订,无变更说明章节)
|
||
|
||
| 位置 | 改动 |
|
||
|---|---|
|
||
| 3.2.1 用户分油 请求体 | **删 `goodsNo`**,**新增 `amount`**(必填,String V13,「本单发放给司机的金额,单位元,最多两位小数且必须大于 0」);请求示例同步 |
|
||
| **油券库存查询 `syb.oil.oilCard.stockList`** | **整节删除** + 目录条目删除 |
|
||
| 分油记录查询 | 响应删 `productName` 字段与示例行 |
|
||
| 订单状态查询 | 响应删 `province` / `goods_name` 字段行;两处 JSON 示例删对应 3 行;`oil_status_zsy` 描述由「中石油下单状态 1待处理/2已发券/3发券失败」改为「**发放状态:0未提交 / 2发放成功 / 3发放失败**」 |
|
||
|
||
校验:XML 良构 ✓、XSD 全过 ✓、段落 1717 → **1234**;残留检查 `goodsNo`/`stockList`/`油券库存`/`productName`/`goods_name`/`goods_no`/`province`/`中石油` 均为 **0**。
|
||
|
||
最终 `share` 请求体仅剩 6 个参数:`orgNo` / `amount` / `mobile` / `name` / `saleOrderNo` / `oilCardType`。
|
||
|
||
### 额度管控:改用合作商余额(已实现)
|
||
|
||
去掉 `goodsNo` 后,原先由 `yoshop_partners_goods.stock_num` 承担的下单额度管控,改由 **`yoshop_partners.balance`(合作商余额)** 承担。
|
||
|
||
**新增** `app/common/service/PartnersBalance.php`:
|
||
|
||
| 方法 | 说明 |
|
||
|---|---|
|
||
| `deduct()` | **原子扣减**:`UPDATE yoshop_partners SET balance = balance - amt WHERE partners_id=? AND balance >= amt`,`affected=1` 才算成功 —— 天然防并发超扣。成功返回流水ID |
|
||
| `refund()` | 回补余额并写退款流水 |
|
||
| `bindOrder()` | 建单后把 `order_id` 回填到扣款流水(`deduct` 时还没有订单ID) |
|
||
| `balance()` | 查询当前余额 |
|
||
|
||
流水写入 `yoshop_partners_balance_log`,场景沿用现有枚举:扣减 = `CONSUME(20)`,回补 = `REFUND(40)`;金额拼接前用 `number_format` 规范化,避免注入。
|
||
|
||
**接入点**
|
||
|
||
| 位置 | 行为 |
|
||
|---|---|
|
||
| `OilCard::share` | **幂等检查通过后**才扣款(重复 `saleOrderNo` 直接返回原单,不重复扣);扣款失败 → `2028 账户余额不足`;建单抛异常或未成功 → 立即回补;建单成功 → `bindOrder` 回填订单ID |
|
||
| `PartnersQueue` | 三条发放失败路径(缺司机信息 / 7.7 调用失败 / `data.status=2`)在**状态条件跃迁 `affected=1` 时**回补余额,天然幂等 |
|
||
| `store/controller/partners/Order::share`(后台重新发放) | 失败时余额已回补,重发前**重新扣减**;若状态被其它进程改变导致重置失败 → 回补刚扣的金额 |
|
||
|
||
**资金一致性**:先扣后建单、失败即回补;所有回补都挂在「条件跃迁胜出」之后,重复消息 / 多进程不会重复回补。
|
||
|
||
**文档**:`amount` 字段取值说明补充「下单时平台校验并扣减对接公司账户余额,余额不足返回错误码 2028;发放失败时该笔金额原路回补」。错误码 `2028 账户余额不足` 原本就在附录 4.2 中,无需新增。
|
||
|
||
**运营入口**:后台「合作商管理 → 充值」已可维护余额,「合作商 → 余额明细」可查流水,无需新增页面。
|
||
|
||
### 合作商「可售商品 + 库存」下线(已清理)
|
||
|
||
额度改由余额承担后,`yoshop_partners_goods` / `yoshop_partners_stock_log` 已无任何读写方,整体移除。
|
||
|
||
**删除的文件(5 个 PHP + 1 个 Vue)**
|
||
`app/api/model/PartnersGoods.php`、`app/common/model/PartnersGoods.php`、`app/store/model/PartnersGoods.php`、`app/common/model/partners/StockLog.php`、`app/store/model/partners/StockLog.php`、`admin-vue/src/views/partners/modules/MultiGoods.vue`
|
||
|
||
**改动的文件**
|
||
|
||
| 文件 | 改动 |
|
||
|---|---|
|
||
| `app/store/model/Partners.php` | `add()` / `edit()` 去掉 `checkGoodsData`、`PartnersGoodsModel::increased/updates`、`StockLogModel::increased` 及两个 import |
|
||
| `app/store/controller/Partners.php` | `detail()` 不再返回 `goodsList`(连同 `allot_num` 填充逻辑),去 import |
|
||
| `admin-vue/views/partners/{Create,Update}.vue` | 移除 `<MultiGoods>` 组件、`goodsList` data、提交时的 `values.goodsList`、`handleGoodsChange`、import 与 components 注册 |
|
||
| `admin-vue/views/partners/modules/index.js` | 移除 MultiGoods 导入导出 |
|
||
| `admin-vue/common/model/partners/Index.js` | 移除 `GoodsApi` import、`formData.goods`、`getGoodsList()` 方法及其在 `getFromData` 中的调用 |
|
||
|
||
**数据库**:`qyt_migration.sql` 第 4 节把两张表注释标记为「已下线,仅历史数据」,并附上 `DROP TABLE` 语句(**已注释**)。两表仍有历史数据,是否物理删除由你决定,确认后取消注释执行即可。
|
||
|
||
校验:PHP 端 `PartnersGoods` / `StockLog` / `partners_goods` / `partners_stock_log` 全仓残留 **0**;admin-vue `MultiGoods` / `goodsList` 残留 **0**,eslint **0 problems**。
|
||
|
||
---
|
||
|
||
## 附 I. 后台「分油公司 / 分油用户」菜单下线(2026-09-06)
|
||
|
||
企油通改为单企业配置(`config/qyt.php`)、分油用户池取消后,这两个菜单对应的 `yoshop_company` / `yoshop_account` 已无业务意义,后端接口也早已返回「已停用」。本次把前端入口整体收掉。
|
||
|
||
### 删除
|
||
|
||
| 类型 | 路径 |
|
||
|---|---|
|
||
| 页面 | `views/company/`(Index / Create / Update / balance / modules 共 8 个文件 + style.less)、`views/account/Index.vue` |
|
||
| API | `api/company/{index,balance,recharge}.js`、`api/account/index.js` |
|
||
| 模型 / 枚举 | `common/model/company/Index.js`、`common/enum/company/**`(3 个) |
|
||
| 用户分油弹窗 | `views/user/modules/OilForm.vue`(依赖已停用的 `/user/oil`) |
|
||
|
||
### 改动
|
||
|
||
| 文件 | 改动 |
|
||
|---|---|
|
||
| `config/router.config.js` | 移除整个 `/company` 路由块(含嵌套的 `/account`),菜单「分油公司」「分油用户」「公司余额明细」一并消失 |
|
||
| `common/model/user/Index.js` | 去 `CompanyApi` import、`formData.companyList`、`getCompanyList()` 及其在 `getFromData` 的调用 |
|
||
| `views/user/{Create,Update}.vue` | 移除表单里的「分油公司」下拉(数据源已不存在) |
|
||
| `views/user/Index.vue` | 移除 `OilForm` 组件、import、注册、`handleOil()` 与那行已注释的「分油」按钮 |
|
||
| `views/user/modules/index.js` | 移除 OilForm 导入导出 |
|
||
| `api/user/index.js` | 移除 `oil: '/user/oil'` 与 `oil()` 方法 |
|
||
|
||
### 校验
|
||
|
||
- 残留引用检查:`views/company` / `api/company` / `model/company` / `enum/company` / `views/account/Index` / `api/account` 均为 **0**;`OilForm` 仅剩合作商订单页那个(不同文件,需保留)。
|
||
- eslint:本次改动引入 **0 新错误**。改动过程中在 `views/partners/{Create,Update}.vue` 留下的 3 处 `comma-dangle` 已修复。当前全量仅剩 2 个**改动前就存在**的错误:`config/router.config.js` 的 `comma-dangle`、`views/user/grade/modules/index.js` 的 `eol-last`(两者均未被本次改动触碰)。
|
||
|
||
### 后端未动(说明)
|
||
|
||
`app/store/controller/{Company,Account,User}.php` 及 `yoshop_company` / `yoshop_account` 的模型仍在仓库中,相关方法已返回「已停用」提示,现在没有任何前端调用方。保留是为了不影响历史数据查询与可能的权限表(`yoshop_store_api` / `yoshop_store_menu`)记录;如需彻底清除,可在确认权限表无关联后单独处理。
|