From 47c752434caa50e59638afe4ec5e32f823208068 Mon Sep 17 00:00:00 2001 From: Cui Zhi Feng <7426394+wuxixiaocui@user.noreply.gitee.com> Date: 星期二, 08 十月 2024 17:13:21 +0800 Subject: [PATCH] 支付改造 --- src/main/resources/application-local.yml | 5 src/main/java/com/mzl/flower/config/SybPaymentProperties.java | 13 + src/main/java/com/mzl/flower/service/payment/OrderSalesService.java | 6 src/main/java/com/mzl/flower/web/payment/OrderController.java | 10 src/main/java/com/mzl/flower/service/payment/OrderService.java | 17 src/main/java/com/mzl/flower/schedule/ScheduleService.java | 8 src/main/java/com/mzl/flower/web/customer/OrderCustomerController.java | 33 +- src/main/resources/application-prod.yml | 5 src/main/resources/application-test.yml | 5 src/main/java/com/mzl/flower/web/customer/FlowerCustomerController.java | 2 src/main/java/com/mzl/flower/service/payment/OrderItemSalesService.java | 6 src/main/java/com/mzl/flower/web/payment/SalesController.java | 4 src/main/java/com/mzl/flower/service/payment/UserPaymentSybService.java | 548 +++++++++++++++++++++++++++++++++++++++++++++ src/main/resources/application-dev.yml | 5 src/main/java/com/mzl/flower/web/payment/PaymentCallBackSybResource.java | 28 ++ 15 files changed, 649 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/mzl/flower/config/SybPaymentProperties.java b/src/main/java/com/mzl/flower/config/SybPaymentProperties.java new file mode 100644 index 0000000..ebf4a00 --- /dev/null +++ b/src/main/java/com/mzl/flower/config/SybPaymentProperties.java @@ -0,0 +1,13 @@ +package com.mzl.flower.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties(prefix = "syb") +public class SybPaymentProperties { + + private String callBackUrl; +} diff --git a/src/main/java/com/mzl/flower/schedule/ScheduleService.java b/src/main/java/com/mzl/flower/schedule/ScheduleService.java index 765abb7..1cf50e6 100644 --- a/src/main/java/com/mzl/flower/schedule/ScheduleService.java +++ b/src/main/java/com/mzl/flower/schedule/ScheduleService.java @@ -46,6 +46,9 @@ private UserPaymentV3Service paymentV3Service; @Autowired + private UserPaymentSybService paymentSybService; + + @Autowired private OrderService orderService; @Autowired @@ -114,10 +117,11 @@ try { LocalDateTime createdTime = o.getCreateTime().plusMinutes(5); if (createdTime.isBefore(LocalDateTime.now())) { - boolean f = paymentV3Service.checkOrderStatus(o.getId()); + /*boolean f = paymentV3Service.checkOrderStatus(o.getId()); if(!f){ paymentV3Service.cancelOrder(o.getId()); - } + }*/ + paymentSybService.cancelOrder(o.getId()); } } catch (Exception e) { log.error(e.getMessage(), e); diff --git a/src/main/java/com/mzl/flower/service/payment/OrderItemSalesService.java b/src/main/java/com/mzl/flower/service/payment/OrderItemSalesService.java index 1be4b9b..7fddc66 100644 --- a/src/main/java/com/mzl/flower/service/payment/OrderItemSalesService.java +++ b/src/main/java/com/mzl/flower/service/payment/OrderItemSalesService.java @@ -50,7 +50,7 @@ private OrderItemMapper orderItemMapper; @Autowired - private UserPaymentV3Service paymentV3Service; + private UserPaymentSybService paymentSybService; @Autowired private SequenceNo sequenceNo; @@ -329,7 +329,7 @@ return rr; } - public OrderItem doAudit(OrderItemSalesAuditDTO dto, String status){ + public OrderItem doAudit(OrderItemSalesAuditDTO dto, String status) throws Exception { OrderItemSales sl = orderItemSalesMapper.selectById(dto.getId()); if(sl == null){ throw new ValidationException("售后单不存在"); @@ -447,7 +447,7 @@ if(Constants.ORDER_SALES_STATUS.AGREED.name().equals(sl.getStatus())){ if(totalFeeWithPacking.doubleValue() > 0) { - String refundId = paymentV3Service.refundOrderSub(o, totalFeeWithPacking); + String refundId = paymentSybService.refundOrderSub(o, totalFeeWithPacking); sl.setRefundId(refundId); } } diff --git a/src/main/java/com/mzl/flower/service/payment/OrderSalesService.java b/src/main/java/com/mzl/flower/service/payment/OrderSalesService.java index 684d00b..00b8b8f 100644 --- a/src/main/java/com/mzl/flower/service/payment/OrderSalesService.java +++ b/src/main/java/com/mzl/flower/service/payment/OrderSalesService.java @@ -55,7 +55,7 @@ private UserWechatMapper wechatMapper; @Autowired - private UserPaymentV3Service paymentV3Service; + private UserPaymentSybService paymentSybService; @Autowired private OrderRefundMapper orderRefundMapper; @@ -192,7 +192,7 @@ salesItemMapper.updateById(item); } - public void doAudit(OrderSalesAuditDTO dto){ + public void doAudit(OrderSalesAuditDTO dto) throws Exception { OrderSales s = salesMapper.selectById(dto.getId()); s.setAuditRemarks(dto.getAuditRemarks()); s.setAuditStatus(dto.getAuditStatus()); @@ -214,7 +214,7 @@ if(Constants.SALES_AUDIT_STATUS.AGREE.name().equals(s.getAuditStatus())){ if(totalAmount.doubleValue() > 0) { Order o = orderMapper.selectById(s.getOrderId()); - String transferId = paymentV3Service.refundOrderSub(o, totalAmount); + String transferId = paymentSybService.refundOrderSub(o, totalAmount); s.setTransferId(transferId); /*if(totalAmount.doubleValue() > o.getTotalAmount().doubleValue()){ diff --git a/src/main/java/com/mzl/flower/service/payment/OrderService.java b/src/main/java/com/mzl/flower/service/payment/OrderService.java index 47f3acb..2f84bb7 100644 --- a/src/main/java/com/mzl/flower/service/payment/OrderService.java +++ b/src/main/java/com/mzl/flower/service/payment/OrderService.java @@ -44,6 +44,7 @@ import com.mzl.flower.mapper.supplier.StationMapper; import com.mzl.flower.mapper.system.UserWechatMapper; import com.mzl.flower.mapper.warehouse.WarehouseLocationMapper; +import com.mzl.flower.pay.SybPayService; import com.mzl.flower.service.BaseService; import com.mzl.flower.service.comment.FlowerCommentService; import com.mzl.flower.service.coupon.CouponRecordService; @@ -99,6 +100,9 @@ @Autowired private UserPaymentV3Service paymentV3Service; + + @Autowired + private UserPaymentSybService paymentSybService; @Autowired private SequenceNo sequenceNo; @@ -453,7 +457,7 @@ } } - public Map commitOrder(OrderCommitDTO dto, PreOrderDTO p, Map<Long, PriceDTO> priceMap) { + public Map commitOrder(OrderCommitDTO dto, PreOrderDTO p, Map<Long, PriceDTO> priceMap) throws Exception { String userId = SecurityUtils.getUserId(); p.getFlowers().forEach(flower -> { // 限购数量 鲜花数量校验 @@ -620,8 +624,9 @@ } } - Map map = paymentV3Service.wxPrepay(order); + Map map = paymentSybService.prepay(order); map.put("_testV2OrderId", order.getId()); + return map; } @@ -1427,7 +1432,7 @@ return dto; } - public void processAbnormalOrder(String id) { + public void processAbnormalOrder(String id) throws Exception { Order o = orderMapper.selectById(id); String transferId = o.getTransferId(); if (StringUtils.isNotEmpty(transferId)) { @@ -1466,13 +1471,13 @@ transferId = "NoNeedRefund"; if (deductAmount.doubleValue() > 0) { - transferId = paymentV3Service.refundOrderSub(o, deductAmount); + transferId = paymentSybService.refundOrderSub(o, deductAmount); } o.setTransferId(transferId); orderMapper.updateById(o); } - public void processLevelDown(OrderReduceDTO dto) { + public void processLevelDown(OrderReduceDTO dto) throws Exception { Order o = orderMapper.selectById(dto.getId()); String transferId = o.getTransferId(); if (StringUtils.isNotEmpty(transferId)) { @@ -1487,7 +1492,7 @@ } BigDecimal amount = dto.getAmount(); - transferId = paymentV3Service.refundOrderSub(o, amount); + transferId = paymentSybService.refundOrderSub(o, amount); o.setTransferId(transferId); o.setTransferTime(LocalDateTime.now()); o.update(SecurityUtils.getUserId()); diff --git a/src/main/java/com/mzl/flower/service/payment/UserPaymentSybService.java b/src/main/java/com/mzl/flower/service/payment/UserPaymentSybService.java new file mode 100644 index 0000000..b53e9c1 --- /dev/null +++ b/src/main/java/com/mzl/flower/service/payment/UserPaymentSybService.java @@ -0,0 +1,548 @@ +package com.mzl.flower.service.payment; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.mzl.flower.config.SybPaymentProperties; +import com.mzl.flower.config.exception.ValidationException; +import com.mzl.flower.config.security.SecurityUtils; +import com.mzl.flower.constant.Constants; +import com.mzl.flower.dto.request.payment.UserPaymentDTO; +import com.mzl.flower.entity.flower.Flower; +import com.mzl.flower.entity.payment.*; +import com.mzl.flower.mapper.flower.FlowerMapper; +import com.mzl.flower.mapper.payment.*; +import com.mzl.flower.pay.SybConstants; +import com.mzl.flower.pay.SybPayService; +import com.mzl.flower.pay.SybUtil; +import com.mzl.flower.service.BaseService; +import com.mzl.flower.service.coupon.CouponRecordService; +import com.mzl.flower.service.flower.FlowerService; +import com.mzl.flower.service.point.PointGoodsService; +import com.mzl.flower.utils.UUIDGenerator; +import io.micrometer.core.instrument.util.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +@Service +@Transactional +@Slf4j +public class UserPaymentSybService extends BaseService { + + @Autowired + private UserPaymentMapper userPaymentMapper; + + @Autowired + private RedisLockService lockService; + + @Autowired + private OrderMapper orderMapper; + + @Autowired + private OrderItemMapper orderItemMapper; + + @Autowired + private FlowerMapper flowerMapper; + + @Autowired + private FlowerService flowerService; + + @Autowired + private DeliveryOrderService deliveryOrderService; + + @Autowired + private OrderRefundMapper orderRefundMapper; + + @Autowired + private OrderPointGoodsMapper orderPointGoodsMapper; + + @Autowired + private PointGoodsService pointGoodsService; + + @Autowired + private CouponRecordService couponRecordService; + + @Autowired + private OrderService orderService; + + @Autowired + private SybPaymentProperties sybPaymentProperties; + + /** + * 通联支付 + * + * @param order + * @return + */ + public Map prepay(Order order) throws Exception { + String userId = SecurityUtils.getUserId(); + UserPayment up = prepareUserPayment(userId, order); + log.info("UserPayment: " + toJSONString(up)); + + SybPayService service = new SybPayService(); + long trxamt = prepareAmount(up.getPaymentAmount()); + String reqsn = order.getId(); + String unireqsn = ""; + String body = "通联支付"; + String remark = "通联支付"; + String notifyUrl = sybPaymentProperties.getCallBackUrl() + "/flower/api/ua/notify/syb/paid"; + + // 调用接口 + Map map = service.createOrder(trxamt, reqsn, unireqsn, body, remark, notifyUrl); + + up.setPrepayResponse(toJSONString(map)); + + userPaymentMapper.insert(up); + + return map; + } + + private Integer prepareAmount(BigDecimal amount){ + return amount.multiply(new BigDecimal(100)).intValue(); + } + + private UserPayment prepareUserPayment(String userId, Order order){ + UserPayment up = new UserPayment(); + up.setId(UUIDGenerator.getUUID()); + up.setUserId(userId); + up.setOrderId(order.getId()); + up.setPaymentAmount(order.getTotalAmount()); + up.setPaymentTime(LocalDateTime.now()); + up.create(userId); + + return up; + } + + /** + * 动态遍历获取所有收到的参数,此步非常关键,因为收银宝以后可能会加字段,动态获取可以兼容由于收银宝加字段而引起的签名异常 + * @param request + * @return + */ + private TreeMap<String, String> getParams(HttpServletRequest request){ + TreeMap<String, String> map = new TreeMap<>(); + Map reqMap = request.getParameterMap(); + for(Object key:reqMap.keySet()){ + String value = ((String[])reqMap.get(key))[0]; + System.out.println(key+";"+value); + map.put(key.toString(),value); + } + return map; + } + + public String handlePayCallback(HttpServletRequest request) { + try { + request.setCharacterEncoding("UTF-8");//通知传输的编码为GBK + TreeMap<String,String> params = getParams(request);//动态遍历获取所有收到的参数,此步非常关键,因为收银宝以后可能会加字段,动态获取可以兼容 + + String appkey = ""; + if("RSA".equals(params.get("signtype"))) + appkey = SybConstants.SYB_RSATLPUBKEY; + else if("SM2".equals(params.get("signtype"))) + appkey = SybConstants.SYB_SM2TLPUBKEY; + else + appkey = SybConstants.SYB_MD5_APPKEY; + boolean isSign = SybUtil.validSign(params, appkey, params.get("signtype"));// 接受到推送通知,首先验签 + log.info("验签结果:" + isSign); + + //验签完毕进行业务处理 + if(isSign){ + String originalXml = toJSONString(params); + log.info("transaction: " + originalXml); + String outTradeNo = params.get("cusorderid");//统一下单对应的reqsn订单号 + String transactionId = params.get("trxid");//通联收银宝交易流水号 + String orderId = outTradeNo; + Integer trxamt = Integer.parseInt(params.get("trxamt"));//交易金额 单位:分 + log.info("======trxamt: " + trxamt); + + String trxstatus = params.get("trxstatus");//支付状态 + String status = Constants.PAYMENT_STATUS.FAILED.name(); + //交易状态详见交易返回码说明 + /*0000:交易成功 + 错误码为空: 交易处理中,请查询交易,如果是实时交易(例如刷卡支付,交易撤销,退货),建议每隔一段时间(例如30秒)查询交易 + 1001:交易不存在 + 2008或者2000 : 交易处理中,请查询交易,如果是实时交易(例如刷卡支付,交易撤销,退货),建议每隔一段时间(10秒)查询交易 + 3开头的错误码代表交易失败 + 3888-流水号重复 + 3889-交易控制失败,具体原因看errmsg + 3099-渠道商户错误 + 3014-交易金额小于应收手续费 + 3031-校验实名信息失败 + 3088-交易未支付(在查询时间区间内未成功支付,如已影响资金24小时内会做差错退款处理) + 3089-撤销异常,如已影响资金24小时内会做差错退款处理 + 3045-其他错误,具体原因看errmsg + 3999-其他错误,具体原因看errmsg + 其他3开头的错误码代表交易失败,具体原因请读取errmsg + */ + if ("0000".equals(trxstatus)){ + status = Constants.PAYMENT_STATUS.SUCCESS.name(); + } + + UserPaymentDTO dto = new UserPaymentDTO(); + dto.setOrderId(orderId); + dto.setTransactionId(transactionId); + dto.setOutTradeNo(outTradeNo); + dto.setOriginalXml(originalXml); + dto.setPaymentAmountCallback(trxamt + ""); + dto.setStatus(status); + + saveCallbackInfo(dto, Constants.ORDER_STATUS_BACKEND.PAYMENT.name()); + } + } catch (Exception e) { + log.error("解析付款通知出错:{}", e.getMessage(), e); + } + + return "success"; + } + + public void saveCallbackInfo(UserPaymentDTO dto, String orderStatus){ + String orderId = dto.getOrderId(); + boolean lock = lockService.getObjectLock(RedisLockService.LOCK_KEY_PAYMENT_NOTIFY_, orderId); + if(!lock){ + return; + } + + try { + UserPayment up = userPaymentMapper.selectOne( + new QueryWrapper<UserPayment>().eq("order_id", orderId)); + BeanUtils.copyProperties(dto, up); + + up.setPaymentTimeCallback(LocalDateTime.now()); + userPaymentMapper.updateById(up); + + Order order = orderMapper.selectById(orderId); + if(Constants.ORDER_STATUS_BACKEND.PAYMENT.name().equals(orderStatus)) { + order.setPaymentTrId(dto.getTransactionId()); + if (up.getPaymentAmountCallback() != null) { + order.setPaymentAmount(new BigDecimal(up.getPaymentAmountCallback()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));//转换成单位元 + } else { + order.setPaymentAmount(order.getTotalAmount()); + } + order.setPaymentTime(up.getPaymentTimeCallback()); + order.setStatus(Constants.ORDER_STATUS.SEND.name()); + } else if (Constants.ORDER_STATUS_BACKEND.CANCEL.name().equals(orderStatus)){ + order.setStatus(Constants.ORDER_STATUS.CANCEL.name()); + } + order.setStatusBackend(orderStatus); + orderMapper.updateById(order); + + if(Constants.ORDER_STATUS_BACKEND.PAYMENT.name().equals(orderStatus)) { + postPayment(order); + } else if (Constants.ORDER_STATUS_BACKEND.CANCEL.name().equals(orderStatus)){ + releasePrepayLock(order); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + lockService.releaseObjectLock(RedisLockService.LOCK_KEY_PAYMENT_NOTIFY_, orderId); + } + } + + private void postPayment(Order order){ + log.info("回调后处理订单信息:" + toJSONString(order)); + //创建配送单 + deliveryOrderService.createDeliveryOrder(order); + flowerService.updateFlowerSales(order); + } + + public boolean checkOrderStatusPayAgain(String outTradeNo) throws Exception { + UserPayment up = userPaymentMapper.selectOne( + new QueryWrapper<UserPayment>().eq("order_id", outTradeNo)); + String s = up.getStatus(); + if(StringUtils.isNotEmpty(s)){ + return true; + } + + SybPayService service = new SybPayService(); + Map<String,String> params = service.query(outTradeNo, up.getTransactionId()); + + String originalXml = toJSONString(params);//回调请求内容 + log.info("message: " + originalXml); + String transactionId = params.get("trxid");//通联收银宝交易流水号 + String orderId = outTradeNo; + + String trxcode = params.get("trxcode"); + /* 交易类型 + VSP501:微信支付 + VSP502:微信支付撤销 + VSP503:微信支付退款 + */ + String trxstatus = params.get("trxstatus");//支付状态 + if("VSP501".equals(trxcode) && "0000".equals(trxstatus)){ + String status = Constants.PAYMENT_STATUS.SUCCESS.name(); + UserPaymentDTO dto = new UserPaymentDTO(); + dto.setOrderId(orderId); + dto.setTransactionId(transactionId); + dto.setOutTradeNo(outTradeNo); + dto.setOriginalXml(originalXml); + String trxamtStr = params.get("trxamt");//交易金额 单位:分 + log.info("======trxamt: " + trxamtStr); + dto.setPaymentAmountCallback(trxamtStr); + + dto.setStatus(status); + + String orderStatus = Constants.ORDER_STATUS_BACKEND.PAYMENT.name(); + + saveCallbackInfo(dto, orderStatus); + + return true; + } + + return !("2008".equals(trxstatus) || "2000".equals(trxstatus)); + } + + public boolean checkOrderStatusRefund(String outTradeNo) throws Exception { + UserPayment up = userPaymentMapper.selectOne( + new QueryWrapper<UserPayment>().eq("order_id", outTradeNo)); + String s = up.getStatus(); + if(StringUtils.isEmpty(s)){ + return true; + } + + SybPayService service = new SybPayService(); + Map<String,String> params = service.query(outTradeNo, up.getTransactionId()); + + String originalXml = toJSONString(params);//回调请求内容 + log.info("message: " + originalXml); + + String trxcode = params.get("trxcode"); + /* 交易类型 + VSP501:微信支付 + VSP502:微信支付撤销 + VSP503:微信支付退款 + */ + if ("VSP502".equals(trxcode)|| "VSP503".equals(trxcode)){ + String trxid = params.get("trxid"); + updateOrderRefund(outTradeNo, trxid); + + return true; + } + + return false; + } + + public void cancelOrder(String orderId) throws Exception { + UserPayment up = userPaymentMapper.selectOne( + new QueryWrapper<UserPayment>().eq("order_id", orderId)); + if(StringUtils.isNotEmpty(up.getStatus())){ + throw new ValidationException("订单不可取消"); + } + + SybPayService service = new SybPayService(); + Map<String,String> map = service.close(null, orderId); + log.info("======关闭订单结果" + toJSONString(map)); + + String retcode = map.get("retcode"); + if(!"SUCCESS".equals(retcode)){ + throw new ValidationException("取消订单失败: " + map.get("retmsg")); + } + + Order order = orderMapper.selectById(orderId); + order.setStatus(Constants.ORDER_STATUS.CANCEL.name()); + order.setStatusBackend(Constants.ORDER_STATUS_BACKEND.CANCEL.name()); + order.setCancelTime(LocalDateTime.now()); + order.update(SecurityUtils.getUserId()); + orderMapper.updateById(order); + + up.setStatus(Constants.PAYMENT_STATUS.CLOSED.name()); + up.update(SecurityUtils.getUserId()); + userPaymentMapper.updateById(up); + + releasePrepayLock(order); + } + + private void releasePrepayLock(Order order){ + log.info("恢复库存 积分商品兑换券 优惠券: " + order); + revertFlowerStock(order.getId()); + + //恢复积分商品兑换券 + revertPointGoodsRecord(order.getId()); + + //恢复优惠券 + String memberCouponId = order.getMemberCouponId(); + if(StringUtils.isNotEmpty(memberCouponId)) { + couponRecordService.cancelCouponUsage(order.getId()); + } + } + + private void revertPointGoodsRecord(String orderId){ + List<OrderPointGoods> ls = orderPointGoodsMapper.selectList(new QueryWrapper<OrderPointGoods>() + .eq("order_id", orderId)); + if(ls != null && ls.size() > 0){ + for(OrderPointGoods pg : ls){ + pointGoodsService.revertExchangeGoods(pg.getGoodsRecordId()); + } + } + } + + public Map payAgain(String orderId){ + // 获取订单里面的商品是否有限购的,如果有则判断是否已经超过限购数量 + List<OrderItem> orderItemList = orderItemMapper.selectList(new QueryWrapper<OrderItem>() + .eq("order_id", orderId)); + + orderItemList.forEach(orderItem -> { + // 限购数量 鲜花数量校验 + Integer completeNumToday=orderService.getFlowerCompleteNumToday(orderItem.getCreateBy(),orderItem.getFlowerId()); + Integer tmp=completeNumToday+orderItem.getNum(); + Flower flower=flowerMapper.selectById(orderItem.getFlowerId()); + if(null!=flower.getLimited() && tmp.compareTo(flower.getLimited())>0){ + throw new ValidationException("商品:'"+flower.getName()+"' 昨天17:00到今天17:00 超过限售数量:"+flower.getLimited()+"!"); + } + }); + + UserPayment up = userPaymentMapper.selectOne( + new QueryWrapper<UserPayment>().eq("order_id", orderId)); + if(StringUtils.isNotEmpty(up.getStatus())){ + throw new ValidationException("订单不可再支付"); + } + + return parseObject(up.getPrepayResponse(), TreeMap.class); + } + + public synchronized void revertFlowerStock(String orderId){ + List<OrderItem> ls = orderItemMapper.selectList(new QueryWrapper<OrderItem>() + .eq("order_id", orderId)); + for(OrderItem c : ls){ + flowerMapper.addFlowerStock(c.getFlowerId(), c.getNum()); + } + } + + public void refundOrderCustomer(String orderId) throws Exception { + UserPayment up = userPaymentMapper.selectOne( + new QueryWrapper<UserPayment>().eq("order_id", orderId)); + if(up.getPaymentAmount() == null){ + throw new ValidationException("订单不可退款"); + } + + long trxamt = up.getPaymentAmount().longValue(); + String reqsn = orderId; + String oldtrxid = up.getTransactionId(); + String oldreqsn = null; + + SybPayService service = new SybPayService(); + Map<String,String> map = service.cancel(trxamt, reqsn, oldtrxid, oldreqsn); + String retcode = map.get("retcode"); + if(!"SUCCESS".equals(retcode)){ + throw new ValidationException("订单退款失败: " + map.get("retmsg")); + } + + updateOrderRefund(orderId, oldtrxid); + } + + /** + * 退款 + * + * @param orderId + */ + public void refundOrder(String orderId) throws Exception { + UserPayment up = userPaymentMapper.selectOne( + new QueryWrapper<UserPayment>().eq("order_id", orderId)); + if(up.getPaymentAmount() == null){ + throw new ValidationException("订单不可退款"); + } + + long trxamt = up.getPaymentAmount().longValue(); + String reqsn = orderId; + String oldtrxid = up.getTransactionId(); + String oldreqsn = null; + + SybPayService service = new SybPayService(); + Map<String,String> map = service.refund(trxamt, reqsn, oldtrxid, oldreqsn); + String retcode = map.get("retcode"); + if(!"SUCCESS".equals(retcode)){ + throw new ValidationException("订单退款失败: " + map.get("retmsg")); + } + + updateOrderRefund(orderId, oldtrxid); + } + + private void updateOrderRefund(String orderId, String refundNo){ + Order o = orderMapper.selectById(orderId); + + if(Constants.ORDER_STATUS.REFUND.name().equals(o.getStatus())){ + return; + } + + o.setRefundAmount(o.getPaymentAmount()); + o.setRefundNo(refundNo); + o.setRefundTime(LocalDateTime.now()); + + o.setStatus(Constants.ORDER_STATUS.REFUND.name()); + o.setStatusBackend(Constants.ORDER_STATUS_BACKEND.REFUND.name()); + o.update("sys"); + + orderMapper.updateById(o); + + deliveryOrderService.refundDelete(orderId); + + releasePrepayLock(o); + } + + public String refundOrderSub(Order o, BigDecimal refundAmount) throws Exception { + if(o.getPaymentTime() == null || o.getPaymentAmount() == null){ + throw new ValidationException("未支付订单不可退款"); + } + + if(o.getRefundTime() != null){ + throw new ValidationException("已全额退款订单不可退款"); + } + + if (refundAmount == null || refundAmount.doubleValue() == 0) { + throw new ValidationException("退款金额不能为空"); + } + + List<OrderRefund> reLs = orderRefundMapper.selectList(new QueryWrapper<OrderRefund>() + .eq("order_id", o.getId())); + BigDecimal rra = new BigDecimal(0); + if(reLs != null && reLs.size() > 0){ + for(OrderRefund r : reLs){ + rra = rra.add(r.getRefundAmount()); + } + } + + long total = (long)prepareAmount(o.getPaymentAmount()); + long refund = (long)prepareAmount(refundAmount); + + long rraa = (long)prepareAmount(rra); + if(rraa + refund > total){ + throw new ValidationException("退款金额不能大于订单金额"); + } + + OrderRefund re = new OrderRefund(); + re.setId(UUIDGenerator.getUUID()); + re.setOrderId(o.getId()); + re.setOrderAmount(o.getPaymentAmount()); + re.setRefundAmount(refundAmount); + + UserPayment up = userPaymentMapper.selectOne( + new QueryWrapper<UserPayment>().eq("order_id", o.getId())); + + long trxamt = refund; + String reqsn = o.getId(); + String oldtrxid = up.getTransactionId(); + String oldreqsn = null; + + SybPayService service = new SybPayService(); + Map<String,String> map = service.refund(trxamt, reqsn, oldtrxid, oldreqsn); + String retcode = map.get("retcode"); + if(!"SUCCESS".equals(retcode)){ + throw new ValidationException("订单退款失败: " + map.get("retmsg")); + } + + re.setRequest(toJSONString(map)); + re.create(SecurityUtils.getUserId()); + + orderRefundMapper.insert(re); + + return re.getId(); + } + +} diff --git a/src/main/java/com/mzl/flower/web/customer/FlowerCustomerController.java b/src/main/java/com/mzl/flower/web/customer/FlowerCustomerController.java index e29a410..1062f85 100644 --- a/src/main/java/com/mzl/flower/web/customer/FlowerCustomerController.java +++ b/src/main/java/com/mzl/flower/web/customer/FlowerCustomerController.java @@ -169,7 +169,7 @@ @PostMapping("/order/commit") @ApiOperation(value = "提交订单") - public ResponseEntity<ReturnDataDTO<?>> commitOrder(@RequestBody OrderCommitDTO dto){ + public ResponseEntity<ReturnDataDTO<?>> commitOrder(@RequestBody OrderCommitDTO dto) throws Exception { Map<Long, PriceDTO > priceMap = new HashMap<>(); PreOrderDTO p = orderService.processPreOrderInfo(dto.getFlowers(), priceMap); Map map; diff --git a/src/main/java/com/mzl/flower/web/customer/OrderCustomerController.java b/src/main/java/com/mzl/flower/web/customer/OrderCustomerController.java index a18d47f..4247628 100644 --- a/src/main/java/com/mzl/flower/web/customer/OrderCustomerController.java +++ b/src/main/java/com/mzl/flower/web/customer/OrderCustomerController.java @@ -13,6 +13,7 @@ import com.mzl.flower.dto.response.payment.OrderListDTO; import com.mzl.flower.entity.payment.Order; import com.mzl.flower.service.payment.OrderService; +import com.mzl.flower.service.payment.UserPaymentSybService; import com.mzl.flower.service.payment.UserPaymentV3Service; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -37,7 +38,7 @@ private OrderService orderService; @Autowired - private UserPaymentV3Service paymentV3Service; + private UserPaymentSybService paymentSybService; @GetMapping("/list") @ApiOperation(value = "查询订单列表") @@ -79,12 +80,12 @@ @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "订单id", required = true, dataType = "String", paramType = "query") }) - public ResponseEntity<ReturnDataDTO<?>> payAgain(String id){ - boolean f = paymentV3Service.checkOrderStatus(id, true); + public ResponseEntity<ReturnDataDTO<?>> payAgain(String id) throws Exception { + boolean f = paymentSybService.checkOrderStatusPayAgain(id); if(f){ throw new ValidationException("订单不可再支付"); } - return returnData(R.SUCCESS.getCode(), paymentV3Service.payAgain(id)); + return returnData(R.SUCCESS.getCode(), paymentSybService.payAgain(id)); } @GetMapping(value = "/refund") @@ -92,20 +93,15 @@ @ApiImplicitParam(name = "id", value = "订单id", required = true, dataType = "String", paramType = "query"), }) @ApiOperation(value = "退款") - public ResponseEntity<ReturnDataDTO> refundOrder(String id) { + public ResponseEntity<ReturnDataDTO> refundOrder(String id) throws Exception { orderService.refundCheck(id); - paymentV3Service.refundOrder(id); + boolean f = paymentSybService.checkOrderStatusRefund(id); + if(f) { + throw new ValidationException("订单不可退款"); + } + paymentSybService.refundOrderCustomer(id); return returnData(R.SUCCESS.getCode(), null); } - - /*@GetMapping(value = "/refund/check") - @ApiImplicitParams({ - @ApiImplicitParam(name = "id", value = "订单id", required = true, dataType = "String", paramType = "query"), - }) - @ApiOperation(value = "查询退款") - public ResponseEntity<ReturnDataDTO> refundQuery(String id) { - return returnData(R.SUCCESS.getCode(), paymentV3Service.refundQuery(id)); - }*/ @PostMapping("/evaluate") @ApiOperation(value = "评价") @@ -131,11 +127,8 @@ @ApiImplicitParam(name = "id", value = "订单id", required = true, dataType = "String", paramType = "query"), }) @ApiOperation(value = "取消订单") - public ResponseEntity<ReturnDataDTO> cancelOrder(String id) { - boolean f = paymentV3Service.checkOrderStatus(id); - if(!f){ - paymentV3Service.cancelOrder(id); - } + public ResponseEntity<ReturnDataDTO> cancelOrder(String id) throws Exception { + paymentSybService.cancelOrder(id); return returnData(R.SUCCESS.getCode(), null); } diff --git a/src/main/java/com/mzl/flower/web/payment/OrderController.java b/src/main/java/com/mzl/flower/web/payment/OrderController.java index 0d9d2d6..5b60475 100644 --- a/src/main/java/com/mzl/flower/web/payment/OrderController.java +++ b/src/main/java/com/mzl/flower/web/payment/OrderController.java @@ -11,7 +11,7 @@ import com.mzl.flower.dto.response.payment.*; import com.mzl.flower.service.payment.DeliveryOrderService; import com.mzl.flower.service.payment.OrderService; -import com.mzl.flower.service.payment.UserPaymentV3Service; +import com.mzl.flower.service.payment.UserPaymentSybService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -36,7 +36,7 @@ private OrderService orderService; @Autowired - private UserPaymentV3Service paymentV3Service; + private UserPaymentSybService paymentSybService; @Autowired private DeliveryOrderService deliveryOrderService; @@ -88,7 +88,7 @@ @GetMapping("/list/abnormal/process") @ApiOperation(value = "异常订单处理(不管有没有退款金额,建议都要处理)") - public ResponseEntity<ReturnDataDTO> processLevelDown(String id) { + public ResponseEntity<ReturnDataDTO> processLevelDown(String id) throws Exception { orderService.processAbnormalOrder(id); return returnData(R.SUCCESS.getCode(), null); } @@ -175,9 +175,9 @@ @ApiImplicitParam(name = "id", value = "订单id", required = true, dataType = "String", paramType = "query"), }) @ApiOperation(value = "退款") - public ResponseEntity<ReturnDataDTO> refundOrder(String id) { + public ResponseEntity<ReturnDataDTO> refundOrder(String id) throws Exception { orderService.refundCheckAdmin(id); - paymentV3Service.refundOrder(id); + paymentSybService.refundOrder(id); return returnData(R.SUCCESS.getCode(), null); } diff --git a/src/main/java/com/mzl/flower/web/payment/PaymentCallBackSybResource.java b/src/main/java/com/mzl/flower/web/payment/PaymentCallBackSybResource.java new file mode 100644 index 0000000..4c09a10 --- /dev/null +++ b/src/main/java/com/mzl/flower/web/payment/PaymentCallBackSybResource.java @@ -0,0 +1,28 @@ +package com.mzl.flower.web.payment; + +import com.mzl.flower.service.payment.UserPaymentSybService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + +@RestController +@RequestMapping("/api/ua/notify/syb") +@Slf4j +public class PaymentCallBackSybResource { + + @Autowired + private UserPaymentSybService paymentSybService; + + @RequestMapping(value = "/paid", method = RequestMethod.POST) + @ResponseBody + public String handlePayCallback(HttpServletRequest request) { + log.info("通联回调"); + return paymentSybService.handlePayCallback(request); + } + +} diff --git a/src/main/java/com/mzl/flower/web/payment/SalesController.java b/src/main/java/com/mzl/flower/web/payment/SalesController.java index 32cac36..597b9ad 100644 --- a/src/main/java/com/mzl/flower/web/payment/SalesController.java +++ b/src/main/java/com/mzl/flower/web/payment/SalesController.java @@ -70,7 +70,7 @@ @PostMapping("/audit/agree") @ApiOperation(value = "审核售后单-通过") - public ResponseEntity<ReturnDataDTO> agree(@RequestBody OrderItemSalesAuditDTO dto) { + public ResponseEntity<ReturnDataDTO> agree(@RequestBody OrderItemSalesAuditDTO dto) throws Exception { OrderItem oi = salesService.doAudit(dto, Constants.ORDER_SALES_STATUS.AGREED.name()); orderItemSettlementService.saveItemSettlementInfo(oi, SecurityUtils.getUserId(), Constants.S_TYPE.SALES); return returnData(R.SUCCESS.getCode(), null); @@ -78,7 +78,7 @@ @PostMapping("/audit/reject") @ApiOperation(value = "审核售后单-拒绝") - public ResponseEntity<ReturnDataDTO> reject(@RequestBody OrderItemSalesAuditDTO dto) { + public ResponseEntity<ReturnDataDTO> reject(@RequestBody OrderItemSalesAuditDTO dto) throws Exception { salesService.doAudit(dto, Constants.ORDER_SALES_STATUS.REJECTED.name()); return returnData(R.SUCCESS.getCode(), null); } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index e4c8c1d..d40c618 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -51,4 +51,7 @@ upload: fileServerPath: http://47.99.58.211/files fileGroup: /group1 - localServerPath: /data/files \ No newline at end of file + localServerPath: /data/files + +syb: + callBackUrl: http://localhost \ No newline at end of file diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 1366594..b6c192b 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -51,4 +51,7 @@ upload: fileServerPath: http://47.99.58.211/files fileGroup: /group1 - localServerPath: /data/files \ No newline at end of file + localServerPath: /data/files + +syb: + callBackUrl: http://localhost \ No newline at end of file diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 34806f4..c5405ea 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -61,4 +61,7 @@ upload: fileServerPath: https://www.hmyxianhua.com/files fileGroup: /group1 - localServerPath: /data/files \ No newline at end of file + localServerPath: /data/files + +syb: + callBackUrl: https://www.hmyxianhua.com \ No newline at end of file diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index e57b439..5c6ee55 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -51,4 +51,7 @@ upload: fileServerPath: http://47.99.58.211/files fileGroup: /group1 - localServerPath: /data/files \ No newline at end of file + localServerPath: /data/files + +syb: + callBackUrl: http://localhost \ No newline at end of file -- Gitblit v1.9.3