| | |
| | | @TableField("payment_status") |
| | | private Integer paymentStatus; |
| | | |
| | | @ApiModelProperty(value = "支付方式(1=微信,2=支付宝)") |
| | | @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=工商银行)") |
| | | @TableField("payment_type") |
| | | private Integer paymentType; |
| | | |
| | |
| | | @TableField("payment_status") |
| | | private Integer paymentStatus; |
| | | |
| | | @ApiModelProperty(value = "支付方式(1=微信,2=支付宝)") |
| | | @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=工商银行)") |
| | | @TableField("payment_type") |
| | | private Integer paymentType; |
| | | |
| | |
| | | </if> |
| | | AND ts.del_flag = ${@com.ruoyi.common.core.enums.DelFlagEnum@NO.getCode()} |
| | | AND ts.status = ${@com.ruoyi.common.core.enums.status.SiteStatusEnum@NORMAL_USE.getCode()} |
| | | AND ts.accounting_strategy_id IS NOT NULL |
| | | AND (tp.partner_type IS NULL OR tp.partner_type != 3) |
| | | </where> |
| | | <if test="query.sortType != null"> |
| | |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Paths; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | | import static org.junit.jupiter.api.Assertions.assertTrue; |
| | | |
| | | class SiteMapperVisibilityTest { |
| | |
| | | assertTrue(mapper.contains("p.partner_type = 3")); |
| | | assertTrue(mapper.contains("member_discount_flag as memberDiscountFlag")); |
| | | assertTrue(mapper.contains("CASE WHEN ts.member_discount_flag = 1 THEN tasd.vipElectrovalence")); |
| | | assertFalse(mapper.contains("ts.accounting_strategy_id IS NOT NULL")); |
| | | } |
| | | } |
| | |
| | | if (invoice.getBillingTime() != null) { |
| | | export.setBillingTime(DateUtils.localDateTimeToString(invoice.getBillingTime())); |
| | | } |
| | | return ExcelExportUtil.exportExcel(new ExportParams(), OrderInvoiceExport.class, Collections.singletonList(export)); |
| | | return ExcelExportUtil.exportExcel( |
| | | new ExportParams(), |
| | | OrderInvoiceExport.class, |
| | | new ArrayList<>(Collections.singletonList(export))); |
| | | } |
| | | |
| | | private String buildInvoiceFileName(TOrderInvoiceVO invoice) { |
| | |
| | | import com.ruoyi.other.api.feignClient.CouponClient; |
| | | import com.ruoyi.other.api.feignClient.GoodsClient; |
| | | import com.ruoyi.payment.api.feignClient.AliPaymentClient; |
| | | import com.ruoyi.payment.api.feignClient.IcbcPaymentClient; |
| | | import com.ruoyi.payment.api.feignClient.WxPaymentClient; |
| | | import com.ruoyi.payment.api.model.RefundReq; |
| | | import com.ruoyi.payment.api.model.RefundResp; |
| | | import com.ruoyi.payment.api.model.WxPaymentRefundModel; |
| | | import com.ruoyi.payment.api.vo.WxRefundNotifyResp; |
| | | import com.ruoyi.payment.api.vo.IcbcRefundReq; |
| | | import com.ruoyi.payment.api.vo.IcbcRefundResp; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import io.swagger.annotations.Api; |
| | |
| | | private AliPaymentClient aliPaymentClient; |
| | | @Resource |
| | | private WxPaymentClient wxPaymentClient; |
| | | @Resource |
| | | private IcbcPaymentClient icbcPaymentClient; |
| | | @Resource |
| | | private AppCouponClient appCouponClient; |
| | | @Resource |
| | |
| | | tShoppingOrderRefund.setPayTime(byId.getPayTime()); |
| | | tShoppingOrderRefund.setPayCode(byId.getSerialNumber()); |
| | | tShoppingOrderRefund.setPayAmount(byId.getPaymentAmount()); |
| | | tShoppingOrderRefund.setPayType(1); |
| | | tShoppingOrderRefund.setPayType(byId.getPaymentType()); |
| | | tShoppingOrderRefund.setShoppingOrderId(byId.getId()); |
| | | tShoppingOrderRefund.setRefundAmount(byId.getPaymentAmount()); |
| | | tShoppingOrderRefund.setRefundStatus(1); |
| | |
| | | shoppingOrderService.updateById(byId); |
| | | } |
| | | break; |
| | | case 3: |
| | | IcbcRefundReq icbcRefundReq = new IcbcRefundReq(); |
| | | icbcRefundReq.setOutTradeNo(byId.getCode()); |
| | | icbcRefundReq.setOrderId(byId.getSerialNumber()); |
| | | icbcRefundReq.setOutRefundNo(tShoppingOrderRefund.getCode()); |
| | | icbcRefundReq.setRefundAmount(byId.getPaymentAmount()); |
| | | icbcRefundReq.setTotalAmount(byId.getPaymentAmount()); |
| | | icbcRefundReq.setReason("后台购物订单退款"); |
| | | R<IcbcRefundResp> icbcRefundResult = icbcPaymentClient.refund(icbcRefundReq); |
| | | IcbcRefundResp icbcRefundResp = icbcRefundResult == null ? null : icbcRefundResult.getData(); |
| | | if (icbcRefundResult == null || icbcRefundResult.getCode() != 200 || icbcRefundResp == null || !"SUCCESS".equals(icbcRefundResp.getStatus())) { |
| | | return AjaxResult.error(icbcRefundResult == null ? "工行退款服务无响应" : icbcRefundResult.getMsg()); |
| | | } |
| | | tShoppingOrderRefund.setRefundStatus(2); |
| | | tShoppingOrderRefund.setRefundSerialNumber(icbcRefundResp.getRefundId()); |
| | | tShoppingOrderRefund.setRefundTime(LocalDateTime.now()); |
| | | shoppingOrderRefundService.save(tShoppingOrderRefund); |
| | | byId.setStatus(4); |
| | | byId.setRefundCode(tShoppingOrderRefund.getCode()); |
| | | byId.setRefundAmount(byId.getPaymentAmount()); |
| | | byId.setRefundStatus(2); |
| | | byId.setRefundSerialNumber(icbcRefundResp.getRefundId()); |
| | | byId.setRefundTime(LocalDateTime.now()); |
| | | break; |
| | | } |
| | | shoppingOrderService.updateById(byId); |
| | | return AjaxResult.success(); |
| | |
| | | @PostMapping("/callBack") |
| | | public R callBack(@RequestParam("code")String code,@RequestParam("outTradeNo")String outTradeNo){ |
| | | TVipOrder one = vipOrderService.lambdaQuery().eq(TVipOrder::getCode, code).one(); |
| | | one.setSerialNumber(outTradeNo); |
| | | one.setPaymentStatus(2); |
| | | vipOrderService.updateById(one); |
| | | if (one == null) { |
| | | return R.fail("会员订单不存在"); |
| | | } |
| | | boolean updated = vipOrderService.update(new LambdaUpdateWrapper<TVipOrder>() |
| | | .eq(TVipOrder::getId, one.getId()) |
| | | .eq(TVipOrder::getPaymentStatus, 1) |
| | | .set(TVipOrder::getSerialNumber, outTradeNo) |
| | | .set(TVipOrder::getPaymentStatus, 2) |
| | | .set(TVipOrder::getPayTime, LocalDateTime.now())); |
| | | if (!updated) { |
| | | return R.ok(); |
| | | } |
| | | GiveVipDto giveVipDto = new GiveVipDto(); |
| | | giveVipDto.setVipId(one.getVipId()); |
| | | giveVipDto.setType(one.getVipType()); |
| | |
| | | private String code; |
| | | @ApiModelProperty("支付流水号") |
| | | private String tradeNo; |
| | | @ApiModelProperty("1微信2支付宝") |
| | | @ApiModelProperty("1微信2支付宝3工商银行") |
| | | private Integer payType; |
| | | @ApiModelProperty("支付金额") |
| | | private BigDecimal payAmount; |
| | |
| | | |
| | | List<SixCircleDto> circle(@Param("siteIds")List<Integer> siteIds,@Param("sixBefore")LocalDate sixBefore, @Param("partnerView") Boolean partnerView); |
| | | |
| | | BigDecimal sumSuccessfulShareAmount(@Param("siteIds") List<Integer> siteIds); |
| | | |
| | | Map<String, Object> countAll(@Param("siteIds")List<Integer> siteIds, @Param("partnerView") Boolean partnerView); |
| | | List<Map<String, Object>> chargingOrderShareIncomeByPayChannel(@Param("sixBefore")LocalDate sixBefore,@Param("siteIds") List<Integer> siteIds); |
| | | |
| | |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | private IcbcPaymentClient icbcPaymentClient; |
| | | @Resource |
| | | private TChargingOrderShareRecordMapper chargingOrderShareRecordMapper; |
| | | @Value("${icbc.share.online-enabled:false}") |
| | | private boolean icbcOnlineShareEnabled; |
| | | @Resource |
| | | private ChargingOrderSettlementExecutor chargingOrderSettlementExecutor; |
| | | @Resource |
| | |
| | | |
| | | @Override |
| | | public Map<String, Object> countAll(List<Integer> siteIds, Boolean partnerView) { |
| | | return this.baseMapper.countAll(siteIds, partnerView); |
| | | Map<String, Object> result = this.baseMapper.countAll(siteIds, partnerView); |
| | | if (!Boolean.TRUE.equals(partnerView) && result != null) { |
| | | result.put("commission_amount", this.baseMapper.sumSuccessfulShareAmount(siteIds)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | |
| | | shoppingOrderRefund.setRefundContent("后台退款"); |
| | | shoppingOrderRefund.setRefundReason("后台退款"); |
| | | shoppingOrderRefund.setRefundRemark(payOrderQueryDto.getRemark()); |
| | | shoppingOrderRefund.setRefundTotalAmount(shoppingOrder.getRefundAmount().add(payOrderQueryDto.getRefundAmount())); |
| | | shoppingOrderRefund.setRefundTotalAmount(money(shoppingOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount())); |
| | | shoppingOrderRefund.setPayAmount(shoppingOrder.getPaymentAmount()); |
| | | |
| | | if (1 == shoppingOrder.getPaymentType()) { |
| | |
| | | shoppingOrderRefundService.save(shoppingOrderRefund); |
| | | } |
| | | } |
| | | if (3 == shoppingOrder.getPaymentType()) { |
| | | IcbcRefundReq refundReq = new IcbcRefundReq(); |
| | | refundReq.setOutTradeNo(shoppingOrder.getCode()); |
| | | refundReq.setOrderId(shoppingOrder.getSerialNumber()); |
| | | refundReq.setOutRefundNo(shoppingOrderRefund.getRefundCode()); |
| | | refundReq.setRefundAmount(payOrderQueryDto.getRefundAmount()); |
| | | refundReq.setTotalAmount(shoppingOrder.getPaymentAmount()); |
| | | refundReq.setReason("后台商城订单退款"); |
| | | R<IcbcRefundResp> refundResult = icbcPaymentClient.refund(refundReq); |
| | | IcbcRefundResp refundResp = refundResult == null ? null : refundResult.getData(); |
| | | if (refundResult == null || refundResult.getCode() != 200 || refundResp == null || !"SUCCESS".equals(refundResp.getStatus())) { |
| | | return R.fail(refundResult == null ? "工行退款服务无响应" |
| | | : firstNotBlank(refundResp == null ? null : refundResp.getRawResponse(), refundResult.getMsg(), "工行退款失败")); |
| | | } |
| | | shoppingOrder.setRefundStatus(2); |
| | | shoppingOrder.setRefundAmount(money(shoppingOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount())); |
| | | shoppingOrder.setRefundSerialNumber(refundResp.getRefundId()); |
| | | shoppingOrder.setRefundTime(LocalDateTime.now()); |
| | | shoppingOrderService.updateById(shoppingOrder); |
| | | shoppingOrderRefund.setRefundStatus(2); |
| | | shoppingOrderRefund.setRefundSerialNumber(refundResp.getRefundId()); |
| | | shoppingOrderRefundService.save(shoppingOrderRefund); |
| | | } |
| | | // if(3 == tChargingOrder.getPaymentType()){ |
| | | // RefundReq dto = new RefundReq(); |
| | | // dto.setOutTradeNo(tChargingOrder.getCode()); |
| | |
| | | vipOrderRefund.setRefundContent("后台退款"); |
| | | vipOrderRefund.setRefundReason("后台退款"); |
| | | vipOrderRefund.setRefundRemark(payOrderQueryDto.getRemark()); |
| | | vipOrderRefund.setRefundTotalAmount(vipOrder.getRefundAmount().add(payOrderQueryDto.getRefundAmount())); |
| | | vipOrderRefund.setRefundTotalAmount(money(vipOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount())); |
| | | vipOrderRefund.setPayAmount(vipOrder.getPaymentAmount()); |
| | | |
| | | if (1 == vipOrder.getPaymentType()) { |
| | |
| | | vipOrderService.updateById(vipOrder); |
| | | vipOrderRefundService.save(vipOrderRefund); |
| | | } |
| | | } |
| | | if (3 == vipOrder.getPaymentType()) { |
| | | IcbcRefundReq refundReq = new IcbcRefundReq(); |
| | | refundReq.setOutTradeNo(vipOrder.getCode()); |
| | | refundReq.setOrderId(vipOrder.getSerialNumber()); |
| | | refundReq.setOutRefundNo(vipOrderRefund.getRefundCode()); |
| | | refundReq.setRefundAmount(payOrderQueryDto.getRefundAmount()); |
| | | refundReq.setTotalAmount(vipOrder.getPaymentAmount()); |
| | | refundReq.setReason("后台会员订单退款"); |
| | | R<IcbcRefundResp> refundResult = icbcPaymentClient.refund(refundReq); |
| | | IcbcRefundResp refundResp = refundResult == null ? null : refundResult.getData(); |
| | | if (refundResult == null || refundResult.getCode() != 200 || refundResp == null || !"SUCCESS".equals(refundResp.getStatus())) { |
| | | return R.fail(refundResult == null ? "工行退款服务无响应" |
| | | : firstNotBlank(refundResp == null ? null : refundResp.getRawResponse(), refundResult.getMsg(), "工行退款失败")); |
| | | } |
| | | vipOrder.setRefundStatus(2); |
| | | vipOrder.setRefundAmount(money(vipOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount())); |
| | | vipOrderService.updateById(vipOrder); |
| | | vipOrderRefund.setRefundStatus(2); |
| | | vipOrderRefund.setRefundSerialNumber(refundResp.getRefundId()); |
| | | vipOrderRefundService.save(vipOrderRefund); |
| | | } |
| | | // if(3 == tChargingOrder.getPaymentType()){ |
| | | // RefundReq dto = new RefundReq(); |
| | |
| | | record.setSubMerId(partner.getIcbcSubMerId()); |
| | | record.setSubMerPrtclNo(partner.getIcbcSubMerPrtclNo()); |
| | | } |
| | | boolean needOnlineShare = shouldProcessIcbcOnlineShare(payChannel, record.getShareAmount(), partner); |
| | | boolean needOnlineShare = shouldProcessIcbcOnlineShare(icbcOnlineShareEnabled, payChannel, record.getShareAmount(), partner); |
| | | record.setNeedOnlineShare(needOnlineShare); |
| | | record.setOnlineShareStatus(needOnlineShare ? "INIT" : "RECORDED"); |
| | | if ("ICBC".equals(payChannel) && record.getShareAmount().compareTo(BigDecimal.ZERO) > 0 && !needOnlineShare) { |
| | | record.setFailReason("未配置完整工行二级商户参数,仅记录本地分账"); |
| | | record.setFailReason(icbcOnlineShareEnabled |
| | | ? "未配置完整工行二级商户参数,仅记录本地分账" |
| | | : "工行线上分账已关闭,仅记录本地分账"); |
| | | } |
| | | record.setRetryCount(0); |
| | | record.setDelFlag(false); |
| | |
| | | } |
| | | |
| | | static boolean shouldProcessIcbcOnlineShare(String payChannel, BigDecimal shareAmount, Partner partner) { |
| | | return "ICBC".equals(payChannel) |
| | | return shouldProcessIcbcOnlineShare(true, payChannel, shareAmount, partner); |
| | | } |
| | | |
| | | static boolean shouldProcessIcbcOnlineShare(boolean onlineShareEnabled, String payChannel, BigDecimal shareAmount, Partner partner) { |
| | | return onlineShareEnabled |
| | | && "ICBC".equals(payChannel) |
| | | && shareAmount != null |
| | | && shareAmount.compareTo(BigDecimal.ZERO) > 0 |
| | | && partner != null |
| | |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.api.dto.GrantCouponDto; |
| | |
| | | import com.ruoyi.other.api.feignClient.CouponClient; |
| | | import com.ruoyi.other.api.feignClient.GoodsClient; |
| | | import com.ruoyi.payment.api.feignClient.AliPaymentClient; |
| | | import com.ruoyi.payment.api.feignClient.IcbcPaymentClient; |
| | | import com.ruoyi.payment.api.feignClient.WxPaymentClient; |
| | | import com.ruoyi.payment.api.model.RefundReq; |
| | | import com.ruoyi.payment.api.model.RefundResp; |
| | | import com.ruoyi.payment.api.model.WxPaymentRefundModel; |
| | | import com.ruoyi.payment.api.vo.AliQueryOrder; |
| | | import com.ruoyi.payment.api.vo.IcbcPaymentResp; |
| | | import com.ruoyi.payment.api.vo.IcbcRefundReq; |
| | | import com.ruoyi.payment.api.vo.IcbcRefundResp; |
| | | import com.ruoyi.payment.api.vo.NotifyV3PayDecodeRespBody; |
| | | import org.redisson.api.RLock; |
| | | import org.redisson.api.RedissonClient; |
| | |
| | | |
| | | @Resource |
| | | private AliPaymentClient aliPaymentClient; |
| | | |
| | | @Resource |
| | | private IcbcPaymentClient icbcPaymentClient; |
| | | |
| | | @Resource |
| | | private TShoppingOrderRefundService shoppingOrderRefundService; |
| | |
| | | BigDecimal refundAmount = shoppingOrder.getPaymentAmount().subtract(bigDecimal); |
| | | |
| | | //先查询第三方订单状态订单是否退款 |
| | | //支付方式(1=微信,2=支付宝) |
| | | // 支付方式(1=微信,2=支付宝,3=工商银行) |
| | | Integer paymentType = shoppingOrder.getPaymentType(); |
| | | if(1 == paymentType){ |
| | | NotifyV3PayDecodeRespBody data = wxPaymentClient.queryOrderInfo(shoppingOrder.getCode()).getData(); |
| | |
| | | } |
| | | if("WAIT_BUYER_PAY".equals(tradeStatus)){ |
| | | return AjaxResult.error("订单正在支付中,不能操作退款"); |
| | | } |
| | | } |
| | | if (3 == paymentType) { |
| | | R<IcbcPaymentResp> queryResult = icbcPaymentClient.query(shoppingOrder.getCode()); |
| | | IcbcPaymentResp queryResp = queryResult == null ? null : queryResult.getData(); |
| | | if (queryResult == null || queryResult.getCode() != 200 || queryResp == null || !"0".equals(queryResp.getStatus())) { |
| | | return AjaxResult.error(queryResult == null ? "工行支付查询无响应" : "订单尚未支付成功,不能退款"); |
| | | } |
| | | } |
| | | //退款成功后需要判断商品库存类型后决定是否需要回退库存 |
| | |
| | | SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-DDTHH:mm:ss+TIMEZONE"); |
| | | AjaxResult success = cancelShoppingOrderWxRefund(resp.getOutTradeNo(), resp.getTradeNo(), "SUCCESS", sdf1.format(new Date())); |
| | | } |
| | | } |
| | | if (3 == paymentType) { |
| | | IcbcRefundReq refundReq = new IcbcRefundReq(); |
| | | refundReq.setOutTradeNo(shoppingOrder.getCode()); |
| | | refundReq.setOrderId(shoppingOrder.getSerialNumber()); |
| | | refundReq.setOutRefundNo(shoppingOrderRefund.getRefundCode()); |
| | | refundReq.setRefundAmount(refundAmount); |
| | | refundReq.setTotalAmount(shoppingOrder.getPaymentAmount()); |
| | | refundReq.setReason("取消商城订单"); |
| | | R<IcbcRefundResp> refundResult = icbcPaymentClient.refund(refundReq); |
| | | IcbcRefundResp refundResp = refundResult == null ? null : refundResult.getData(); |
| | | if (refundResult == null || refundResult.getCode() != 200 || refundResp == null || !"SUCCESS".equals(refundResp.getStatus())) { |
| | | return AjaxResult.error(refundResult == null ? "工行退款无响应" : refundResult.getMsg()); |
| | | } |
| | | shoppingOrderRefundService.save(shoppingOrderRefund); |
| | | cancelShoppingOrderWxRefund(shoppingOrderRefund.getRefundCode(), refundResp.getRefundId(), "SUCCESS", refundResp.getRefundTime()); |
| | | } |
| | | return AjaxResult.success(); |
| | | } |
| | |
| | | |
| | | @Override |
| | | public void callBack(String code,String outTradeNo) { |
| | | //改变订单状态 |
| | | TShoppingOrder shoppingOrder = this.baseMapper.selectOne(Wrappers.lambdaQuery(TShoppingOrder.class).eq(TShoppingOrder::getCode, code)); |
| | | shoppingOrder.setPaymentStatus(2); |
| | | shoppingOrder.setSerialNumber(outTradeNo); |
| | | shoppingOrder.setPayTime(LocalDateTime.now()); |
| | | this.updateById(shoppingOrder); |
| | | if (shoppingOrder == null) { |
| | | throw new IllegalArgumentException("商城订单不存在:" + code); |
| | | } |
| | | boolean updated = this.update(new LambdaUpdateWrapper<TShoppingOrder>() |
| | | .eq(TShoppingOrder::getId, shoppingOrder.getId()) |
| | | .eq(TShoppingOrder::getPaymentStatus, 1) |
| | | .set(TShoppingOrder::getPaymentStatus, 2) |
| | | .set(TShoppingOrder::getSerialNumber, outTradeNo) |
| | | .set(TShoppingOrder::getPayTime, LocalDateTime.now())); |
| | | if (!updated) { |
| | | return; |
| | | } |
| | | //如果是优惠券,赠送优惠券 |
| | | if (shoppingOrder.getOrderType()==2){ |
| | | GrantCouponDto grantCouponDto = new GrantCouponDto(); |
| | |
| | | </select> |
| | | <select id="charge" resultType="com.ruoyi.order.dto.SixChargingDto"> |
| | | <choose> |
| | | <when test="partnerView != null and partnerView"> |
| | | SELECT |
| | | DATE_FORMAT(a.create_time, '%m') AS MONTH, |
| | | ROUND(SUM(IFNULL(s.electricity_share_amount, 0)), 2) AS electrovalence, |
| | | ROUND(SUM(IFNULL(s.service_share_amount, 0)), 2) AS service_charge |
| | | FROM t_charging_order a |
| | | LEFT JOIN ( |
| | | SELECT charging_order_id, |
| | | SUM(IFNULL(electricity_share_amount, 0)) AS electricity_share_amount, |
| | | SUM(IFNULL(service_share_amount, 0)) AS service_share_amount |
| | | FROM t_charging_order_share_record |
| | | WHERE del_flag = 0 AND charging_order_id IS NOT NULL AND online_share_status = 'SUCCESS' |
| | | GROUP BY charging_order_id |
| | | ) s ON a.id = s.charging_order_id |
| | | <where> |
| | | a.del_flag = 0 and a.recharge_payment_status = 2 |
| | | <if test="sixBefore != null"> |
| | | AND a.create_time >= #{sixBefore} |
| | | </if> |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND a.site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | </where> |
| | | GROUP BY DATE_FORMAT(a.create_time, '%m') |
| | | </when> |
| | | <otherwise> |
| | | SELECT |
| | | DATE_FORMAT(a.create_time, '%m') AS MONTH, |
| | | SUM(IFNULL(b.period_electric_price, 0)) AS electrovalence, |
| | | SUM( |
| | | CASE |
| | | WHEN a.order_source = 0 THEN IFNULL(b.period_service_price, 0) |
| | | WHEN a.order_source = 1 THEN IFNULL(b.period_service_price, 0) |
| | | ELSE IFNULL(b.period_service_price, 0) * 0.8 |
| | | END |
| | | ) AS service_charge |
| | | FROM |
| | | t_charging_order a |
| | | LEFT JOIN t_charging_order_accounting_strategy b ON a.id = b.charging_order_id |
| | | <where> |
| | | a.del_flag = 0 and a.recharge_payment_status = 2 and a.status = 5 |
| | | <if test="sixBefore != null"> |
| | | AND a.create_time >= #{sixBefore} |
| | | </if> |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND a.site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | </where> |
| | | GROUP BY |
| | | DATE_FORMAT(a.create_time, '%m') |
| | | </otherwise> |
| | | <when test="partnerView != null and partnerView"> |
| | | SELECT DATE_FORMAT(create_time, '%m') AS MONTH, |
| | | ROUND(SUM(IFNULL(electricity_share_amount, 0)), 2) AS electrovalence, |
| | | ROUND(SUM(IFNULL(service_share_amount, 0)), 2) AS service_charge |
| | | FROM t_charging_order_share_record |
| | | WHERE del_flag = 0 AND online_share_status IN ('SUCCESS', 'RECORDED') |
| | | <if test="sixBefore != null"> |
| | | AND create_time >= #{sixBefore} |
| | | </if> |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | GROUP BY DATE_FORMAT(create_time, '%m') |
| | | </when> |
| | | <otherwise> |
| | | SELECT DATE_FORMAT(billing_cycle, '%m') AS MONTH, |
| | | ROUND(SUM(IFNULL(total_electricity_charge, 0)), 2) AS electrovalence, |
| | | ROUND(SUM(IFNULL(total_service_fee, 0) - IFNULL(tripartite_commission, 0)), 2) AS service_charge |
| | | FROM t_charging_settlement_bill |
| | | WHERE statistical_date_type = 1 AND site_id != 0 |
| | | <if test="sixBefore != null"> |
| | | AND billing_cycle >= #{sixBefore} |
| | | </if> |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | GROUP BY DATE_FORMAT(billing_cycle, '%m') |
| | | </otherwise> |
| | | </choose> |
| | | |
| | | |
| | | </select> |
| | | |
| | | <select id="circle" resultType="com.ruoyi.order.dto.SixCircleDto"> |
| | | <choose> |
| | | <when test="partnerView != null and partnerView"> |
| | | SELECT |
| | | a.site_id as siteId, |
| | | ROUND(SUM(IFNULL(s.share_amount, 0)), 2) AS paymentAmount |
| | | FROM t_charging_order a |
| | | LEFT JOIN ( |
| | | SELECT charging_order_id, SUM(IFNULL(share_amount, 0)) AS share_amount |
| | | FROM t_charging_order_share_record |
| | | WHERE del_flag = 0 AND charging_order_id IS NOT NULL AND online_share_status = 'SUCCESS' |
| | | GROUP BY charging_order_id |
| | | ) s ON a.id = s.charging_order_id |
| | | <where> |
| | | a.del_flag = 0 and a.recharge_payment_status = 2 |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND a.site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | <if test="sixBefore != null"> |
| | | AND a.create_time >= #{sixBefore} |
| | | </if> |
| | | </where> |
| | | GROUP BY a.site_id |
| | | </when> |
| | | <otherwise> |
| | | SELECT |
| | | a.site_id as siteId, |
| | | ROUND(SUM(CASE |
| | | WHEN a.order_source = 0 THEN IFNULL(b.period_electric_price, 0) + IFNULL(b.period_service_price, 0) |
| | | WHEN a.order_source = 1 THEN IFNULL(b.period_electric_price, 0) + IFNULL(b.period_service_price, 0) |
| | | ELSE (IFNULL(b.period_electric_price, 0) + IFNULL(b.period_service_price, 0) * 0.8) |
| | | END), 2) AS paymentAmount |
| | | FROM |
| | | t_charging_order a |
| | | LEFT JOIN t_charging_order_accounting_strategy b ON a.id = b.charging_order_id |
| | | <where> |
| | | a.del_flag = 0 and a.recharge_payment_status = 2 and a.status = 5 |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND a.site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | <if test="sixBefore != null"> |
| | | AND a.create_time >= #{sixBefore} |
| | | </if> |
| | | </where> |
| | | GROUP BY a.site_id |
| | | </otherwise> |
| | | <when test="partnerView != null and partnerView"> |
| | | SELECT site_id AS siteId, |
| | | ROUND(SUM(IFNULL(share_amount, 0)), 2) AS paymentAmount |
| | | FROM t_charging_order_share_record |
| | | WHERE del_flag = 0 AND online_share_status IN ('SUCCESS', 'RECORDED') |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | <if test="sixBefore != null"> |
| | | AND create_time >= #{sixBefore} |
| | | </if> |
| | | GROUP BY site_id |
| | | </when> |
| | | <otherwise> |
| | | SELECT site_id AS siteId, |
| | | ROUND(SUM(IFNULL(total_electricity_charge, 0) + IFNULL(total_service_fee, 0) |
| | | - IFNULL(tripartite_commission, 0)), 2) AS paymentAmount |
| | | FROM t_charging_settlement_bill |
| | | WHERE statistical_date_type = 1 AND site_id != 0 |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | <if test="sixBefore != null"> |
| | | AND billing_cycle >= #{sixBefore} |
| | | </if> |
| | | GROUP BY site_id |
| | | </otherwise> |
| | | </choose> |
| | | |
| | | |
| | | </select> |
| | | |
| | | <select id="countAll" resultType="java.util.Map"> |
| | | SELECT |
| | | <choose> |
| | | <when test="partnerView != null and partnerView"> |
| | | ROUND(SUM(IFNULL(s.electricity_share_amount, 0)), 2) AS electrovalence, |
| | | ROUND(SUM(IFNULL(s.service_share_amount, 0)), 2) AS service_charge, |
| | | ROUND(SUM(IFNULL(s.share_amount, 0)), 2) AS commission_amount, |
| | | 0 AS sharing_amount |
| | | </when> |
| | | <otherwise> |
| | | ROUND(SUM(IFNULL(b.period_electric_price, 0)), 2) AS electrovalence, |
| | | ROUND(SUM(CASE WHEN a.order_source = 2 THEN IFNULL(b.period_service_price, 0) * 0.8 ELSE IFNULL(b.period_service_price, 0) END), 2) AS service_charge, |
| | | ROUND(SUM(IFNULL(s.share_amount, 0)), 2) AS commission_amount, |
| | | ROUND(SUM(CASE WHEN a.order_source = 2 THEN IFNULL(b.period_service_price, 0) * 0.2 ELSE 0 END), 2) AS sharing_amount |
| | | </otherwise> |
| | | <when test="partnerView != null and partnerView"> |
| | | SELECT COALESCE(ROUND(SUM(IFNULL(electricity_share_amount, 0)), 2), 0) AS electrovalence, |
| | | COALESCE(ROUND(SUM(IFNULL(service_share_amount, 0)), 2), 0) AS service_charge, |
| | | COALESCE(ROUND(SUM(IFNULL(share_amount, 0)), 2), 0) AS commission_amount, |
| | | 0 AS sharing_amount |
| | | FROM t_charging_order_share_record |
| | | WHERE del_flag = 0 AND online_share_status IN ('SUCCESS', 'RECORDED') |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | </when> |
| | | <otherwise> |
| | | SELECT COALESCE(ROUND(SUM(IFNULL(total_electricity_charge, 0)), 2), 0) AS electrovalence, |
| | | COALESCE(ROUND(SUM(IFNULL(total_service_fee, 0) - IFNULL(tripartite_commission, 0)), 2), 0) AS service_charge, |
| | | 0 AS commission_amount, |
| | | COALESCE(ROUND(SUM(IFNULL(tripartite_commission, 0)), 2), 0) AS sharing_amount |
| | | FROM t_charging_settlement_bill |
| | | WHERE statistical_date_type = 1 AND site_id != 0 |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | </otherwise> |
| | | </choose> |
| | | FROM t_charging_order a |
| | | LEFT JOIN ( |
| | | SELECT charging_order_id, |
| | | SUM(IFNULL(period_electric_price, 0)) AS period_electric_price, |
| | | SUM(IFNULL(period_service_price, 0)) AS period_service_price |
| | | FROM t_charging_order_accounting_strategy |
| | | GROUP BY charging_order_id |
| | | ) b ON a.id = b.charging_order_id |
| | | LEFT JOIN ( |
| | | SELECT charging_order_id, |
| | | SUM(IFNULL(electricity_share_amount, 0)) AS electricity_share_amount, |
| | | SUM(IFNULL(service_share_amount, 0)) AS service_share_amount, |
| | | SUM(IFNULL(share_amount, 0)) AS share_amount |
| | | FROM t_charging_order_share_record |
| | | WHERE del_flag = 0 AND charging_order_id IS NOT NULL AND online_share_status = 'SUCCESS' |
| | | GROUP BY charging_order_id |
| | | ) s ON a.id = s.charging_order_id |
| | | WHERE a.del_flag = 0 AND a.recharge_payment_status = 2 |
| | | <if test="partnerView == null or !partnerView"> |
| | | AND a.status = 5 |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="sumSuccessfulShareAmount" resultType="java.math.BigDecimal"> |
| | | SELECT COALESCE(ROUND(SUM(IFNULL(share_amount, 0)), 2), 0) |
| | | FROM t_charging_order_share_record |
| | | WHERE del_flag = 0 AND online_share_status IN ('SUCCESS', 'RECORDED') |
| | | <if test="siteIds != null and siteIds.size() > 0"> |
| | | AND a.site_id IN |
| | | AND site_id IN |
| | | <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| New file |
| | |
| | | package com.ruoyi.order.controller; |
| | | |
| | | import com.ruoyi.order.api.vo.TOrderInvoiceVO; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.test.util.ReflectionTestUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; |
| | | import static org.junit.jupiter.api.Assertions.assertNotNull; |
| | | |
| | | class TOrderInvoiceControllerTest { |
| | | |
| | | @Test |
| | | void buildsWorkbookForSingleInvoice() { |
| | | TOrderInvoiceVO invoice = new TOrderInvoiceVO(); |
| | | invoice.setId(2034946998168854530L); |
| | | invoice.setCode("16120260320185546502"); |
| | | invoice.setName("测试企业"); |
| | | invoice.setTotalAmount(new BigDecimal("51.20")); |
| | | |
| | | TOrderInvoiceController controller = new TOrderInvoiceController(); |
| | | Workbook workbook = ReflectionTestUtils.invokeMethod(controller, "buildInvoiceWorkbook", invoice); |
| | | |
| | | assertNotNull(workbook); |
| | | assertDoesNotThrow(() -> workbook.close()); |
| | | } |
| | | } |
| | |
| | | |
| | | partner.setIcbcSubMerPrtclNo("2310119900550201"); |
| | | assertTrue(TChargingOrderServiceImpl.shouldProcessIcbcOnlineShare("ICBC", new BigDecimal("1.00"), partner)); |
| | | assertFalse(TChargingOrderServiceImpl.shouldProcessIcbcOnlineShare(false, "ICBC", new BigDecimal("1.00"), partner)); |
| | | assertFalse(TChargingOrderServiceImpl.shouldProcessIcbcOnlineShare("ICBC", BigDecimal.ZERO, partner)); |
| | | assertFalse(TChargingOrderServiceImpl.shouldProcessIcbcOnlineShare("BALANCE", new BigDecimal("1.00"), partner)); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.order.service.impl; |
| | | |
| | | import com.ruoyi.order.mapper.TChargingOrderMapper; |
| | | import org.junit.jupiter.api.BeforeEach; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.test.util.ReflectionTestUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertSame; |
| | | import static org.mockito.Mockito.mock; |
| | | import static org.mockito.Mockito.never; |
| | | import static org.mockito.Mockito.verify; |
| | | import static org.mockito.Mockito.when; |
| | | |
| | | class PlatformRevenueAnalysisTest { |
| | | private TChargingOrderServiceImpl service; |
| | | private TChargingOrderMapper mapper; |
| | | private List<Integer> siteIds; |
| | | |
| | | @BeforeEach |
| | | void setUp() { |
| | | service = new TChargingOrderServiceImpl(); |
| | | mapper = mock(TChargingOrderMapper.class); |
| | | siteIds = new ArrayList<>(); |
| | | siteIds.add(122); |
| | | siteIds.add(123); |
| | | ReflectionTestUtils.setField(service, "baseMapper", mapper); |
| | | } |
| | | |
| | | @Test |
| | | void platformViewAddsSuccessfulPartnerShareAmount() { |
| | | Map<String, Object> totals = new HashMap<>(); |
| | | totals.put("electrovalence", new BigDecimal("100.00")); |
| | | when(mapper.countAll(siteIds, false)).thenReturn(totals); |
| | | when(mapper.sumSuccessfulShareAmount(siteIds)).thenReturn(new BigDecimal("12.34")); |
| | | |
| | | Map<String, Object> result = service.countAll(siteIds, false); |
| | | |
| | | assertSame(totals, result); |
| | | assertEquals(new BigDecimal("12.34"), result.get("commission_amount")); |
| | | verify(mapper).sumSuccessfulShareAmount(siteIds); |
| | | } |
| | | |
| | | @Test |
| | | void partnerViewUsesShareRecordTotalsWithoutASecondQuery() { |
| | | Map<String, Object> totals = new HashMap<>(); |
| | | totals.put("commission_amount", new BigDecimal("8.90")); |
| | | when(mapper.countAll(siteIds, true)).thenReturn(totals); |
| | | |
| | | Map<String, Object> result = service.countAll(siteIds, true); |
| | | |
| | | assertSame(totals, result); |
| | | assertEquals(new BigDecimal("8.90"), result.get("commission_amount")); |
| | | verify(mapper, never()).sumSuccessfulShareAmount(siteIds); |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.other.service.TGoodsService; |
| | | import com.ruoyi.other.util.RedisLock; |
| | | import com.ruoyi.payment.api.feignClient.AliPaymentClient; |
| | | import com.ruoyi.payment.api.feignClient.WxPaymentClient; |
| | | import com.ruoyi.payment.api.feignClient.IcbcPaymentClient; |
| | | import com.ruoyi.payment.api.vo.AliPaymentReq; |
| | | import com.ruoyi.payment.api.vo.AliPaymentResp; |
| | | import com.ruoyi.payment.api.vo.PaymentOrder; |
| | | import com.ruoyi.payment.api.vo.IcbcPaymentReq; |
| | | import com.ruoyi.payment.api.vo.IcbcPaymentResp; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | |
| | | @Resource |
| | | private TCouponService couponService; |
| | | @Resource |
| | | private WxPaymentClient wxPaymentClient; |
| | | private IcbcPaymentClient icbcPaymentClient; |
| | | @Resource |
| | | private RedisService redisService; |
| | | |
| | |
| | | exchangeDto.setVipDiscount(vipDiscount); |
| | | exchangeDto.setUserId(userId); |
| | | exchangeDto.setPhone(user.getPhone()); |
| | | boolean wechatMiniProgramPay = exchangeDto.getPayMethod() == 1; |
| | | if (wechatMiniProgramPay) { |
| | | exchangeDto.setPayMethod(3); |
| | | } |
| | | //创建订单 |
| | | TShoppingOrder shopOrder = orderClient.shopCreate(exchangeDto).getData(); |
| | | if (exchangeDto.getPayMethod()==1) { |
| | | //调起支付 |
| | | PaymentOrder paymentOrder = new PaymentOrder(); |
| | | paymentOrder.setCode(shopOrder.getCode()); |
| | | paymentOrder.setAmount(exchangeDto.getPayPrice()); |
| | | paymentOrder.setOpenId(user.getWxOpenid()); |
| | | paymentOrder.setDescription("购买商品"); |
| | | R<Map<String, Object>> mapR = wxPaymentClient.orderPay(paymentOrder); |
| | | mapR.getData().put("orderId",shopOrder.getId().toString()); |
| | | return mapR; |
| | | if (wechatMiniProgramPay) { |
| | | IcbcPaymentReq paymentReq = new IcbcPaymentReq(); |
| | | paymentReq.setOutTradeNo(shopOrder.getCode()); |
| | | paymentReq.setAmount(exchangeDto.getPayPrice()); |
| | | paymentReq.setOpenId(user.getWxOpenid()); |
| | | paymentReq.setPaymentType(1); |
| | | paymentReq.setSubject("购买商品"); |
| | | paymentReq.setBody(exchangeDto.getTitle()); |
| | | R<IcbcPaymentResp> paymentResult = icbcPaymentClient.payment(paymentReq); |
| | | if (paymentResult == null || paymentResult.getCode() != 200 || paymentResult.getData() == null) { |
| | | return R.fail(paymentResult == null ? "工行支付无响应" : paymentResult.getMsg()); |
| | | } |
| | | IcbcPaymentResp paymentResp = paymentResult.getData(); |
| | | if (!"SUCCESS".equals(paymentResp.getStatus())) { |
| | | return R.fail(paymentResp.getRawResponse()); |
| | | } |
| | | Map<String, Object> data = JSON.parseObject(JSON.toJSONString(paymentResp), Map.class); |
| | | data.put("orderId", shopOrder.getId().toString()); |
| | | return R.ok(data); |
| | | }else { |
| | | AliPaymentReq req = new AliPaymentReq(); |
| | | req.setOutTradeNo(shopOrder.getCode()); |
| | |
| | | import com.ruoyi.other.service.TVipService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.payment.api.feignClient.AliPaymentClient; |
| | | import com.ruoyi.payment.api.feignClient.WxPaymentClient; |
| | | import com.ruoyi.payment.api.feignClient.IcbcPaymentClient; |
| | | import com.ruoyi.payment.api.vo.AliPaymentReq; |
| | | import com.ruoyi.payment.api.vo.AliPaymentResp; |
| | | import com.ruoyi.payment.api.vo.PaymentOrder; |
| | | import com.ruoyi.payment.api.vo.IcbcPaymentReq; |
| | | import com.ruoyi.payment.api.vo.IcbcPaymentResp; |
| | | import org.apache.poi.util.StringUtil; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | private AppUserClient appUserClient; |
| | | |
| | | @Resource |
| | | private WxPaymentClient wxPaymentClient; |
| | | private IcbcPaymentClient icbcPaymentClient; |
| | | @Resource |
| | | private AliPaymentClient aliPaymentClient; |
| | | |
| | |
| | | shopOrder.setDiscountAmount(discountMoney); |
| | | shopOrder.setPaymentAmount(payMoney); |
| | | shopOrder.setPaymentStatus(1); |
| | | shopOrder.setPaymentType(payType); |
| | | shopOrder.setPaymentType(payType == 1 ? 3 : payType); |
| | | shopOrder.setPayTime(LocalDateTime.now()); |
| | | shopOrder.setDelFlag(false); |
| | | R<Long> longR = orderClient.addVipOrder(shopOrder); |
| | |
| | | } |
| | | |
| | | if (payType==1){ |
| | | //调起支付 |
| | | PaymentOrder paymentOrder = new PaymentOrder(); |
| | | paymentOrder.setCode(shopOrder.getCode()); |
| | | paymentOrder.setAmount(shopOrder.getPaymentAmount()); |
| | | paymentOrder.setOpenId(user.getWxOpenid()); |
| | | paymentOrder.setDescription("购买会员"); |
| | | return AjaxResult.success(wxPaymentClient.orderPay(paymentOrder).getData()); |
| | | IcbcPaymentReq paymentReq = new IcbcPaymentReq(); |
| | | paymentReq.setOutTradeNo(shopOrder.getCode()); |
| | | paymentReq.setAmount(shopOrder.getPaymentAmount()); |
| | | paymentReq.setOpenId(user.getWxOpenid()); |
| | | paymentReq.setPaymentType(1); |
| | | paymentReq.setSubject("购买会员"); |
| | | paymentReq.setBody(shopOrder.getTitle()); |
| | | R<IcbcPaymentResp> paymentResult = icbcPaymentClient.payment(paymentReq); |
| | | if (paymentResult == null || paymentResult.getCode() != 200 || paymentResult.getData() == null) { |
| | | return AjaxResult.error(paymentResult == null ? "工行支付无响应" : paymentResult.getMsg()); |
| | | } |
| | | IcbcPaymentResp paymentResp = paymentResult.getData(); |
| | | if (!"SUCCESS".equals(paymentResp.getStatus())) { |
| | | return AjaxResult.error(paymentResp.getRawResponse()); |
| | | } |
| | | return AjaxResult.success(paymentResp); |
| | | }else { |
| | | AliPaymentReq req = new AliPaymentReq(); |
| | | req.setOutTradeNo(shopOrder.getCode()); |
| | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.order.api.feignClient.ChargingOrderClient; |
| | | import com.ruoyi.order.api.feignClient.OrderClient; |
| | | import com.ruoyi.payment.api.vo.IcbcPaymentReq; |
| | | import com.ruoyi.payment.api.vo.IcbcPaymentResp; |
| | | import com.ruoyi.payment.api.vo.IcbcRefundReq; |
| | |
| | | |
| | | @Resource |
| | | private ChargingOrderClient chargingOrderClient; |
| | | |
| | | @Resource |
| | | private OrderClient orderClient; |
| | | |
| | | @PostMapping("/payment") |
| | | public R<IcbcPaymentResp> payment(@RequestBody IcbcPaymentReq req) { |
| | |
| | | callback.get("out_trade_no"), callback.get("transaction_id")); |
| | | } |
| | | log.info("工行支付回调解析结果:{}", JSON.toJSONString(callback)); |
| | | dispatchChargingOrderCallback(callback); |
| | | dispatchPaymentCallback(callback); |
| | | success = true; |
| | | } catch (Exception e) { |
| | | log.error("工行支付回调处理失败,已记录原始请求并返回fail等待重试", e); |
| | |
| | | return values == null || values.length == 0 ? null : values[0]; |
| | | } |
| | | |
| | | private void dispatchChargingOrderCallback(Map<String, String> callback) { |
| | | void dispatchPaymentCallback(Map<String, String> callback) { |
| | | String outTradeNo = callback.get("out_trade_no"); |
| | | String transactionId = callback.get("transaction_id"); |
| | | String attach = callback.get("attach"); |
| | |
| | | log.info("工行测试支付回调成功,订单号:{},流水号:{},支付类型:{}", outTradeNo, transactionId, attach); |
| | | return; |
| | | } |
| | | if (outTradeNo != null && outTradeNo.startsWith("HY")) { |
| | | orderClient.vipCallBack(outTradeNo, transactionId); |
| | | return; |
| | | } |
| | | if (outTradeNo != null && outTradeNo.startsWith("GW")) { |
| | | orderClient.callBack(outTradeNo, transactionId); |
| | | return; |
| | | } |
| | | if (outTradeNo == null || !outTradeNo.startsWith("CD")) { |
| | | throw new IllegalArgumentException("工行回调订单类型不支持:" + outTradeNo); |
| | | } |
| | | Integer paymentType = Integer.valueOf(attach); |
| | | if (Integer.valueOf(1).equals(paymentType)) { |
| | | chargingOrderClient.chargingOrderWXCallback(outTradeNo, transactionId, attach); |
| | |
| | | JSONObject responseObject = parseObject(responseJson); |
| | | IcbcPaymentFlowRecord record = new IcbcPaymentFlowRecord(); |
| | | record.setOutTradeNo(outTradeNo); |
| | | record.setBusinessType(outTradeNo != null && outTradeNo.startsWith("ICBCTEST") ? "TEST" : "CHARGING_ORDER"); |
| | | record.setBusinessType(resolveBusinessType(outTradeNo)); |
| | | record.setEventType(eventType); |
| | | record.setPaymentType(paymentType); |
| | | record.setAmount(amount); |
| | |
| | | private String truncate(String value, int maxLength) { |
| | | return value == null || value.length() <= maxLength ? value : value.substring(0, maxLength); |
| | | } |
| | | |
| | | private String resolveBusinessType(String outTradeNo) { |
| | | if (outTradeNo != null && outTradeNo.startsWith("ICBCTEST")) { |
| | | return "TEST"; |
| | | } |
| | | if (outTradeNo != null && outTradeNo.startsWith("HY")) { |
| | | return "VIP_ORDER"; |
| | | } |
| | | if (outTradeNo != null && outTradeNo.startsWith("GW")) { |
| | | return "SHOPPING_ORDER"; |
| | | } |
| | | return "CHARGING_ORDER"; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.payment.controller; |
| | | |
| | | import com.ruoyi.order.api.feignClient.ChargingOrderClient; |
| | | import com.ruoyi.order.api.feignClient.OrderClient; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.junit.jupiter.api.extension.ExtendWith; |
| | | import org.mockito.InjectMocks; |
| | | import org.mockito.Mock; |
| | | import org.mockito.junit.jupiter.MockitoExtension; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | import static org.mockito.Mockito.verify; |
| | | import static org.mockito.Mockito.verifyNoInteractions; |
| | | |
| | | @ExtendWith(MockitoExtension.class) |
| | | class IcbcPayControllerDispatchTest { |
| | | |
| | | @Mock |
| | | private ChargingOrderClient chargingOrderClient; |
| | | |
| | | @Mock |
| | | private OrderClient orderClient; |
| | | |
| | | @InjectMocks |
| | | private IcbcPayController controller; |
| | | |
| | | @Test |
| | | void dispatchesVipOrderByOrderPrefix() { |
| | | controller.dispatchPaymentCallback(callback("HY202607210001", "ICBC-VIP-1", "1")); |
| | | |
| | | verify(orderClient).vipCallBack("HY202607210001", "ICBC-VIP-1"); |
| | | verifyNoInteractions(chargingOrderClient); |
| | | } |
| | | |
| | | @Test |
| | | void dispatchesShoppingOrderByOrderPrefix() { |
| | | controller.dispatchPaymentCallback(callback("GW202607210001", "ICBC-SHOP-1", "1")); |
| | | |
| | | verify(orderClient).callBack("GW202607210001", "ICBC-SHOP-1"); |
| | | verifyNoInteractions(chargingOrderClient); |
| | | } |
| | | |
| | | @Test |
| | | void keepsChargingOrderPaymentTypeDispatch() { |
| | | controller.dispatchPaymentCallback(callback("CD202607210001", "ICBC-CHARGE-1", "1")); |
| | | |
| | | verify(chargingOrderClient).chargingOrderWXCallback("CD202607210001", "ICBC-CHARGE-1", "1"); |
| | | verifyNoInteractions(orderClient); |
| | | } |
| | | |
| | | private Map<String, String> callback(String outTradeNo, String transactionId, String attach) { |
| | | Map<String, String> callback = new HashMap<>(); |
| | | callback.put("out_trade_no", outTradeNo); |
| | | callback.put("transaction_id", transactionId); |
| | | callback.put("attach", attach); |
| | | return callback; |
| | | } |
| | | } |