Просмотр исходного кода

[POS][修改]:POS会员识别接口修改,新增支付计算接口

release_toaliyun_real
Stormeye Wu 6 лет назад
Родитель
Сommit
94cd851354
6 измененных файлов: 420 добавлений и 124 удалений
  1. +48
    -8
      mallinkPosApi/src/main/java/com/iformall/controller/PosController.java
  2. +11
    -5
      mallinkPosApi/src/main/java/com/iformall/service/PosService.java
  3. +306
    -101
      mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java
  4. +42
    -1
      mallinkPosApi/src/test/java/com/iformall/pos/test/PosAppTest.java
  5. +10
    -9
      mallinkService/src/main/java/com/iformall/enums/EnumPosActionType.java
  6. +3
    -0
      mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java

+ 48
- 8
mallinkPosApi/src/main/java/com/iformall/controller/PosController.java Просмотреть файл

@@ -210,7 +210,7 @@ public class PosController extends BaseController {
"\"coupon_order_id\":\"string(必填)\"," +
"\"scene_type\":\"string(1支付2:核销)(必填)\"," +
"\"pos_order_id\":\"string(选填)\"," +
"\"pos_amount\":\"单位(分)(选填)\"}")
"\"pos_amount\":\"string单位(分)(选填)\"}")
@PostMapping("/checkCouponOrder")
@SystemControllerLog(description = "券检查是否可用-场景(核销/支付)")
public Map<String, String> checkCouponOrder(@RequestBody Map<String, String> params) {
@@ -226,7 +226,47 @@ public class PosController extends BaseController {
logger.info(WxPayConstant.RES_KEY + ": " + resKey);

try {
retMap = posService.couponOrderVerifyDo(params, EnumVerifyActionType.CHECK);
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\":\"string单位(分)(必填)\"}")
@PostMapping("/calcMem")
@SystemControllerLog(description = "支付计算接口")
public Map<String, String> calcForMem(@RequestBody Map<String, String> params) {
JSONObject payContent = new JSONObject();

// 1. check sign
Map<String, String> 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.calcMem(params);
return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "",
WxPayConstant.RET_SUCCESS, null);
} catch (MallinkException e) {
@@ -264,7 +304,7 @@ public class PosController extends BaseController {
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) {
@@ -301,7 +341,7 @@ public class PosController extends BaseController {
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) {
@@ -338,7 +378,7 @@ public class PosController extends BaseController {
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,
@@ -397,7 +437,7 @@ public class PosController extends BaseController {
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,
@@ -437,7 +477,7 @@ public class PosController extends BaseController {
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,
@@ -507,7 +547,7 @@ public class PosController extends BaseController {
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) {


+ 11
- 5
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<String, String> checkMember(Map<String, String> params) throws MallinkException;

/**
* 支付计算
* @param params
* @return
*/
Map<String, String> calcMem(Map<String, String> params) throws MallinkException;

/**
* 核销动作(check, pre_verify, verify)
* @param params
@@ -42,7 +48,7 @@ public interface PosService {
* @return
* @throws MallinkException
*/
Map<String, String> couponOrderVerifyDo(Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException;
Map<String, String> couponOrderVerifyDo(Map<String, String> params, EnumPosActionType actionType) throws MallinkException;

/**
* 核销取消(check, pre_verify, verify) for selected_coupon_list
@@ -51,7 +57,7 @@ public interface PosService {
* @return
* @throws MallinkException
*/
Map<String, String> couponOrderVerifyCancel(Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException;
Map<String, String> couponOrderVerifyCancel(Map<String, String> params, EnumPosActionType actionType) throws MallinkException;

/**
* 核销动作(check, pre_verify, verify) for selected_coupon_list
@@ -60,7 +66,7 @@ public interface PosService {
* @return
* @throws MallinkException
*/
Map<String, String> couponOrderVerifyListDo(Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException;
Map<String, String> couponOrderVerifyListDo(Map<String, String> params, EnumPosActionType actionType) throws MallinkException;

/**
* 消费卡POS预支付


+ 306
- 101
mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java Просмотреть файл

@@ -58,8 +58,6 @@ public class PosServiceImpl implements PosService {
private final WxCouponMapper couponMapper;




/**
* 门店用户登录检查
* @param params
@@ -209,6 +207,7 @@ public class PosServiceImpl implements PosService {

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
@@ -234,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<WxLevelConfig> 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<WxLevelMerchantCVo> 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<String, Object> coQ = new HashMap<>();
coQ.put("tenantId", tenantId);
@@ -340,17 +310,244 @@ public class PosServiceImpl implements PosService {
} else {
retMap.put(WxPayConstant.AVAIL_CO_LIST, "[]");
}
return retMap;
}



@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, String> calcMem(Map<String, String> params) throws MallinkException {
Map<String, String> 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<selCoArr.size();i++) {
String couponOrderIdStr = selCoArr.getString(i);
if (couponOrderIdStr != null) {
try {
Map<String, String> 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<String, String> calcOneCouponVerify(Long merchantId, Long posAmount, String couponOrderIdStr) {
Map<String, String> 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<WxCouponMerchant> 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<String, String> retMap, String tenantId, WxCUser user, Long merchantId) {
Integer discount = 100;
String level = WxLevelConfigService.DEFAULT_LEVEL;
// Level, 折扣
List<WxLevelConfig> 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<WxLevelMerchantCVo> 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<String, String> couponOrderVerifyDo(@RequestBody Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException {
public Map<String, String> couponOrderVerifyDo(@RequestBody Map<String, String> params, EnumPosActionType actionType) throws MallinkException {
Map<String, String> retMap = new HashMap<>();

String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID
@@ -383,7 +580,7 @@ public class PosServiceImpl implements PosService {
if (StringUtils.isBlank(couponOrderIdStr)) {
errParam(WxPayConstant.COUPON_ORDER_ID);
}
if (actionType.equals(EnumVerifyActionType.CHECK)) {
if (actionType.equals(EnumPosActionType.CHECK)) {
if (StringUtils.isBlank(sceneTypeStr)) {
errParam(WxPayConstant.SCENE_TYPE);
}
@@ -393,20 +590,20 @@ public class PosServiceImpl implements PosService {
logger.error(e.getMessage());
throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage());
}
} else if (actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT)) {
} else if (actionType.equals(EnumPosActionType.VERIFY_INDEPENT)) {
sceneType = EnumPosSceneType.VERIFY.getCode();
} else if (actionType.equals(EnumVerifyActionType.VERIFY_PAY)) {
} else if (actionType.equals(EnumPosActionType.VERIFY_PAY)) {
sceneType = EnumPosSceneType.PAY.getCode();
}
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)) {
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);
}
@@ -417,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) {
@@ -455,7 +652,7 @@ public class PosServiceImpl implements PosService {

@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, String> couponOrderVerifyListDo(@RequestBody Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException {
public Map<String, String> couponOrderVerifyListDo(@RequestBody Map<String, String> params, EnumPosActionType actionType) throws MallinkException {
Map<String, String> retMap = new HashMap<>();

String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID
@@ -487,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);
}
@@ -501,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);
}
@@ -547,7 +744,7 @@ public class PosServiceImpl implements PosService {
}

private Map<String, String> doVerifyActionForOneCouponOrder(
EnumVerifyActionType actionType, Integer sceneType,
EnumPosActionType actionType, Integer sceneType,
String tenantId, String merchantIdStr, Long merchantId,
String buUserIdStr, Long buUserId,
String posOrderIdStr, Long posOrderId, Integer posAmount,
@@ -560,7 +757,7 @@ public class PosServiceImpl implements PosService {
throw new MallinkException(ErrorCode.COUPON_ORDER_IS_NULL);
}
// 4.1 检查券类型
if (actionType.equals(EnumVerifyActionType.CHECK)) {
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()) ||
@@ -580,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())
@@ -594,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()) ||
@@ -650,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)) {
@@ -701,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)) {
@@ -811,7 +1008,7 @@ public class PosServiceImpl implements PosService {

@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, String> couponOrderVerifyCancel(Map<String, String> params, EnumVerifyActionType actionType) {
public Map<String, String> couponOrderVerifyCancel(Map<String, String> params, EnumPosActionType actionType) {
Map<String, String> retMap = new HashMap<>();

String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID
@@ -833,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);
}
@@ -896,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);
@@ -913,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)) {
@@ -1040,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<String, String> retMap) {
int num = 0;
// 1. insert posOrderId
@@ -1068,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());
@@ -1922,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;
}

@@ -1940,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


+ 42
- 1
mallinkPosApi/src/test/java/com/iformall/pos/test/PosAppTest.java Просмотреть файл

@@ -176,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";
@@ -257,10 +266,11 @@ public class PosAppTest {

private void doCheckMem(String memId, String phone, String posOrderId, String posAmount) throws Exception {
Map<String, String> 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);
}
@@ -285,6 +295,37 @@ public class PosAppTest {
Assert.assertEquals(resSigned, true);
}

private void doCalcMem(String memId, String phone, String posAmount, String selCoList) throws Exception {
Map<String, String> 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<String,String> 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<String, String> reqObj = new HashMap<>();
reqObj.put(WxPayConstant.NONCE_STR, "1");


mallinkService/src/main/java/com/iformall/enums/EnumVerifyActionType.java → 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;
}

+ 3
- 0
mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java Просмотреть файл

@@ -59,7 +59,9 @@ 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";
@@ -78,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";


Загрузка…
Отмена
Сохранить