From 700cbb19a285e639bb05404503efa3da9988c083 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期二, 21 七月 2026 22:53:55 +0800
Subject: [PATCH] 分账可开关

---
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java           |   70 +++++
 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TShoppingOrder.java                         |    2 
 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TVipServiceImpl.java                     |   32 +
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java           |   50 +++
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java                      |    2 
 ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/controller/TOrderInvoiceControllerTest.java           |   29 ++
 ruoyi-service/ruoyi-payment/src/test/java/com/ruoyi/payment/controller/IcbcPayControllerDispatchTest.java     |   60 +++++
 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TVipOrder.java                              |    2 
 ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/IcbcPayController.java                 |   19 +
 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGoodsController.java                      |   40 ++-
 ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml                        |    1 
 ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingOrderShareConfigurationTest.java |    1 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java               |    5 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PayOrderInfoDto.java                              |    2 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java              |   31 ++
 ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/mapper/SiteMapperVisibilityTest.java    |    2 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TVipOrderController.java                   |   15 +
 ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml                            |  250 ++++++++------------
 ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/PlatformRevenueAnalysisTest.java         |   62 +++++
 ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/icbc/service/IcbcPaymentFlowRecorder.java         |   15 +
 20 files changed, 496 insertions(+), 194 deletions(-)

diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TShoppingOrder.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TShoppingOrder.java
index 16a7aea..62ac512 100644
--- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TShoppingOrder.java
+++ b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TShoppingOrder.java
@@ -93,7 +93,7 @@
     @TableField("payment_status")
     private Integer paymentStatus;
 
-    @ApiModelProperty(value = "支付方式(1=微信,2=支付宝)")
+    @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=工商银行)")
     @TableField("payment_type")
     private Integer paymentType;
 
diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TVipOrder.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TVipOrder.java
index 35ebd28..6429838 100644
--- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TVipOrder.java
+++ b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TVipOrder.java
@@ -80,7 +80,7 @@
     @TableField("payment_status")
     private Integer paymentStatus;
 
-    @ApiModelProperty(value = "支付方式(1=微信,2=支付宝)")
+    @ApiModelProperty(value = "支付方式(1=微信,2=支付宝,3=工商银行)")
     @TableField("payment_type")
     private Integer paymentType;
 
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
index 1cd169b..99547a6 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
@@ -196,7 +196,6 @@
 			</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">
diff --git a/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/mapper/SiteMapperVisibilityTest.java b/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/mapper/SiteMapperVisibilityTest.java
index c5001a0..8e34ab3 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/mapper/SiteMapperVisibilityTest.java
+++ b/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/mapper/SiteMapperVisibilityTest.java
@@ -6,6 +6,7 @@
 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 {
@@ -19,5 +20,6 @@
         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"));
     }
 }
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java
index 0c090a1..12bfda9 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java
@@ -230,7 +230,10 @@
 		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) {
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java
index 2a03221..5b25cf7 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java
@@ -36,11 +36,14 @@
 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;
@@ -81,6 +84,8 @@
 	private AliPaymentClient aliPaymentClient;
 	@Resource
 	private WxPaymentClient wxPaymentClient;
+	@Resource
+	private IcbcPaymentClient icbcPaymentClient;
 	@Resource
 	private AppCouponClient appCouponClient;
 	@Resource
@@ -208,7 +213,7 @@
 		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);
@@ -276,6 +281,30 @@
 					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();
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TVipOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TVipOrderController.java
index 44d164b..2009a50 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TVipOrderController.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TVipOrderController.java
@@ -141,9 +141,18 @@
     @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());
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PayOrderInfoDto.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PayOrderInfoDto.java
index 1eb02d8..6f38492 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PayOrderInfoDto.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/PayOrderInfoDto.java
@@ -16,7 +16,7 @@
     private String code;
     @ApiModelProperty("支付流水号")
     private String tradeNo;
-    @ApiModelProperty("1微信2支付宝")
+    @ApiModelProperty("1微信2支付宝3工商银行")
     private Integer payType;
     @ApiModelProperty("支付金额")
     private BigDecimal payAmount;
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java
index 93f27e4..89c1a50 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java
@@ -96,6 +96,8 @@
 
 	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);
 
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
index b0d733f..621e638 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -88,6 +88,7 @@
 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;
@@ -168,6 +169,8 @@
 	private IcbcPaymentClient icbcPaymentClient;
 	@Resource
 	private TChargingOrderShareRecordMapper chargingOrderShareRecordMapper;
+	@Value("${icbc.share.online-enabled:false}")
+	private boolean icbcOnlineShareEnabled;
 	@Resource
 	private ChargingOrderSettlementExecutor chargingOrderSettlementExecutor;
 	@Resource
@@ -3111,7 +3114,11 @@
 	
 	@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;
 	}
 
 	/**
@@ -5237,7 +5244,7 @@
 			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()) {
@@ -5281,6 +5288,29 @@
 					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());
@@ -5318,7 +5348,7 @@
 			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()) {
@@ -5361,6 +5391,27 @@
 					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();
@@ -7531,11 +7582,13 @@
 			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);
@@ -7728,7 +7781,12 @@
 	}
 
 	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
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java
index b6a365f..3c366cc 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java
@@ -2,6 +2,7 @@
 
 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;
@@ -29,11 +30,15 @@
 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;
@@ -85,6 +90,9 @@
 
     @Resource
     private AliPaymentClient aliPaymentClient;
+
+    @Resource
+    private IcbcPaymentClient icbcPaymentClient;
 
     @Resource
     private TShoppingOrderRefundService shoppingOrderRefundService;
@@ -387,7 +395,7 @@
         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();
@@ -413,6 +421,13 @@
             }
             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 ? "工行支付查询无响应" : "订单尚未支付成功,不能退款");
             }
         }
         //退款成功后需要判断商品库存类型后决定是否需要回退库存
@@ -473,6 +488,22 @@
                 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();
     }
@@ -588,12 +619,19 @@
 
     @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();
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
index 35437f1..430db87 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
+++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
@@ -407,162 +407,120 @@
     </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 &gt;= #{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 &gt;= #{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 &gt;= #{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 &gt;= #{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 &gt;= #{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 &gt;= #{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 &gt;= #{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 &gt;= #{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>
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/controller/TOrderInvoiceControllerTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/controller/TOrderInvoiceControllerTest.java
new file mode 100644
index 0000000..9f3c301
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/controller/TOrderInvoiceControllerTest.java
@@ -0,0 +1,29 @@
+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());
+    }
+}
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingOrderShareConfigurationTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingOrderShareConfigurationTest.java
index 950ea25..c0df5de 100644
--- a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingOrderShareConfigurationTest.java
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingOrderShareConfigurationTest.java
@@ -20,6 +20,7 @@
 
         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));
     }
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/PlatformRevenueAnalysisTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/PlatformRevenueAnalysisTest.java
new file mode 100644
index 0000000..5d9aaf7
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/PlatformRevenueAnalysisTest.java
@@ -0,0 +1,62 @@
+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);
+    }
+}
diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGoodsController.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGoodsController.java
index 93a1dd2..87c82d3 100644
--- a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGoodsController.java
+++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGoodsController.java
@@ -36,10 +36,11 @@
 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;
@@ -80,7 +81,7 @@
     @Resource
     private TCouponService couponService;
     @Resource
-    private WxPaymentClient wxPaymentClient;
+    private IcbcPaymentClient icbcPaymentClient;
     @Resource
     private RedisService redisService;
     
@@ -379,18 +380,31 @@
         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());
diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TVipServiceImpl.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TVipServiceImpl.java
index 47fb78a..2627cd2 100644
--- a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TVipServiceImpl.java
+++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TVipServiceImpl.java
@@ -20,10 +20,11 @@
 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;
@@ -52,7 +53,7 @@
     private AppUserClient appUserClient;
 
     @Resource
-    private WxPaymentClient wxPaymentClient;
+    private IcbcPaymentClient icbcPaymentClient;
     @Resource
     private AliPaymentClient aliPaymentClient;
 
@@ -109,7 +110,7 @@
         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);
@@ -118,13 +119,22 @@
         }
     
         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());
diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/IcbcPayController.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/IcbcPayController.java
index 54f6821..7e26bcd 100644
--- a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/IcbcPayController.java
+++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/controller/IcbcPayController.java
@@ -4,6 +4,7 @@
 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;
@@ -51,6 +52,9 @@
 
     @Resource
     private ChargingOrderClient chargingOrderClient;
+
+    @Resource
+    private OrderClient orderClient;
 
     @PostMapping("/payment")
     public R<IcbcPaymentResp> payment(@RequestBody IcbcPaymentReq req) {
@@ -242,7 +246,7 @@
                         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);
@@ -304,7 +308,7 @@
         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");
@@ -312,6 +316,17 @@
             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);
diff --git a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/icbc/service/IcbcPaymentFlowRecorder.java b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/icbc/service/IcbcPaymentFlowRecorder.java
index fd9729f..219428f 100644
--- a/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/icbc/service/IcbcPaymentFlowRecorder.java
+++ b/ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/icbc/service/IcbcPaymentFlowRecorder.java
@@ -32,7 +32,7 @@
             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);
@@ -89,4 +89,17 @@
     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";
+    }
 }
diff --git a/ruoyi-service/ruoyi-payment/src/test/java/com/ruoyi/payment/controller/IcbcPayControllerDispatchTest.java b/ruoyi-service/ruoyi-payment/src/test/java/com/ruoyi/payment/controller/IcbcPayControllerDispatchTest.java
new file mode 100644
index 0000000..5d26fd5
--- /dev/null
+++ b/ruoyi-service/ruoyi-payment/src/test/java/com/ruoyi/payment/controller/IcbcPayControllerDispatchTest.java
@@ -0,0 +1,60 @@
+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;
+    }
+}

--
Gitblit v1.7.1