|
|
|
@@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
import org.springframework.web.bind.annotation.RequestBody; |
|
|
|
import springfox.documentation.spring.web.json.Json; |
|
|
|
|
|
|
|
import java.text.ParseException; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
@@ -32,7 +33,7 @@ public class PosServiceImpl implements PosService { |
|
|
|
|
|
|
|
private final Logger logger = LoggerFactory.getLogger(this.getClass()); |
|
|
|
|
|
|
|
// neu时间格式, 4位年2位月2位日2位24小时制时2位分2位秒3位毫秒 |
|
|
|
// 东软时间格式, 4位年2位月2位日2位24小时制时2位分2位秒3位毫秒 时区+8 北京时间 |
|
|
|
private final SimpleDateFormat neuDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
|
|
|
private final SimpleDateFormat mydateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
|
|
|
|
|
|
|
@@ -705,10 +706,10 @@ public class PosServiceImpl implements PosService { |
|
|
|
return discountObj; |
|
|
|
} |
|
|
|
|
|
|
|
//@Override |
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public Map<String, String> couponOrderVerify(Map<String, String> params) throws MallinkException { |
|
|
|
Map<String, String> dataMap = new HashMap<>(); |
|
|
|
public JSONObject couponOrderVerify(Map<String, String> params) throws MallinkException { |
|
|
|
JSONObject dataMap = new JSONObject(); |
|
|
|
|
|
|
|
String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID |
|
|
|
String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID |
|
|
|
@@ -749,6 +750,7 @@ public class PosServiceImpl implements PosService { |
|
|
|
dataMap.put(WxPayConstant.ORDER_CREATE_SN, orderCreateSN); |
|
|
|
} |
|
|
|
|
|
|
|
// 0. 场景 |
|
|
|
Integer iSceneType; |
|
|
|
try { |
|
|
|
iSceneType = Integer.valueOf(sceneTypeStr); |
|
|
|
@@ -796,7 +798,7 @@ public class PosServiceImpl implements PosService { |
|
|
|
errParam(WxPayConstant.COUPON_ORDER_LIST); |
|
|
|
} |
|
|
|
JSONArray couponOrderArr = JSON.parseArray(coListStr); |
|
|
|
if (couponOrderArr.size() > 1) { |
|
|
|
if (couponOrderArr.size() != 1) { |
|
|
|
String errMessage = "核销只能使用一张券"; |
|
|
|
logger.error(errMessage); |
|
|
|
throw new MallinkException(ErrorCode.VERIFY_ERROR.getCode(), errMessage); |
|
|
|
@@ -929,8 +931,8 @@ public class PosServiceImpl implements PosService { |
|
|
|
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 selCoListStr = params.get(WxPayConstant.COUPON_ORDER_LIST); // 选中的优惠券列表 |
|
|
|
String posAmountStr = params.get(WxPayConstant.ORDER_AMOUNT); // POS订单总额(单位:分) |
|
|
|
String selCoListStr = params.get(WxPayConstant.COUPON_ORDER_LIST); // 选中的优惠券列表 |
|
|
|
Integer sceneType = EnumPosSceneType.PAY.getCode(); // 此接口只有支付使用 |
|
|
|
|
|
|
|
if (StringUtils.isBlank(tenantId)) { |
|
|
|
@@ -1280,48 +1282,78 @@ public class PosServiceImpl implements PosService { |
|
|
|
throw new MallinkException(500, errMessage); |
|
|
|
} |
|
|
|
|
|
|
|
//@Override |
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public Map<String, String> couponOrderVerifyCancel(Map<String, String> params, EnumPosActionType actionType) { |
|
|
|
Map<String, String> retMap = new HashMap<>(); |
|
|
|
public JSONObject couponOrderVerifyCancel(Map<String, String> params) { |
|
|
|
JSONObject retMap = new JSONObject(); |
|
|
|
|
|
|
|
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 couponOrderIdStr = params.get(WxPayConstant.COUPON_ORDER_ID); // 券ID |
|
|
|
String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID |
|
|
|
String sceneTypeStr = params.get(WxPayConstant.SCENE_TYPE); // 交易场景 |
|
|
|
String orderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID |
|
|
|
String paymentInfoStr = params.get(WxPayConstant.PAYMENT_INFO); // 优惠信息 |
|
|
|
|
|
|
|
if (StringUtils.isBlank(tenantId)) { |
|
|
|
errParam(WxPayConstant.TENANT_ID); |
|
|
|
} else { |
|
|
|
retMap.put(WxPayConstant.TENANT_ID, tenantId); |
|
|
|
} |
|
|
|
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(couponOrderIdStr)) { |
|
|
|
errParam(WxPayConstant.COUPON_ORDER_ID); |
|
|
|
if (StringUtils.isBlank(sceneTypeStr)) { |
|
|
|
errParam(WxPayConstant.SCENE_TYPE); |
|
|
|
} else { |
|
|
|
retMap.put(WxPayConstant.SCENE_TYPE, sceneTypeStr); |
|
|
|
} |
|
|
|
if (actionType.equals(EnumPosActionType.PAY_VERIFY_PRE) || actionType.equals(EnumPosActionType.VERIFY_INDEPENT)) { |
|
|
|
if (StringUtils.isBlank(posOrderIdStr)) { |
|
|
|
errParam(WxPayConstant.POS_ORDER_ID); |
|
|
|
} |
|
|
|
if (StringUtils.isBlank(orderIdStr)) { |
|
|
|
errParam(WxPayConstant.POS_ORDER_ID); |
|
|
|
} else { |
|
|
|
retMap.put(WxPayConstant.POS_ORDER_ID, orderIdStr); |
|
|
|
} |
|
|
|
if (StringUtils.isBlank(paymentInfoStr)) { |
|
|
|
errParam(WxPayConstant.PAYMENT_INFO); |
|
|
|
} |
|
|
|
|
|
|
|
Integer iSceneType; |
|
|
|
try { |
|
|
|
iSceneType = Integer.valueOf(sceneTypeStr); |
|
|
|
} catch (NumberFormatException e) { |
|
|
|
logger.error(e.getMessage()); |
|
|
|
throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR); |
|
|
|
} |
|
|
|
|
|
|
|
Long merchantId, buUserId, posOrderId = 0L; |
|
|
|
try { |
|
|
|
merchantId = Long.valueOf(merchantIdStr); |
|
|
|
buUserId = Long.valueOf(buUserIdStr); |
|
|
|
posOrderId = Long.valueOf(posOrderIdStr); |
|
|
|
posOrderId = Long.valueOf(orderIdStr); |
|
|
|
} 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); |
|
|
|
|
|
|
|
JSONObject paymentInfo = JSON.parseObject(paymentInfoStr); |
|
|
|
if (paymentInfo == null) { |
|
|
|
errParam(WxPayConstant.PAYMENT_INFO); |
|
|
|
} |
|
|
|
String couponOrderIdStr = paymentInfo.getString(WxPayConstant.COUPON_ID); |
|
|
|
if (StringUtils.isBlank(couponOrderIdStr)) { |
|
|
|
errParam(WxPayConstant.PAYMENT_INFO); |
|
|
|
} |
|
|
|
// 4. check couponOrderId |
|
|
|
WxCouponOrderCVo couponOrderCVo = couponOrderService.detailCUserVo(couponOrderIdStr); |
|
|
|
if (couponOrderCVo == null) { |
|
|
|
@@ -1341,61 +1373,72 @@ public class PosServiceImpl implements PosService { |
|
|
|
logger.error("券: coupon-" + couponOrderCVo.getCouponId() + "核销: couponMerchantId-" + merchantIdStr + " 门店不适用"); |
|
|
|
throw new MallinkException(ErrorCode.VERIFY_COUPON_ORDER_MERCHANT_IS_NULL); |
|
|
|
} |
|
|
|
|
|
|
|
// 5. 核销后无法反向 |
|
|
|
WxCoupon coupon = couponMapper.selectByPrimaryKey(couponOrderCVo.getCouponId()); |
|
|
|
if (coupon.getSalePrice() > 0 || |
|
|
|
(coupon.getSubsidyType() > EnumCouponSubsidyType.NO_SUBSIDY.getCode() && coupon.getSubsidyNum() > 0)) { |
|
|
|
logger.error("券包ID: " + couponOrderCVo.getId() + "核销无法退回"); |
|
|
|
logger.error("券包ID: " + couponOrderIdStr + "核销无法退回"); |
|
|
|
throw new MallinkException(ErrorCode.POS_COUPON_ORDER_VERIFY_NOT_CANCEL); |
|
|
|
} |
|
|
|
|
|
|
|
WxCouponOrder couponOrder = new WxCouponOrder(); |
|
|
|
couponOrder.setId(couponOrderCVo.getId()); |
|
|
|
|
|
|
|
// 预核销取消 |
|
|
|
if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode()) && |
|
|
|
actionType.equals(EnumPosActionType.PAY_VERIFY_PRE_CANCEL)) { |
|
|
|
logger.info("券已被预核销: " + couponOrderIdStr); |
|
|
|
if (!couponOrderCVo.getBUserId().equals(buUserId)) { |
|
|
|
logger.error(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL.getMessage() + ": " + buUserIdStr); |
|
|
|
throw new MallinkException(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL); |
|
|
|
} |
|
|
|
// 6. 核销撤销 |
|
|
|
if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()) && |
|
|
|
iSceneType.equals(EnumPosSceneType.VERIFY.getCode())) { |
|
|
|
logger.info("券已被核销无法取消: " + couponOrderIdStr); |
|
|
|
JSONObject refundObj = new JSONObject(); |
|
|
|
String errMesg = String.format("此券核销后无法退回, 券%s抵用%s元, 购买花费%s元", |
|
|
|
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_TIME_FROM_IFORMALL, neuDateFormat.format(new Date())); |
|
|
|
refundObj.put(WxPayConstant.PRICE, coupon.getPrice()); |
|
|
|
refundObj.put(WxPayConstant.SALE_PRICE, coupon.getSalePrice()); |
|
|
|
retMap.put(WxPayConstant.COUPON_REFUND_RESULT, JSON.toJSONString(refundObj)); |
|
|
|
return retMap; |
|
|
|
/* |
|
|
|
try { |
|
|
|
cancelPreVerify(couponOrderCVo, posOrderId); |
|
|
|
retMap.put(WxPayConstant.CANCEL, WxPayConstant.TRUE); |
|
|
|
cancelVerify(couponOrderCVo, buUserId, posOrderId); |
|
|
|
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_TIME_FROM_IFORMALL, neuDateFormat.format(new Date())); |
|
|
|
retMap.put(WxPayConstant.COUPON_REFUND_RESULT, JSON.toJSONString(refundObj)); |
|
|
|
return retMap; |
|
|
|
} catch (MallinkException e) { |
|
|
|
logger.error(e.getMessage()); |
|
|
|
throw new MallinkException(e.getErrorCode(), e.getMessage()); |
|
|
|
JSONObject refundObj = new JSONObject(); |
|
|
|
refundObj.put(WxPayConstant.COUPON_REFUND_ID, String.valueOf(couponOrderCVo.getId())); |
|
|
|
refundObj.put(WxPayConstant.COUPON_REFUND_RESULT, e.getErrorCode()); |
|
|
|
refundObj.put(WxPayConstant.COUPON_REFUND_RESULT_MSG, "核销撤销失败: " + e.getMessage()); |
|
|
|
refundObj.put(WxPayConstant.REFUND_TIME_FROM_IFORMALL, neuDateFormat.format(new Date())); |
|
|
|
retMap.put(WxPayConstant.COUPON_REFUND_RESULT, JSON.toJSONString(refundObj)); |
|
|
|
return retMap; |
|
|
|
} |
|
|
|
*/ |
|
|
|
} |
|
|
|
// 核销取消 |
|
|
|
if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()) && |
|
|
|
actionType.equals(EnumPosActionType.VERIFY_CANCEL)) { |
|
|
|
// 检查是否有发放的券, 有则无法退券 |
|
|
|
// 6. 预核销取消 |
|
|
|
else if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode()) && |
|
|
|
iSceneType.equals(EnumPosSceneType.PAY.getCode())) { |
|
|
|
logger.info("券已被预核销: " + couponOrderIdStr); |
|
|
|
if (!couponOrderCVo.getBUserId().equals(buUserId)) { |
|
|
|
logger.error(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL.getMessage() + ": " + buUserIdStr); |
|
|
|
throw new MallinkException(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL); |
|
|
|
} |
|
|
|
try { |
|
|
|
cancelVerify(couponOrderCVo, buUserId, posOrderId); |
|
|
|
cancelPreVerify(couponOrderCVo, posOrderId); |
|
|
|
retMap.put(WxPayConstant.CANCEL, WxPayConstant.TRUE); |
|
|
|
return retMap; |
|
|
|
} catch (MallinkException e) { |
|
|
|
logger.error(e.getMessage()); |
|
|
|
throw new MallinkException(e.getErrorCode(), e.getMessage()); |
|
|
|
} |
|
|
|
/* |
|
|
|
logger.info("券已被核销无法取消: " + couponOrderIdStr); |
|
|
|
retMap.put(WxPayConstant.CANCEL, WxPayConstant.FALSE); |
|
|
|
Map cancelMap = new HashMap(); |
|
|
|
cancelMap.put(WxPayConstant.PRICE, coupon.getPrice()); |
|
|
|
cancelMap.put(WxPayConstant.SALE_PRICE, coupon.getSalePrice()); |
|
|
|
retMap.put(WxPayConstant.CANCEL_JSON, JSON.toJSONString(cancelMap)); |
|
|
|
String errMessage = String.format("此券核销后无法退回,原价:%s元, 售价:%s元", coupon.getPriceStr(), coupon.getSalePriceStr()); |
|
|
|
// TODO 系统发放的券, 也加入核销信息中 |
|
|
|
retMap.put(WxPayConstant.CANCEL_DES, errMessage); |
|
|
|
return retMap; |
|
|
|
*/ |
|
|
|
} |
|
|
|
String errMessage = "取消异常:未知的核销状态-" + couponOrderCVo.getCouponOrderStatus()+ ", 核销action-" + actionType.getCode(); |
|
|
|
|
|
|
|
String errMessage = "取消异常:未知的核销状态-" + couponOrderCVo.getCouponOrderStatus()+ ", 场景-" + iSceneType; |
|
|
|
logger.error(errMessage); |
|
|
|
throw new MallinkException(500, errMessage); |
|
|
|
} |
|
|
|
|