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

[POS][修改]:卡支付撤销

release_toaliyun_real
Stormeye Wu 6 лет назад
Родитель
Сommit
b00e2e50a7
7 измененных файлов: 238 добавлений и 263 удалений
  1. +17
    -10
      mallinkPosApi/src/main/java/com/iformall/controller/PosController.java
  2. +153
    -85
      mallinkPosApi/src/main/java/com/iformall/service/impl/PosServiceImpl.java
  3. +32
    -159
      mallinkPosApi/src/test/java/com/iformall/pos/test/PosAppTest.java
  4. +7
    -5
      mallinkService/src/main/java/com/iformall/common/ErrorCode.java
  5. +1
    -0
      mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java
  6. +11
    -4
      mallinkService/src/main/java/com/iformall/pay/WxPayConstant.java
  7. +17
    -0
      mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java

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

@@ -47,7 +47,7 @@ public class PosController extends BaseController {
"\"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\"," +
"\"order_operation_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:可用)\"," +
@@ -234,10 +234,14 @@ public class PosController extends BaseController {
"\"nonce_str\":\"string(必填)\"," +
"\"tenant_id\":\"string(必填)\"," +
"\"merchant_id\":\"string(必填)\"," +
"\"bu_user_id\":\"string(必填)\"," +
"\"pos_order_id\":\"string(必填)\"," +
"\"pos_amount\":\"string(单位:分)(必填)\"," +
"\"card_id\":\"string(必填)\" }")
"\"order_operation_id\":\"string(必填)\"," +
"\"business_type\":\"string(0:核销1支付(必填)\"," +
"\"order_number_of_platform\":\"string(必填)\"," +
"\"order_amount\":\"string单位(分)(选填)\"," +
"\"order_amount_left\":\"string单位(分)(选填)\"," +
"\"order_create_sn\":\"string单位(分)(必填)\"," +
"\"card_id\":\"string(必填)\"," +
"\"amount_paid_by_card\":\"string(必填)\"}")
@PostMapping("/cardPayPre")
@SystemControllerLog(description = "消费卡支付")
public Map<String, String> cardPayPre(@RequestBody Map<String, String> params) {
@@ -263,18 +267,21 @@ 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(必填)\"," +
"\"pos_order_id\":\"string(必填)\"," +
"\"pos_amount\":\"string(单位:分)(必填)\"," +
"\"order_operation_id\":\"string(必填)\"," +
"\"order_number_of_platform\":\"string(必填)\"," +
"\"order_amount\":\"string单位(分)(选填)\"," +
"\"order_amount_left\":\"string单位(分)(选填)\"," +
"\"order_create_sn\":\"string单位(分)(必填)\"," +
"\"payment_info\":{" +
"\"card_id\":\"string(必填)\"," +
"\"card_spend_id\":\"string(必填)\"}")
@PostMapping("/cardPayPreCancel")
@SystemControllerLog(description = "消费卡支付取消")
@SystemControllerLog(description = "消费卡支付取消")
public Map<String, String> cardPayPreCancel(@RequestBody Map<String, String> params) {
JSONObject payContent = new JSONObject();
JSONObject retObj = new JSONObject();


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

@@ -924,7 +924,7 @@ public class PosServiceImpl implements PosService {
String buUserIdStr = params.get(WxPayConstant.BUSER_ID); // POS操作员ID
String sceneTypeStr = params.get(WxPayConstant.SCENE_TYPE); // 交易场景
String orderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID
String orderCreateSN = params.get(WxPayConstant.ORDER_CREATE_SN); // POS SN号
String orderCreateSN = params.get(WxPayConstant.ORDER_CREATE_SN); // POS SN号
String paymentInfoStr = params.get(WxPayConstant.PAYMENT_INFO); // 优惠信息

if (StringUtils.isBlank(tenantId)) {
@@ -1030,7 +1030,7 @@ public class PosServiceImpl implements PosService {
couponOrderIdStr, couponOrderCVo.getPriceStr(), couponOrderCVo.getSalePriceStr());
refundObj.put(WxPayConstant.COUPON_REFUND_ID, couponOrderIdStr);
refundObj.put(WxPayConstant.COUPON_REFUND_RESULT, "0");
refundObj.put(WxPayConstant.COUPON_REFUND_RESULT_MSG, errMesg);
refundObj.put(WxPayConstant.REFUND_RESULT_MSG, errMesg);
refundObj.put(WxPayConstant.REFUND_TIME_FROM_IFORMALL, neuDateFormat.format(new Date()));
refundObj.put(WxPayConstant.PRICE, coupon.getPrice());
refundObj.put(WxPayConstant.SALE_PRICE, coupon.getSalePrice());
@@ -1120,7 +1120,7 @@ public class PosServiceImpl implements PosService {
JSONObject refundObj = new JSONObject();
refundObj.put(WxPayConstant.COUPON_REFUND_ID, String.valueOf(couponOrderCVo.getId()));
refundObj.put(WxPayConstant.COUPON_REFUND_RESULT, "0");
refundObj.put(WxPayConstant.COUPON_REFUND_RESULT_MSG, "核销撤销成功");
refundObj.put(WxPayConstant.REFUND_RESULT_MSG, "核销撤销成功");
refundObj.put(WxPayConstant.REFUND_TIME_FROM_IFORMALL, neuDateFormat.format(new Date()));
refundObj.put(WxPayConstant.PROMOTION_AMOUNT, 0);
refundObj.put(WxPayConstant.AMOUNT_LEFT_AFTER_PAY, amountLeftAfterPay + couponOrderCVo.getPrice());
@@ -1402,82 +1402,86 @@ public class PosServiceImpl implements PosService {
String buUserIdStr = params.get(WxPayConstant.BUSER_ID); // POS操作员ID
String sceneTypeStr = params.get(WxPayConstant.SCENE_TYPE); // 交易场景
String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID
String posAmountStr = params.get(WxPayConstant.ORDER_AMOUNT); // POS订单总额(单位:分)
String posAmountLeftStr = params.get(WxPayConstant.ORDER_AMOUNT_LEFT); // POS订单总额(单位:分)
String cardIdStr = params.get(WxPayConstant.CARD_ID); // 消费卡ID
String orderAmountStr = params.get(WxPayConstant.ORDER_AMOUNT); // POS订单总额(单位:分)
String orderAmountLeftStr = params.get(WxPayConstant.ORDER_AMOUNT_LEFT); // 本次需要支付的订单金额(单位:分)
String cardIdStr = params.get(WxPayConstant.CARD_ID); // 消费卡ID
String amountByCardStr = params.get(WxPayConstant.AMOUNT_PAID_BY_CARD); // 预付卡支付金额

if (StringUtils.isBlank(tenantId)) {
errParam(WxPayConstant.TENANT_ID);
} else {
retMap.put(WxPayConstant.TENANT_ID, tenantId);
}
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 (!config.getCard().equals(EnumEnableType.Enable.getCode())) {
logger.error(ErrorCode.POS_CONFIG_MEM_COUPON_DISABLE.getMessage());
throw new MallinkException(ErrorCode.POS_CONFIG_MEM_COUPON_DISABLE);
if (config.getCard().equals(EnumPosEnableType.Disable.getCode())) {
logger.error(ErrorCode.POS_CONFIG_MEM_CARD_DISABLE.getMessage());
throw new MallinkException(ErrorCode.POS_CONFIG_MEM_CARD_DISABLE);
}
if (StringUtils.isBlank(merchantIdStr)) {
errParam(WxPayConstant.MERCHANT_ID);
} else {
retMap.put(WxPayConstant.MERCHANT_ID, merchantIdStr);
}
if (StringUtils.isBlank(buUserIdStr)) {
errParam(WxPayConstant.BUSER_ID);
} else {
retMap.put(WxPayConstant.BUSER_ID, buUserIdStr);
}
if (StringUtils.isBlank(sceneTypeStr)) {
errParam(WxPayConstant.SCENE_TYPE);
} else {
retMap.put(WxPayConstant.SCENE_TYPE, sceneTypeStr);
}
if (!sceneTypeStr.equals(EnumPosSceneType.PAY.getCode().toString())) {
logger.error(ErrorCode.POS_CARD_ONLY_SUPPORT_PAY.getMessage());
throw new MallinkException(ErrorCode.POS_CARD_ONLY_SUPPORT_PAY);
}
if (StringUtils.isBlank(posOrderIdStr)) {
errParam(WxPayConstant.POS_ORDER_ID);
} else {
retMap.put(WxPayConstant.POS_ORDER_ID, posOrderIdStr);
}
if (StringUtils.isBlank(posAmountStr)) {
if (StringUtils.isBlank(orderAmountStr)) {
errParam(WxPayConstant.ORDER_AMOUNT);
} else {
retMap.put(WxPayConstant.ORDER_AMOUNT, orderAmountStr);
}
if (StringUtils.isBlank(orderAmountLeftStr)) {
errParam(WxPayConstant.ORDER_AMOUNT_LEFT);
} else {
retMap.put(WxPayConstant.ORDER_AMOUNT_LEFT, orderAmountLeftStr);
}
if (StringUtils.isBlank(cardIdStr)) {
errParam(WxPayConstant.CARD_ID);
} else {
retMap.put(WxPayConstant.CARD_ID, cardIdStr);
}
if (StringUtils.isBlank(amountByCardStr)) {
errParam(WxPayConstant.AMOUNT_PAID_BY_CARD);
} else {
retMap.put(WxPayConstant.AMOUNT_PAID_BY_CARD, amountByCardStr);
}

Long merchantId, buUserId, posOrderId, cardId;
Integer posAmount = 0;
Integer amountByCard = 0;
try {
merchantId = Long.valueOf(merchantIdStr);
buUserId = Long.valueOf(buUserIdStr);
posOrderId = Long.valueOf(posOrderIdStr);
posAmount = Integer.valueOf(posAmountStr);
amountByCard = Integer.valueOf(amountByCardStr);
cardId = Long.valueOf(cardIdStr);
} catch (NumberFormatException e) {
logger.error(e.getMessage());
throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage());
}
WxCardInfo cardInfo = cardInfoService.getById(cardId);
if(cardInfo == null) {
String errMessage = "卡不存在: " + cardIdStr;
logger.error(errMessage);
throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND.getCode(), errMessage);
}
WxCouponMerchant couponMerchant = cardSpendService.checkMerchantInCoupon(cardInfo, merchantId);
if(couponMerchant == null) {
String errMessage = "商户不支持此卡 " + cardIdStr;
logger.error(errMessage);
throw new MallinkException(ErrorCode.COUPON_ORDER_MERANT_IS_NULL.getCode(), errMessage);
}
// 2. check merchant
WxMerchant merchant = merchantService.getById(merchantId);
if (merchant == null) {
logger.error(ErrorCode.MERCHANT_INFO_NOT_FOUND.getMessage() + ": " + merchantIdStr);
throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND);
}
if (merchant.getIsDel().equals(EnumDelStatus.DEL.getCode()) || merchant.getStatus().equals(EnumMerchantStatus.NOT_VALID.getCode())) {
logger.error(ErrorCode.MERCHANT_INFO_NOT_VALID.getMessage() + ": " + merchantIdStr);
throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_VALID);
}
WxMerchant merchant = checkAndGetMerchant(merchantId);
// 3. check buUser
WxMerchantBUser buUser = merchantBUserService.getById(buUserId);
if (buUser == null) {
logger.error(ErrorCode.USER_IS_EMPTY.getMessage() + ": " + buUserIdStr);
throw new MallinkException(ErrorCode.USER_IS_EMPTY);
}
if (!buUser.getMerchantId().equals(merchantId)) {
logger.error(ErrorCode.VERIFY_BUSER_MERCHANT_NOT_BELONG.getMessage() + ": " + buUserIdStr);
throw new MallinkException(ErrorCode.VERIFY_BUSER_MERCHANT_NOT_BELONG);
}
WxMerchantBUser buUser = checkAndGetMerchantUser(buUserId, merchantId);

WxCouponOrder couponOrder = couponOrderService.getById(cardId);
if(couponOrder == null) {
@@ -1485,10 +1489,13 @@ public class PosServiceImpl implements PosService {
throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND);
}

if(posAmount > cardInfo.getRemainingAmount()) {
WxCardInfo cardInfo = checkAndGetCardinfo(cardId, merchantId);

if(amountByCard > cardInfo.getRemainingAmount()) {
logger.error("卡余额不足: " + cardIdStr);
throw new MallinkException(ErrorCode.CARD_REMAIN_AMOUNT_IS_NOT_ENOUGH);
}

WxCardSpend record = new WxCardSpend();
record.setPayFrom(EnumCardSpendFrom.POS.getCode());
record.setTenantId(merchant.getTenantId());
@@ -1496,16 +1503,18 @@ public class PosServiceImpl implements PosService {
record.setOwnerId(couponOrder.getOwnerId());
record.setMerchantId(merchantId);
record.setPosOrderId(posOrderId);
record.setDeductionAmount(posAmount);
record.setDeductionAmount(amountByCard);

try {
WxCardSpend cardSpend = cardSpendService.cardSpendForPosPrePay(record);
JSONObject retObj = new JSONObject();
retObj.put(WxPayConstant.ID, cardSpend.getId());
retObj.put(WxPayConstant.DEDUCT_AMOUNT, posAmount);
retObj.put(WxPayConstant.REMAIN_AMOUNT, cardSpend.getCardRemainAmount());
retObj.put(WxPayConstant.PRE_PAY, WxPayConstant.TRUE);
retMap.put(WxPayConstant.RET, JSON.toJSONString(retObj));
JSONObject cardPaymentObj = new JSONObject();
cardPaymentObj.put(WxPayConstant.CARD_ID, cardId);
cardPaymentObj.put(WxPayConstant.CARD_AMOUNT_BEFORE_PAY, cardSpend.getCardBeforeAmount());
cardPaymentObj.put(WxPayConstant.PAYMENT_AMOUNT, cardSpend.getPayment());
cardPaymentObj.put(WxPayConstant.CARD_AMOUNT_AFTER_PAY, cardSpend.getCardRemainAmount());
cardPaymentObj.put(WxPayConstant.CARD_SPEND_ID, cardSpend.getId().toString());
cardPaymentObj.put(WxPayConstant.CARD_SPEND_TIME, neuDateFormat.format(cardSpend.getCreateDate()));
retMap.put(WxPayConstant.CARD_PAYMENT_DATA, JSON.toJSONString(cardPaymentObj));
} catch (MallinkException e) {
logger.error("card spend error, req 2: " + record.toString() + ", e:" + e.getMessage());
throw new MallinkException(e.getErrorCode(), e.getMessage());
@@ -1525,67 +1534,105 @@ 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 posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID
String posAmountStr = params.get(WxPayConstant.ORDER_AMOUNT); // POS订单总额(单位:分)
String cardIdStr = params.get(WxPayConstant.CARD_ID); // 消费卡ID
String cardSpendIdStr = params.get(WxPayConstant.CARD_SPEND_ID); // 消费卡花费ID
String sceneTypeStr = params.get(WxPayConstant.SCENE_TYPE); // 交易场景
String orderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID
String orderAmountStr = params.get(WxPayConstant.ORDER_AMOUNT); // POS订单总额(单位:分)
String orderAmountLeftStr = params.get(WxPayConstant.ORDER_AMOUNT_LEFT); // 本次需要支付的剩余金额
String orderCreateSN = params.get(WxPayConstant.ORDER_CREATE_SN); // POS SN号
String paymentInfoStr = params.get(WxPayConstant.PAYMENT_INFO); // 优惠信息

if (StringUtils.isBlank(tenantId)) {
errParam(WxPayConstant.TENANT_ID);
} else {
retMap.put(WxPayConstant.TENANT_ID, tenantId);
}
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 (!config.getCard().equals(EnumEnableType.Enable.getCode())) {
logger.error(ErrorCode.POS_CONFIG_MEM_COUPON_DISABLE.getMessage());
throw new MallinkException(ErrorCode.POS_CONFIG_MEM_COUPON_DISABLE);
if (config.getCard().equals(EnumPosEnableType.Disable.getCode())) {
logger.error(ErrorCode.POS_CONFIG_MEM_CARD_DISABLE.getMessage());
throw new MallinkException(ErrorCode.POS_CONFIG_MEM_CARD_DISABLE);
}
if (StringUtils.isBlank(merchantIdStr)) {
errParam(WxPayConstant.MERCHANT_ID);
} else {
retMap.put(WxPayConstant.MERCHANT_ID, merchantIdStr);
}
if (StringUtils.isBlank(buUserIdStr)) {
errParam(WxPayConstant.BUSER_ID);
} else {
retMap.put(WxPayConstant.BUSER_ID, buUserIdStr);
}
if (StringUtils.isBlank(posOrderIdStr)) {
if (StringUtils.isBlank(sceneTypeStr)) {
errParam(WxPayConstant.SCENE_TYPE);
} else {
retMap.put(WxPayConstant.SCENE_TYPE, sceneTypeStr);
}
if (!sceneTypeStr.equals(EnumPosSceneType.PAY.getCode().toString())) {
logger.error(ErrorCode.POS_CARD_ONLY_SUPPORT_PAY.getMessage());
throw new MallinkException(ErrorCode.POS_CARD_ONLY_SUPPORT_PAY);
}
if (StringUtils.isBlank(orderIdStr)) {
errParam(WxPayConstant.POS_ORDER_ID);
} else {
retMap.put(WxPayConstant.POS_ORDER_ID, orderIdStr);
}
if (StringUtils.isBlank(posAmountStr)) {
if (StringUtils.isBlank(orderAmountStr)) {
errParam(WxPayConstant.ORDER_AMOUNT);
} else {
retMap.put(WxPayConstant.ORDER_AMOUNT, orderAmountStr);
}
if (StringUtils.isBlank(orderAmountLeftStr)) {
errParam(WxPayConstant.ORDER_AMOUNT_LEFT);
} else {
retMap.put(WxPayConstant.ORDER_AMOUNT_LEFT, orderCreateSN);
}
if (StringUtils.isBlank(orderCreateSN)) {
errParam(WxPayConstant.ORDER_CREATE_SN);
} else {
retMap.put(WxPayConstant.ORDER_CREATE_SN, orderAmountLeftStr);
}
if (StringUtils.isBlank(paymentInfoStr)) {
errParam(WxPayConstant.PAYMENT_INFO);
}

JSONObject paymentInfo = JSON.parseObject(paymentInfoStr);
if (paymentInfo == null) {
errParam(WxPayConstant.PAYMENT_INFO);
}
String cardIdStr = paymentInfo.getString(WxPayConstant.CARD_ID);
if (StringUtils.isBlank(cardIdStr)) {
errParam(WxPayConstant.CARD_ID);
errParam(WxPayConstant.PAYMENT_INFO);
}
String cardSpendIdStr = paymentInfo.getString(WxPayConstant.CARD_SPEND_ID);
if (StringUtils.isBlank(cardSpendIdStr)) {
errParam(WxPayConstant.CARD_SPEND_ID);
errParam(WxPayConstant.PAYMENT_INFO);
}
String amountPaidByCardStr = paymentInfo.getString(WxPayConstant.AMOUNT_PAID_BY_CARD);
if (StringUtils.isBlank(amountPaidByCardStr)) {
errParam(WxPayConstant.PAYMENT_INFO);
}
String amountLeftAfterPayStr = paymentInfo.getString(WxPayConstant.AMOUNT_LEFT_AFTER_PAY);
if (StringUtils.isBlank(amountLeftAfterPayStr)) {
errParam(WxPayConstant.PAYMENT_INFO);
}

Long merchantId, buUserId, posOrderId, cardId, cardSpendId;
Integer posAmount = 0;
Integer amountPaidByCard, amountLeftAfterPay;
try {
merchantId = Long.valueOf(merchantIdStr);
buUserId = Long.valueOf(buUserIdStr);
posOrderId = Long.valueOf(posOrderIdStr);
posAmount = Integer.valueOf(posAmountStr);
posOrderId = Long.valueOf(orderIdStr);
cardId = Long.valueOf(cardIdStr);
cardSpendId = Long.valueOf(cardSpendIdStr);
amountPaidByCard = Integer.valueOf(amountLeftAfterPayStr);
amountLeftAfterPay = Integer.valueOf(amountLeftAfterPayStr);
} catch (NumberFormatException e) {
logger.error(e.getMessage());
throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage());
}
WxCardInfo cardInfo = cardInfoService.getById(cardId);
if(cardInfo == null) {
String errMessage = "卡不存在: " + cardIdStr;
logger.error(errMessage);
throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND.getCode(), errMessage);
}
WxCouponMerchant couponMerchant = cardSpendService.checkMerchantInCoupon(cardInfo, merchantId);
if(couponMerchant == null) {
String errMessage = "商户不支持此卡 " + cardIdStr;
logger.error(errMessage);
throw new MallinkException(ErrorCode.COUPON_ORDER_MERANT_IS_NULL.getCode(), errMessage);
}
// 2. check merchant
WxMerchant merchant = checkAndGetMerchant(merchantId);
// 3. check buUser
@@ -1597,24 +1644,28 @@ public class PosServiceImpl implements PosService {
throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND);
}

WxCardInfo cardInfo = checkAndGetCardinfo(cardId, merchantId);

WxCardSpend record = cardSpendService.getById(cardSpendId);
if (record == null) {
logger.error(ErrorCode.CARD_SPEND_IS_NOT_FOUND.getMessage() + ": " + cardSpendIdStr);
throw new MallinkException(ErrorCode.CARD_SPEND_IS_NOT_FOUND);
}
if (record.getPayStatus().equals(EnumCardSpendStatus.PREV_PAY.getCode())) {
logger.error(ErrorCode.POS_CAR_PAY_NOT_CANCEL.getMessage());
throw new MallinkException(ErrorCode.POS_CAR_PAY_NOT_CANCEL);
if (!record.getPayStatus().equals(EnumCardSpendStatus.PREV_PAY.getCode())) {
logger.error(ErrorCode.POS_CARD_PAY_NOT_CANCEL.getMessage());
throw new MallinkException(ErrorCode.POS_CARD_PAY_NOT_CANCEL);
}

try {
WxCardInfo updateCardInfo = cardSpendService.cardSpendForPosPrePayCancel(cardInfo, record);
JSONObject retObj = new JSONObject();
retObj.put(WxPayConstant.CARD_ID, cardId);
retObj.put(WxPayConstant.ORG_REMAIN_AMOUNT, cardInfo.getRemainingAmount());
retObj.put(WxPayConstant.REMAIN_AMOUNT, updateCardInfo.getRemainingAmount());
retObj.put(WxPayConstant.CANCEL, WxPayConstant.TRUE);
retMap.put(WxPayConstant.RET, JSON.toJSONString(retObj));
JSONObject refundObj = new JSONObject();
refundObj.put(WxPayConstant.CARD_ID, cardIdStr);
refundObj.put(WxPayConstant.CARD_REFUND_RESULT, "0");
refundObj.put(WxPayConstant.REFUND_RESULT_MSG, "卡支付撤销成功");
refundObj.put(WxPayConstant.REFUND_TIME_FROM_IFORMALL, neuDateFormat.format(new Date()));
refundObj.put(WxPayConstant.AMOUNT_PAID_BY_CARD, 0);
refundObj.put(WxPayConstant.AMOUNT_LEFT_AFTER_PAY, amountLeftAfterPay + record.getDeductionAmount());
retMap.put(WxPayConstant.CARD_REFUND_RESULT, JSON.toJSONString(refundObj));
} catch (MallinkException e) {
logger.error("card spend error, req 2: " + record.toString() + ", e:" + e.getMessage());
throw new MallinkException(e.getErrorCode(), e.getMessage());
@@ -1626,6 +1677,23 @@ public class PosServiceImpl implements PosService {
return retMap;
}

private WxCardInfo checkAndGetCardinfo(Long cardId, Long merchantId) {
WxCardInfo cardInfo = cardInfoService.getById(cardId);
if(cardInfo == null) {
String errMessage = "卡不存在: " + cardId;
logger.error(errMessage);
throw new MallinkException(ErrorCode.CARD_IS_NOT_FOUND.getCode(), errMessage);
}

WxCouponMerchant couponMerchant = cardSpendService.checkMerchantInCoupon(cardInfo, merchantId);
if(couponMerchant == null) {
String errMessage = "商户不支持此卡 " + cardId;
logger.error(errMessage);
throw new MallinkException(ErrorCode.COUPON_ORDER_MERANT_IS_NULL.getCode(), errMessage);
}
return cardInfo;
}

@Override
@Transactional(rollbackFor = Exception.class)
public JSONObject posOrderSync(Map<String, String> params) throws MallinkException {


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

@@ -8,7 +8,6 @@ import com.iformall.PosApplication;
import com.iformall.enums.EnumPosSceneType;
import com.iformall.pay.WxPayConstant;
import com.iformall.pay.WxPayment;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
@@ -185,53 +184,6 @@ public class PosAppTest {
boolean resSigned = sendAndRes("/queryAndCalc", reqObj);
Assert.assertEquals(resSigned, true);
}
/*
@Test
public void getPosMemConfigTest() 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);
boolean resSigned = sendAndRes("/getPosMemConfig", reqObj);
Assert.assertEquals(resSigned, true);
}

@Test
public void getQrCodeTest() 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);
boolean resSigned = sendAndRes("/getQrCode", reqObj);
Assert.assertEquals(resSigned, true);
}

@Test
public void checkMemTest() throws Exception {
String memId = "321178010928119808";
String phone = "13910154397";
String posOrderId = "1";
String posAmount = "200";
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_ORDER_ID, posOrderId);
reqObj.put(WxPayConstant.ORDER_AMOUNT, posAmount);
boolean resSigned = sendAndRes("/checkMem", reqObj);
Assert.assertEquals(resSigned, true);
}
*/



@Test
public void verifyTest() throws Exception {
@@ -407,136 +359,57 @@ public class PosAppTest {
Assert.assertEquals(resSigned, true);
}

@Test
public void couponOrderPreVerifyTest() throws Exception {
String couponOrderId = "321877927162249216";
String posOrderId = "1";
String posAmount = "200";
doPreVerify(couponOrderId, posOrderId, posAmount);
}

@Test
public void couponOrderPreVerifyCancelTest() throws Exception {
String couponOrderId = "321877927162249216";
String posOrderId = "1";
doPreVerifyCancel(couponOrderId, posOrderId);
}

@Test
public void couponOrderPayVerifyTest() throws Exception {
String couponOrderId = "321877927162249216";
String posOrderId = "1";
String posAmount = "200";
doPayVerifyOne(couponOrderId, posOrderId, posAmount);
}

@Test
public void couponOrderPayVerifyListTest() throws Exception {
String couponOrderIdList = "[\"321878223800205312\"]";
String posOrderId = "1";
String posAmount = "200";
doPayVerifyList(couponOrderIdList, posOrderId, posAmount);
}

@Test
public void cardPayPreTest() throws Exception {
String cardId = "321883878446825472";
String sceneType = "1"; // 支付
String posOrderId = "1";
String posAmount = "200";
doCardPayPre(cardId, posOrderId, posAmount);
}

@Test
public void cardPayPreCancelTest() throws Exception {
String cardId = "321883878446825472";
String posOrderId = "1";
String cardSpendId = "1";
doCardPayPreCancel(cardId, cardSpendId, posOrderId);
}

private void doPreVerify(String couponOrderId, String posOrderId, String posAmount) throws Exception {
String orderAmount = "2000";
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);
reqObj.put(WxPayConstant.COUPON_ORDER_ID, couponOrderId);
reqObj.put(WxPayConstant.POS_ORDER_ID, posOrderId);
reqObj.put(WxPayConstant.ORDER_AMOUNT, posAmount);
boolean resSigned = sendAndRes("/couponOrderPreVerify", reqObj);
Assert.assertEquals(resSigned, true);
}


private void doPreVerifyCancel(String couponOrderId, String posOrderId) 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);
reqObj.put(WxPayConstant.COUPON_ORDER_ID, couponOrderId);
reqObj.put(WxPayConstant.POS_ORDER_ID, posOrderId);
boolean resSigned = sendAndRes("/couponOrderPreVerifyCancel", reqObj);
Assert.assertEquals(resSigned, true);
}

private void doPayVerifyOne(String couponOrderId, 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);
reqObj.put(WxPayConstant.COUPON_ORDER_ID, couponOrderId);
reqObj.put(WxPayConstant.SCENE_TYPE, sceneType);
reqObj.put(WxPayConstant.POS_ORDER_ID, posOrderId);
reqObj.put(WxPayConstant.ORDER_AMOUNT, posAmount);
boolean resSigned = sendAndRes("/couponOrderPayVerifyOne", reqObj);
reqObj.put(WxPayConstant.ORDER_AMOUNT, orderAmount);
reqObj.put(WxPayConstant.ORDER_AMOUNT_LEFT, orderAmount);
reqObj.put(WxPayConstant.NEU_ORDER_CREATE_SN, posSN);
reqObj.put(WxPayConstant.CARD_ID, cardId);
reqObj.put(WxPayConstant.AMOUNT_PAID_BY_CARD, orderAmount);
boolean resSigned = sendAndRes("/cardPayPre", reqObj);
Assert.assertEquals(resSigned, true);
}
}

private void doPayVerifyList(String couponOrderIdList, String posOrderId, String posAmount) throws Exception {
@Test
public void cardPayPreCancelTest() throws Exception {
String cardId = "321883878446825472";
String cardSpendId = "328803369448411136";
String sceneType = "1"; // 支付
String posOrderId = "1";
String orderAmount = "2000";
JSONObject paymentInfo = new JSONObject();
paymentInfo.put(WxPayConstant.CARD_ID, cardId);
paymentInfo.put(WxPayConstant.CARD_SPEND_ID, cardSpendId);
paymentInfo.put(WxPayConstant.ORDER_AMOUNT, orderAmount);
paymentInfo.put(WxPayConstant.ORDER_AMOUNT_LEFT, orderAmount);
paymentInfo.put(WxPayConstant.AMOUNT_PAID_BY_CARD, orderAmount);
paymentInfo.put(WxPayConstant.AMOUNT_LEFT_AFTER_PAY, "0");
Map<String, String> reqObj = new HashMap<>();
reqObj.put(WxPayConstant.NONCE_STR, "1");
reqObj.put(WxPayConstant.PAYMENT_INFO, JSON.toJSONString(paymentInfo));
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);
reqObj.put(WxPayConstant.COUPON_ORDER_LIST, couponOrderIdList);
reqObj.put(WxPayConstant.SCENE_TYPE, sceneType);
reqObj.put(WxPayConstant.POS_ORDER_ID, posOrderId);
reqObj.put(WxPayConstant.ORDER_AMOUNT, posAmount);
boolean resSigned = sendAndRes("/couponOrderPayVerifyList", reqObj);
Assert.assertEquals(resSigned, true);
}

private void doCardPayPre(String cardId, String posOrderId, String posAmount) 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);
reqObj.put(WxPayConstant.POS_ORDER_ID, posOrderId);
reqObj.put(WxPayConstant.ORDER_AMOUNT, posAmount);
reqObj.put(WxPayConstant.CARD_ID, cardId);
boolean resSigned = sendAndRes("/cardPayPre", reqObj);
Assert.assertEquals(resSigned, true);
}


private void doCardPayPreCancel(String cardId, String cardSpendId, String posOrderId) 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);
reqObj.put(WxPayConstant.POS_ORDER_ID, posOrderId);
reqObj.put(WxPayConstant.CARD_ID, cardId);
reqObj.put(WxPayConstant.CARD_SPEND_ID, cardSpendId);
reqObj.put(WxPayConstant.ORDER_AMOUNT, orderAmount);
reqObj.put(WxPayConstant.ORDER_AMOUNT_LEFT, orderAmount);
reqObj.put(WxPayConstant.ORDER_CREATE_SN, posSN);
boolean resSigned = sendAndRes("/cardPayPreCancel", reqObj);
Assert.assertEquals(resSigned, true);
Assert.assertEquals(resSigned, true);
}

private boolean sendAndRes(String url, Map<String, String> reqObj) throws Exception {


+ 7
- 5
mallinkService/src/main/java/com/iformall/common/ErrorCode.java Просмотреть файл

@@ -242,11 +242,13 @@ public enum ErrorCode{
POS_CONFIG_NOT_FOUND(11100, "POS会员相关未设置"),
POS_CONFIG_MEM_DISCOUNT_DISABLE(11101, "POS会员折扣未启用"),
POS_CONFIG_MEM_COUPON_DISABLE(11102, "POS会员优惠券未启用"),
POS_COUPON_ORDER_NOT_VERIFY(11103, "此券未核销"),
POS_COUPON_ORDER_VERIFY_NOT_CANCEL(11104, "此券核销无法取消"),
POS_COUPON_PAY_ERROR(11105, "POS券包支付异常"),
POS_CAR_PAY_NOT_CANCEL(11106, "卡支付无法取消"),
POS_COUPON_REFUND_ERROR(11105, "POS券包退款异常"),
POS_CONFIG_MEM_CARD_DISABLE(11103, "POS会员卡支付未启用"),
POS_COUPON_ORDER_NOT_VERIFY(11104, "此券未核销"),
POS_COUPON_ORDER_VERIFY_NOT_CANCEL(11105, "此券核销无法取消"),
POS_COUPON_PAY_ERROR(11106, "POS券包支付异常"),
POS_COUPON_REFUND_ERROR(11107, "POS券包退款异常"),
POS_CARD_PAY_NOT_CANCEL(11108, "卡支付无法取消"),
POS_CARD_ONLY_SUPPORT_PAY(11109, "卡支付只支持支付"),
POS_CMD_FAIL(11200, "POS命令错误"),




+ 1
- 0
mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java Просмотреть файл

@@ -1,6 +1,7 @@
package com.iformall.domain.po;

import cn.afterturn.easypoi.excel.annotation.Excel;
import com.iformall.common.ErrorCode;
import lombok.Data;
import lombok.EqualsAndHashCode;



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

@@ -36,13 +36,19 @@ public class WxPayConstant {
public final static String MEM_ID = "mem_id";
public final static String MEM_PHONE = "mem_phone_number";
public final static String CARD_ID = "card_id";
public final static String CARD_SPEND_ID = "card_spend_id";
public final static String AMOUNT_PAID_BY_CARD = "amount_paid_by_card";
public final static String CARD_AMOUNT_BEFORE_PAY = "card_amount_before_pay";
public final static String PAYMENT_AMOUNT = "payment_amount";
public final static String CARD_AMOUNT_AFTER_PAY = "card_amount_after_pay";
public final static String CARD_SPEND_ID = "payment_id_from_iformall";
public final static String CARD_SPEND_TIME = "payment_time_from_iformall";
public final static String PHONE = "phone";
public final static String PASSWORD = "password";
public final static String MEM_CONFIG = "mem_config";

public final static String PROMOTION_AMOUNT = "promotion_amount";
public final static String AMOUNT_LEFT_AFTER_PAY = "amount_left_after_pay";
public final static String CARD_PAYMENT_DATA = "card_payment_data";

public final static String TITLE = "title";
public final static String COVER_IMG = "cover_img";
@@ -55,7 +61,7 @@ public class WxPayConstant {
public final static String STATUS = "status";
public final static String STATUS_DES = "status_des";

public final static String SCENE_TYPE = "scene_type";
public final static String SCENE_TYPE = "business_type";
public final static String SCENE_VERIFY = "2";
public final static String SCENE_PAY = "1";

@@ -89,9 +95,10 @@ public class WxPayConstant {

public final static String COUPON_REFUND_RESULT = "coupon_refund_result";
public final static String COUPON_REFUND_ID = "coupon_refund_id";
public final static String COUPON_REFUND_RESULT_CODE = "result_code";
public final static String COUPON_REFUND_RESULT_MSG = "result_msg";
public final static String REFUND_RESULT_CODE = "result_code";
public final static String REFUND_RESULT_MSG = "result_msg";
public final static String REFUND_TIME_FROM_IFORMALL = "refund_time_from_iformall";
public final static String CARD_REFUND_RESULT = "card_refund_result";

public final static String COUPON_PROMOTION_AMOUNT = "coupon_promotion_amount";



+ 17
- 0
mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java Просмотреть файл

@@ -579,6 +579,22 @@ public class WxCardSpendServiceImpl implements WxCardSpendService {
throw new MallinkException(ErrorCode.SYS_MCH_NOT_FOUND);
}

// 查询是否有已有的
WxCardSpend oldCardSpend = null;
WxCardSpend cardSpendQ = new WxCardSpend();
cardSpendQ.setCardId(record.getCardId());
cardSpendQ.setPayFrom(EnumCardSpendFrom.POS.getCode());
cardSpendQ.setPosOrderId(record.getPosOrderId());
cardSpendQ.setPayStatus(EnumCardSpendStatus.PREV_PAY.getCode());
try {
oldCardSpend = wxCardSpendMapper.selectOne(cardSpendQ);
} catch (Exception e) {
logger.error(e.getMessage());
}
if (oldCardSpend != null) {
return oldCardSpend;
}

// 4. 扣减计算
Double paymentD = 1.0 * cardInfo.getSaleAmount() * record.getDeductionAmount() / cardInfo.getAmount();
Integer payment = paymentD.intValue();
@@ -591,6 +607,7 @@ public class WxCardSpendServiceImpl implements WxCardSpendService {
real_payment = Math.min(real_payment, cardInfo.getRemainingShareFeeAmount());
remain_real_pament = cardInfo.getRemainingShareFeeAmount() - real_payment;
}
// 4.1 TODO 是否已扣减??

// 5 insert card_spend
record.setId(idWorker.nextId());


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