diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/sys/WxUserDataRuleController.java b/mallinkAdmin/src/main/java/com/iformall/controller/sys/WxUserDataRuleController.java index 861e8743b..eee9ec850 100644 --- a/mallinkAdmin/src/main/java/com/iformall/controller/sys/WxUserDataRuleController.java +++ b/mallinkAdmin/src/main/java/com/iformall/controller/sys/WxUserDataRuleController.java @@ -2,9 +2,12 @@ package com.iformall.controller.sys; import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; import com.iformall.common.ResultData; import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.MallUserInfo; import com.iformall.domain.po.WxUserDataRule; +import com.iformall.enums.EnumUserAdmin; import com.iformall.service.WxUserDataRuleService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -31,6 +34,11 @@ public class WxUserDataRuleController extends BaseController { @SystemControllerLog(description = "用户数据权限-新增") public ResultData modify(@RequestBody WxUserDataRule wxUserDataRule) { logger.debug("[" + getIpAddr() + "] wxDataRuleTarget::modify"); + MallUserInfo currentUser = getUser(); + // 系统管理员才能修改信息 + if (!currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode())) { + return new ResultData(ErrorCode.USER_NO_PERMISSION.getCode(), "系统管理员才能修改信息"); + } wxUserDataRuleService.modify(wxUserDataRule); return new ResultData(); } diff --git a/mallinkAdmin/src/main/java/com/iformall/log/UserDataRuleAspect.java b/mallinkAdmin/src/main/java/com/iformall/log/UserDataRuleAspect.java index 879e90bed..f7c889c7a 100644 --- a/mallinkAdmin/src/main/java/com/iformall/log/UserDataRuleAspect.java +++ b/mallinkAdmin/src/main/java/com/iformall/log/UserDataRuleAspect.java @@ -62,7 +62,7 @@ public class UserDataRuleAspect { buildingFloor = StringUtils.join(data, ","); } - String businessForRule = byUserId.getBusinessForRule(); + String businessForRule = byUserId.getBusiness(); if (StringUtils.isNotEmpty(businessForRule)) { Object[] data = JSONArray.parseArray(businessForRule).toArray(); businessForRule = StringUtils.join(data, ","); diff --git a/mallinkAdmin/src/main/resources/db/migration/V201908281420__POS_CHANGED.sql b/mallinkAdmin/src/main/resources/db/migration/V201908281420__POS_CHANGED.sql new file mode 100644 index 000000000..1ade9c355 --- /dev/null +++ b/mallinkAdmin/src/main/resources/db/migration/V201908281420__POS_CHANGED.sql @@ -0,0 +1,13 @@ +alter table wx_order +add `pos_order_create_time` bigint(20) NULL COMMENT 'POS系统订单创建时间'; + +alter table wx_pay_order +add `pos_pay_order_time` bigint(20) NULL COMMENT '支付订单创建时间,来源于POS', +add `pos_pay_order_no` varchar(20) NULL COMMENT '支付订单流水号, 来源于POS, 第三方(微信、支付宝、富茂预付卡)支付订单流水号,富茂优惠券ID,现金和富茂会员折扣时为空', +add `pos_pay_desc` varchar(100) NULL COMMENT 'POS支付描述', +modify `pos_pay_id` bigint(20) NULL COMMENT '支付订单号,来源于POS'; + +alter table pos_mall_config +modify `discount` tinyint(6) NOT NULL DEFAULT '0' COMMENT '会员折扣是否开启,0-禁用,1-可用', +modify `coupon` tinyint(6) NOT NULL DEFAULT '0' COMMENT '会员优惠券是否开启,0-禁用,1-单选可用,2-多选可用', +modify `card` tinyint(6) NOT NULL DEFAULT '0' COMMENT '会员消费卡是否开启,0-禁用,1-可用' after `coupon`; diff --git a/mallinkBApi/src/main/java/com/iformall/controller/PosController.java b/mallinkBApi/src/main/java/com/iformall/controller/PosController.java index 57a89fcbb..2ef784c86 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/PosController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/PosController.java @@ -66,11 +66,9 @@ public class PosController extends BaseController { String couponOrderIdStr = params.get(WxPayConstant.COUPON_ORDER_ID); // 券包ID if (StringUtils.isBlank(couponOrderIdStr)) { - String errMessage = "request params[coupon_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.COUPON_ORDER_ID); } - String verifyType = WxPayConstant.VERIFY_TYPE_INDEPENT; + String verifyType = WxPayConstant.SCENE_VERIFY; return posService.checkCouponOrderForIndepentVerify(user, verifyType, couponOrderIdStr); } @@ -98,14 +96,10 @@ public class PosController extends BaseController { String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单金额(单位:分) if (StringUtils.isBlank(posOrderIdStr)) { - String errMessage = "request params[pos_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_ORDER_ID); } if (StringUtils.isBlank(posAmountStr)) { - String errMessage = "request params[pos_amount] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_AMOUNT); } if (StringUtils.isBlank(memIdStr) && StringUtils.isBlank(memPhoneStr)) { @@ -125,21 +119,15 @@ public class PosController extends BaseController { String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单金额 if (StringUtils.isBlank(couponOrderIdStr)) { - String errMessage = "request params[coupon_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.COUPON_ORDER_ID); } if (StringUtils.isBlank(posOrderIdStr)) { - String errMessage = "request params[pos_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_ORDER_ID); } if (StringUtils.isBlank(posAmountStr)) { - String errMessage = "request params[pos_amount] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_AMOUNT); } - String verifyType = WxPayConstant.VERIFY_TYPE_PAY; + String verifyType = WxPayConstant.SCENE_PAY; return posService.checkCouponOrderForPayVerify(user, verifyType, couponOrderIdStr, posOrderIdStr, posAmountStr); } @@ -153,24 +141,16 @@ public class PosController extends BaseController { String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单金额(单位:分) if (StringUtils.isBlank(couponOrderIdStr)) { - String errMessage = "request params[coupon_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.COUPON_ORDER_ID); } if (StringUtils.isBlank(deductAmountStr)) { - String errMessage = "request params[deduct_amount] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.DEDUCT_AMOUNT); } if (StringUtils.isBlank(posOrderIdStr)) { - String errMessage = "request params[pos_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_ORDER_ID); } if (StringUtils.isBlank(posAmountStr)) { - String errMessage = "request params[pos_amount] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_AMOUNT); } return posService.couponOrderPreVerify(user, couponOrderIdStr, deductAmountStr, posOrderIdStr, posAmountStr); } @@ -182,9 +162,7 @@ public class PosController extends BaseController { WxMerchantBUser user = getUser(); String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID if (StringUtils.isBlank(posOrderIdStr)) { - String errMessage = "request params[pos_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_ORDER_ID); } // 1. 获取订单信息 // 2. 获取所有的支付订单信息 @@ -202,21 +180,21 @@ public class PosController extends BaseController { String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单金额(单位:分) if (StringUtils.isBlank(couponOrderIdStr)) { - String errMessage = "request params[coupon_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.COUPON_ORDER_ID); } if (StringUtils.isBlank(posOrderIdStr)) { - String errMessage = "request params[pos_order_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_ORDER_ID); } if (StringUtils.isBlank(posAmountStr)) { - String errMessage = "request params[pos_amount] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + return errParam(WxPayConstant.POS_AMOUNT); } return posService.couponOrderPreVerifyCancel(user, couponOrderIdStr, posOrderIdStr, posAmountStr); } + private ResultData errParam(String paramStr) { + String errMessage = String.format("request params[%s] error.", paramStr); + logger.error(errMessage); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + } diff --git a/mallinkBApi/src/main/java/com/iformall/utils/PosUtil.java b/mallinkBApi/src/main/java/com/iformall/utils/PosUtil.java index c5a8e57eb..8d68994ce 100755 --- a/mallinkBApi/src/main/java/com/iformall/utils/PosUtil.java +++ b/mallinkBApi/src/main/java/com/iformall/utils/PosUtil.java @@ -269,7 +269,7 @@ public class PosUtil { paramMap.put(WxPayConstant.TENANT_ID, tenantId); paramMap.put(WxPayConstant.MERCHANT_ID, merchantId); paramMap.put(WxPayConstant.BUSER_ID, buUserId); - paramMap.put(WxPayConstant.VERIFY_TYPE, verifyType); + paramMap.put(WxPayConstant.SCENE_TYPE, verifyType); paramMap.put(WxPayConstant.COUPON_ORDER_ID, couponOrderId); if (StringUtils.isNotBlank(posOrderId)) { paramMap.put(WxPayConstant.POS_ORDER_ID, posOrderId); diff --git a/mallinkPosApi/src/main/java/com/iformall/controller/PosController.java b/mallinkPosApi/src/main/java/com/iformall/controller/PosController.java index ea8a23d55..0078b6477 100644 --- a/mallinkPosApi/src/main/java/com/iformall/controller/PosController.java +++ b/mallinkPosApi/src/main/java/com/iformall/controller/PosController.java @@ -34,12 +34,25 @@ public class PosController extends BaseController { private final ThDevInfoService thDevInfoService; private final WxCouponOrderService couponOrderService; - @ApiOperation(value = "门店用户登录检查", notes = "{" + + @ApiOperation(value = "门店用户登录检查, 同时会返回会员折扣/优惠券/消费卡是否启用,mall信息及注册二维码及小票二维码规则", notes = "request: \n{" + "\"dev_id\":\"string(必填)\"," + "\"nonce_str\":\"string(必填)," + "\"tenant_id\":\"string(必填)\"," + "\"phone\":\"string(必填)\"," + - "\"password\":\"string(必填)\"}") + "\"password\":\"string(必填)\"}\n" + + "response: \n{" + + "\"return_code\":\"SUCCESS\",\"return_msg\":\"\",\"result_code\":\"SUCCESS\"," + + "\"tenant_id\":\"456\",\"mall_name\":\"富茂中心\"," + + "\"merchant_id\":\"320833942159982592\",\"merchant_name\":\"东软合作\"," + + "\"merchant_img\":\"https://s3.cn-northwest-1.amazonaws.com.cn/iformall-net/234/WechatIMG5071.png\"," + + "\"bu_user_id\":\"320834180694245376\"," + + "\"qrcode_url\":\"https://s3.cn-northwest-1.amazonaws.com.cn/iformall-net/456/formall_c.png\"," + + "\"pos_qrcode_rule\":\"https://ctest.malls.iformall.com/order/(二维码规则: url + POS订单ID)\"," + + "\"discount\":\"false(是否支持会员折扣,false:禁用,true:可用)\"," + + "\"coupon\":\"0(会员优惠券是否开启,0-禁用,1-单选可用,2-多选可用)\",\"coupon_desc\":\"禁用(会员优惠券是否开启描述)\"," + + "\"card\":\"false(是否支持卡支付,false:禁用,true:可用)\"" + + "\"nonce_str\":\"2d8320f95e73419ebd42fcfded970d5b\"," + + "\"sign\":\"62139EE7897CF3BA44D9DBECA95AF6B116A9C49BBBB574BF3D2AF2939EE30423\"}") @PostMapping("/checkUserPassword") @SystemControllerLog(description = "门店用户登录检查") public Map checkUserPassword(@RequestBody Map params) { @@ -51,8 +64,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { retMap = posService.checkUserPassword(params); @@ -68,10 +81,20 @@ public class PosController extends BaseController { } } - @ApiOperation(value = "获取会员折扣/优惠券/消费卡是否启用", notes = "{" + + @ApiOperation(value = "获取会员折扣/优惠券/消费卡是否启用, 同时返回注册二维码及小票二维码规则", notes = "request: \n{" + "\"dev_id\":\"string(必填)\"," + "\"nonce_str\":\"string(必填)\"," + - "\"tenant_id\":\"string(必填)\"}") + "\"tenant_id\":\"string(必填)\"}\n" + + "\"response: \n{" + + "\"return_code\":\"SUCCESS\",\"return_msg\":\"\",\"result_code\":\"SUCCESS\"," + + "\"tenant_id\":\"456\",\"mall_name\":\"富茂中心\"," + + "\"qrcode_url\":\"https://s3.cn-northwest-1.amazonaws.com.cn/iformall-net/456/formall_c.png\"," + + "\"pos_qrcode_rule\":\"https://ctest.malls.iformall.com/order/(二维码规则: url + POS订单ID)\"," + + "\"discount\":\"false(是否支持会员折扣,false:禁用,true:可用)\"," + + "\"coupon\":\"0(会员优惠券是否开启,0-禁用,1-单选可用,2-多选可用)\",\"coupon_desc\":\"禁用(会员优惠券是否开启描述)\"," + + "\"card\":\"false(是否支持卡支付,false:禁用,true:可用)\"" + + "\"nonce_str\":\"eea09381622540868d22dee631054b30\"," + + "\"sign\":\"0EADC3B7D4B77D0AC923C095B6172955D462366FB4BF142467B4935FA7833A91\"}") @PostMapping("/getPosMemConfig") @SystemControllerLog(description = "获取会员折扣/优惠券/消费卡是否启用") public Map getMemStatus(@RequestBody Map params) { @@ -83,8 +106,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { retMap = posService.getPosMemConfig(params); @@ -100,10 +123,17 @@ public class PosController extends BaseController { } } - @ApiOperation(value = "获取注册二维码及小票二维码规则", notes = "{" + + @ApiOperation(value = "获取注册二维码及小票二维码规则", notes = "request: \n{" + "\"dev_id\":\"string(必填)\"," + "\"nonce_str\":\"string(必填)\"," + - "\"tenant_id\":\"string(必填)\"}") + "\"tenant_id\":\"string(必填)\"}\n" + + "\"response: \n{" + + "\"return_code\":\"SUCCESS\",\"return_msg\":\"\",\"result_code\":\"SUCCESS\"," + + "\"tenant_id\":\"456\",\"mall_name\":\"富茂中心\"," + + "\"qrcode_url\":\"https://s3.cn-northwest-1.amazonaws.com.cn/iformall-net/456/formall_c.png\"," + + "\"pos_qrcode_rule\":\"https://ctest.malls.iformall.com/order/(二维码规则: url + POS订单ID)\"," + + "\"nonce_str\":\"5604985305904f35bc9eeeda94346f8d\"," + + "\"sign\":\"5760C5989C3DD2F99CB3506EDBA0FB84A77BC60313F65206EB774A203108AA82\"}") @PostMapping("/getQrCode") @SystemControllerLog(description = "获取注册二维码及小票二维码规则") public Map getQrCode(@RequestBody Map params) { @@ -115,8 +145,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { retMap = posService.doGetQrCode(params); @@ -133,15 +163,15 @@ public class PosController extends BaseController { } - @ApiOperation(value = "会员识别", notes = "{" + + @ApiOperation(value = "会员识别", notes = "request: \n{" + "\"dev_id\":\"string(必填)\"," + + "\"nonce_str\":\"string(必填)\"," + "\"tenant_id\":\"string(必填)\"," + "\"merchant_id\":\"string(必填)\"," + "\"mem_id\":\"string(选填)\"," + "\"mem_phone\":\"string(选填)\"," + "\"pos_order_id\":\"string(必填)\"," + - "\"pos_amount\":\"string(单位:分)(必填)\"," + - "\"nonce_str\":\"string(必填)\"}") + "\"pos_amount\":\"string(单位:分)(必填)\"}") @PostMapping("/checkMem") @SystemControllerLog(description = "会员识别") public Map checkMem(@RequestBody Map params) { @@ -153,8 +183,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { retMap = posService.checkMember(params); @@ -171,19 +201,59 @@ public class PosController extends BaseController { } } - @ApiOperation(value = "券核销检查", notes = "{" + + @ApiOperation(value = "券检查是否可用-场景(核销/支付)", notes = "{" + "\"dev_id\":\"string(必填)\"," + "\"nonce_str\":\"string(必填)\"," + "\"tenant_id\":\"string(必填)\"," + "\"merchant_id\":\"string(必填)\"," + "\"bu_user_id\":\"string(必填)\"," + "\"coupon_order_id\":\"string(必填)\"," + - "\"verify_type\":\"independent, pay(必填)\"," + + "\"scene_type\":\"string(1支付2:核销)(必填)\"," + + "\"pos_order_id\":\"string(选填)\"," + + "\"pos_amount\":\"string单位(分)(选填)\"}") + @PostMapping("/checkCouponOrder") + @SystemControllerLog(description = "券检查是否可用-场景(核销/支付)") + public Map checkCouponOrder(@RequestBody Map params) { + JSONObject payContent = new JSONObject(); + + // 1. check sign + Map retMap = checkSign(params, payContent); + if (retMap != null) { + // 签名相关异常返回 + return retMap; + } + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); + + try { + retMap = posService.couponOrderVerifyDo(params, EnumPosActionType.CHECK); + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_SUCCESS, null); + } catch (MallinkException e) { + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_FAIL, + e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", + WxPayConstant.RET_FAIL, + 500, e.getMessage()); + } + } + + @ApiOperation(value = "支付计算接口", notes = "{" + + "\"dev_id\":\"string(必填)\"," + + "\"nonce_str\":\"string(必填)\"," + + "\"tenant_id\":\"string(必填)\"," + + "\"merchant_id\":\"string(必填)\"," + + "\"bu_user_id\":\"string(必填)\"," + + "\"mem_id\":\"string(选填)\"," + + "\"mem_phone\":\"string(选填)\"," + + "\"sel_co_list\":\"json array[券包ID list](必填),例[\"1\",\"2\",\"3\"]\"" + "\"pos_order_id\":\"string(选填)\"," + - "\"pos_amount\":\"单位(分)(选填)\"}") - @PostMapping("/checkCouponOrderForVerify") - @SystemControllerLog(description = "券核销检查") - public Map checkCouponOrderVerify(@RequestBody Map params) { + "\"pos_amount\":\"string单位(分)(必填)\"}") + @PostMapping("/calcMem") + @SystemControllerLog(description = "支付计算接口") + public Map calcForMem(@RequestBody Map params) { JSONObject payContent = new JSONObject(); // 1. check sign @@ -192,11 +262,11 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { - retMap = posService.couponOrderVerifyDo(params, EnumVerifyActionType.CHECK); + retMap = posService.calcMem(params); return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_SUCCESS, null); } catch (MallinkException e) { @@ -230,11 +300,11 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { - retMap = posService.couponOrderVerifyDo(params, EnumVerifyActionType.PRE_VERIFY); + retMap = posService.couponOrderVerifyDo(params, EnumPosActionType.PRE_VERIFY); return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_SUCCESS, null); } catch (MallinkException e) { @@ -267,11 +337,11 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { - retMap = posService.couponOrderVerifyCancel(params, EnumVerifyActionType.PRE_VERIFY_CANCEL); + retMap = posService.couponOrderVerifyCancel(params, EnumPosActionType.PRE_VERIFY_CANCEL); return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_SUCCESS, null); } catch (MallinkException e) { @@ -304,11 +374,11 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { - retMap = posService.couponOrderVerifyDo(params, EnumVerifyActionType.VERIFY_INDEPENT); + retMap = posService.couponOrderVerifyDo(params, EnumPosActionType.VERIFY_INDEPENT); } catch (MallinkException e) { return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_FAIL, @@ -363,11 +433,11 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { - retMap = posService.couponOrderVerifyDo(params, EnumVerifyActionType.VERIFY_PAY); + retMap = posService.couponOrderVerifyDo(params, EnumPosActionType.VERIFY_PAY); } catch (MallinkException e) { return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_FAIL, @@ -403,11 +473,11 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { - retMap = posService.couponOrderVerifyListDo(params, EnumVerifyActionType.VERIFY_PAY); + retMap = posService.couponOrderVerifyListDo(params, EnumPosActionType.VERIFY_PAY); } catch (MallinkException e) { return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_FAIL, @@ -444,7 +514,7 @@ public class PosController extends BaseController { ErrorCode.SYS_PARAMETER_CAST_ERROR); } String errCode = retMap.get(WxPayConstant.VERIFY); - if(errCode.equalsIgnoreCase("true")) { + if(errCode.equalsIgnoreCase(WxPayConstant.TRUE)) { // 核销成功 couponOrderService.sendInsideCouponVerifyMsg(tenantId, couponOrderId, buUserId, EnumCouponVerifyType.VERIFY_POS_PAY.getCode()); } @@ -473,11 +543,11 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { - retMap = posService.couponOrderVerifyCancel(params, EnumVerifyActionType.VERIFY_CANCEL); + retMap = posService.couponOrderVerifyCancel(params, EnumPosActionType.VERIFY_CANCEL); return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_SUCCESS, null); } catch (MallinkException e) { @@ -511,8 +581,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { retMap = posService.cardPayPre(params); @@ -550,8 +620,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { retMap = posService.cardPayPreCancel(params); @@ -588,8 +658,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { retMap = posService.cardPay(params); @@ -627,8 +697,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { retMap = posService.cardPayCancel(params); @@ -658,8 +728,8 @@ public class PosController extends BaseController { // 签名相关异常返回 return retMap; } - String resKey = payContent.getString("resKey"); - logger.info("resKey: " + resKey); + String resKey = payContent.getString(WxPayConstant.RES_KEY); + logger.info(WxPayConstant.RES_KEY + ": " + resKey); try { @@ -754,39 +824,39 @@ public class PosController extends BaseController { String devId = params.get(WxPayConstant.DEV_ID); // 开发者ID String sign = params.get(WxPayConstant.SIGN); // 签名 if (StringUtils.isBlank(devId)) { - String errorMessage = "request params[dev_id] error."; + String errorMessage = String.format("request params[%s] error.", WxPayConstant.DEV_ID); return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errorMessage); } if (StringUtils.isBlank(sign)) { - String errorMessage = "request params[sign] error."; + String errorMessage = String.format("request params[%s] error.", WxPayConstant.SIGN); return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errorMessage); } // 查询开发者信息 ThDevInfo devInfo = thDevInfoService.getByDevId(devId); if (devInfo == null) { - String errorMessage = "Can't found devInfo[dev_id="+devId+"] record in db."; + String errorMessage = String.format("Can't found devInfo[%s=%s] record in db.", WxPayConstant.DEV_ID, devId); return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_NOT_FOUND.getCode(), errorMessage); } if (devInfo.getState().equals(EnumEnableType.Disable.getCode())) { - String errorMessage = "devInfo not available [dev_id="+devId+"] record in db."; + String errorMessage = String.format("devInfo not available [%s=%s] record in db.", WxPayConstant.DEV_ID, devId); return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_IS_DISABLED.getCode(), errorMessage); } if (StringUtils.isBlank(devInfo.getReqKey())) { - String errorMessage = "reqKey is null[dev_id="+devId+"] record in db."; + String errorMessage = String.format("%s is null[%s=%s] record in db.", WxPayConstant.REQ_KEY, WxPayConstant.DEV_ID, devId); return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_REQ_KEY_IS_NULL.getCode(), errorMessage); } if (StringUtils.isBlank(devInfo.getResKey())) { - String errorMessage = "resKey is null[dev_id="+devId+"] record in db."; + String errorMessage = String.format("%s is null[%s=%s] record in db.", WxPayConstant.RES_KEY, WxPayConstant.DEV_ID, devId); return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_RES_KEY_IS_NULL.getCode(), errorMessage); } - payContent.put("resKey", devInfo.getResKey()); + payContent.put(WxPayConstant.RES_KEY, devInfo.getResKey()); boolean signVerified = WxPayment.verifyNotifyHMAC(params, devInfo.getReqKey()); if (!signVerified) { String errorMessage = "签名错误"; - logger.error("checksign error, params: " + params.toString()); + logger.error(errorMessage + ": " + params.toString()); return buildReturnMap(WxPayConstant.RET_FAIL, errorMessage, WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_RES_KEY_IS_NULL.getCode(), errorMessage); } return null; diff --git a/mallinkPosApi/src/main/java/com/iformall/service/PosService.java b/mallinkPosApi/src/main/java/com/iformall/service/PosService.java index 33af9520d..3d818dcf3 100644 --- a/mallinkPosApi/src/main/java/com/iformall/service/PosService.java +++ b/mallinkPosApi/src/main/java/com/iformall/service/PosService.java @@ -1,8 +1,7 @@ package com.iformall.service; -import com.iformall.enums.EnumVerifyActionType; +import com.iformall.enums.EnumPosActionType; import com.iformall.exception.MallinkException; -import org.springframework.web.bind.annotation.RequestBody; import java.util.Map; @@ -35,6 +34,13 @@ public interface PosService { */ Map checkMember(Map params) throws MallinkException; + /** + * 支付计算 + * @param params + * @return + */ + Map calcMem(Map params) throws MallinkException; + /** * 核销动作(check, pre_verify, verify) * @param params @@ -42,7 +48,7 @@ public interface PosService { * @return * @throws MallinkException */ - Map couponOrderVerifyDo(Map params, EnumVerifyActionType actionType) throws MallinkException; + Map couponOrderVerifyDo(Map params, EnumPosActionType actionType) throws MallinkException; /** * 核销取消(check, pre_verify, verify) for selected_coupon_list @@ -51,7 +57,7 @@ public interface PosService { * @return * @throws MallinkException */ - Map couponOrderVerifyCancel(Map params, EnumVerifyActionType actionType) throws MallinkException; + Map couponOrderVerifyCancel(Map params, EnumPosActionType actionType) throws MallinkException; /** * 核销动作(check, pre_verify, verify) for selected_coupon_list @@ -60,7 +66,7 @@ public interface PosService { * @return * @throws MallinkException */ - Map couponOrderVerifyListDo(Map params, EnumVerifyActionType actionType) throws MallinkException; + Map couponOrderVerifyListDo(Map params, EnumPosActionType actionType) throws MallinkException; /** * 消费卡POS预支付 diff --git a/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java b/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java index f7941f207..250192127 100644 --- a/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java +++ b/mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java @@ -4,15 +4,13 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.iformall.common.ErrorCode; +import com.iformall.common.IdWorker; import com.iformall.domain.po.*; import com.iformall.domain.vo.WxCouponOrderCVo; import com.iformall.domain.vo.WxLevelMerchantCVo; import com.iformall.enums.*; import com.iformall.exception.MallinkException; -import com.iformall.mapper.WxCouponMapper; -import com.iformall.mapper.WxCouponMerchantMapper; -import com.iformall.mapper.WxCouponOrderMapper; -import com.iformall.mapper.WxOrderMapper; +import com.iformall.mapper.*; import com.iformall.pay.WxPayConstant; import com.iformall.service.*; import lombok.AllArgsConstructor; @@ -23,6 +21,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestBody; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; @@ -35,6 +34,10 @@ public class PosServiceImpl implements PosService { private final Logger logger = LoggerFactory.getLogger(this.getClass()); + // neu时间格式, 4位年2位月2位日2位24小时制时2位分2位秒3位毫秒 + private final SimpleDateFormat neuDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + private final SimpleDateFormat mydateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private final WxMallService mallService; private final PosMallConfigService posMallConfigService; private final WxCUserService cUserService; @@ -49,13 +52,12 @@ public class PosServiceImpl implements PosService { private final WxCardSpendService cardSpendService; private final WxOrderMapper orderMapper; + private final WxPayOrderMapper payOrderMapper; private final WxCouponOrderMapper couponOrderMapper; private final WxCouponMerchantMapper couponMerchantMapper; private final WxCouponMapper couponMapper; - private final SimpleDateFormat mydateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - /** * 门店用户登录检查 * @param params @@ -78,6 +80,18 @@ public class PosServiceImpl implements PosService { if (StringUtils.isBlank(password)) { errParam(WxPayConstant.PASSWORD); } + WxMall mall = mallService.getByTenantId(tenantId); + if (mall == null) { + logger.error(ErrorCode.MALL_INFO_NOT_FOUND.getMessage()); + throw new MallinkException(ErrorCode.MALL_INFO_NOT_FOUND); + } + + PosMallConfig config = posMallConfigService.getByTenantId(tenantId); + if (config == null) { + logger.error(ErrorCode.MALL_INFO_NOT_FOUND.getMessage()); + throw new MallinkException(ErrorCode.MALL_INFO_NOT_FOUND); + } + WxMerchantBUser user = new WxMerchantBUser(); user.setTenantId(tenantId); user.setPhone(phone); @@ -96,8 +110,19 @@ public class PosServiceImpl implements PosService { // check password if (user1.getUserPwd().equalsIgnoreCase(password)) { retMap.put(WxPayConstant.TENANT_ID, user1.getTenantId()); + retMap.put(WxPayConstant.MALL_NAME, mall.getName()); retMap.put(WxPayConstant.MERCHANT_ID, String.valueOf(user1.getMerchantId())); + retMap.put(WxPayConstant.MERCHANT_NAME, merchant.getName()); + retMap.put(WxPayConstant.MERCHANT_IMG, merchant.getImgUrl()); retMap.put(WxPayConstant.BUSER_ID, String.valueOf(user1.getId())); + + retMap.put(WxPayConstant.REG_QRCODE_URL, mall.getImgQrcodeWeapp()); + retMap.put(WxPayConstant.POS_QRCODE_RULE, mall.getPosQrcodeRule()); + + retMap.put(WxPayConstant.MEM_DISCOUNT, String.valueOf(config.getDiscount().equals(EnumPosEnableType.Enable.getCode()))); + retMap.put(WxPayConstant.MEM_COUPON, String.valueOf(config.getCoupon())); + retMap.put(WxPayConstant.MEM_COUPON_DESC, EnumPosCouponEnableType.getEnum(config.getCoupon()).getMessage()); + retMap.put(WxPayConstant.MEM_CARD, String.valueOf(config.getCard().equals(EnumPosEnableType.Enable.getCode()))); return retMap; } else { logger.error(ErrorCode.PASSWORD_ERROR.getMessage()); @@ -123,14 +148,25 @@ public class PosServiceImpl implements PosService { if (StringUtils.isBlank(tenantId)) { errParam(WxPayConstant.TENANT_ID); } + WxMall mall = mallService.getByTenantId(tenantId); + if (mall == null) { + logger.error(ErrorCode.MALL_INFO_NOT_FOUND.getMessage()); + throw new MallinkException(ErrorCode.MALL_INFO_NOT_FOUND); + } PosMallConfig config = posMallConfigService.getByTenantId(tenantId); if (config == null) { logger.error(ErrorCode.MALL_INFO_NOT_FOUND.getMessage()); throw new MallinkException(ErrorCode.MALL_INFO_NOT_FOUND); } - retMap.put(WxPayConstant.MEM_DISCOUNT, String.valueOf(config.getDiscount().equals(EnumEnableType.Enable.getCode()))); - retMap.put(WxPayConstant.MEM_COUPON, String.valueOf(config.getCoupon().equals(EnumEnableType.Enable.getCode()))); - retMap.put(WxPayConstant.MEM_CARD, String.valueOf(config.getCard().equals(EnumEnableType.Enable.getCode()))); + retMap.put(WxPayConstant.TENANT_ID, mall.getTenantId()); + retMap.put(WxPayConstant.MALL_NAME, mall.getName()); + retMap.put(WxPayConstant.REG_QRCODE_URL, mall.getImgQrcodeWeapp()); + retMap.put(WxPayConstant.POS_QRCODE_RULE, mall.getPosQrcodeRule()); + + retMap.put(WxPayConstant.MEM_DISCOUNT, String.valueOf(config.getDiscount().equals(EnumPosEnableType.Enable.getCode()))); + retMap.put(WxPayConstant.MEM_COUPON, String.valueOf(config.getCoupon())); + retMap.put(WxPayConstant.MEM_COUPON_DESC, EnumPosCouponEnableType.getEnum(config.getCoupon()).getMessage()); + retMap.put(WxPayConstant.MEM_CARD, String.valueOf(config.getCard().equals(EnumPosEnableType.Enable.getCode()))); return retMap; } @@ -153,6 +189,8 @@ public class PosServiceImpl implements PosService { logger.error(ErrorCode.MALL_INFO_NOT_FOUND.getMessage()); throw new MallinkException(ErrorCode.MALL_INFO_NOT_FOUND); } + retMap.put(WxPayConstant.TENANT_ID, mall.getTenantId()); + retMap.put(WxPayConstant.MALL_NAME, mall.getName()); retMap.put(WxPayConstant.REG_QRCODE_URL, mall.getImgQrcodeWeapp()); retMap.put(WxPayConstant.POS_QRCODE_RULE, mall.getPosQrcodeRule()); return retMap; @@ -167,11 +205,12 @@ public class PosServiceImpl implements PosService { public Map checkMember(Map params) throws MallinkException { Map retMap = new HashMap<>(); - String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID - String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID + String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID + String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID + String buUserIdStr = params.get(WxPayConstant.BUSER_ID); // POS操作员ID String memIdStr = params.get(WxPayConstant.MEM_ID); // 会员ID - String memPhoneStr = params.get(WxPayConstant.MEM_PHONE); // 会员手机 - String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID + String memPhoneStr = params.get(WxPayConstant.MEM_PHONE); // 会员手机 + String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单金额(单位:分) if (StringUtils.isBlank(tenantId)) { @@ -194,83 +233,54 @@ public class PosServiceImpl implements PosService { errParam(WxPayConstant.POS_AMOUNT); } - if (StringUtils.isBlank(memIdStr) && StringUtils.isBlank(memPhoneStr)) { - String errMessage = "please give one value for mem_id or mem_phone"; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); - } - WxCUser user = null; - if (StringUtils.isNotBlank(memIdStr)) { - Long memId; - try { - memId = Long.valueOf(memIdStr); - } catch (NumberFormatException e) { - logger.error(e.getMessage()); - throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); - } - - user = cUserService.getById(memId); - } - if (StringUtils.isNotBlank(memPhoneStr)) { - WxCUser q = new WxCUser(); - q.setTenantId(tenantId); - q.setPhone(memPhoneStr); - user = cUserService.getByObject(q); - } - - if (user == null) { - logger.error(ErrorCode.USER_NOT_MEMBER.getMessage()); - throw new MallinkException(ErrorCode.USER_NOT_MEMBER); - } - - Long merchantId, posOrderId; - Integer posAmount = 0; + // 1. 商户ID, B端用户ID + Long merchantId, buUserId, posOrderId; + Long posAmount = 0L; try { merchantId = Long.valueOf(merchantIdStr); + buUserId = Long.valueOf(buUserIdStr); posOrderId = Long.valueOf(posOrderIdStr); - posAmount = Integer.valueOf(posAmountStr); + posAmount = Long.valueOf(posAmountStr); } catch (NumberFormatException e) { logger.error(e.getMessage()); throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR); } - Integer discount = 100; - if (config.getDiscount().equals(EnumEnableType.Enable.getCode())) { - - // Level, 折扣 - List levelList = levelConfigService.getByTenantId(tenantId); - - String level = WxLevelConfigService.DEFAULT_LEVEL; - Long levelId = 0L; - for (WxLevelConfig levelConfig : levelList) { - if (user.getScore() >= levelConfig.getPoints()) { - if (levelConfig.getDiscountEnable().equals(EnumLevelConfigDiscountStatus.ENABLE.getCode())) - levelId = levelConfig.getId(); - level = levelConfig.getLevel(); - } - } - - WxLevelMerchant levelMerchant = new WxLevelMerchant(); - levelMerchant.setTenantId(tenantId); - levelMerchant.setLevelId(levelId); - levelMerchant.setMerchantId(merchantId); - List levelMerchantList = levelConfigService.findListCVo(levelMerchant); - if (levelMerchantList.size() >= 1) { - WxLevelMerchantCVo levelMerchantCVo = levelMerchantList.get(0); - if (levelMerchantCVo != null) { - discount = levelMerchantCVo.getDiscount(); - } - } + // 2. check merchant + WxMerchant merchant = checkAndGetMerchant(merchantId); + // 3. check buUser + WxMerchantBUser buUser = checkAndGetMerchantUser(buUserId, merchantId); - retMap.put(WxPayConstant.MEM_LEVEL, level); + // 3. 会员ID + if (StringUtils.isBlank(memIdStr) && StringUtils.isBlank(memPhoneStr)) { + errParam2(WxPayConstant.MEM_ID, WxPayConstant.MEM_PHONE); + } + // 4. 获取会员信息 + WxCUser user = getMemUser(tenantId, memIdStr, memPhoneStr); + if (user == null) { + logger.error(ErrorCode.USER_NOT_MEMBER.getMessage()); + throw new MallinkException(ErrorCode.USER_NOT_MEMBER); } - retMap.put(WxPayConstant.MEM_DISCOUNT, discount.toString()); + // 5. 会员level及折扣 + Integer discount = 100; + if (config.getDiscount().equals(EnumEnableType.Enable.getCode())) { + discount = getMemLevelDiscount(retMap, tenantId, user, merchantId); + } else { + retMap.put(WxPayConstant.MEM_DISCOUNT_RATE, discount.toString()); + } Double remainAmountD = posAmount * 1.0D * discount / 100; - long remainAmount = Math.round(remainAmountD); + Long remainAmount = Math.round(remainAmountD); + Long discountAmount = posAmount - remainAmount; + + retMap.put(WxPayConstant.MEM_ID, user.getId().toString()); + retMap.put(WxPayConstant.MEM_PHONE, user.getPhone()); + retMap.put(WxPayConstant.ORG_AMOUNT, posAmountStr); + retMap.put(WxPayConstant.DISCOUNT_AMOUNT, String.valueOf(discountAmount)); + retMap.put(WxPayConstant.REMAIN_AMOUNT, String.valueOf(remainAmount)); - // 优惠券列表 + // 6. 优惠券列表 if (config.getCoupon().equals(EnumEnableType.Enable.getCode())) { Map coQ = new HashMap<>(); coQ.put("tenantId", tenantId); @@ -300,27 +310,255 @@ public class PosServiceImpl implements PosService { } else { retMap.put(WxPayConstant.AVAIL_CO_LIST, "[]"); } + return retMap; + } + + + + @Override + @Transactional(rollbackFor = Exception.class) + public Map calcMem(Map params) throws MallinkException { + Map retMap = new HashMap<>(); + + String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID + String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID + String buUserIdStr = params.get(WxPayConstant.BUSER_ID); // POS操作员ID + String memIdStr = params.get(WxPayConstant.MEM_ID); // 会员ID + String memPhoneStr = params.get(WxPayConstant.MEM_PHONE); // 会员手机 + String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单金额(单位:分) + String selCoListStr = params.get(WxPayConstant.SELECTED_COUPON_ORDER_LIST); // 选中的优惠券列表 + + if (StringUtils.isBlank(tenantId)) { + errParam(WxPayConstant.TENANT_ID); + } + + PosMallConfig config = posMallConfigService.getByTenantId(tenantId); + if (config == null) { + logger.error(ErrorCode.POS_CONFIG_NOT_FOUND.getMessage()); + throw new MallinkException(ErrorCode.POS_CONFIG_NOT_FOUND); + } + + if (StringUtils.isBlank(merchantIdStr)) { + errParam(WxPayConstant.MERCHANT_ID); + } + if (StringUtils.isBlank(posAmountStr)) { + errParam(WxPayConstant.POS_AMOUNT); + } + if (StringUtils.isBlank(selCoListStr)) { + errParam(WxPayConstant.SELECTED_COUPON_ORDER_LIST); + } + if (StringUtils.isBlank(memIdStr) && StringUtils.isBlank(memPhoneStr)) { + errParam2(WxPayConstant.MEM_ID, WxPayConstant.MEM_PHONE); + } + // 1. 商户ID, B端用户ID + Long merchantId, buUserId, posOrderId; + Long posAmount = 0L; + try { + merchantId = Long.valueOf(merchantIdStr); + buUserId = Long.valueOf(buUserIdStr); + posAmount = Long.valueOf(posAmountStr); + } catch (NumberFormatException e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR); + } + + // 2. check merchant + WxMerchant merchant = checkAndGetMerchant(merchantId); + // 3. check buUser + WxMerchantBUser buUser = checkAndGetMerchantUser(buUserId, merchantId); + + // 4. 获取会员信息 + WxCUser user = getMemUser(tenantId, memIdStr, memPhoneStr); + if (user == null) { + logger.error(ErrorCode.USER_NOT_MEMBER.getMessage()); + throw new MallinkException(ErrorCode.USER_NOT_MEMBER); + } + + // 5. 获取折扣率 + Integer discount = 100; + if (config.getDiscount().equals(EnumEnableType.Enable.getCode())) { + discount = getMemLevelDiscount(retMap, tenantId, user, merchantId); + } else { + retMap.put(WxPayConstant.MEM_DISCOUNT_RATE, discount.toString()); + } + // 6. 计算折扣及剩余支付金额(四舍五入) + Double remainAmountD = posAmount * 1.0D * discount / 100; + Long remainAmount = Math.round(remainAmountD); + Long discountAmount = posAmount - remainAmount; retMap.put(WxPayConstant.MEM_ID, user.getId().toString()); retMap.put(WxPayConstant.MEM_PHONE, user.getPhone()); retMap.put(WxPayConstant.ORG_AMOUNT, posAmountStr); + retMap.put(WxPayConstant.DISCOUNT_AMOUNT, String.valueOf(discountAmount)); + + // 7. 计算券抵扣及剩余支付金额(四舍五入) + JSONArray selCoArr = JSONObject.parseArray(selCoListStr); + if (selCoArr.size() <= 0) { + errParam(WxPayConstant.SELECTED_COUPON_ORDER_LIST); + } + JSONArray coRetArr = new JSONArray(); + for(int i=0;i oneRetMap = calcOneCouponVerify(merchantId, posAmount, couponOrderIdStr); + coRetArr.add(oneRetMap); + posAmount = Long.valueOf(oneRetMap.get(WxPayConstant.REMAIN_AMOUNT)); + if (posAmount.equals(0L)) { + break; + } + } catch (MallinkException e) { + throw new MallinkException(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + throw new MallinkException(500, e.getMessage()); + } + } + } + retMap.put(WxPayConstant.MEM_COUPONS, coRetArr.toJSONString()); + retMap.put(WxPayConstant.REMAIN_AMOUNT, String.valueOf(posAmount)); + return retMap; + } + + private Map calcOneCouponVerify(Long merchantId, Long posAmount, String couponOrderIdStr) { + Map retMap = new HashMap<>(); + // 1. 获取券包信息 + WxCouponOrderCVo couponOrderCVo = couponOrderService.detailCUserVo(couponOrderIdStr); + if (couponOrderCVo == null) { + logger.error(ErrorCode.COUPON_ORDER_IS_NULL.getMessage() + ": " + couponOrderIdStr); + throw new MallinkException(ErrorCode.COUPON_ORDER_IS_NULL); + } + // 2. 检查券类型 + if (!(couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_MULTIMCH.getCode()) || + couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_MANJIAN.getCode()) || + couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_DAIJIN.getCode()) + )) { + logger.error(ErrorCode.VERIFY_COUPON_TYPE_NOT_SUPPORT.getMessage()); + throw new MallinkException(ErrorCode.VERIFY_COUPON_TYPE_NOT_SUPPORT); + } + + // 3. 券包状态检查 + if (couponOrderCVo.getCouponOrderStatus() == EnumCouponOrderStatus.COUPON_ORDER_OVER_TIME.getCode()) { + logger.error("已过期: couponOrder-" + couponOrderIdStr); + throw new MallinkException(ErrorCode.COUPON_ORDER_IS_OVER_TIME); + } + if (couponOrderCVo.getCouponOrderStatus() == EnumCouponOrderStatus.COUPON_ORDER_INVALID.getCode()) { + logger.error("已作废: couponOrder-" + couponOrderIdStr); + throw new MallinkException(ErrorCode.COUPON_ORDER_IS_INVALID); + } + if (couponOrderCVo.getCouponOrderStatus() == EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()) { + logger.error("已经核销过的券: couponOrder-" + couponOrderIdStr); + throw new MallinkException(ErrorCode.COUPON_ORDER_IS_USED); + } + + Date now = new Date(); + // 4. 检查有效期 + if (couponOrderCVo.getValidStartDate() != null && couponOrderCVo.getValidEndDate() != null) { + if (couponOrderCVo.getValidStartDate().getTime() > now.getTime()) { + logger.error("此券有效期未开始:" + couponOrderIdStr); + throw new MallinkException(ErrorCode.COUPON_ORDER_IS_EARLIER_THAN_VALIDDATE); + } + if (couponOrderCVo.getValidEndDate().getTime() < now.getTime()) { + logger.error("此券有效期已结束:" + couponOrderIdStr); + throw new MallinkException(ErrorCode.COUPON_ORDER_IS_EARLIER_THAN_VALIDDATE); + } + } + // 5 券已过期 + if (couponOrderCVo.getExpiredTime().before(now)) { + logger.error("此券已过期:" + couponOrderIdStr); + throw new MallinkException(ErrorCode.COUPON_ORDER_IS_EARLIER_THAN_VALIDDATE); + } + + Long couponOrderId = couponOrderCVo.getId(); + + // 6. 检查适用门店 + WxCouponMerchant wxCouponMerchant = new WxCouponMerchant(); + wxCouponMerchant.setProductId(couponOrderCVo.getCouponId()); + wxCouponMerchant.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode()); + List couponMerchantList = couponMerchantMapper.findList(wxCouponMerchant); + if (!couponMerchantList.stream().anyMatch(cm->cm.getMerchantId().equals(merchantId))){ + logger.error("券: coupon-" + couponOrderCVo.getCouponId() + "核销: couponMerchantId-" + merchantId + " 门店不适用"); + throw new MallinkException(ErrorCode.VERIFY_COUPON_ORDER_MERCHANT_IS_NULL); + } + + Long remainAmount = posAmount - couponOrderCVo.getPrice(); + if (remainAmount < 0L) { + remainAmount = 0L; + } + Long discountAmount = posAmount - remainAmount; + retMap.put(WxPayConstant.ID, couponOrderIdStr); + retMap.put(WxPayConstant.PRICE, String.valueOf(couponOrderCVo.getPrice())); + retMap.put(WxPayConstant.DEDUCT_AMOUNT, String.valueOf(discountAmount)); retMap.put(WxPayConstant.REMAIN_AMOUNT, String.valueOf(remainAmount)); return retMap; } + private WxCUser getMemUser(String tenantId, String memIdStr, String memPhoneStr) { + WxCUser user = null; + if (StringUtils.isNotBlank(memIdStr)) { + Long memId; + try { + memId = Long.valueOf(memIdStr); + } catch (NumberFormatException e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); + } + + user = cUserService.getById(memId); + } + if (StringUtils.isNotBlank(memPhoneStr)) { + WxCUser q = new WxCUser(); + q.setTenantId(tenantId); + q.setPhone(memPhoneStr); + user = cUserService.getByObject(q); + } + return user; + } + + private Integer getMemLevelDiscount(Map retMap, String tenantId, WxCUser user, Long merchantId) { + Integer discount = 100; + String level = WxLevelConfigService.DEFAULT_LEVEL; + // Level, 折扣 + List levelList = levelConfigService.getByTenantId(tenantId); + Long levelId = 0L; + for (WxLevelConfig levelConfig : levelList) { + if (user.getScore() >= levelConfig.getPoints()) { + if (levelConfig.getDiscountEnable().equals(EnumLevelConfigDiscountStatus.ENABLE.getCode())) + levelId = levelConfig.getId(); + level = levelConfig.getLevel(); + } + } + + WxLevelMerchant levelMerchant = new WxLevelMerchant(); + levelMerchant.setTenantId(tenantId); + levelMerchant.setLevelId(levelId); + levelMerchant.setMerchantId(merchantId); + List levelMerchantList = levelConfigService.findListCVo(levelMerchant); + if (levelMerchantList.size() >= 1) { + WxLevelMerchantCVo levelMerchantCVo = levelMerchantList.get(0); + if (levelMerchantCVo != null) { + discount = levelMerchantCVo.getDiscount(); + } + } + + retMap.put(WxPayConstant.MEM_LEVEL, level); + retMap.put(WxPayConstant.MEM_DISCOUNT_RATE, discount.toString()); + return discount; + } + @Override @Transactional(rollbackFor = Exception.class) - public Map couponOrderVerifyDo(@RequestBody Map params, EnumVerifyActionType actionType) throws MallinkException { + public Map couponOrderVerifyDo(@RequestBody Map params, EnumPosActionType actionType) throws MallinkException { Map retMap = new HashMap<>(); String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID String buUserIdStr = params.get(WxPayConstant.BUSER_ID); // POS操作员ID - String verifyType = params.get(WxPayConstant.VERIFY_TYPE); // 核销类型 + String sceneTypeStr = params.get(WxPayConstant.SCENE_TYPE); // 场景类型 String couponOrderIdStr = params.get(WxPayConstant.COUPON_ORDER_ID); // 券ID String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单总额(单位:分) + Integer sceneType = null; if (StringUtils.isBlank(tenantId)) { errParam(WxPayConstant.TENANT_ID); } @@ -329,7 +567,7 @@ public class PosServiceImpl implements PosService { logger.error(ErrorCode.POS_CONFIG_NOT_FOUND.getMessage()); throw new MallinkException(ErrorCode.POS_CONFIG_NOT_FOUND); } - if (!config.getCoupon().equals(EnumEnableType.Enable.getCode())) { + if (!config.getCoupon().equals(EnumPosEnableType.Disable.getCode())) { logger.error(ErrorCode.POS_CONFIG_MEM_COUPON_DISABLE.getMessage()); throw new MallinkException(ErrorCode.POS_CONFIG_MEM_COUPON_DISABLE); } @@ -342,28 +580,30 @@ public class PosServiceImpl implements PosService { if (StringUtils.isBlank(couponOrderIdStr)) { errParam(WxPayConstant.COUPON_ORDER_ID); } - if (actionType.equals(EnumVerifyActionType.CHECK)) { - if (StringUtils.isBlank(verifyType)) { - errParam(WxPayConstant.VERIFY_TYPE); + if (actionType.equals(EnumPosActionType.CHECK)) { + if (StringUtils.isBlank(sceneTypeStr)) { + errParam(WxPayConstant.SCENE_TYPE); } - if (!(verifyType.equalsIgnoreCase(WxPayConstant.VERIFY_TYPE_INDEPENT) || verifyType.equalsIgnoreCase(WxPayConstant.VERIFY_TYPE_PAY))) { - String errMessage = "request params[verify_type] only support independent or pay."; - throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), errMessage); + try { + sceneType = Integer.valueOf(sceneTypeStr); + } catch (NumberFormatException e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); } - } else if (actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT)) { - verifyType = WxPayConstant.VERIFY_TYPE_INDEPENT; - } else if (actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { - verifyType = WxPayConstant.VERIFY_TYPE_PAY; - } - if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || - actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT) || - actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { + } else if (actionType.equals(EnumPosActionType.VERIFY_INDEPENT)) { + sceneType = EnumPosSceneType.VERIFY.getCode(); + } else if (actionType.equals(EnumPosActionType.VERIFY_PAY)) { + sceneType = EnumPosSceneType.PAY.getCode(); + } + if (actionType.equals(EnumPosActionType.PRE_VERIFY) || + actionType.equals(EnumPosActionType.VERIFY_INDEPENT) || + actionType.equals(EnumPosActionType.VERIFY_PAY)) { if (StringUtils.isBlank(posOrderIdStr)) { errParam(WxPayConstant.POS_ORDER_ID); } } - if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || - actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { + if (actionType.equals(EnumPosActionType.PRE_VERIFY) || + actionType.equals(EnumPosActionType.VERIFY_PAY)) { if (StringUtils.isBlank(posAmountStr)) { errParam(WxPayConstant.POS_AMOUNT); } @@ -374,13 +614,13 @@ public class PosServiceImpl implements PosService { try { merchantId = Long.valueOf(merchantIdStr); buUserId = Long.valueOf(buUserIdStr); - if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || - actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT) || - actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { + if (actionType.equals(EnumPosActionType.PRE_VERIFY) || + actionType.equals(EnumPosActionType.VERIFY_INDEPENT) || + actionType.equals(EnumPosActionType.VERIFY_PAY)) { posOrderId = Long.valueOf(posOrderIdStr); } - if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || - actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { + if (actionType.equals(EnumPosActionType.PRE_VERIFY) || + actionType.equals(EnumPosActionType.VERIFY_PAY)) { posAmount = Integer.valueOf(posAmountStr); } } catch (NumberFormatException e) { @@ -396,7 +636,7 @@ public class PosServiceImpl implements PosService { if (couponOrderIdStr != null) { try { Map oneRetMap = doVerifyActionForOneCouponOrder( - actionType, verifyType, + actionType, sceneType, tenantId, merchantIdStr, merchantId, buUserIdStr, buUserId, posOrderIdStr, posOrderId, posAmount, @@ -412,7 +652,7 @@ public class PosServiceImpl implements PosService { @Override @Transactional(rollbackFor = Exception.class) - public Map couponOrderVerifyListDo(@RequestBody Map params, EnumVerifyActionType actionType) throws MallinkException { + public Map couponOrderVerifyListDo(@RequestBody Map params, EnumPosActionType actionType) throws MallinkException { Map retMap = new HashMap<>(); String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID @@ -421,7 +661,7 @@ public class PosServiceImpl implements PosService { String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID String posAmountStr = params.get(WxPayConstant.POS_AMOUNT); // POS订单总额(单位:分) String selCoListStr = params.get(WxPayConstant.SELECTED_COUPON_ORDER_LIST); // 选中的优惠券列表 - String verifyType = WxPayConstant.VERIFY_TYPE_PAY; // 此接口只有支付使用 + Integer sceneType = EnumPosSceneType.PAY.getCode(); // 此接口只有支付使用 if (StringUtils.isBlank(tenantId)) { errParam(WxPayConstant.TENANT_ID); @@ -444,7 +684,7 @@ public class PosServiceImpl implements PosService { if (StringUtils.isBlank(selCoListStr)) { errParam(WxPayConstant.SELECTED_COUPON_ORDER_LIST); } - if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT)) { + if (actionType.equals(EnumPosActionType.PRE_VERIFY) || actionType.equals(EnumPosActionType.VERIFY_INDEPENT)) { if (StringUtils.isBlank(posOrderIdStr)) { errParam(WxPayConstant.POS_ORDER_ID); } @@ -458,9 +698,9 @@ public class PosServiceImpl implements PosService { try { merchantId = Long.valueOf(merchantIdStr); buUserId = Long.valueOf(buUserIdStr); - if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || - actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT) || - actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { + if (actionType.equals(EnumPosActionType.PRE_VERIFY) || + actionType.equals(EnumPosActionType.VERIFY_INDEPENT) || + actionType.equals(EnumPosActionType.VERIFY_PAY)) { posOrderId = Long.valueOf(posOrderIdStr); posAmount = Integer.valueOf(posAmountStr); } @@ -485,7 +725,7 @@ public class PosServiceImpl implements PosService { if (couponOrderIdStr != null) { try { Map oneRetMap = doVerifyActionForOneCouponOrder( - actionType, verifyType, + actionType, sceneType, tenantId, merchantIdStr, merchantId, buUserIdStr, buUserId, posOrderIdStr, posOrderId, posAmount, @@ -504,7 +744,7 @@ public class PosServiceImpl implements PosService { } private Map doVerifyActionForOneCouponOrder( - EnumVerifyActionType actionType, String verifyType, + EnumPosActionType actionType, Integer sceneType, String tenantId, String merchantIdStr, Long merchantId, String buUserIdStr, Long buUserId, String posOrderIdStr, Long posOrderId, Integer posAmount, @@ -517,8 +757,8 @@ public class PosServiceImpl implements PosService { throw new MallinkException(ErrorCode.COUPON_ORDER_IS_NULL); } // 4.1 检查券类型 - if (actionType.equals(EnumVerifyActionType.CHECK)) { - if (verifyType.equalsIgnoreCase(WxPayConstant.VERIFY_TYPE_INDEPENT)) { + if (actionType.equals(EnumPosActionType.CHECK)) { + if (sceneType.equals(EnumPosSceneType.VERIFY.getCode())) { if (!(couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_MULTIMCH.getCode()) || couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_LIPIN.getCode()) || couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_PRESS.getCode()) || @@ -528,7 +768,7 @@ public class PosServiceImpl implements PosService { throw new MallinkException(ErrorCode.VERIFY_COUPON_TYPE_NOT_SUPPORT); } } - if (verifyType.equalsIgnoreCase(WxPayConstant.VERIFY_TYPE_PAY)) { + if (sceneType.equals(EnumPosSceneType.PAY.getCode())) { if (!(couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_MULTIMCH.getCode()) || couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_MANJIAN.getCode()) || couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_DAIJIN.getCode()) @@ -537,7 +777,7 @@ public class PosServiceImpl implements PosService { throw new MallinkException(ErrorCode.VERIFY_COUPON_TYPE_NOT_SUPPORT); } } - } else if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { + } else if (actionType.equals(EnumPosActionType.PRE_VERIFY) || actionType.equals(EnumPosActionType.VERIFY_PAY)) { if (!(couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_MULTIMCH.getCode()) || couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_MANJIAN.getCode()) || couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_DAIJIN.getCode()) @@ -551,7 +791,7 @@ public class PosServiceImpl implements PosService { throw new MallinkException(ErrorCode.VERIFY_MANJIAN_USER_PRICE_NOT_TOUCH); } } - } else if (actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT)) { + } else if (actionType.equals(EnumPosActionType.VERIFY_INDEPENT)) { if (!(couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_MULTIMCH.getCode()) || couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_LIPIN.getCode()) || couponOrderCVo.getCouponType().equals(EnumCouponType.COUPON_PRESS.getCode()) || @@ -607,7 +847,7 @@ public class PosServiceImpl implements PosService { throw new MallinkException(ErrorCode.VERIFY_COUPON_ORDER_MERCHANT_IS_NULL); } - if (actionType.equals(EnumVerifyActionType.CHECK)) { + if (actionType.equals(EnumPosActionType.CHECK)) { if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode())) { logger.info("券已被预核销: " + couponOrderIdStr); if (!couponOrderCVo.getBUserId().equals(buUserId)) { @@ -658,7 +898,7 @@ public class PosServiceImpl implements PosService { retMap.put(WxPayConstant.STATUS, EnumCouponOrderStatus.getEnum(couponOrderCVo.getCouponOrderStatus()).getMessage()); return retMap; } - } else if (actionType.equals(EnumVerifyActionType.PRE_VERIFY)) { + } else if (actionType.equals(EnumPosActionType.PRE_VERIFY)) { if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode())) { logger.info("券已被预核销: " + couponOrderIdStr); if (!couponOrderCVo.getBUserId().equals(buUserId)) { @@ -768,7 +1008,7 @@ public class PosServiceImpl implements PosService { @Override @Transactional(rollbackFor = Exception.class) - public Map couponOrderVerifyCancel(Map params, EnumVerifyActionType actionType) { + public Map couponOrderVerifyCancel(Map params, EnumPosActionType actionType) { Map retMap = new HashMap<>(); String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID @@ -790,7 +1030,7 @@ public class PosServiceImpl implements PosService { if (StringUtils.isBlank(couponOrderIdStr)) { errParam(WxPayConstant.COUPON_ORDER_ID); } - if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT)) { + if (actionType.equals(EnumPosActionType.PRE_VERIFY) || actionType.equals(EnumPosActionType.VERIFY_INDEPENT)) { if (StringUtils.isBlank(posOrderIdStr)) { errParam(WxPayConstant.POS_ORDER_ID); } @@ -853,7 +1093,7 @@ public class PosServiceImpl implements PosService { // 预核销取消 if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode()) && - actionType.equals(EnumVerifyActionType.PRE_VERIFY_CANCEL)) { + actionType.equals(EnumPosActionType.PRE_VERIFY_CANCEL)) { logger.info("券已被预核销: " + couponOrderIdStr); if (!couponOrderCVo.getBUserId().equals(buUserId)) { logger.error(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL.getMessage() + ": " + buUserIdStr); @@ -870,7 +1110,7 @@ public class PosServiceImpl implements PosService { } // 核销取消 if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()) && - actionType.equals(EnumVerifyActionType.VERIFY_CANCEL)) { + actionType.equals(EnumPosActionType.VERIFY_CANCEL)) { logger.info("券已被核销: " + couponOrderIdStr); boolean force = false; if (StringUtils.isNotBlank(forceStr)) { @@ -997,7 +1237,7 @@ public class PosServiceImpl implements PosService { * @param buUserId * @param posOrderId */ - private void doVerify(EnumVerifyActionType actionType, WxCouponOrderCVo couponOrderCVo, WxCoupon coupon, + private void doVerify(EnumPosActionType actionType, WxCouponOrderCVo couponOrderCVo, WxCoupon coupon, Long merchantId, Long buUserId, Long posOrderId, Map retMap) { int num = 0; // 1. insert posOrderId @@ -1025,13 +1265,13 @@ public class PosServiceImpl implements PosService { couponOrder.setId(couponOrderCVo.getId()); couponOrder.setTenantId(couponOrderCVo.getTenantId()); couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()); //1核销 - if (actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT)) { + if (actionType.equals(EnumPosActionType.VERIFY_INDEPENT)) { couponOrder.setVerifyType(EnumCouponVerifyType.VERIFY_POS_INDEPENDENT.getCode()); } else { couponOrder.setVerifyType(EnumCouponVerifyType.VERIFY_POS_PAY.getCode()); } if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode()) && - actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { + actionType.equals(EnumPosActionType.VERIFY_PAY)) { couponOrder.setBUserId(buUserId); } couponOrder.setUpdateDate(new Date()); @@ -1181,9 +1421,7 @@ public class PosServiceImpl implements PosService { String cardIdStr = params.get(WxPayConstant.CARD_ID); // 消费卡ID if (StringUtils.isBlank(tenantId)) { - String errMessage = "request params[tenant_id] error."; - logger.error(errMessage); - throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + errParam(WxPayConstant.TENANT_ID); } PosMallConfig config = posMallConfigService.getByTenantId(tenantId); if (config == null) { @@ -1569,24 +1807,32 @@ public class PosServiceImpl implements PosService { if (StringUtils.isBlank(posStatusStr)) { errParam(WxPayConstant.NEU_ORDER_STATUS); } - Long merchantId, buUserId, posOrderId, cardId; + + Long merchantId, buUserId, posOrderId, memId; Integer posAmount = 0; + Date orderTime = null; try { merchantId = Long.valueOf(merchantIdStr); buUserId = Long.valueOf(buUserIdStr); + memId = Long.valueOf(cuUserIdStr); posOrderId = Long.valueOf(posOrderIdStr); posAmount = Integer.valueOf(posAmountStr); } catch (NumberFormatException e) { logger.error(e.getMessage()); throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); } + try { + orderTime = neuDateFormat.parse(posOrderTimeStr); + } catch (ParseException e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); + } // 2. check merchant WxMerchant merchant = checkAndGetMerchant(merchantId); // 3. check buUser - WxMerchantBUser merchantBUser = checkAndGetMerchantUser(merchantId, buUserId); - if (posStatusStr.equalsIgnoreCase("0")) { - // TODO - // add to wx_order + final WxMerchantBUser merchantBUser = checkAndGetMerchantUser(merchantId, buUserId); + if (posStatusStr.equalsIgnoreCase(WxPayConstant.NEU_ORDER_PAY)) { + WxOrder order = createOrderByPos(merchantBUser, memId, posOrderId, posAmount, orderTime); String payDetail = params.get(WxPayConstant.NEU_PAY_DETAIL); JSONObject payDetailObj = JSON.parseObject(payDetail); JSONArray payDetailList = payDetailObj.getJSONArray(WxPayConstant.NEU_PAY_DETAIL_LIST); @@ -1594,17 +1840,38 @@ public class PosServiceImpl implements PosService { JSONObject payOrderObj = payDetailList.getJSONObject(i); // ADD to wx_pay_order String neuPayOrderType = payOrderObj.getString(WxPayConstant.NEU_PAY_ORDER_TYPE); - if (neuPayOrderType.equalsIgnoreCase(String.valueOf(EnumPosPamentType.MEM_DISCOUNT.getCode()))) { + String neuPayOrderIdStr = payOrderObj.getString(WxPayConstant.NEU_PAY_ORDER_ID); + String neuPaymentAmount = payOrderObj.getString(WxPayConstant.NEU_PAY_ORDER_AMOUNT); + String neuPayOrderTimeStr = payOrderObj.getString(WxPayConstant.NEU_PAY_ORDER_TIME); + String neuPayThirdNo = payOrderObj.getString(WxPayConstant.NEU_PAY_ORDER_OUT_NO); + Date neuPosPayOrderTime = null; + try { + neuPosPayOrderTime = neuDateFormat.parse(neuPayOrderTimeStr); + } catch (ParseException e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); + } + Long neuPayOrderId; + try { + neuPayOrderId = Long.valueOf(neuPayOrderIdStr); + } catch (NumberFormatException e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); + } + if (neuPayOrderType.equalsIgnoreCase(String.valueOf(EnumNeuPosPamentType.MEM_DISCOUNT.getCode()))) { // 会员折扣 - } else if (neuPayOrderType.equalsIgnoreCase(String.valueOf(EnumPosPamentType.MEM_COUPON.getCode()))) { + WxPayOrder payOrder = payOrderFromMemDiscount(merchantBUser, order, memId, neuPayOrderId, neuPaymentAmount, neuPosPayOrderTime); + } else if (neuPayOrderType.equalsIgnoreCase(String.valueOf(EnumNeuPosPamentType.MEM_COUPON.getCode()))) { // 优惠券, 交易核销 - String couponOrderIdStr = payOrderObj.getString(WxPayConstant.NEU_PAY_ORDER_OUT_NO); - } else if (neuPayOrderType.equalsIgnoreCase(String.valueOf(EnumPosPamentType.MEM_CARD.getCode()))) { + WxPayOrder payOrder = payOrderFromCouponVerify(merchantBUser, order, memId, neuPayOrderId, neuPaymentAmount, neuPosPayOrderTime, neuPayThirdNo); + } else if (neuPayOrderType.equalsIgnoreCase(String.valueOf(EnumNeuPosPamentType.MEM_CARD.getCode()))) { // 预付卡, 不能退 - } + WxPayOrder payOrder = payOrderFromCard(merchantBUser, order, memId, neuPayOrderId, neuPaymentAmount, neuPosPayOrderTime, neuPayThirdNo); + } else { + } } - } else if (posStatusStr.equalsIgnoreCase("1")) { + } else if (posStatusStr.equalsIgnoreCase(WxPayConstant.NEU_ORDER_REFUND)) { // TODO // add to wx_order String refundDetail = params.get(WxPayConstant.NEU_REFUND_DETAIL); @@ -1615,14 +1882,16 @@ public class PosServiceImpl implements PosService { // TODO // ADD to wx_pay_order String neuRefundOrderType = refundOrderObj.getString(WxPayConstant.NEU_REFUND_ORDER_TYPE); - if (neuRefundOrderType.equalsIgnoreCase(String.valueOf(EnumPosRefundType.MEM_DISCOUNT.getCode()))) { + if (neuRefundOrderType.equalsIgnoreCase(String.valueOf(EnumNeuPosRefundType.MEM_DISCOUNT.getCode()))) { // 会员折扣, - } else if (neuRefundOrderType.equalsIgnoreCase(String.valueOf(EnumPosRefundType.MEM_COUPON.getCode()))) { + } else if (neuRefundOrderType.equalsIgnoreCase(String.valueOf(EnumNeuPosRefundType.MEM_COUPON.getCode()))) { // 优惠券, 退优惠券 - } else if (neuRefundOrderType.equalsIgnoreCase(String.valueOf(EnumPosRefundType.MEM_CARD.getCode()))) { + } else if (neuRefundOrderType.equalsIgnoreCase(String.valueOf(EnumNeuPosRefundType.MEM_CARD.getCode()))) { // 预付卡, 不能退 - } else if (neuRefundOrderType.equalsIgnoreCase(String.valueOf(EnumPosRefundType.BOOK.getCode()))) { + } else if (neuRefundOrderType.equalsIgnoreCase(String.valueOf(EnumNeuPosRefundType.BOOK.getCode()))) { // 记账 + } else { + } } } @@ -1630,6 +1899,191 @@ public class PosServiceImpl implements PosService { return retMap; } + /** + * 支付订单-会员折扣 + * @param merchantBUser + * @param order + * @param memId + * @param posPayOrderId + * @param neuPaymentAmount + * @param neuPosPayOrderTime + */ + public WxPayOrder payOrderFromMemDiscount( + WxMerchantBUser merchantBUser, + WxOrder order, + Long memId, + Long posPayOrderId, String neuPaymentAmount, Date neuPosPayOrderTime) { + WxPayOrder payOrder = new WxPayOrder() {{ + Date curDate = new Date(); + final IdWorker idWorker = IdWorker.get(); + Long id = idWorker.nextId(); + setId(id); + setTenantId(merchantBUser.getTenantId()); + setCUserId(memId); + setOrderId(order.getId()); + setCreateTime(curDate); + setUpdateTime(curDate); + setPayTimeStart(curDate); + setPayTimeEnd(curDate); + setPayOrderNo(String.valueOf(id)); + setPayAmount(Integer.valueOf(neuPaymentAmount)); + setPayVendor(EnumPayWay.PAY_WAY_POS_NEU.getCode()); + setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); + setShare(EnumPayShare.NO.getCode()); + setPosPayOrderId(posPayOrderId); + setPosPayOrderTime(neuPosPayOrderTime.getTime()); + setPosPaymentType(EnumNeuPosPamentType.MEM_DISCOUNT.getCode()); + setPosPayDesc("POS会员折扣支付"); + }}; + int sqlRow = payOrderMapper.insertSelective(payOrder); + if (sqlRow != 1) { + logger.error("pay order insert error: " + payOrder.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return payOrder; + } + + /** + * 支付订单-优惠券 + * @param merchantBUser + * @param order + * @param memId + * @param posPayOrderId + * @param neuPaymentAmount + * @param neuPosPayOrderTime + */ + public WxPayOrder payOrderFromCouponVerify( + WxMerchantBUser merchantBUser, + WxOrder order, + Long memId, + Long posPayOrderId, String neuPaymentAmount, Date neuPosPayOrderTime, String posPayOrderNo) { + // 1. insert into PayOrder + WxPayOrder payOrder = new WxPayOrder() {{ + Date curDate = new Date(); + final IdWorker idWorker = IdWorker.get(); + Long id = idWorker.nextId(); + setId(id); + setTenantId(merchantBUser.getTenantId()); + setCUserId(memId); + setOrderId(order.getId()); + setCreateTime(curDate); + setUpdateTime(curDate); + setPayTimeStart(curDate); + setPayTimeEnd(curDate); + setPayOrderNo(String.valueOf(id)); + setPayAmount(Integer.valueOf(neuPaymentAmount)); + setPayVendor(EnumPayWay.PAY_WAY_POS_NEU.getCode()); + setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); + setShare(EnumPayShare.NO.getCode()); + setPosPayOrderId(posPayOrderId); + setPosPayOrderTime(neuPosPayOrderTime.getTime()); + setPosPaymentType(EnumNeuPosPamentType.MEM_DISCOUNT.getCode()); + setPosPayDesc("POS优惠券支付"); + setPosPayOrderNo(posPayOrderNo); + }}; + int sqlRow = payOrderMapper.insertSelective(payOrder); + if (sqlRow != 1) { + logger.error("pay order insert error: " + payOrder.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + // 2. 核销 + return payOrder; + } + + /** + * 支付订单-预付卡 + * @param merchantBUser + * @param order + * @param memId + * @param posPayOrderId + * @param neuPaymentAmount + * @param neuPosPayOrderTime + * @param posPayOrderNo + */ + public WxPayOrder payOrderFromCard( + WxMerchantBUser merchantBUser, + WxOrder order, + Long memId, + Long posPayOrderId, String neuPaymentAmount, Date neuPosPayOrderTime, String posPayOrderNo) { + // 1. insert into PayOrder + WxPayOrder payOrder = new WxPayOrder() {{ + Date curDate = new Date(); + final IdWorker idWorker = IdWorker.get(); + Long id = idWorker.nextId(); + setId(id); + setTenantId(merchantBUser.getTenantId()); + setCUserId(memId); + setOrderId(order.getId()); + setCreateTime(curDate); + setUpdateTime(curDate); + setPayTimeStart(curDate); + setPayTimeEnd(curDate); + setPayOrderNo(String.valueOf(id)); + setPayAmount(Integer.valueOf(neuPaymentAmount)); + setPayVendor(EnumPayWay.PAY_WAY_POS_NEU.getCode()); + setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); + setShare(EnumPayShare.NO.getCode()); + setPosPayOrderId(posPayOrderId); + setPosPayOrderTime(neuPosPayOrderTime.getTime()); + setPosPaymentType(EnumNeuPosPamentType.MEM_DISCOUNT.getCode()); + setPosPayDesc("POS富茂卡支付"); + setPosPayOrderNo(posPayOrderNo); + + }}; + int sqlRow = payOrderMapper.insertSelective(payOrder); + if (sqlRow != 1) { + logger.error("pay order insert error: " + payOrder.toString()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + // 2. 卡支付 card spend + // 3。卡支付 后续 + return payOrder; + } + + /** + * 基于NEUPOS订单信息创建订单 + * @param merchantBUser + * @param memId + * @param posOrderId + * @param posAmount + * @param posOrderTime + * @return + */ + public WxOrder createOrderByPos( + final WxMerchantBUser merchantBUser, + final Long memId, + final Long posOrderId, final Integer posAmount, final Date posOrderTime + ) { + WxOrder order = new WxOrder() {{ + Date curr = new Date(); + String bodyStr = "POS支付, 金额: " + posAmount; + final IdWorker idWorker = IdWorker.get(); + Long orderId = idWorker.nextId(); + + setId(orderId); + setTenantId(merchantBUser.getTenantId()); + setOrderNumber(orderId); + setType(EnumOrderType.POSPAY.getCode()); + setProductId(merchantBUser.getId()); + setCUserId(memId); + setPaymentType(EnumPayType.PAY_PAYMENT.getCode()); + setPayment(posAmount); + setOrderStatus(EnumOrderStatus.ORDER_STATUS_PAYMENT_SUCCESS.getCode()); + setDetail(bodyStr); + setCreateDate(curr); + setUpdateDate(curr); + setPosOrderId(posOrderId); + setPosOrderCreateTime(posOrderTime.getTime()); + }}; + try { + orderMapper.insertSelective(order); + } catch (Exception e) { + logger.error(e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL); + } + return order; + } + /** * 检查及获取商户信息 @@ -1665,10 +2119,6 @@ public class PosServiceImpl implements PosService { logger.error(ErrorCode.VERIFY_BUSER_MERCHANT_NOT_BELONG.getMessage() + ": " + buUserId); throw new MallinkException(ErrorCode.VERIFY_BUSER_MERCHANT_NOT_BELONG); } - if (buUser.getStatus().equals(EnumMerchantStatus.NOT_VALID.getCode())) { - logger.error(ErrorCode.MERCHANT_BUSER_NOT_VALID.getMessage() + ": " + buUserId); - throw new MallinkException(ErrorCode.MERCHANT_BUSER_NOT_VALID); - } return buUser; } @@ -1683,6 +2133,18 @@ public class PosServiceImpl implements PosService { throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); } + /** + * 输入参数错误 + * @param param1Str + * @param param2Str + * @throws MallinkException + */ + private void errParam2(String param1Str, String param2Str) throws MallinkException { + String errMessage = String.format("please give one value for %s or %s", param1Str, param2Str); + logger.error(errMessage); + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); + } + /** * POS订单添加 * @return diff --git a/mallinkPosApi/src/test/java/com/iformall/pos/test/PosAppTest.java b/mallinkPosApi/src/test/java/com/iformall/pos/test/PosAppTest.java index 7476c021d..57432fe04 100644 --- a/mallinkPosApi/src/test/java/com/iformall/pos/test/PosAppTest.java +++ b/mallinkPosApi/src/test/java/com/iformall/pos/test/PosAppTest.java @@ -105,10 +105,11 @@ public class PosAppTest { reqObj.put(WxPayConstant.DEV_ID, devId); reqObj.put(WxPayConstant.TENANT_ID, tenantId); reqObj.put(WxPayConstant.PHONE, phone); + reqObj.put(WxPayConstant.PASSWORD, password); reqObj.put(WxPayConstant.SIGN, WxPayment.createSignHMAC(reqObj, devReqKey)); String reqJsonStr = JSONObject.toJSONString(reqObj); MvcResult result = mockMvc.perform( - MockMvcRequestBuilders.post("/getPosMemConfig") + MockMvcRequestBuilders.post("/checkUserPassword") .contentType(MediaType.APPLICATION_JSON) .content(reqJsonStr)) .andExpect(MockMvcResultMatchers.status().isOk()) @@ -175,6 +176,15 @@ public class PosAppTest { doCheckMem(memId, phone, posOrderId, posAmount); } + @Test + public void checkCalcTest() throws Exception { + String memId = "321178010928119808"; + String phone = "13910154397"; + String posAmount = "20000"; + String selCoList = "[\"321877927162249216\"]"; + doCalcMem(memId, phone, posAmount, selCoList); + } + @Test public void checkCouponOrderForIndeepdentVerifyTest() throws Exception { String couponOrderId = "321877927162249216"; @@ -256,10 +266,11 @@ public class PosAppTest { private void doCheckMem(String memId, String phone, String posOrderId, String posAmount) throws Exception { Map reqObj = new HashMap<>(); - reqObj.put(WxPayConstant.NONCE_STR, "1"); + reqObj.put(WxPayConstant.NONCE_STR, "1"); reqObj.put(WxPayConstant.DEV_ID, devId); reqObj.put(WxPayConstant.TENANT_ID, tenantId); reqObj.put(WxPayConstant.MERCHANT_ID, merchantId); + reqObj.put(WxPayConstant.BUSER_ID, buUserId); if (StringUtils.isNotBlank(memId)) { reqObj.put(WxPayConstant.MEM_ID, memId); } @@ -284,6 +295,37 @@ public class PosAppTest { Assert.assertEquals(resSigned, true); } + private void doCalcMem(String memId, String phone, String posAmount, String selCoList) throws Exception { + Map reqObj = new HashMap<>(); + reqObj.put(WxPayConstant.NONCE_STR, "1"); + reqObj.put(WxPayConstant.DEV_ID, devId); + reqObj.put(WxPayConstant.TENANT_ID, tenantId); + reqObj.put(WxPayConstant.MERCHANT_ID, merchantId); + reqObj.put(WxPayConstant.BUSER_ID, buUserId); + if (StringUtils.isNotBlank(memId)) { + reqObj.put(WxPayConstant.MEM_ID, memId); + } + if (StringUtils.isNotBlank(phone)) { + reqObj.put(WxPayConstant.MEM_PHONE, phone); + } + reqObj.put(WxPayConstant.POS_AMOUNT, posAmount); + reqObj.put(WxPayConstant.SELECTED_COUPON_ORDER_LIST, selCoList); + reqObj.put(WxPayConstant.SIGN, WxPayment.createSignHMAC(reqObj, devReqKey)); + String reqJsonStr = JSONObject.toJSONString(reqObj); + MvcResult result = mockMvc.perform( + MockMvcRequestBuilders.post("/calcMem") + .contentType(MediaType.APPLICATION_JSON) + .content(reqJsonStr)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andReturn(); + String responseStr = result.getResponse().getContentAsString(); + ObjectMapper mapper = new ObjectMapper(); + Map respMap = mapper.readValue(responseStr, Map.class); + boolean resSigned = WxPayment.verifyNotifyHMAC(respMap, devResKey); + Assert.assertEquals(resSigned, true); + } + private void doCheckVerify(String couponOrderId, String verifyType, String posOrderId, String posAmount) throws Exception { Map reqObj = new HashMap<>(); reqObj.put(WxPayConstant.NONCE_STR, "1"); @@ -292,13 +334,13 @@ public class PosAppTest { reqObj.put(WxPayConstant.MERCHANT_ID, merchantId); reqObj.put(WxPayConstant.BUSER_ID, buUserId); reqObj.put(WxPayConstant.COUPON_ORDER_ID, couponOrderId); - reqObj.put(WxPayConstant.VERIFY_TYPE, verifyType); + reqObj.put(WxPayConstant.SCENE_TYPE, verifyType); reqObj.put(WxPayConstant.POS_ORDER_ID, posOrderId); reqObj.put(WxPayConstant.POS_AMOUNT, posAmount); reqObj.put(WxPayConstant.SIGN, WxPayment.createSignHMAC(reqObj, devReqKey)); String reqJsonStr = JSONObject.toJSONString(reqObj); MvcResult result = mockMvc.perform( - MockMvcRequestBuilders.post("/checkCouponOrderForVerify") + MockMvcRequestBuilders.post("/checkCouponOrder") .contentType(MediaType.APPLICATION_JSON) .content(reqJsonStr)) .andExpect(MockMvcResultMatchers.status().isOk()) diff --git a/mallinkService/src/main/java/com/iformall/domain/po/PosMallConfig.java b/mallinkService/src/main/java/com/iformall/domain/po/PosMallConfig.java index fe9386fd1..87a449eef 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/PosMallConfig.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/PosMallConfig.java @@ -23,11 +23,11 @@ public class PosMallConfig extends BaseEntity { @io.swagger.annotations.ApiModelProperty(value="租户ID",name="tenantId") private String tenantId; - @io.swagger.annotations.ApiModelProperty(value="会员折扣是否开启,0-使用中,1-禁用",name="discount") + @io.swagger.annotations.ApiModelProperty(value="会员折扣是否开启,0-禁用,1-可用",name="discount") private Integer discount; - @io.swagger.annotations.ApiModelProperty(value="会员优惠券是否开启,0-使用中,1-禁用",name="coupon") + @io.swagger.annotations.ApiModelProperty(value="会员优惠券是否开启,0-禁用,1-单选可用,2-多选可用,",name="coupon") private Integer coupon; - @io.swagger.annotations.ApiModelProperty(value="会员消费卡是否开启,0-使用中,1-禁用",name="card") + @io.swagger.annotations.ApiModelProperty(value="会员消费卡是否开启,0-禁用,1-可用",name="card") private Integer card; @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createDate") private Date createDate; diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxOrder.java b/mallinkService/src/main/java/com/iformall/domain/po/WxOrder.java index 12d8ef6af..d3990a0bf 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxOrder.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxOrder.java @@ -40,7 +40,7 @@ public class WxOrder extends BaseEntity { private Long couponChannelId; @io.swagger.annotations.ApiModelProperty(value="产品ID(type-0:couponId, 1:buserId, 3:merchantId)",name="productId") private Long productId; - @io.swagger.annotations.ApiModelProperty(value="类型(0:券,1:B刷卡支付,2:C扫码支付,3:储值卡)",name="type") + @io.swagger.annotations.ApiModelProperty(value="类型(0:券,1:B刷卡支付,2:C扫码支付,3:储值卡, 10:POS支付)",name="type") private Integer type; @io.swagger.annotations.ApiModelProperty(value="0: 付款 1: 退款",name="paymentType") private Integer paymentType; @@ -70,6 +70,11 @@ public class WxOrder extends BaseEntity { @io.swagger.annotations.ApiModelProperty(value = "formId", name = "formId") private String formId; + @io.swagger.annotations.ApiModelProperty(value = "POS系统订单ID", name = "posOrderId") + private Long posOrderId; + @io.swagger.annotations.ApiModelProperty(value="POS系统订单创建时间",name="posOrderCreateTime") + private Long posOrderCreateTime; + @Transient protected List statusS; diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxPayOrder.java b/mallinkService/src/main/java/com/iformall/domain/po/WxPayOrder.java index da3f8623b..7c88e64c3 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxPayOrder.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxPayOrder.java @@ -64,5 +64,16 @@ public class WxPayOrder extends BaseEntity { @io.swagger.annotations.ApiModelProperty(value="支付后结果来源(0:callback, 1:query)",name="payEndFrom") private Integer payEndFrom; + @io.swagger.annotations.ApiModelProperty(value="支付订单号,来源于POS",name="posPayOrderId") + private Long posPayOrderId; + @io.swagger.annotations.ApiModelProperty(value="支付订单创建时间,来源于POS",name="posPayOrderTime") + private Long posPayOrderTime; + @io.swagger.annotations.ApiModelProperty(value="支付方式: 0微信;1支付宝;2现金;3会员折扣;4优惠券;5预付卡;6银行卡,来源于POS",name="posPaymentType") + private Integer posPaymentType; + @io.swagger.annotations.ApiModelProperty(value="支付订单流水号, 来源于POS, 第三方(微信、支付宝、富茂预付卡)支付订单流水号,富茂优惠券ID,现金和富茂会员折扣时为空",name="posPayOrderNo") + private String posPayOrderNo; + @io.swagger.annotations.ApiModelProperty(value="POS支付描述",name="posPayDesc") + private String posPayDesc; + } diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumPosPamentType.java b/mallinkService/src/main/java/com/iformall/enums/EnumNeuPosPamentType.java similarity index 78% rename from mallinkService/src/main/java/com/iformall/enums/EnumPosPamentType.java rename to mallinkService/src/main/java/com/iformall/enums/EnumNeuPosPamentType.java index 8fc872015..b9d38bb52 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumPosPamentType.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumNeuPosPamentType.java @@ -3,7 +3,7 @@ package com.iformall.enums; /** * Created by Stormeye on 2018/08/09. */ -public enum EnumPosPamentType { +public enum EnumNeuPosPamentType { // 来源于Neusoft的定义 0微信;1支付宝;2现金;3会员折扣;4优惠券;5预付卡;6银行卡 WECHAT(0, "微信"), @@ -14,8 +14,8 @@ public enum EnumPosPamentType { MEM_CARD(5, "预付卡"), MEM_BANKCARD(6, "银行卡"), ; - public static EnumPosPamentType getEnum(Integer code) { - for (EnumPosPamentType value : values()) { + public static EnumNeuPosPamentType getEnum(Integer code) { + for (EnumNeuPosPamentType value : values()) { if (value.getCode().equals(code)) { return value; } @@ -26,7 +26,7 @@ public enum EnumPosPamentType { private Integer code; private String message; - EnumPosPamentType(Integer code, String message) { + EnumNeuPosPamentType(Integer code, String message) { this.code = code; this.message = message; } diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumPosRefundType.java b/mallinkService/src/main/java/com/iformall/enums/EnumNeuPosRefundType.java similarity index 79% rename from mallinkService/src/main/java/com/iformall/enums/EnumPosRefundType.java rename to mallinkService/src/main/java/com/iformall/enums/EnumNeuPosRefundType.java index fb88cf679..b474c537c 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumPosRefundType.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumNeuPosRefundType.java @@ -3,7 +3,7 @@ package com.iformall.enums; /** * Created by Stormeye on 2018/08/09. */ -public enum EnumPosRefundType { +public enum EnumNeuPosRefundType { // 来源于Neusoft的定义 0微信;1支付宝;2现金;3会员折扣;4优惠券;5预付卡;6银行卡;7记账 WECHAT(0, "微信"), @@ -15,8 +15,8 @@ public enum EnumPosRefundType { MEM_BANKCARD(6, "银行卡"), BOOK(7, "记账"), ; - public static EnumPosRefundType getEnum(Integer code) { - for (EnumPosRefundType value : values()) { + public static EnumNeuPosRefundType getEnum(Integer code) { + for (EnumNeuPosRefundType value : values()) { if (value.getCode().equals(code)) { return value; } @@ -27,7 +27,7 @@ public enum EnumPosRefundType { private Integer code; private String message; - EnumPosRefundType(Integer code, String message) { + EnumNeuPosRefundType(Integer code, String message) { this.code = code; this.message = message; } diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumOrderType.java b/mallinkService/src/main/java/com/iformall/enums/EnumOrderType.java index d8d922ed0..3beed9124 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumOrderType.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumOrderType.java @@ -11,7 +11,8 @@ public enum EnumOrderType { MICROPAY(1,"B收款码支付"), NATIVEPAY(2,"C扫码支付"), PREPAIDCARD(3, "储值卡"), - CREDIT(4,"积分支付") + CREDIT(4,"积分支付"), + POSPAY(10, "POS支付") ; public static EnumOrderType getEnum(Integer code) { diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumPayWay.java b/mallinkService/src/main/java/com/iformall/enums/EnumPayWay.java index d06ce91eb..1ecfb2492 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumPayWay.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumPayWay.java @@ -9,7 +9,10 @@ public enum EnumPayWay { PAY_WAY_WECHAT(1, "微信支付"), PAY_WAY_WECHAT_WAP(2, "微信H5"), PAY_WAY_ALIPAY(3, "支付宝"), - PAY_WAY_ALIPAY_WAP(4, "支付宝H5"); + PAY_WAY_ALIPAY_WAP(4, "支付宝H5"), + PAY_WAY_POS_B(10, "POS B端"), + PAY_WAY_POS_NEU(11, "POS 东软"), + ; public static EnumPayWay getEnum(Integer code) { for (EnumPayWay value : values()) { diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumVerifyActionType.java b/mallinkService/src/main/java/com/iformall/enums/EnumPosActionType.java similarity index 58% rename from mallinkService/src/main/java/com/iformall/enums/EnumVerifyActionType.java rename to mallinkService/src/main/java/com/iformall/enums/EnumPosActionType.java index 715ca2824..76954a15e 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumVerifyActionType.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumPosActionType.java @@ -3,20 +3,21 @@ package com.iformall.enums; /** * Created by Stormeye on 2018/08/09. */ -public enum EnumVerifyActionType { +public enum EnumPosActionType { // 0: 检查, 1: 预核销 2: 预核销撤销 3:独立核销 4: 交易核销 5:核销撤销 CHECK(0, "检查"), - PRE_VERIFY(1, "预核销"), - PRE_VERIFY_CANCEL(2, "预核销撤销"), - VERIFY_INDEPENT(3,"独立核销"), - VERIFY_PAY(4,"交易核销"), - VERIFY_CANCEL(5,"核销撤销") + CALC(1, "计算"), + PRE_VERIFY(2, "预核销"), + PRE_VERIFY_CANCEL(3, "预核销撤销"), + VERIFY_INDEPENT(4,"独立核销"), + VERIFY_PAY(5,"交易核销"), + VERIFY_CANCEL(6,"核销撤销") ; - public static EnumVerifyActionType getEnum(Integer code) { - for (EnumVerifyActionType value : values()) { + public static EnumPosActionType getEnum(Integer code) { + for (EnumPosActionType value : values()) { if (value.getCode().equals(code)) { return value; } @@ -27,7 +28,7 @@ public enum EnumVerifyActionType { private Integer code; private String message; - EnumVerifyActionType(Integer code, String message) { + EnumPosActionType(Integer code, String message) { this.code = code; this.message = message; } diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumPosCouponEnableType.java b/mallinkService/src/main/java/com/iformall/enums/EnumPosCouponEnableType.java new file mode 100644 index 000000000..e33abbd1b --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/enums/EnumPosCouponEnableType.java @@ -0,0 +1,39 @@ +package com.iformall.enums; + +/** + * Created by Stormeye on 2018/08/09. + */ +public enum EnumPosCouponEnableType { + + // 0:禁用 1:单选可用 + + Disable(0, "禁用"), + SingleEnable(1, "单选可用"), + MultiEnable(2, "多选可用") + ; + + public static EnumPosCouponEnableType getEnum(Integer code) { + for (EnumPosCouponEnableType value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumPosCouponEnableType(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumPosEnableType.java b/mallinkService/src/main/java/com/iformall/enums/EnumPosEnableType.java new file mode 100644 index 000000000..797894732 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/enums/EnumPosEnableType.java @@ -0,0 +1,38 @@ +package com.iformall.enums; + +/** + * Created by Stormeye on 2018/08/09. + */ +public enum EnumPosEnableType { + + // 0:禁用 1:可用 + + Disable(0, "禁用"), + Enable(1, "可用") + ; + + public static EnumPosEnableType getEnum(Integer code) { + for (EnumPosEnableType value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumPosEnableType(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumPosSceneType.java b/mallinkService/src/main/java/com/iformall/enums/EnumPosSceneType.java new file mode 100644 index 000000000..9769921aa --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/enums/EnumPosSceneType.java @@ -0,0 +1,38 @@ +package com.iformall.enums; + + +/** + * @author gongbiao + */ + +public enum EnumPosSceneType { + + PAY(1,"支付"), + VERIFY(2,"核销") + ; + + public static EnumPosSceneType getEnum(Integer code) { + for (EnumPosSceneType value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumPosSceneType(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java b/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java index 922f90e28..4909ac38d 100644 --- a/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java +++ b/mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java @@ -19,7 +19,10 @@ public class WxPayConstant { public final static String TENANT_ID = "tenant_id"; + public final static String MALL_NAME = "mall_name"; public final static String MERCHANT_ID = "merchant_id"; + public final static String MERCHANT_NAME = "merchant_name"; + public final static String MERCHANT_IMG = "merchant_img"; public final static String BUSER_ID = "bu_user_id"; public final static String COUPON_ORDER_ID = "coupon_order_id"; public final static String SELECTED_COUPON_ORDER_LIST = "sel_co_list"; @@ -40,9 +43,9 @@ public class WxPayConstant { public final static String PRICE = "price"; public final static String STATUS = "status"; - public final static String VERIFY_TYPE = "verify_type"; - public final static String VERIFY_TYPE_INDEPENT = "independent"; - public final static String VERIFY_TYPE_PAY = "pay"; + public final static String SCENE_TYPE = "scene_type"; + public final static String SCENE_VERIFY = "2"; + public final static String SCENE_PAY = "1"; public final static String CHECK = "check"; public final static String PRE_VERIFY = "pre_verify"; @@ -56,7 +59,10 @@ public class WxPayConstant { public final static String MEM_DISCOUNT = "discount"; + public final static String MEM_DISCOUNT_RATE = "discount_rate"; public final static String MEM_COUPON = "coupon"; + public final static String MEM_COUPONS = "coupons"; + public final static String MEM_COUPON_DESC = "coupon_desc"; public final static String MEM_CARD = "card"; public final static String MEM_LEVEL = "level"; public final static String AVAIL_CO_LIST = "avail_co_list"; @@ -74,6 +80,7 @@ public class WxPayConstant { public final static String SALE_FEE = "sale_fee"; public final static String ORG_AMOUNT = "org_amount"; + public final static String DISCOUNT_AMOUNT = "discount_amount"; public final static String ORG_REMAIN_AMOUNT = "org_remain_amount"; public final static String RET = "ret"; @@ -82,6 +89,7 @@ public class WxPayConstant { public final static String FALSE = "false"; + //// 东软相关定义 public final static String NEU_TENANT_ID = "TenantID"; // 富茂系统商场ID public final static String NEU_MERCHANT_ID = "MerchantID"; // 富茂系统商户ID public final static String NEU_BU_USER_ID = "OrderOperatorID"; // 富茂系统登录操作员ID @@ -115,4 +123,8 @@ public class WxPayConstant { public final static String NEU_REFUND_ORDER_OUT_NO = "OuterRefundNumber"; // 第三方(微信、支付宝、富茂预付卡)支付订单流水号,富茂优惠券ID,现金和富茂会员折扣时为空 public final static String NEU_REFUND_ORDER_AMOUNT = "RefundAmount"; // 退款金额 public final static String NEU_REFUND_ORDER_OUT_TIME = "RefundTime"; // 第三方支付系统返回的支付时间,现金和富茂会员折扣时为空 + + public final static String NEU_ORDER_PAY = "0"; // 有效, 优惠券从预核销处理为核销, 卡从预支付->支付 + public final static String NEU_ORDER_REFUND = "1"; // 取消 + } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java index 2d5e2cb2c..c701f728b 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxBillAllServiceImpl.java @@ -1607,7 +1607,7 @@ public class WxBillAllServiceImpl implements WxBillAllService { oweMerchantVo.setBalance(map.get("balance")==null?"0":map.get("balance").toString()); list.add(oweMerchantVo); } - String name = "商户列表"; + String name = "商户账单列表"; excelService.exportExcel(list, null, name, ReceivedAndPayVo.class, name + ".xlsx", response, false); } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxBillRentServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxBillRentServiceImpl.java index 87d1f2d8b..95aa005c7 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxBillRentServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxBillRentServiceImpl.java @@ -321,6 +321,7 @@ public class WxBillRentServiceImpl implements WxBillRentService { long newReceivePay; if(ratioVo != null){ newReceivePay = ratioVo.getPrice(); + ratio = ratioVo.getRatio(); }else{ BigDecimal hundred = new BigDecimal(100); BigDecimal revenue = new BigDecimal(record.getRevenue() == null ? 0 : record.getRevenue()).divide(hundred); diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxRentContractServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxRentContractServiceImpl.java index 7ac99f7a4..4adb63d2c 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxRentContractServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxRentContractServiceImpl.java @@ -1250,11 +1250,22 @@ public class WxRentContractServiceImpl implements WxRentContractService { double needpayD = WxRentContractServiceImpl.getNeedPay(0,priceD,startDate,endDate); needpay = new Double(needpayD).longValue(); }else{ - //年 需要除12 Double priceD = new Double(price); + + //年或者设置跳点率为年周期 除12 if(EnumPriceUnit.Y.getCode().equals(wxRentContract.getPriceUnit())){ priceD = new Double(price)/12; } + if (wxRentContract.getType().equals(EnumRentContractType.RENT_BY_JOINT.getCode())) { + //设置跳点率为年周期 price不变 + if(EnumMissTimeType.PERIOD.getCode().equals(wxRentContract.getBusDiscountTime())){ + return priceD.longValue(); + } + //年或者设置跳点率为年周期 除12 + if(EnumMissTimeType.YEAR.getCode().equals(wxRentContract.getBusDiscountTime())){ + priceD = new Double(price)/12; + } + } //生成金额直接计算 if(!saveDb){ diff --git a/mallinkService/src/main/resources/mapper/PosMallConfigMapper.xml b/mallinkService/src/main/resources/mapper/PosMallConfigMapper.xml index 36943fff7..32a58c7ab 100644 --- a/mallinkService/src/main/resources/mapper/PosMallConfigMapper.xml +++ b/mallinkService/src/main/resources/mapper/PosMallConfigMapper.xml @@ -21,8 +21,8 @@ and `id` = #{id} - and `tenant_id` like concat('%', #{tenantId},'%') - + and `tenant_id` = #{tenantId} + and `discount` = #{discount} diff --git a/mallinkService/src/main/resources/mapper/WxMerchantMapper.xml b/mallinkService/src/main/resources/mapper/WxMerchantMapper.xml index 5cdc3d524..681406ce5 100644 --- a/mallinkService/src/main/resources/mapper/WxMerchantMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxMerchantMapper.xml @@ -238,10 +238,10 @@ inner join wx_merchant m on ms.merchant_id = m.id inner join wx_shop s on s.id=ms.shop_id where m.tenant_id=#{tenantId} and s.is_del=0 - + and m.business_id in (${businessForRule}) - + and s.`floor` in (${floorForRule}) ) diff --git a/mallinkService/src/main/resources/mapper/WxMerchantTradeDailyMapper.xml b/mallinkService/src/main/resources/mapper/WxMerchantTradeDailyMapper.xml index 157d7c007..f91af3e34 100644 --- a/mallinkService/src/main/resources/mapper/WxMerchantTradeDailyMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxMerchantTradeDailyMapper.xml @@ -150,10 +150,10 @@ inner join wx_merchant m on ms.merchant_id = m.id inner join wx_shop s on s.id=ms.shop_id where m.tenant_id=#{tenantId} and s.is_del=0 - + and m.business_id in (${businessForRule}) - + and s.`floor` in (${floorForRule}) ) diff --git a/mallinkService/src/main/resources/mapper/WxPropertyContractMapper.xml b/mallinkService/src/main/resources/mapper/WxPropertyContractMapper.xml index 17fa3c140..8dec54644 100644 --- a/mallinkService/src/main/resources/mapper/WxPropertyContractMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxPropertyContractMapper.xml @@ -149,10 +149,10 @@ inner join wx_merchant m on ms.merchant_id = m.id inner join wx_shop s on s.id=ms.shop_id where m.tenant_id=#{tenantId} and s.is_del=0 - + and m.business_id in (${businessForRule}) - + and s.`floor` in (${floorForRule}) ) diff --git a/mallinkService/src/main/resources/mapper/WxRentContractMapper.xml b/mallinkService/src/main/resources/mapper/WxRentContractMapper.xml index 42321f244..04d155c0f 100644 --- a/mallinkService/src/main/resources/mapper/WxRentContractMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxRentContractMapper.xml @@ -177,10 +177,10 @@ inner join wx_merchant m on ms.merchant_id = m.id inner join wx_shop s on s.id=ms.shop_id where m.tenant_id=#{tenantId} and s.is_del=0 - + and m.business_id in (${businessForRule}) - + and s.`floor` in (${floorForRule}) ) @@ -382,6 +382,22 @@ and rc.`rent_shop_type` = #{rentShopType} and rc.`apply_status` = #{applyStatus} and rc.`operation_type` = #{operationType} + + + and rc.merchant_id in( + select ms.merchant_id from (select merchant_id,shop_id from wx_merchant_shop where is_del=0) ms + inner join wx_merchant m on ms.merchant_id = m.id + inner join wx_shop s on s.id=ms.shop_id + where m.tenant_id=#{tenantId} and s.is_del=0 + + and m.business_id in (${businessForRule}) + + + and s.`floor` in (${floorForRule}) + + ) + + order by ${sortColumns} order by rc.createtime desc,rc.id desc