- jeepay-plus支付系统,已完成如下云喇叭、云打印对接工作:
- 一、表结构
- 二、后端接口编码
- 1.1 > 添加设备参数配置model
- 1.1.1 命名方式为:厂商首字母 + Speaker/Printer + Params
- 1.1.2 在目录:
- 1.2 > 设备参数配置
- 1.3 > 设备对接
- 1.3.1 ISpeakerService为云喇叭接口定义
- 1.3.2 IPrinterService为云打印接口定义
- 1.3.3 以博实结云喇叭设备为例:
- 三、前端配置编码
- 1.1 > 厂商参数配置
- 1.1.1 只有manage项目有厂商参数配置
- 1.1.2 CommonAddOrEdit.vue文件为新增/修改组件
- 1.1.3 以博实结厂商参数配置组件为例:
jeepay-plus支付系统,已完成如下云喇叭、云打印对接工作:
- 云喇叭:智谷物联、博实结、品生
- 云打印:智谷物联、博实结、飞鹅
一、表结构
云喇叭、云打印表结构通用
-- 设备厂商配置表
DROP TABLE IF EXISTS `t_device_provide_config`;
CREATE TABLE `t_device_provide_config` (
`config_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '厂商配置ID',
`config_desc` VARCHAR(32) NOT NULL COMMENT '厂商配置备注信息, 会在商户侧进行回显',
`device_type` TINYINT(6) NOT NULL COMMENT '设备类型: 1-云喇叭, 2-云打印, 3-扫码pos',
`provider` VARCHAR(20) NOT NULL COMMENT '设备厂商: zgwl-智谷物联, bsj-博实结, fe-飞鹅, ps-品生',
`app_id` VARCHAR(64) COMMENT '厂商配置参数appId(扫码POS定义唯一appId)',
`provider_params` TEXT COMMENT '厂商配置参数,json字符串',
`state` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '状态: 0-停用,1-启用',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`config_id`),
UNIQUE KEY (`app_id`)
) ENGINE=INNODB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COMMENT='设备厂商配置表';
-- 商户门店设备配置表
DROP TABLE IF EXISTS `t_mch_store_device`;
CREATE TABLE `t_mch_store_device` (
`device_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '设备ID',
`device_name` VARCHAR(128) NOT NULL COMMENT '设备名称',
`batch_id` VARCHAR(64) COMMENT '批次号',
`config_id` BIGINT(20) NOT NULL COMMENT '关联厂商配置ID',
`device_type` TINYINT(6) NOT NULL COMMENT '设备类型: 1-云喇叭, 2-云打印, 3-扫码POS',
`provider` VARCHAR(20) NOT NULL COMMENT '设备厂商:参考配置表',
`device_no` VARCHAR(128) NOT NULL COMMENT '设备号',
`device_params` TEXT NOT NULL COMMENT '设备参数,json字符串',
`biz_config_params` TEXT COMMENT '业务配置参数,json字符串',
`store_id` BIGINT(20) DEFAULT NULL COMMENT '门店ID',
`mch_no` VARCHAR(64) DEFAULT NULL COMMENT '商户号',
`agent_no` VARCHAR(64) DEFAULT NULL COMMENT '代理商号',
`state` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '状态: 0-停用,1-启用',
`bind_state` TINYINT(6) NOT NULL DEFAULT 0 COMMENT '商户绑定状态: 0-未绑定,1-已绑定',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`device_id`),
UNIQUE KEY `IDX_Provider_Type_DeviceNo` (`provider`, `device_type`, `device_no`)
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COMMENT='商户门店设备配置表';
二、后端接口编码
1.1 > 添加设备参数配置model
1.1.1 命名方式为:厂商首字母 + Speaker/Printer + Params
云喇叭、云打印两种设备同时对接且参数配置一致情况下,可省略Speaker/Printer,如:智谷物联—-ZgwlParams。
1.1.2 在目录:
com.jeequan.jeepay.core.model.device(core项目),添加常量类,包含三个参数:providerParams、deviceParams、bizConfigParams,分别为厂商参数、设备参数、业务参数
1.2 > 设备参数配置
配置接口在manage、agent、merchant项目的MchStoreDeviceController内。包括新增、修改、划拨/收回、绑定/解绑、测试等接口,参考操作手册。
如果设备参数只有一个属性:设备号,则无需进行修改。
特殊情况如飞鹅,需通过接口将设备信息注册,此时在新增、修改设备时需同步处理。
1.3 > 设备对接
1.3.1 ISpeakerService为云喇叭接口定义
public interface ISpeakerService {
/** 调起播报 **/
void send(JSONObject deviceParams, PayOrderInfo4Device speakPayOrderInfo) throws BizException;
/** 自定义语音播报 **/
void sendCustomMsg(JSONObject deviceParams, PayOrderInfo4Device speakPayOrderInfo) throws BizException;
}
覆写send()
函数: 实现播报推送
覆写sendCustomMsg()
函数:厂商喇叭自定义消息推送
1.3.2 IPrinterService为云打印接口定义
public interface IPrinterService {
/** 调起打印
* @param deviceParams
* @param printPayOrderInfo
* **/
void send(JSONObject deviceParams, PayOrderInfo4Device printPayOrderInfo) throws BizException;
/** 添加打印机
* @param deviceParams
* **/
String addPrinter(JSONObject deviceParams);
/** 修改打印机
* @param deviceParams
* **/
String editPrinter(JSONObject deviceParams);
/** 清除打印队列
* @param deviceParams
* **/
String clearPrinter(JSONObject deviceParams);
}
覆写send()
函数: 实现打印推送
覆写addPrinter()
函数:实现在厂商端注册打印机
覆写editPrinter()
函数:实现在厂商端修改打印机
覆写clearPrinter()
函数:实现在厂商端清除打印队列
1.3.3 以博实结云喇叭设备为例:
实现ISpeakerService接口,覆写send()
函数: 实现播报推送。send()
函数为调用厂商设备逻辑,异常抛出BizException即可
@Slf4j
@Service
public class BsjSpeakerService implements ISpeakerService {
private static final String REQ_URL = "https://ioe.car900.com/v1/openApi/dev/controlDevice.json";
@Override
public void send(JSONObject deviceParams, PayOrderInfo4Device payOrderInfo) throws BizException {
JSONObject bsjJSON = new JSONObject();
bsjJSON.put("providerParams", JSON.parseObject(deviceParams.getString("providerParams")));
bsjJSON.put("deviceParams", JSON.parseObject(deviceParams.getString("deviceParams")));
// 博实结参数
BsjParams bsjParams = JSON.parseObject(bsjJSON.toJSONString(), BsjParams.class);
JSONObject resJSON = speak(bsjParams, payOrderInfo);
if (resJSON == null) {
throw new BizException("请求失败");
}
if (resJSON.getIntValue("code") != 0) {
throw new BizException(resJSON.getString("msg"));
}
}
@Override
public void sendCustomMsg(JSONObject deviceParams, PayOrderInfo4Device payOrderInfo) {
return;
}
/**
* 发起请求
*/
private JSONObject speak(BsjParams bsjParams, PayOrderInfo4Device payOrderInfo) throws BizException {
JSONObject reqParams = new JSONObject();
reqParams.put("money", AmountUtil.convertCent2Dollar(payOrderInfo.getAmount())); // 金额
reqParams.put("broadCastType", getPayTypeCode(payOrderInfo.getIfCode())); //1-收款成功 2-支付宝收款成功 3-微信收款成功
return BsjUtil.get(REQ_URL, bsjParams, reqParams);
}
/**
* 支付方式
*/
private int getPayTypeCode(String ifCode) {
if (StringUtils.isBlank(ifCode)) {
return 1;
}
if (CS.IF_CODE.WXPAY.equals(ifCode)) { // 微信
return 2;
}else if (CS.IF_CODE.ALIPAY.equals(ifCode)) { // 支付宝
return 3;
}else {
return 1;
}
}
}
三、前端配置编码
1.1 > 厂商参数配置
1.1.1 只有manage项目有厂商参数配置
在项目的src\views\device下,SpeakerList、PrinterList分别对应云喇叭、云打印列表,一般无需修改。
CommonAddOrEdit.vue文件为新增/修改主入口。
provider目录为厂商参数配置组件
mchstoredevice目录为设备列表及相关组件
1.1.2 CommonAddOrEdit.vue文件为新增/修改组件
参考以下代码添加要对接的厂商,命名:provider为厂商首字母小写,providerName为厂商名称
/** 定义云喇叭厂商 **/
const speakerProviderList = [
{ provider: 'zgwl', providerName: '智谷物联' },
{ provider: 'bsj', providerName: '博实结' },
{ provider: 'ps', providerName: '品生' }
]
/** 定义云打印厂商 **/
const printerProviderList = [
{ provider: 'fe', providerName: '飞鹅' },
{ provider: 'zgwl', providerName: '智谷物联' },
{ provider: 'bsj', providerName: '博实结' }
]
参考以下代码添加厂商参数配置组件,命名为:厂商首字母 + Config
/** 定义厂商参数配置组件 **/
const allConfigPage = {
'bsj': BsjConfig,
'zgwl': ZgwlConfig,
'fe': FeConfig,
'ps': PsConfig
}
1.1.3 以博实结厂商参数配置组件为例:
<template>
<a-form v-if="vdata.currentConfig" ref="formRef" :model="vdata.currentConfig" layout="vertical" :rules="vdata.formRules">
<a-divider orientation="left">
<a-tag color="#FF4B33">博实结设备参数配置</a-tag>
</a-divider>
<a-row justify="space-between" type="flex">
<a-col :span="11">
<a-form-item label="appId" name="appId">
<a-input v-model:value="vdata.currentConfig.appId" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :span="11">
<a-form-item label="appSecret" name="appSecret">
<a-input v-model:value="vdata.currentConfig.appSecret" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :span="11">
<a-form-item label="userCode" name="userCode">
<a-input v-model:value="vdata.currentConfig.userCode" placeholder="请输入" />
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
<script lang="ts" setup>
import {reactive, ref, defineExpose} from 'vue'
// 当前的form
const formRef = ref()
const vdata = reactive({
// 配置对象
currentConfig: {} as any,
// 表单规则
formRules: {
appId: [{ required: true, message: '请输入appId', trigger: 'blur' }],
appSecret: [{ required: true, message: '请输入appSecret', trigger: 'blur' }],
userCode: [{ required: true, message: '请输入userCode', trigger: 'blur' }]
}
})
// 对外提供的页面的渲染函数 ( ifDefineArray = 接口的配置定义项数组, currentConfig = 当前配置项 )
function pageRender(currentConfig: any){
// 赋值
vdata.currentConfig = currentConfig
// 重置form验证
if (formRef.value !== undefined && formRef.value !== null) {
formRef.value.resetFields()
}
}
// 对外提供的获取配置参数函数 (返回JSON类型)
function getConfigParams(){
return formRef.value.validate().then( () => {
return vdata.currentConfig
})
}
defineExpose({ getConfigParams, pageRender })
</script>