|
|
@@ -0,0 +1,136 @@
|
|
|
+package org.dromara.server.hik.event.domain;
|
|
|
+
|
|
|
+
|
|
|
+import io.seata.common.util.StringUtils;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.io.Serial;
|
|
|
+import java.io.Serializable;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 应答 ConsumptionEvent 的 参数类
|
|
|
+ */
|
|
|
+@Data
|
|
|
+public class ConsumptionEventConfirmBo implements Serializable {
|
|
|
+
|
|
|
+ @Serial
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
+
|
|
|
+ /*wo, req, object, 消费事件确认*/
|
|
|
+ private Integer serialNo;
|
|
|
+ /*req, int, 消费流水号, desc:交易预处理、确认请求流水号保持一致,与交易记录流水号保持一致*/
|
|
|
+ private String result;
|
|
|
+ /*wo, req, enum, 结果, subType:string, [success#交易成功,balanceNotEnough#余额不足,remainingTimesNotEnough#剩余次数不足,noSuchPerson#查无此人,currentTimeNoRight#当前时间段无消费权限,refundSuccess#纠错成功,transactionNotCheckedByDevice#交易未经过设备校验,failed#失败,paying#正在支付,QRCodeExist#重复二维码,QRCodeExpired#二维码过期,amountExceededTheLimit#单次消费超出限额,QRCodeInvalid#无效二维码,continuePay#继续支付],
|
|
|
+ desc:1、当结果为paying时,表示平台与三方服务的支付没有完成,需要设备通过订单状态查询协议获取支付结果。
|
|
|
+ 2、平台二维码消费,同一个二维码只能消费一次,多次刷会消费失败,对应QRCodeExist。
|
|
|
+ 3、continuePay:当组合支付时,平台账户余额不足时,返回该字段,并携带remainingAmount字段下发*/
|
|
|
+ private String reason;
|
|
|
+ /*wo, opt, enum, 失败原因, subType:string, [noPermissionForWeChat#平台未开通微信支付,noPermissionForAlipay#平台未开通支付宝支付,noPermissionForCurrentPayment#平台不支持当前支付方式,deviceNotBoundToMerchant#设备未在平台绑定商户,deviceNotRegistered#当前设备未注册,platformException#支付平台异常,other#其他], dep:or,{$.ConsumptionEventConfirm.result,eq,failed}, desc:二维码支付失败原因*/
|
|
|
+ private String mode;
|
|
|
+ /*wo, opt, enum, 消费模式, subType:string, [amount#金额,quota#定额,count#计次,setMeal#套餐,box#格口消费]*/
|
|
|
+ private String actualPayment;
|
|
|
+ /*wo, opt, string, 实付金额(单位:分), desc:敏感字段加密。当mode为amount/quota/setMeal/box时,该字段必填*/
|
|
|
+ private String remainingAmount;
|
|
|
+ /*opt, string, 组合支付方式下需要二次扣费的金额(单位:分), desc:敏感字段加密。组合支付时使用:设备预处理上报后,等待平台返回结果,若虚拟账户余额不足的情况下,平台支持返回剩余还需要扣费的金额,由设备进行二次展示,第二次扣费支持平台端移动支付和设备端移动支付,当二次扣费成功后,虚拟账户才实际扣费。*/
|
|
|
+ private String balanceBeforeDeduct;
|
|
|
+ /*wo, opt, string, 未扣款前的余额(单位:分),
|
|
|
+ desc:当mode为amount/quota/setMeal/box时,该字段必填;
|
|
|
+ 当result为success,mode为amout或quota,balanceBeforeDeduct为0时,消费成功 ,设备认为最大消费金额配置为0*/
|
|
|
+ private String name;
|
|
|
+ /*wo, opt, string, 姓名, range:[0,128], desc:敏感字段加密。*/
|
|
|
+ private String employeeNoString;
|
|
|
+ /*wo, opt, string, 工号, range:[0,32], desc:敏感字段加密。*/
|
|
|
+ private String cardNo;
|
|
|
+ /*wo, opt, string, 卡号, range:[0,32], desc:敏感字段加密。*/
|
|
|
+ private Integer times;
|
|
|
+ //*wo, opt, int, 将要抵扣的次数, desc:当mode为count时,该字段必填。纠错退次时,该字段表示需要回退的次数*//*
|
|
|
+
|
|
|
+ private String customTTSBroadcastVoice;
|
|
|
+ //*opt, string, 自定义TTS播报语音, range:[1,64], desc:消费事件确认的时候,平台下发该字段。存在该字段且校验成功则优先播报,否则按照设备原本播报规则播报。平台消费结果为成功,该字段为消费成功的自定义语音;平台消费结果为失败,该字段为消费失败的自定义语音*//*
|
|
|
+ private Integer remainingTimes;
|
|
|
+ //*wo, opt, int, 未抵扣前的次数,
|
|
|
+// desc:当mode为count时,该字段可选;
|
|
|
+// 当result为success,mode为count,remaining times为0时,消费成功 ,设备认为最大消费次数配置为0*//*
|
|
|
+ private ContentInfo contentInfo;
|
|
|
+
|
|
|
+ /*
|
|
|
+
|
|
|
+
|
|
|
+ private String QRCodeType;
|
|
|
+ *//*opt, enum, 二维码类型, subType:string, [Alipay#支付宝,WeChat#微信,DigitalCurrencyICBC#工行数字人民币,Private#自研二维码,integrationPayment#聚合支付二维码],
|
|
|
+ desc:当用户使用支付宝或微信或工行数字人民币支付时,平台会返回该字段,用于告知设备,当前用户采用的支付方式,此时工号和卡号无效。
|
|
|
+ 如果返回的是自研二维码,设备走本地支付流程。*//*
|
|
|
+ private String boxID;
|
|
|
+ *//*ro, opt, string, 格口编号, range:[0,7], dep:and,{$.ConsumptionEventConfirm.mode,eq,box},
|
|
|
+ desc:第1位 L 表示格口箱在控制柜左侧,R表示格口箱在控制柜右侧,和控制柜同一列为M
|
|
|
+ 2,3位表示格口箱编号
|
|
|
+ 4,5位表示格口所在格口箱的列号,靠近控制柜的为第一列
|
|
|
+ 6,7位表示格口的行号,从上至下排序*//*
|
|
|
+ private String currencyType;
|
|
|
+ *//*opt, enum, 币种类型, subType:string, [CNY#人民币,USD#美元,EUR#欧元,GBP#英镑,HKD#中国香港元,SGD#新加坡元,KRW#元(韩元),PLN#波兰兹罗提,BYR#白俄罗斯卢布,RUB#俄罗斯卢布,THB#泰国泰铢,TRY#土耳其里拉,VND#越南盾,ILS#以色列新谢克尔,UAH#乌克兰格里夫纳,CZK#捷克克朗,DDK#丹麦克朗,NOK#挪威克朗,SEK#瑞典克朗,BRL#巴西雷亚尔,IQD#伊拉克第纳尔,IDR#印尼卢比,INR#印度卢比,AED#阿联酋迪拉姆,IRR#伊朗土曼,BGN#保加利亚列弗,HUF#匈牙利福林,MYR#马来西亚林吉特,MXN#墨西哥比索], desc:默认是USD。该字段和decimalPlace字段搭配使用,无该字段和decimalPlace字段表示使用的是人民币,小数位为2*//*
|
|
|
+ private Integer decimalPlace;
|
|
|
+ *//*opt, int, 小数位, range:[0,3], desc:表示货币的小数位,默认为2*//*
|
|
|
+
|
|
|
+
|
|
|
+ private String paymentOrderNo;
|
|
|
+ *//*opt, string, 三方支付订单号, range:[1,64], desc:移动支付(微信、支付宝、工号数字人民币)时的订单编号。如果是平台三方支付,需要当查询结果为成功时,需要返回平台维护的三方支付订单号*//*
|
|
|
+ private String secondaryConfirmType;
|
|
|
+ *//*opt, enum, 二次确认类型, subType:string, [none#不需二次确认,highPaymentAmount#大额消费], desc:1、无该字段,表示不需二次确认。2、设备在线时,是否做二次确认,以平台返回该字段为准。3、在/ISAPI/Consume/defaultMode?format=json中配置的highPaymentAmountInfo仅在设备离线时有效。*//*
|
|
|
+ private String userPassword;
|
|
|
+ *//*opt, string, 人员凭证密码, range:[4,8], dep:or,{$.ConsumptionEventConfirm.secondaryConfirmType,eq,highPaymentAmount}, desc:人员凭证密码,用于二次确认,敏感信息加密。*//*
|
|
|
+*/
|
|
|
+ @Data
|
|
|
+ public static class ContentInfo implements Serializable {
|
|
|
+ @Serial
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
+ /*opt, object, 自定义消费结果文字信息, desc:消费平台可以下发自定义的主副标题。设备收到后会将这个字段透传显示在消费结果提示界面*/
|
|
|
+ private String title;
|
|
|
+ /*opt, string, 标题, range:[0,32]*/
|
|
|
+ private String content;
|
|
|
+ /*opt, string, 内容, range:[0,32]*/
|
|
|
+
|
|
|
+ private Map<String, Object> toMap(){
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ if(StringUtils.isNotBlank(title)){
|
|
|
+ map.put("title", title);
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotBlank(content)){
|
|
|
+ map.put("content", content);
|
|
|
+ }
|
|
|
+ if (map.isEmpty()){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, Object> toMap() {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ putIfNotEmpty(map, "serialNo", serialNo);
|
|
|
+ putIfNotEmpty(map, "result", result);
|
|
|
+ putIfNotEmpty(map, "reason", reason);
|
|
|
+ putIfNotEmpty(map, "mode", mode);
|
|
|
+ putIfNotEmpty(map, "name", name);
|
|
|
+ putIfNotEmpty(map, "employeeNoString", employeeNoString);
|
|
|
+ putIfNotEmpty(map, "cardNo", cardNo);
|
|
|
+ putIfNotEmpty(map, "actualPayment", actualPayment);
|
|
|
+ putIfNotEmpty(map, "balanceBeforeDeduct", balanceBeforeDeduct);
|
|
|
+ putIfNotEmpty(map, "times", times);
|
|
|
+ putIfNotEmpty(map, "remainingTimes", remainingTimes);
|
|
|
+ putIfNotEmpty(map, "customTTSBroadcastVoice", customTTSBroadcastVoice);
|
|
|
+ putIfNotEmpty(map, "contentInfo", contentInfo != null ? contentInfo.toMap() : null);
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void putIfNotEmpty(Map<String, Object> map, String key, Object value) {
|
|
|
+ if (value instanceof String && ((String) value).isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (value != null) {
|
|
|
+ map.put(key, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|