| | |
| | | package com.ruoyi.order.service.impl.order; |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | |
| | | import com.ruoyi.order.service.account.PaymentMessageService; |
| | | import com.ruoyi.order.service.account.ProfitSharingService; |
| | | import com.ruoyi.order.service.order.*; |
| | | import com.ruoyi.order.util.HuiFuTianXiaUtil; |
| | | import com.ruoyi.system.api.constant.AppErrorConstant; |
| | | import com.ruoyi.system.api.constant.DelayTaskEnum; |
| | | import com.ruoyi.system.api.constant.SecurityConstant; |
| | |
| | | import lombok.extern.log4j.Log4j2; |
| | | import org.redisson.api.RLock; |
| | | import org.redisson.api.RedissonClient; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.NumberFormat; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | |
| | | |
| | | @Resource |
| | | private OrderRefundService orderRefundService; |
| | | |
| | | @Value("${wx.pay.callbackPath}") |
| | | private String callbackPath; |
| | | |
| | | |
| | | /** |
| | |
| | | if (null != goodsNameList) { |
| | | goodsName = String.join(",", goodsNameList); |
| | | } |
| | | // 小程序微信下单支付 |
| | | createWxPayInfo(appPlaceOrderVo, userId, order.getShopId(), goodsName, outTradeNo, |
| | | // // 小程序微信下单支付 |
| | | // createWxPayInfo(appPlaceOrderVo, userId, order.getShopId(), goodsName, outTradeNo, |
| | | // orderId, order.getPayMoney(), appPlaceOrderDto.getOpenid(), |
| | | // appPlaceOrderDto.getSpbillCreateIp()); |
| | | |
| | | // 小程序微信下单支付 TODO 更换支付渠道(汇付天下) |
| | | createWxPayInfo1(appPlaceOrderVo, userId, order.getShopId(), goodsName, outTradeNo, |
| | | orderId, order.getPayMoney(), appPlaceOrderDto.getOpenid(), |
| | | appPlaceOrderDto.getSpbillCreateIp()); |
| | | //生成自动取消订单延时任务 |
| | |
| | | * @param payerClientIp |
| | | */ |
| | | |
| | | private void createWxPayInfo(AppPlaceOrderVo appPlaceOrderVo, Long userId, Long shopId, |
| | | private void createWxPayInfo1(AppPlaceOrderVo appPlaceOrderVo, Long userId, Long shopId, |
| | | String goodsName, String outTradeNo, |
| | | String orderId, BigDecimal payMoney, |
| | | String openid, String payerClientIp){ |
| | | try { |
| | | WxPayConfig config = wxService.getConfig(); |
| | | PartnerTransactionsRequest request = new PartnerTransactionsRequest(); |
| | | request.setSpAppid(config.getAppId()); |
| | | request.setSpMchid(config.getMchId()); |
| | | request.setSubMchid(config.getSubMchId()); |
| | | // 商品描述 body |
| | | String description = goodsName + "-商品购买"; |
| | | |
| | | request.setDescription(description); |
| | | request.setOutTradeNo(outTradeNo); |
| | | request.setNotifyUrl(callbackPath + "/order/app/notify/wechatPaymentCallback"); |
| | | |
| | | |
| | | R<com.alibaba.fastjson.JSONObject> r = HuiFuTianXiaUtil.weixinPayment(outTradeNo, description, payMoney.doubleValue(), openid, request.getNotifyUrl()); |
| | | if(r.getCode() != 200){ |
| | | throw new ServiceException(r.getMsg()); |
| | | } |
| | | com.alibaba.fastjson.JSONObject data = r.getData(); |
| | | String mainMchId = WxPayConfiguration.getPlatformTyMacId(); |
| | | // 支付相关信息返回 |
| | | appPlaceOrderVo.setAppId(result.getAppId()); |
| | | appPlaceOrderVo.setAppId(data.getString("appId")); |
| | | appPlaceOrderVo.setMchId(config.getMchId()); |
| | | appPlaceOrderVo.setTimeStamp(result.getTimeStamp()); |
| | | appPlaceOrderVo.setNonceStr(result.getNonceStr()); |
| | | appPlaceOrderVo.setPackageStr(result.getPackageValue()); |
| | | appPlaceOrderVo.setSignType(result.getSignType()); |
| | | appPlaceOrderVo.setPaySign(result.getPaySign()); |
| | | appPlaceOrderVo.setPrepayId(result.getPackageValue()); |
| | | appPlaceOrderVo.setTimeStamp(data.getString("timeStamp")); |
| | | appPlaceOrderVo.setNonceStr(data.getString("nonceStr")); |
| | | appPlaceOrderVo.setPackageStr(data.getString("package")); |
| | | appPlaceOrderVo.setSignType(data.getString("signType")); |
| | | appPlaceOrderVo.setPaySign(data.getString("paySign")); |
| | | |
| | | // 保存支付订单统一下单日志 |
| | | paymentMessageService.savePaymentMessage("1", orderId, payRequestJson, payResponseJson); |
| | | paymentMessageService.savePaymentMessage("1", orderId, JSON.toJSONString(request), data.toJSONString()); |
| | | |
| | | // 保存支付订单统一下单支付记录 |
| | | orderPaymentService.saveOrderPayment(userId, shopId, mainMchId, orderId, outTradeNo, payMoney, |
| | | appPlaceOrderVo.getEndTime(), "Y", openid, |
| | | goodsName, result.getPackageValue()); |
| | | goodsName, appPlaceOrderVo.getPackageStr()); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } |
| | |
| | | } |
| | | appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(), delayTime)); |
| | | // 小程序微信下单支付 |
| | | createWxPayInfo(appPlaceOrderVo, userId, order.getShopId(), orderGoods.getGoodsName(), outTradeNo, |
| | | // createWxPayInfo(appPlaceOrderVo, userId, order.getShopId(), orderGoods.getGoodsName(), outTradeNo, |
| | | // orderId, order.getPayMoney(), appPlaceActivityDto.getOpenid(), |
| | | // appPlaceActivityDto.getSpbillCreateIp()); |
| | | |
| | | // 小程序微信下单支付 TODO 更换支付渠道(汇付天下) |
| | | createWxPayInfo1(appPlaceOrderVo, userId, order.getShopId(), orderGoods.getGoodsName(), outTradeNo, |
| | | orderId, order.getPayMoney(), appPlaceActivityDto.getOpenid(), |
| | | appPlaceActivityDto.getSpbillCreateIp()); |
| | | //生成自动取消订单延时任务 |
| | |
| | | Order order = this.getById(orderId); |
| | | if (order.getOrderStatus() != 2) { |
| | | throw new ServiceException(AppErrorConstant.VERIFY_USED); |
| | | } |
| | | //判断商户是否有分账权限 |
| | | Shop shop = remoteShopService.getShop(shopId).getData(); |
| | | if(shop.getAccountFlag()!=1){ |
| | | throw new ServiceException(AppErrorConstant.SHOP_NO_VERIFY); |
| | | } |
| | | // 根据订单用户ID获取用户信息 |
| | | Member member = remoteMemberService.getMember(order.getUserId()).getData(); |
| | |
| | | } |
| | | this.saveOrUpdate(order); |
| | | // 订单金额大于0时进行分账 |
| | | if (order.getOnlinePayMoney().compareTo(BigDecimal.ZERO)>0) { |
| | | submitProfitSharing(orderId, order.getOrderNo(), order.getShopId(), order.getOnlinePayMoney(),order.getOrderFrom()); |
| | | OrderPayment orderPayment = orderPaymentService.getOne(new QueryWrapper<OrderPayment>() |
| | | .eq("order_id", order.getOrderId()).eq("pay_status", 2) |
| | | .eq("del_flag", 0)); |
| | | BigDecimal bigDecimal = orderPayment.getPayMoney().subtract(orderPayment.getFeeAmount()).setScale(2, BigDecimal.ROUND_HALF_EVEN); |
| | | if (bigDecimal.compareTo(BigDecimal.ZERO)>0) { |
| | | // TODO: 2023/10/17 更换分账渠道(汇付天下) |
| | | // submitProfitSharing(orderId, order.getOrderNo(), order.getShopId(), order.getOnlinePayMoney(),order.getOrderFrom()); |
| | | submitProfitSharing1(orderId, order.getOrderNo(), order.getShopId(), bigDecimal, order.getOrderFrom()); |
| | | } |
| | | //创建支付记录 |
| | | if(merVerifyOrderDto.getRelPayMoney().compareTo(BigDecimal.ZERO)>0){ |
| | |
| | | // 保存分账信息 |
| | | paymentMessageService.savePaymentMessage("4", orderId, sendMessage, resultMessage); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * @description 分账实现 |
| | | * @author jqs |
| | | * @date 2023/9/8 11:56 |
| | | * @param orderId |
| | | * @param orderNo |
| | | * @param shopId |
| | | * @param orderMoney |
| | | * @param orderFrom |
| | | * @return void |
| | | */ |
| | | private void submitProfitSharing1(String orderId, String orderNo, Long shopId, BigDecimal orderMoney, Integer orderFrom) { |
| | | String sendMessage = ""; |
| | | String resultMessage = ""; |
| | | try { |
| | | // 核销完成 开始分账(平台收取服务费) |
| | | OrderPayment payment = orderPaymentService.getByOrderId(orderId); |
| | | String transactionId = payment.getTransactionId(); |
| | | String outTradeNo = payment.getOutTradeNo(); |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); |
| | | String org_req_date = sdf.format(payment.getCreateTime()); |
| | | R<ShopAuthenticationHftxVo> resultMch = remoteShopService.getShopHFTXSubMchId(shopId); |
| | | ShopAuthenticationHftxVo vo = resultMch.getData(); |
| | | if (StringUtils.isEmpty(vo.getHuifuId())) { |
| | | throw new ServiceException("获取商户号失败"); |
| | | } |
| | | // 平台特约商户号,用户平台收取服务费 2023-09-05改变分账方式 |
| | | String platformTyMacId = WxPayConfiguration.getPlatformTyMacId(); |
| | | if (!StringUtils.isEmpty(platformTyMacId)) { |
| | | WxPayConfig config = wxService.getConfig(); |
| | | ShopProportionVo shopProportion = null; |
| | | BigDecimal proportionPercent = null; |
| | | //商户订单获取统一分成 活动订单获取活动分成 |
| | | if(orderFrom==1){ |
| | | if(null == vo.getShareRatio()){ |
| | | proportionPercent = new BigDecimal(redisService.getCacheObject(SecurityConstant.SHOP_COMMON_PROPORTION).toString()); |
| | | }else{ |
| | | proportionPercent = new BigDecimal(vo.getShareRatio()); |
| | | } |
| | | }else{ |
| | | R<ShopProportionVo> resultShopProportion = remoteShopService.getShopProportion(shopId); |
| | | shopProportion = resultShopProportion.getData(); |
| | | proportionPercent = shopProportion.getProportionPercent(); |
| | | } |
| | | if (null != proportionPercent) { |
| | | ProfitSharingRequest request = new ProfitSharingRequest(); |
| | | request.setAppid(config.getAppId()); |
| | | request.setSubMchid(platformTyMacId); |
| | | request.setTransactionId(transactionId); |
| | | request.setOutOrderNo(IdUtils.simpleUUID()); |
| | | List<ProfitSharingRequest.Receiver> receiverList = new ArrayList<>(); |
| | | String description = "订单:" + orderNo + " 平台分账"; |
| | | //商户分成 |
| | | if(proportionPercent.compareTo(BigDecimal.ZERO)>0){ |
| | | PaymentDelaytransHFTXVo result = new PaymentDelaytransHFTXVo(); |
| | | // 计算分成金额 |
| | | int amount = orderMoney.multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_EVEN).intValue(); |
| | | BigDecimal multiply = orderMoney.multiply(proportionPercent.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_EVEN); |
| | | log.info("订单分账:{} 分账金额: {}", orderNo, amount); |
| | | if (amount > 0) { |
| | | // 分账创建 |
| | | ProfitSharingRequest.Receiver receiver = new ProfitSharingRequest.Receiver(); |
| | | receiver.setType("MERCHANT_ID"); |
| | | receiver.setReceiverAccount(vo.getHuifuId()); |
| | | receiver.setAmount(amount); |
| | | receiver.setDescription(description); |
| | | receiverList.add(receiver); |
| | | request.setReceivers(receiverList); |
| | | // 分账完成 |
| | | request.setFinish(true); |
| | | |
| | | //分账对象 |
| | | JSONArray acctInfos = new JSONArray(); |
| | | if(multiply.compareTo(BigDecimal.ZERO) > 0){ |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("div_amt", String.format("%.2f", multiply.doubleValue())); |
| | | jsonObject.put("huifu_id", vo.getHuifuId()); |
| | | acctInfos.add(jsonObject); |
| | | } |
| | | //平台商户 |
| | | BigDecimal pt_amount = orderMoney.subtract(multiply).setScale(2, RoundingMode.HALF_EVEN); |
| | | if(pt_amount.compareTo(BigDecimal.ZERO) > 0){ |
| | | JSONObject jsonObject1 = new JSONObject(); |
| | | jsonObject1.put("div_amt", String.format("%.2f", pt_amount.doubleValue())); |
| | | jsonObject1.put("huifu_id", "6666000141216769"); |
| | | acctInfos.add(jsonObject1); |
| | | } |
| | | |
| | | R<PaymentDelaytransHFTXVo> hftxVoR = HuiFuTianXiaUtil.paymentDelaytrans(request.getOutOrderNo(), org_req_date, outTradeNo, acctInfos); |
| | | if(hftxVoR.getCode() != 200){ |
| | | throw new ServiceException(hftxVoR.getMsg()); |
| | | } |
| | | result = hftxVoR.getData(); |
| | | // 创建分账记录 |
| | | profitSharingService.saveProfitSharing1(shopId, orderId, orderMoney, vo.getHuifuId(), multiply.doubleValue(), result); |
| | | } |
| | | // 保存请求信息 |
| | | sendMessage = JSONObject.toJSONString(request); |
| | | resultMessage = JSONObject.toJSONString(result); |
| | | } |
| | | } else { |
| | | resultMessage = String.format("订单分账:%s 获取商户分成失败", orderNo); |
| | | log.info(resultMessage); |
| | | } |
| | | } else { |
| | | resultMessage = String.format("订单分账:%s 获取微信商户号失败", orderNo); |
| | | log.info(resultMessage); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | resultMessage = String.format("订单分账:%s 分账失败:%s", orderNo, e.getMessage()); |
| | | log.info(resultMessage); |
| | | throw new ServiceException(resultMessage); |
| | | } |
| | | |
| | | // 保存分账信息 |
| | | paymentMessageService.savePaymentMessage("4", orderId, sendMessage, resultMessage); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * @param merVerifyCouponDto |
| | |
| | | @Override |
| | | @Transactional |
| | | @GlobalTransactional(rollbackFor = Exception.class) |
| | | public void payBack(PartnerTransactionsResult transaction) { |
| | | public void payBack(PartnerTransactionsResult transaction, BigDecimal feeAmount) { |
| | | log.info("订单支付回调---"+transaction.toString()); |
| | | // Order order = this.getById(orderId); |
| | | // 更新订单状态 outTradeNo |
| | | String outTradeNo = transaction.getOutTradeNo(); |
| | | Order order = this.getByOutTradeNo(outTradeNo); |
| | | if(order.getOrderStatus() != 1){ |
| | | return; |
| | | } |
| | | String orderId = order.getOrderId(); |
| | | order.setOrderStatus(2); |
| | | order.setPayTime(new Date()); |
| | |
| | | goodsTotalChangeDto.setChangeType(1); |
| | | goodsTotalChangeDto.setChangeNum(orderGoods.getBuyNum()); |
| | | goodsTotalChangeDto.setMoney(orderGoods.getGoodsReceivableMoney()); |
| | | Integer bugGoodsNum = orderMapper.countUserBuyGoodsNum(order.getUserId(), orderGoods.getGoodsId()); |
| | | if (bugGoodsNum == null || bugGoodsNum < 1) { |
| | | goodsTotalChangeDto.setPersonNum(1); |
| | | }else{ |
| | | goodsTotalChangeDto.setPersonNum(0); |
| | | } |
| | | Integer bugGoodsNum = orderMapper.countUserBuyGoodsNum(orderGoods.getGoodsId()); |
| | | goodsTotalChangeDto.setPersonNum(bugGoodsNum); |
| | | goodsTotalChangeDtoList.add(goodsTotalChangeDto); |
| | | } |
| | | //更新商品统计 |
| | |
| | | profitsSharingService.applyProfitSharing(request);*/ |
| | | } |
| | | //修改支付记录生成支付记录 |
| | | orderPaymentService.updatePaySuccess(transaction.getOutTradeNo(), transaction.getTransactionId()); |
| | | orderPaymentService.updatePaySuccess(transaction.getOutTradeNo(), feeAmount, transaction.getTransactionId()); |
| | | PayRecord payRecord = new PayRecord(); |
| | | payRecord.setDelFlag(0); |
| | | payRecord.setOrderId(orderId); |
| | |
| | | goodsTotalChangeDto.setChangeType(2); |
| | | goodsTotalChangeDto.setChangeNum(orderGoods.getBuyNum()); |
| | | goodsTotalChangeDto.setMoney(orderGoods.getGoodsReceivableMoney()); |
| | | Integer bugGoodsNum = orderMapper.countUserBuyGoodsNum(order.getUserId(), orderGoods.getGoodsId()); |
| | | if (bugGoodsNum == null || bugGoodsNum <= orderGoods.getBuyNum()) { |
| | | goodsTotalChangeDto.setPersonNum(1); |
| | | }else{ |
| | | goodsTotalChangeDto.setPersonNum(0); |
| | | } |
| | | Integer bugGoodsNum = orderMapper.countUserBuyGoodsNum(orderGoods.getGoodsId()); |
| | | goodsTotalChangeDto.setPersonNum(bugGoodsNum); |
| | | goodsTotalChangeDtoList.add(goodsTotalChangeDto); |
| | | } |
| | | remoteGoodsService.changeGoodsTotal(goodsTotalChangeDtoList); |
| | |
| | | if(BigDecimal.ZERO.compareTo(onlinePayMoney) < 0){ |
| | | log.info("订单支付金额大于0,可发起退款"); |
| | | // 订单支付金额大于0,可发起退款 |
| | | orderWxApplyRefund(orderId, refundId, onlinePayMoney, orderRefund); |
| | | // orderWxApplyRefund(orderId, refundId, onlinePayMoney, orderRefund); |
| | | // 订单支付金额大于0,可发起退款 todo 修改渠道(汇付天下) |
| | | orderWxApplyRefund1(orderId, refundId, onlinePayMoney, orderRefund); |
| | | } |
| | | |
| | | orderRefund.setRefundStatus(1); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 申请退款API |
| | | */ |
| | | private void orderWxApplyRefund1(String orderId, String outRefundNo, BigDecimal payMoney, OrderRefund orderRefund){ |
| | | try { |
| | | // 创建支付订单 |
| | | OrderPayment orderPayment = orderPaymentService.getByOrderId(orderId); |
| | | if (null == orderPayment) { |
| | | return; |
| | | } |
| | | |
| | | log.info("调用微信退款---发起退款"); |
| | | |
| | | String subMchId = orderPayment.getSubMchId(); |
| | | // WxPayConfig config = wxService.getConfig(); |
| | | |
| | | RefundsRequest request = new RefundsRequest(); |
| | | // request.setSpAppid(config.getAppId()); |
| | | request.setSubMchid(subMchId); |
| | | request.setTransactionId(orderPayment.getTransactionId()); |
| | | request.setOutRefundNo(outRefundNo); |
| | | request.setReason("用户取消订单"); |
| | | // 订单金额 |
| | | int total = orderPayment.getPayMoney().multiply(new BigDecimal(100)).intValue(); |
| | | |
| | | RefundsRequest.Amount amount = RefundsRequest.Amount.builder().refund(total).total(total).currency("CNY").build(); |
| | | request.setAmount(amount); |
| | | request.setNotifyUrl(callbackPath + "/order/app/notify/wechatPaymentRefundCallback"); |
| | | |
| | | // RefundsResult result = wxService.getEcommerceService().refunds(request); |
| | | |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); |
| | | String org_req_date = sdf.format(orderPayment.getCreateTime()); |
| | | String outTradeNo = orderPayment.getOutTradeNo(); |
| | | R<String> r = HuiFuTianXiaUtil.weixinPaymentRefund(outRefundNo, orderPayment.getPayMoney().doubleValue(), org_req_date, outTradeNo, request.getNotifyUrl()); |
| | | if(r.getCode() != 200){ |
| | | throw new ServiceException(r.getMsg()); |
| | | } |
| | | |
| | | // 微信退款id |
| | | orderRefund.setWxRefundId(r.getData()); |
| | | |
| | | // 请求参数 |
| | | Gson gson = new Gson(); |
| | | String refundRequestJson = gson.toJson(request); |
| | | // 返回参数 |
| | | // String refundResponseJson = gson.toJson(result); |
| | | |
| | | // log.info("调用微信退款返回参数---{}", refundResponseJson); |
| | | |
| | | // 保存支付订单统一下单日志 |
| | | // paymentMessageService.savePaymentMessage("3", orderId, refundRequestJson, refundResponseJson); |
| | | |
| | | } catch (Exception e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @param staffTotalDto |
| | | * @return StaffActivityOrderTotalVo |