feat:app流水通知显示备注

feat:咖啡机初步
This commit is contained in:
dzc committed 2026-09-18 12:53:17 +08:00
1 parent c3e6efe5bc
commit 8aa2cfa104
52 files changed
+2887 -2

No files matched your search

+64
View File
@@ -0,0 +1,64 @@
-- 屋里咖啡咖啡机对接一期(饭卡支付):厂商订单扩展表 + 生命周期日志表。
-- 本脚本只新增表,不修改既有表结构,可安全重跑。
-- 字典与菜单权限见同目录 20260918_hard_coffee_dict_menu.txt,由管理员手工添加。
CREATE TABLE IF NOT EXISTS `pjcloudx_hardware`.`hard_coffee_order`
(
`id` bigint NOT NULL COMMENT '编号',
`order_id` bigint NOT NULL COMMENT '本地硬件订单id(hard_order.id)',
`order_no` varchar(32) NOT NULL COMMENT '屋里咖啡订单号(19位数字)',
`hard_id` bigint DEFAULT NULL COMMENT '咖啡机设备id(hard_manager.id)',
`machine_name` varchar(64) DEFAULT NULL COMMENT '厂商机器号快照',
`product` varchar(255) DEFAULT NULL COMMENT '产品名称',
`img` varchar(512) DEFAULT NULL COMMENT '产品图片链接',
`is_cold` char(1) DEFAULT '0' COMMENT '1冷饮 0热饮',
`price` int NOT NULL DEFAULT 0 COMMENT '厂商订单价格(分)',
`phone_no` varchar(32) DEFAULT NULL COMMENT '支付者手机号',
`wuli_notify_status` char(1) NOT NULL DEFAULT '0' COMMENT '支付结果通知厂商状态 0未通知 1成功 2失败',
`wuli_notify_time` datetime DEFAULT NULL COMMENT '最近一次通知厂商时间',
`wuli_notify_count` int NOT NULL DEFAULT 0 COMMENT '通知厂商累计尝试次数',
`refund_sync_amount` int NOT NULL DEFAULT 0 COMMENT '累计已同步厂商退款金额(分)',
`refund_sync_time` datetime DEFAULT NULL COMMENT '最近一次退款同步时间',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
`tenant_id` bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hard_coffee_order_no` (`tenant_id`, `order_no`),
KEY `idx_hard_coffee_order_hard` (`tenant_id`, `hard_id`, `create_time`),
KEY `idx_hard_coffee_order_order` (`tenant_id`, `order_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci
COMMENT = '咖啡机厂商订单扩展(屋里咖啡)';
CREATE TABLE IF NOT EXISTS `pjcloudx_hardware`.`hard_coffee_log`
(
`id` bigint NOT NULL COMMENT '编号',
`order_no` varchar(32) DEFAULT NULL COMMENT '厂商订单号',
`order_id` bigint DEFAULT NULL COMMENT '本地订单id(hard_order.id)',
`hard_id` bigint DEFAULT NULL COMMENT '设备id(hard_manager.id)',
`unique_code` varchar(64) DEFAULT NULL COMMENT '设备唯一编号(厂商机器号)',
`stage` varchar(32) NOT NULL COMMENT '生命周期阶段编码',
`direction` char(1) NOT NULL DEFAULT '1' COMMENT '交互方向 1我方调厂商 2厂商调我方',
`title` varchar(64) NOT NULL COMMENT '阶段中文说明',
`headers` varchar(2048) DEFAULT NULL COMMENT '请求头',
`req` varchar(2048) DEFAULT NULL COMMENT '请求报文',
`res` varchar(2048) DEFAULT NULL COMMENT '响应报文',
`error` varchar(2048) DEFAULT NULL COMMENT '错误信息',
`start_time` datetime DEFAULT NULL COMMENT '开始时间',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
`cost` int DEFAULT NULL COMMENT '耗时(毫秒)',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
`tenant_id` bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (`id`),
KEY `idx_hard_coffee_log_order_no` (`tenant_id`, `order_no`),
KEY `idx_hard_coffee_log_order` (`tenant_id`, `order_id`),
KEY `idx_hard_coffee_log_hard` (`tenant_id`, `hard_id`, `create_time`),
KEY `idx_hard_coffee_log_stage` (`tenant_id`, `stage`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci
COMMENT = '咖啡机使用生命周期日志(屋里咖啡)';
+4
View File
@@ -0,0 +1,4 @@
-- 钱包消息Outbox补充流水备注快照:remark 随钱包流水同事务落库,供消息正文与推送通知展示后台补充的业务说明。
-- 历史流水和未填写场景允许为空,最多保存256个字符,与 wallet_transaction.remark 保持同长度约束。
ALTER TABLE `pjcloudx_wallet`.`wallet_message_outbox`
ADD COLUMN `remark` varchar(256) DEFAULT NULL COMMENT '流水备注快照,由后台操作人员补充业务说明,最多256字符' AFTER `balance`;
+199
View File
@@ -0,0 +1,199 @@
========================================================================
屋里咖啡咖啡机对接一期 - 字典/菜单/权限手工添加清单 (2026-09-18)
========================================================================
说明:以下内容需要管理员在对应环境手工添加(UPMS 管理端或直接执行 SQL)。
SQL 按租户幂等,风格与 db/20260904_add_er_yin_printer.sql 一致,可直接参考执行;
菜单 parent_id 依赖各环境实际菜单主键,请先确认父菜单再执行。
------------------------------------------------------------------------
一、字典项
------------------------------------------------------------------------
1. 设备类型字典 hard_type 增加咖啡机(所有已配置 hard_type 的租户):
INSERT INTO `pjcloudx`.`sys_dict_item`
(`id`, `dict_id`, `item_value`, `label`, `dict_type`, `description`, `sort_order`, `create_by`, `create_time`, `remarks`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_dict_item`) + ROW_NUMBER() OVER (ORDER BY d.`tenant_id`, d.`id`),
d.`id`, '13', '咖啡机', 'hard_type', '屋里咖啡扫码支付咖啡机', 13,
'system', NOW(), '屋里咖啡咖啡机', '0', d.`tenant_id`
FROM `pjcloudx`.`sys_dict` d
WHERE d.`dict_type` = 'hard_type'
AND d.`del_flag` = '0'
AND NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_dict_item` i
WHERE i.`tenant_id` = d.`tenant_id` AND i.`dict_type` = 'hard_type'
AND i.`item_value` = '13' AND i.`del_flag` = '0'
);
2. 新字典 hard_coffee_stage(咖啡机生命周期阶段):
-- 先建字典类型(按租户)
INSERT INTO `pjcloudx`.`sys_dict`
(`id`, `dict_type`, `description`, `create_by`, `create_time`, `remarks`, `system_flag`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_dict`) + ROW_NUMBER() OVER (ORDER BY tenant.`tenant_id`),
'hard_coffee_stage', '咖啡机生命周期阶段', 'system', NOW(), '咖啡机生命周期阶段', '1', '0', tenant.`tenant_id`
FROM (SELECT DISTINCT `tenant_id` FROM `pjcloudx`.`sys_dict` WHERE `del_flag` = '0') tenant
WHERE NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_dict` d
WHERE d.`tenant_id` = tenant.`tenant_id` AND d.`dict_type` = 'hard_coffee_stage' AND d.`del_flag` = '0'
);
-- 再建字典项
INSERT INTO `pjcloudx`.`sys_dict_item`
(`id`, `dict_id`, `item_value`, `label`, `dict_type`, `description`, `sort_order`, `create_by`, `create_time`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_dict_item`) + ROW_NUMBER() OVER (ORDER BY d.`tenant_id`, item.`sort_order`),
d.`id`, item.`item_value`, item.`label`, d.`dict_type`, item.`label`, item.`sort_order`,
'system', NOW(), '0', d.`tenant_id`
FROM `pjcloudx`.`sys_dict` d
JOIN (
SELECT 'GET_ORDER' AS `item_value`, '扫码拉取厂商订单' AS `label`, 1 AS `sort_order`
UNION ALL SELECT 'CREATE_ORDER', '创建本地订单', 2
UNION ALL SELECT 'WALLET_PAY', '饭卡扣款', 3
UNION ALL SELECT 'NOTIFY_PAY', '通知厂商支付结果', 4
UNION ALL SELECT 'QUERY', '厂商查单', 5
UNION ALL SELECT 'REFUND_NOTIFY','通知厂商退款', 6
) item ON item.`item_value` IS NOT NULL
WHERE d.`dict_type` = 'hard_coffee_stage'
AND d.`del_flag` = '0'
AND NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_dict_item` i
WHERE i.`tenant_id` = d.`tenant_id` AND i.`dict_type` = 'hard_coffee_stage'
AND i.`item_value` = item.`item_value` AND i.`del_flag` = '0'
);
3. 新字典 hard_coffee_direction(交互方向):
INSERT INTO `pjcloudx`.`sys_dict`
(`id`, `dict_type`, `description`, `create_by`, `create_time`, `remarks`, `system_flag`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_dict`) + ROW_NUMBER() OVER (ORDER BY tenant.`tenant_id`),
'hard_coffee_direction', '咖啡机日志交互方向', 'system', NOW(), '咖啡机日志交互方向', '1', '0', tenant.`tenant_id`
FROM (SELECT DISTINCT `tenant_id` FROM `pjcloudx`.`sys_dict` WHERE `del_flag` = '0') tenant
WHERE NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_dict` d
WHERE d.`tenant_id` = tenant.`tenant_id` AND d.`dict_type` = 'hard_coffee_direction' AND d.`del_flag` = '0'
);
INSERT INTO `pjcloudx`.`sys_dict_item`
(`id`, `dict_id`, `item_value`, `label`, `dict_type`, `description`, `sort_order`, `create_by`, `create_time`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_dict_item`) + ROW_NUMBER() OVER (ORDER BY d.`tenant_id`, item.`sort_order`),
d.`id`, item.`item_value`, item.`label`, d.`dict_type`, item.`label`, item.`sort_order`,
'system', NOW(), '0', d.`tenant_id`
FROM `pjcloudx`.`sys_dict` d
JOIN (
SELECT '1' AS `item_value`, '我方调厂商' AS `label`, 1 AS `sort_order`
UNION ALL SELECT '2', '厂商调我方', 2
) item ON item.`item_value` IS NOT NULL
WHERE d.`dict_type` = 'hard_coffee_direction'
AND d.`del_flag` = '0'
AND NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_dict_item` i
WHERE i.`tenant_id` = d.`tenant_id` AND i.`dict_type` = 'hard_coffee_direction'
AND i.`item_value` = item.`item_value` AND i.`del_flag` = '0'
);
4. 新字典 hard_coffee_notify_status(通知厂商状态,用于订单列表筛选/展示):
INSERT INTO `pjcloudx`.`sys_dict`
(`id`, `dict_type`, `description`, `create_by`, `create_time`, `remarks`, `system_flag`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_dict`) + ROW_NUMBER() OVER (ORDER BY tenant.`tenant_id`),
'hard_coffee_notify_status', '咖啡机通知厂商状态', 'system', NOW(), '咖啡机通知厂商状态', '1', '0', tenant.`tenant_id`
FROM (SELECT DISTINCT `tenant_id` FROM `pjcloudx`.`sys_dict` WHERE `del_flag` = '0') tenant
WHERE NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_dict` d
WHERE d.`tenant_id` = tenant.`tenant_id` AND d.`dict_type` = 'hard_coffee_notify_status' AND d.`del_flag` = '0'
);
INSERT INTO `pjcloudx`.`sys_dict_item`
(`id`, `dict_id`, `item_value`, `label`, `dict_type`, `description`, `sort_order`, `create_by`, `create_time`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_dict_item`) + ROW_NUMBER() OVER (ORDER BY d.`tenant_id`, item.`sort_order`),
d.`id`, item.`item_value`, item.`label`, d.`dict_type`, item.`label`, item.`sort_order`,
'system', NOW(), '0', d.`tenant_id`
FROM `pjcloudx`.`sys_dict` d
JOIN (
SELECT '0' AS `item_value`, '未通知' AS `label`, 1 AS `sort_order`
UNION ALL SELECT '1', '通知成功', 2
UNION ALL SELECT '2', '通知失败', 3
) item ON item.`item_value` IS NOT NULL
WHERE d.`dict_type` = 'hard_coffee_notify_status'
AND d.`del_flag` = '0'
AND NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_dict_item` i
WHERE i.`tenant_id` = d.`tenant_id` AND i.`dict_type` = 'hard_coffee_notify_status'
AND i.`item_value` = item.`item_value` AND i.`del_flag` = '0'
);
------------------------------------------------------------------------
二、菜单与按钮权限
------------------------------------------------------------------------
说明:
- 「咖啡机订单」建议挂在硬件订单管理菜单下(父菜单 permission = hard_hardOrder_view 所在菜单);
- 「咖啡机日志」建议挂在设备管理菜单下(父菜单 permission = hard_hardManager_view 所在菜单);
- 如各环境父菜单定位不同,请先查 parent_id 再执行。
1. 咖啡机订单菜单(menu_type 1=菜单,含页面路由,路由地址建议 /hard/coffee-order):
INSERT INTO `pjcloudx`.`sys_menu`
(`menu_id`, `name`, `permission`, `parent_id`, `path`, `visible`, `sort_order`, `keep_alive`, `embedded`, `menu_type`, `create_by`, `create_time`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`menu_id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_menu`) + ROW_NUMBER() OVER (ORDER BY parent_menu.`tenant_id`, parent_menu.`menu_id`),
'咖啡机订单', 'hard_hardCoffeeOrder_view', parent_menu.`menu_id`, 'coffee-order',
'1', 30, '0', '0', '1', 'system', NOW(), '0', parent_menu.`tenant_id`
FROM `pjcloudx`.`sys_menu` parent_menu
WHERE parent_menu.`permission` = 'hard_hardOrder_view' AND parent_menu.`del_flag` = '0'
AND NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_menu` existing
WHERE existing.`tenant_id` = parent_menu.`tenant_id`
AND existing.`permission` = 'hard_hardCoffeeOrder_view' AND existing.`del_flag` = '0'
);
2. 咖啡机日志菜单:
INSERT INTO `pjcloudx`.`sys_menu`
(`menu_id`, `name`, `permission`, `parent_id`, `path`, `visible`, `sort_order`, `keep_alive`, `embedded`, `menu_type`, `create_by`, `create_time`, `del_flag`, `tenant_id`)
SELECT (SELECT GREATEST(COALESCE(MAX(`menu_id`), 0), 2026091800000000000) FROM `pjcloudx`.`sys_menu`) + ROW_NUMBER() OVER (ORDER BY parent_menu.`tenant_id`, parent_menu.`menu_id`),
'咖啡机日志', 'hard_hardCoffeeLog_view', parent_menu.`menu_id`, 'coffee-log',
'1', 31, '0', '0', '1', 'system', NOW(), '0', parent_menu.`tenant_id`
FROM `pjcloudx`.`sys_menu` parent_menu
WHERE parent_menu.`permission` = 'hard_hardManager_view' AND parent_menu.`del_flag` = '0'
AND NOT EXISTS (
SELECT 1 FROM `pjcloudx`.`sys_menu` existing
WHERE existing.`tenant_id` = parent_menu.`tenant_id`
AND existing.`permission` = 'hard_hardCoffeeLog_view' AND existing.`del_flag` = '0'
);
------------------------------------------------------------------------
三、第三方密钥 third_key_manage(第三方库 pjcloudx_thirdparty)
------------------------------------------------------------------------
说明:屋里咖啡两对密钥通过 thirdparty 管理端「第三方密钥管理」录入,或按下面模板执行 SQL。
字段映射:app_key=屋里概念里的 appid,app_secret=屋里概念里的 appkey(SHA1签名密钥)。
密钥为平台级全局唯一(跨租户读取),建议维护在默认租户(tenant_id=1)下。
修改密钥后 hardware 侧最多延迟 5 分钟生效(本地缓存)。
1. 我方调厂商 getOrder/callback/refund 的鉴权对(bizType=11):
INSERT INTO `pjcloudx_thirdparty`.`third_key_manage`
(`id`, `name`, `biz_type`, `app_key`, `app_secret`, `status`, `remark`, `create_by`, `create_time`, `del_flag`, `tenant_id`)
VALUES
(2026091800000000001, '屋里咖啡', '11', '<向屋里申请的16位appid>', '<向屋里申请的16位appkey>', '1',
'我方作为第三方支付服务商调厂商接口', 'system', NOW(), '0', 1);
2. 厂商调我方 queryOrder 查单的验签对(bizType=12,我方自行生成后告知屋里):
INSERT INTO `pjcloudx_thirdparty`.`third_key_manage`
(`id`, `name`, `biz_type`, `app_key`, `app_secret`, `status`, `remark`, `create_by`, `create_time`, `del_flag`, `tenant_id`)
VALUES
(2026091800000000002, '屋里咖啡查单', '12', '<我方生成并告知屋里的16位appid>', '<我方生成的16位appkey>', '1',
'厂商调我方queryOrder验签', 'system', NOW(), '0', 1);
------------------------------------------------------------------------
四、后端权限字符串与接口对应关系(前端页面取用)
------------------------------------------------------------------------
hard_hardCoffeeOrder_view:
GET /hard-coffee-manager/order/page 咖啡机订单分页
GET /hard-coffee-manager/order/{id} 咖啡机订单详情(含生命周期时间线)
hard_hardCoffeeLog_view:
GET /hard-coffee-manager/log/page 生命周期日志分页
+72
View File
@@ -0,0 +1,72 @@
# 咖啡机(屋里咖啡)H5支付页对接契约 - 一期饭卡支付
> 交付时间: 2026-09-18。H5 页面在前端仓库(biz_zax_app_cloud)实现,本文档为后端接口契约。
## 1. 页面入口与二维码 URL
用户在咖啡机上选择饮品后,机器展示二维码,URL 由屋里咖啡后台配置,指向我方 H5:
```
https://www.pjzhhq.cn/h5/#/pages/pay/coffee-pay?order_no={厂商订单号}
```
- `order_no`: 厂商订单号,19 位数字(测试环境 18 位)。
- 屋里咖啡后台的「支付跳转 URL 模板」按上述地址配置,占位符以厂商后台实际支持为准。
## 2. 接口(匿名,无需登录态)
网关前缀: `https://www.pjzhhq.cn/api/hard` (StripPrefix 后到 hardware 服务)。
所有响应为统一 `R<T>` 结构 `{code:0, msg, data}`,`code != 0` 时展示 `msg`。
### 2.1 拉取订单信息
```
GET /api/hard/hard-coffee/order-info?orderNo={order_no}
```
响应 `data`:
| 字段 | 类型 | 说明 |
|---|---|---|
| orderId | long | 本地订单id,**支付时回传** |
| orderNo | string | 厂商订单号 |
| product | string | 产品名称 |
| img | string | 产品图片完整链接 |
| isCold | string | `1`冷饮 `0`热饮 |
| price | int | 价格(分) |
| priceYuan | string | 价格(元,两位小数),直接展示 |
| machineName | string | 机器号 |
| paid | boolean | 是否已支付。`true` 时展示"已支付"并禁止再次支付 |
| remainSeconds | long | 支付剩余秒数(下单起5分钟),用于倒计时,超时提示重新发起 |
页面逻辑: 进入页面即调用;`paid=true` 显示已支付结果;`remainSeconds<=0` 显示超时。
### 2.2 饭卡支付(卡号即扣款)
```
POST /api/hard/hard-coffee/card-pay
Content-Type: application/json
{ "orderId": 1234567890, "cardNo": "0123456789" }
```
- 卡号即身份,与消费机刷卡一致,无密码。失败原因见 `msg`(非本单位饭卡/余额不足/订单已超时/订单已支付等)。
响应 `data`:
| 字段 | 类型 | 说明 |
|---|---|---|
| orderId | long | 本地订单id |
| orderNo | string | 厂商订单号 |
| name | string | 支付人姓名(脱敏展示由前端决定) |
| cardNo | string | 饭卡卡号 |
| balanceYuan | string | 支付后余额(元) |
支付成功后展示"取咖啡"提示;出餐由后端回调厂商完成,前端无需轮询(如需兜底可再次调用 2.1 查看 `paid`)。
## 3. 注意事项
1. 匿名接口无租户头,后端通过机器号自动定位租户,前端无需传 TENANT-ID。
2. 同一订单支付窗口 5 分钟,过期后在咖啡机重新发起生成新二维码。
3. 防重复提交由后端并发锁保证,前端支付按钮加 loading 即可。
4. 一期仅饭卡支付;微信/支付宝支付为二期,接口预留扩展。
@@ -0,0 +1,52 @@
# 屋里咖啡咖啡机对接一期 - 联调与部署说明 (2026-09-18)
## 1. 角色与外部配置
我方平台 = 厂商文档中的"第三方支付服务商"。需要在屋里咖啡侧完成配置:
| 配置项 | 值 | 说明 |
|---|---|---|
| 支付跳转URL模板 | `https://www.pjzhhq.cn/h5/#/pages/pay/coffee-pay?order_no=厂商单号参数` | 用户扫码打开我方H5(前端页面由前端仓库实现) |
| 我方提供的查单地址 | `https://www.pjzhhq.cn/api/hard/hard-coffee/wuli/query-order` | 文档3.4 queryOrder,POST form表单 |
| 向屋里申请 | 我方调 getOrder/callback/refund 的 appid/appkey(16位) | 录入 third_key_manage bizType=11 |
| 向屋里分配 | 厂商调我方 queryOrder 的 appid/appkey(16位) | 录入 third_key_manage bizType=12 |
## 2. 密钥与配置
密钥统一在 **thirdparty 服务 third_key_manage 表**维护(管理端「第三方密钥管理」录入或 SQL,模板见 `20260918_hard_coffee_dict_menu.txt` 第三节):
| biz_type | 用途 | app_key | app_secret |
|---|---|---|---|
| 11 屋里咖啡 | 我方调 getOrder/callback/refund | 向屋里申请的 appid | 向屋里申请的 appkey(SHA1签名) |
| 12 屋里咖啡查单 | 厂商调我方 queryOrder 验签 | 我方生成并告知屋里的 appid | 我方生成的 appkey |
密钥为平台级全局唯一(跨租户读取),建议 tenant_id=1;修改后 hardware 侧最多延迟 5 分钟生效(本地缓存)。
Nacos 的 pjcloud-hardware-biz 只保留环境参数:
```yaml
coffee:
base-url: https://test.wulicoffee.com # 生产切 https://www.wulicoffee.com
timeout-millis: 10000
```
## 3. 设备登记(管理端 hard-manager)
1. 先执行 `db/20260918_add_hard_coffee.sql`(两张新表)。
2. 管理端添加字典 hard_type=13 咖啡机(见 dict_menu txt 文件)。
3. 设备管理新增设备: 类型=咖啡机(13), 设备唯一编号=屋里机器号(machine_name), 绑定商户。
4. 未登记的机器扫码会返回"咖啡机未接入平台"。
## 4. 部署顺序
1. 执行 SQL: `db/20260918_add_hard_coffee.sql` → 字典/菜单/third_key_manage 密钥(手工,`20260918_hard_coffee_dict_menu.txt`)。
2. 部署 **pjcloud-thirdparty-biz 先于 pjcloud-hardware-biz**(hardware 通过新增 Feign /third-key-manage/inner/get-by-biz-type 读密钥)。
3. 前端 H5 加 coffee-pay 页面(契约见 `20260918_hard_coffee_h5_api.md`)。
4. 在屋里测试环境发起一笔扫码支付联调,验证: 拉单 → 饭卡支付 → callback → 出餐 → 管理端订单/日志。
## 5. 运维要点
- 支付结果通知厂商失败: hard_coffee_order.wuli_notify_status=2,补偿任务每60秒重试,上限10次(超过需人工介入,管理端订单列表可见)。
- 退款同步: 管理端售后退款成功后自动按差额通知厂商(refund_sync_amount 记账),补偿任务回看近7天补推缺口。
- 生命周期日志: hard_coffee_log 按订单号/本地订单/设备关联,管理端"咖啡机订单详情"含完整时间线。
- 查单验签: 时间戳窗口±5分钟,appid 必须等于 coffee.query-app-id。