Просмотр исходного кода

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_java

caoliqin 2 дней назад
Родитель
Сommit
a5c832af7c

+ 20 - 0
fs-redis/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -16,6 +16,8 @@ import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSeriali
 import org.springframework.data.redis.serializer.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
+import java.math.BigDecimal;
+
 /**
  * redis配置
  *
@@ -110,6 +112,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, BigDecimal> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
 
     @Bean
     public DefaultRedisScript<Long> limitScript()

+ 5 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java

@@ -70,6 +70,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.sql.Timestamp;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -901,8 +902,11 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
             List<FsStorePayment> payments = storePaymentMapper.selectFsStorePaymentByPay(6,fsIntegralOrder.getOrderId());
             if(payments!=null&&payments.size()==1){
                 FsStorePayment payment=payments.get(0);
+
                 V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
-                request.setOrdAmt(payment.getPayMoney().toString());
+                //整数退不了款..要有2位小数
+                request.setOrdAmt(payment.getPayMoney().setScale(2, RoundingMode.DOWN).toString());
+//                request.setOrdAmt(payment.getPayMoney().toString());
                 request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
                 request.setReqSeqId("refund-"+payment.getPayCode());
                 Map<String, Object> extendInfoMap = new HashMap<>();

+ 30 - 16
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -46,6 +46,7 @@ import com.fs.course.service.IFsCourseRedPacketLogService;
 import com.fs.course.service.IFsUserCourseOrderService;
 import com.fs.course.service.IFsUserVipOrderService;
 import com.fs.his.domain.*;
+import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.enums.PaymentMethodEnum;
 import com.fs.his.mapper.*;
 import com.fs.his.param.*;
@@ -1267,22 +1268,35 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             throw new CustomException("用户不存在");
         }
 
-        if (StringUtils.isBlank(payOrderParam.getAppId())) {
-            throw new IllegalArgumentException("appId不能为空");
-        }
-        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(payOrderParam.getAppId());
-        if (fsCoursePlaySourceConfig == null) {
-            throw new CustomException("未找到appId对应的小程序配置: " + payOrderParam.getAppId());
-        }
-        Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
-        if (merchantConfigId == null || merchantConfigId <= 0) {
-            throw new CustomException("小程序没有配置商户信息");
-        }
-        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
-        FsPayConfig payConfig =JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
-        payConfig.setType(merchantAppConfig.getMerchantType());
-        payConfig.setAppId(fsCoursePlaySourceConfig.getAppid());
-        logger.debug("支付配置 his.pay: {}", payConfig);
+        FsPayConfig payConfig=new FsPayConfig();
+        //支付宝可以不需要appid(在没有appid的情况下)【ps:小程序的支付宝没传appid 就G】
+       if (PaymentMethodEnum.ALIPAY==payOrderParam.getPaymentMethod() && StringUtils.isBlank(payOrderParam.getAppId())){
+           String json = configService.selectConfigByKey("his.pay");
+           PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+           payConfig.setType(payConfigDTO.getType());
+       }else {
+           if (StringUtils.isBlank(payOrderParam.getAppId())) {
+               throw new IllegalArgumentException("appId不能为空");
+           }
+           FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(payOrderParam.getAppId());
+           if (fsCoursePlaySourceConfig == null) {
+               throw new CustomException("未找到appId对应的小程序配置: " + payOrderParam.getAppId());
+           }
+           Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+           if (merchantConfigId == null || merchantConfigId <= 0) {
+               throw new CustomException("小程序没有配置商户信息");
+           }
+
+           MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+           payConfig =JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+           payConfig.setType(merchantAppConfig.getMerchantType());
+           payConfig.setAppId(fsCoursePlaySourceConfig.getAppid());
+
+           logger.debug("支付配置 his.pay: {}", payConfig);
+       }
+
+
+
 //        FsPayConfig payConfig = JSONUtil.toBean(json, FsPayConfig.class);
 
         if (isWechatPayment(payOrderParam.getPaymentMethod())) {

+ 7 - 22
fs-service/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.huifuPay.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.spring.SpringUtils;
@@ -158,7 +159,11 @@ public class HuiFuServiceImpl implements HuiFuService {
     public HuiFuRefundResult refund(V2TradePaymentScanpayRefundRequest request) {
         HuiFuRefundResult huiFuRefundResult=null;
         try {
-            doInit(getMerConfig(request.getAppId()));
+            if(ObjectUtils.isNotNull(request.getAppId())){
+                doInit(getMerConfig(request.getAppId()));
+            } else {
+                doInit(getMerConfig());
+            }
             request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
             Map<String, Object> response = doExecute(request);
             String jsonString = JSONObject.toJSONString(response);
@@ -319,27 +324,7 @@ public class HuiFuServiceImpl implements HuiFuService {
         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
         FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
 
-//        FsPayConfig fsPayConfig = new FsPayConfig();
-//        fsPayConfig.setAppId("wxc3f0a952b7bc2b94");
-//        fsPayConfig.setHfProductId("KAZX");
-//        fsPayConfig.setHfSysId("6666000149635112");
-//        fsPayConfig.setHuifuId("6666000149635112");
-//        fsPayConfig.setHfRsaPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCijLcYLMJEe16TS6BtEG9hUezZyYvp2qgpPVGWaaBbb6lud89ILMUC7jyTWufCo2fUQ0nJzYhVlNeMzmGFtg/zFwhkjJIkuCOW+/Koy1ow66Rom8/sNQLb82szHoeklbv17AnD7WJis7cGyy1+3E6jzfaPOB7PTzidK6KyfCWDByOt0JcGe3+6+9+loQFbFRXJ2RpWPQeN72n9FVtSKSvgkGtJNUzh/qBwMPN6ol6xcU/Z2o1sYrRfKC4tcMqccRi/DvvZFJPVlN+YqkJ6lhgAmJg7eZ2fhIgrmzqc96UKp2YUNm+1v8XHCflD9Wv94E6D2JgL4VbF4Zyf+fKYuR7pAgMBAAECggEAfy5UL6ENmuFgHSVF7y+1xdKA2+IbC60ed63XgTVB12jli15Im3MT7ngSg0TUIvERUv4W5MNgkX10rWHo4eKSViPGWE24JuzAQ+j7cuAwwCgPKh4HMAxGIWwyivuvK7JQL1kwRtEccpekc7dS8HhVO0rySBqj2JZmeGrk0HvcKciSWuMjhjT4dJUwSntD07REV6rVjrpQXuvmY40vH88uvHLdH1IcjmJs2yJRNawUNtd+8FvpOCjami7zpB+er+AQ6S2fvpljNqfE5Kadm3MvzBngDdMS3xRvMHfjCifVwFpLP0rLDP6cSn6PJWbkNYQVZi12w8+wb5f7AVlaKXnfdQKBgQDh7VC5+MOqfcUr9h/n2vhFFhQOaGAZCOBc65n8VBj9aRht8ViXFvRrIRmM+QvUbV9/7taFbtAnZXIzu+12T4vnlZv9DTsy6kKloV5923xZ4CpzIVG8crlwJz1wdALeO6M485RtRLjz6nlNKn2m2VJ1d5XFBDhIz5rWUzagPwwpwwKBgQC4L8Eyu6Yn/zQmv8l6rfAsEfUJzfYtojf1PerPYilARtgFuD20cppcOP5oAk2TTX3qaz0Y9atCfL2z2qxtrgKtw2etfhDBmT6l6+pg04SLuyTrVeZ5dxXHt+LRLJnvBbGgnvAM6rSRKdHXT0gfqiRIMw2qIUtndgRr4RK5hqcd4wKBgBYBFh620t/VFhIdC6h6VDnuV4+7rLhje+6w57OCwVhVFxMGMZmtm6qfc6yeSP+sk2OTcINYcp+TqtbNE+i1AKxSjvnLgxuHY2xcViat7OOYCKpj8WEIT3VT7RD5y5m3d0NBvhASZG0lRiE05T4N5pEYT5b7vTuiNLNxMV3UJiwfAoGBAIb2/1QEqwmN+RIX4TSTNnWkpvELSkRAJU8Akwpp/J5MC0mNqzGJ9NB1Nv7SCTRSSV04PaoHgvoSXBPpvgYUx4O6t0MrKG4ktAJzL+jJtcuKU9Bavqrs9znE5mCulRHQE0wGixJ7/dqNUWW7g7coPrPlLTMoeI+UrEK8x7LJF7ZPAoGALHvtu6zzWVeCdELIPUTersVQrH1R3yZuf6rgubg4XFw3meFcd4W8BvXm4EKGRZxdiyZvCtKlkV9u110Rx3RNSbZCOb3MClmkcow8vPIhmyGWIGymAIxr9JcD0p6HogzPvbjRsLh1nFg/+95OL2E353Bp4/oPIgYIfnYNUfD+0gA=");
-//        fsPayConfig.setHfRsaPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjbkiiy2ewzuPsM5uZbAFMJOBWCRRQ2RtH7Dbr9Evbow6IEyvGoen8XKpiuXzapeps3b2eogETHVFQtLooqRHpVRppFKtU1AHZXA7C6wPocfMldJbTykDCowyJwOSYEaFPBjr9cw6dQcBJMIEHj0YWjBPR1dPVzf+y4sUohbrkS/FANBpp24j+Mu0qEqh8TuVuKlvig7jbmXJiJkAmUJ+Tb3Caj20fFTen6juPd3zR/KM3twki06wZZbb4KyCiM/NwozEqJ9PkWSs6rG7aW+BEfzlo3m1a7MlL0vpKNR3f0lbywq09rFAwtA7R2lssWwLMma4LOqtMMqo3yZdv4vObQIDAQAB");
-//        fsPayConfig.setHfRsaPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCijLcYLMJEe16TS6BtEG9hUezZyYvp2qgpPVGWaaBbb6lud89ILMUC7jyTWufCo2fUQ0nJzYhVlNeMzmGFtg/zFwhkjJIkuCOW+/Koy1ow66Rom8/sNQLb82szHoeklbv17AnD7WJis7cGyy1+3E6jzfaPOB7PTzidK6KyfCWDByOt0JcGe3+6+9+loQFbFRXJ2RpWPQeN72n9FVtSKSvgkGtJNUzh/qBwMPN6ol6xcU/Z2o1sYrRfKC4tcMqccRi/DvvZFJPVlN+YqkJ6lhgAmJg7eZ2fhIgrmzqc96UKp2YUNm+1v8XHCflD9Wv94E6D2JgL4VbF4Zyf+fKYuR7pAgMBAAECggEAfy5UL6ENmuFgHSVF7y+1xdKA2+IbC60ed63XgTVB12jli15Im3MT7ngSg0TUIvERUv4W5MNgkX10rWHo4eKSViPGWE24JuzAQ+j7cuAwwCgPKh4HMAxGIWwyivuvK7JQL1kwRtEccpekc7dS8HhVO0rySBqj2JZmeGrk0HvcKciSWuMjhjT4dJUwSntD07REV6rVjrpQXuvmY40vH88uvHLdH1IcjmJs2yJRNawUNtd+8FvpOCjami7zpB+er+AQ6S2fvpljNqfE5Kadm3MvzBngDdMS3xRvMHfjCifVwFpLP0rLDP6cSn6PJWbkNYQVZi12w8+wb5f7AVlaKXnfdQKBgQDh7VC5+MOqfcUr9h/n2vhFFhQOaGAZCOBc65n8VBj9aRht8ViXFvRrIRmM+QvUbV9/7taFbtAnZXIzu+12T4vnlZv9DTsy6kKloV5923xZ4CpzIVG8crlwJz1wdALeO6M485RtRLjz6nlNKn2m2VJ1d5XFBDhIz5rWUzagPwwpwwKBgQC4L8Eyu6Yn/zQmv8l6rfAsEfUJzfYtojf1PerPYilARtgFuD20cppcOP5oAk2TTX3qaz0Y9atCfL2z2qxtrgKtw2etfhDBmT6l6+pg04SLuyTrVeZ5dxXHt+LRLJnvBbGgnvAM6rSRKdHXT0gfqiRIMw2qIUtndgRr4RK5hqcd4wKBgBYBFh620t/VFhIdC6h6VDnuV4+7rLhje+6w57OCwVhVFxMGMZmtm6qfc6yeSP+sk2OTcINYcp+TqtbNE+i1AKxSjvnLgxuHY2xcViat7OOYCKpj8WEIT3VT7RD5y5m3d0NBvhASZG0lRiE05T4N5pEYT5b7vTuiNLNxMV3UJiwfAoGBAIb2/1QEqwmN+RIX4TSTNnWkpvELSkRAJU8Akwpp/J5MC0mNqzGJ9NB1Nv7SCTRSSV04PaoHgvoSXBPpvgYUx4O6t0MrKG4ktAJzL+jJtcuKU9Bavqrs9znE5mCulRHQE0wGixJ7/dqNUWW7g7coPrPlLTMoeI+UrEK8x7LJF7ZPAoGALHvtu6zzWVeCdELIPUTersVQrH1R3yZuf6rgubg4XFw3meFcd4W8BvXm4EKGRZxdiyZvCtKlkV9u110Rx3RNSbZCOb3MClmkcow8vPIhmyGWIGymAIxr9JcD0p6HogzPvbjRsLh1nFg/+95OL2E353Bp4/oPIgYIfnYNUfD+0gA=");
-//        fsPayConfig.setHfRsaPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjbkiiy2ewzuPsM5uZbAFMJOBWCRRQ2RtH7Dbr9Evbow6IEyvGoen8XKpiuXzapeps3b2eogETHVFQtLooqRHpVRppFKtU1AHZXA7C6wPocfMldJbTykDCowyJwOSYEaFPBjr9cw6dQcBJMIEHj0YWjBPR1dPVzf+y4sUohbrkS/FANBpp24j+Mu0qEqh8TuVuKlvig7jbmXJiJkAmUJ+Tb3Caj20fFTen6juPd3zR/KM3twki06wZZbb4KyCiM/NwozEqJ9PkWSs6rG7aW+BEfzlo3m1a7MlL0vpKNR3f0lbywq09rFAwtA7R2lssWwLMma4LOqtMMqo3yZdv4vObQIDAQAB");
-//        fsPayConfig.setHfPayOnlineNotifyUrl("https://userapp.his.cdwjyyh.com//app/hfPay/payNotifyUrl");
-
-//        FsPayConfig fsPayConfig = new FsPayConfig();
-//        fsPayConfig.setAppId("wxb48fe0acfdc70a92");
-//        fsPayConfig.setHfProductId("KAZX");
-//        fsPayConfig.setHfSysId("6666000173104153");
-//        fsPayConfig.setHuifuId("6666000173104153");
-//        fsPayConfig.setHfRsaPrivateKey("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCYzLmE2qBlRQbAosIjPxTZwRItgMgOTT99bRYxa3xQhiq2+YPj2R5lOKu5Y74Po43cg5UG8+7z7r4hV2q+sS3DwvnifHrkytXrnwDuW4ijagiMhr0Am9cEP6WqmuCyy8cMS+MtZ8eBCFefXjDsO4zXDk9/jxpywZ59i85q5Ka03S6lJOW+cq7RToEGJoxF1E98UtewbcPL2FxU5eQnte51RiGGly3drAQh+Tbdt8brjycnfR1SAhEFe/cFAOG6zC1XyJwkCfFynpvihA7SGSrTozBvIxg5ylGTx+HiRPDlYBABzWZkZgtvSGF0V7DQy5Tia/kuksOuePXb59MrUyIBAgMBAAECggEALWH44/2vUAS9aa+tq5xLzBUtGfi68ox9A/rHcaw0AxKmUywuwRi2j2fSkUCPrcNtGga215bR7P+G1w5ItRSYvCEH6P4B3jxkZxQVybXEEo0mtt45+plOtoNU6CQSAujFWOCdO9osBiX9KGdobnGNdj5Y3FEbkOPy9+TzTQpWfTcSWXi3qwsWz05jb04NpqV+xAPDIotAGvDIKJ99kH7/ewlyADvI7axj4JJaHnQOU/UcNHX8gtFgPTxf4e+UGLoPz3TRqFkVM9UIgejFilUUbIcwoCl1sLo3tjdoomYzEYxHPVrtk/8YRRUnzcvThSgydDhO+0GLa8qMCYk+XYrPAQKBgQDaTg+AQqRVQHH2KxYwUmfZXj+RfgBbR1L/v0j5NuxKSdxytBZA6K4I4fX8D/o2PXpkKiGaqyLnf5/wQsmj3fxIzXKyZWcU3lgHE7L18NWl6wPqpz5zJwgKstFcZqJ4HXZgSZw9/iNktIS5K6PZUgsGy+QJ0e4SFqKUED/zRoVKUQKBgQCzLxMsA2rl1n9q93PGOLE9bS0uahtpTePKVLn+ceQ/acDdokCf0MtM3uWJd5ti8BWTMECg4JVXIBUrYeLHwVlZMKvijGZRDYGJUF8hfjWU2pTDI6b2+vSQSVWLkyOdznvzUxrhKDbj21lQNPrKqL/nDfWKH/5QfScfjHviEQ7AsQKBgFXQTaObjsG8XY/pDAXevtfhhpeIslcvSF8kMGlWv7fMJQ4p4H2PeaogOPPmy/K6Y/wv25nTIBtkPdjSSDVUM7HioO2jksvPQ0c05Spsi293XMjHCXN2qmCaPlZWOhOBcWEUTojH993EYE/x6ayp5Y+8Yl3B2hXeM/aEFL9qv0ahAoGADaa7fjHwdfxGjt61aletYTGtLIkW94ngneygkvsYWaBz+i6/X62nn36n3DZJl1sVObaGZftWRWIDWt/FSFS5uurTXZo2vVwbD1wZM1MLQAD7LnbL5Ksv8MI1i0G1h/NQTDR7qsXGkMuIXWz74m7C2BafK1vOo1E1ptisI4gLKLECgYBdCCxkf/jCXcsQEs+hmYWm4gvHahvPIDVI5s2qX/hrJsFx6LaorC1iSmwwJQ7zM/AFqwc/NlCGo2NE44MKFPqIp/08fM4Tx2i8BFQQF3G1Y8oAr/xusqJVSI3CHvw2yD6DDgwTOeQ2TD1v3lnOEB6g0JaamTQQ6NQ0iUNRsDXAPQ==");
-//        fsPayConfig.setHfRsaPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuziAvRIul3mwBlEDSMMvi3v83HEebLpEWoBhcqL/Vlg90tjT51lEO4OksGDU08ypESMaby+Rpvw9rRTFBbdm9oZiiKyKrYChoW9s/Tu5gDIt6k1+YP3204/lOz4Pat9hlRetIhDcgbAiChwDWS/+shfdi6vMX31fO5m5oyo1XlwL477pZYykwxalxgXjWHUkyDRvYGDFquLTELSEq+vpQthYwZ0ghamIkxQV7syjNp06bCMzLmnB9jVEilQuDGqRrlDJpLjKqZkkTwp5JJJRJPLIJag0iLZMJjfdHKmTojcd+y9KRUU+KW0OMUeC2T8SBKpz918ioBKJtuzmUD6YNwIDAQAB");
-//        //fsPayConfig.setHfRsaPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCijLcYLMJEe16TS6BtEG9hUezZyYvp2qgpPVGWaaBbb6lud89ILMUC7jyTWufCo2fUQ0nJzYhVlNeMzmGFtg/zFwhkjJIkuCOW+/Koy1ow66Rom8/sNQLb82szHoeklbv17AnD7WJis7cGyy1+3E6jzfaPOB7PTzidK6KyfCWDByOt0JcGe3+6+9+loQFbFRXJ2RpWPQeN72n9FVtSKSvgkGtJNUzh/qBwMPN6ol6xcU/Z2o1sYrRfKC4tcMqccRi/DvvZFJPVlN+YqkJ6lhgAmJg7eZ2fhIgrmzqc96UKp2YUNm+1v8XHCflD9Wv94E6D2JgL4VbF4Zyf+fKYuR7pAgMBAAECggEAfy5UL6ENmuFgHSVF7y+1xdKA2+IbC60ed63XgTVB12jli15Im3MT7ngSg0TUIvERUv4W5MNgkX10rWHo4eKSViPGWE24JuzAQ+j7cuAwwCgPKh4HMAxGIWwyivuvK7JQL1kwRtEccpekc7dS8HhVO0rySBqj2JZmeGrk0HvcKciSWuMjhjT4dJUwSntD07REV6rVjrpQXuvmY40vH88uvHLdH1IcjmJs2yJRNawUNtd+8FvpOCjami7zpB+er+AQ6S2fvpljNqfE5Kadm3MvzBngDdMS3xRvMHfjCifVwFpLP0rLDP6cSn6PJWbkNYQVZi12w8+wb5f7AVlaKXnfdQKBgQDh7VC5+MOqfcUr9h/n2vhFFhQOaGAZCOBc65n8VBj9aRht8ViXFvRrIRmM+QvUbV9/7taFbtAnZXIzu+12T4vnlZv9DTsy6kKloV5923xZ4CpzIVG8crlwJz1wdALeO6M485RtRLjz6nlNKn2m2VJ1d5XFBDhIz5rWUzagPwwpwwKBgQC4L8Eyu6Yn/zQmv8l6rfAsEfUJzfYtojf1PerPYilARtgFuD20cppcOP5oAk2TTX3qaz0Y9atCfL2z2qxtrgKtw2etfhDBmT6l6+pg04SLuyTrVeZ5dxXHt+LRLJnvBbGgnvAM6rSRKdHXT0gfqiRIMw2qIUtndgRr4RK5hqcd4wKBgBYBFh620t/VFhIdC6h6VDnuV4+7rLhje+6w57OCwVhVFxMGMZmtm6qfc6yeSP+sk2OTcINYcp+TqtbNE+i1AKxSjvnLgxuHY2xcViat7OOYCKpj8WEIT3VT7RD5y5m3d0NBvhASZG0lRiE05T4N5pEYT5b7vTuiNLNxMV3UJiwfAoGBAIb2/1QEqwmN+RIX4TSTNnWkpvELSkRAJU8Akwpp/J5MC0mNqzGJ9NB1Nv7SCTRSSV04PaoHgvoSXBPpvgYUx4O6t0MrKG4ktAJzL+jJtcuKU9Bavqrs9znE5mCulRHQE0wGixJ7/dqNUWW7g7coPrPlLTMoeI+UrEK8x7LJF7ZPAoGALHvtu6zzWVeCdELIPUTersVQrH1R3yZuf6rgubg4XFw3meFcd4W8BvXm4EKGRZxdiyZvCtKlkV9u110Rx3RNSbZCOb3MClmkcow8vPIhmyGWIGymAIxr9JcD0p6HogzPvbjRsLh1nFg/+95OL2E353Bp4/oPIgYIfnYNUfD+0gA=");
-//        //fsPayConfig.setHfRsaPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjbkiiy2ewzuPsM5uZbAFMJOBWCRRQ2RtH7Dbr9Evbow6IEyvGoen8XKpiuXzapeps3b2eogETHVFQtLooqRHpVRppFKtU1AHZXA7C6wPocfMldJbTykDCowyJwOSYEaFPBjr9cw6dQcBJMIEHj0YWjBPR1dPVzf+y4sUohbrkS/FANBpp24j+Mu0qEqh8TuVuKlvig7jbmXJiJkAmUJ+Tb3Caj20fFTen6juPd3zR/KM3twki06wZZbb4KyCiM/NwozEqJ9PkWSs6rG7aW+BEfzlo3m1a7MlL0vpKNR3f0lbywq09rFAwtA7R2lssWwLMma4LOqtMMqo3yZdv4vObQIDAQAB");
-//        fsPayConfig.setHfPayNotifyUrl("https://userapp.baohetangjinyue.cn//app/hfPay/payNotifyUrl");
+
 
         config=fsPayConfig;
         MerConfig merConfig = new MerConfig();

+ 23 - 0
fs-service/src/main/java/com/fs/wxcid/dto/message/RevokeMsgRequest.java

@@ -0,0 +1,23 @@
+package com.fs.wxcid.dto.message;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * 撤回消息请求参数(RevokeMsgNew 接口)
+ */
+@Data
+public class RevokeMsgRequest {
+
+    /**
+     * 要撤回的消息 ID(发送消息时返回的 msgId 或 newMsgId)
+     */
+    @JSONField(name = "msgId")
+    private Long msgId;
+
+    /**
+     * 接收方 wxid(单聊)或群 id(群聊)
+     */
+    @JSONField(name = "toUserName")
+    private String toUserName;
+}

+ 25 - 0
fs-service/src/main/java/com/fs/wxcid/dto/message/RevokeMsgResult.java

@@ -0,0 +1,25 @@
+package com.fs.wxcid.dto.message;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fs.wxcid.dto.common.BaseResponse;
+import lombok.Data;
+
+/**
+ * 撤回消息接口(RevokeMsgNew)返回的 Data 结构
+ */
+@Data
+public class RevokeMsgResult {
+
+    @JSONField(name = "baseResponse")
+    private BaseResponse baseResponse;
+
+    @JSONField(name = "sysWording")
+    private String sysWording;
+
+    /**
+     * 是否撤回成功(根据 baseResponse.ret == 0 判断)
+     */
+    public boolean isSuccess() {
+        return baseResponse != null && baseResponse.getRet() == 0;
+    }
+}

+ 40 - 0
fs-service/src/main/java/com/fs/wxcid/dto/message/SendImageMessageResult.java

@@ -0,0 +1,40 @@
+package com.fs.wxcid.dto.message;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * 发送图片消息的单条结果(SendImageNewMessage 接口 Data 数组中的每个元素)
+ */
+@Data
+public class SendImageMessageResult {
+
+    /**
+     * 图片 ID
+     */
+    @JSONField(name = "imageId")
+    private String imageId;
+
+    /**
+     * 微信底层返回的详细响应信息
+     */
+    @JSONField(name = "resp")
+    private SendImageResponse resp;
+
+    /**
+     * 接收方的微信 ID(如 wxid_xxx)
+     * 注意:接口返回字段名为 toUSerName(拼写错误)
+     */
+    @JSONField(name = "toUSerName")
+    private String toUserName;
+
+    /**
+     * 是否发送成功(根据 resp.baseResponse.ret == 0 判断)
+     */
+    public boolean isSendSuccess() {
+        if (resp == null || resp.getBaseResponse() == null) {
+            return false;
+        }
+        return resp.getBaseResponse().getRet() == 0;
+    }
+}

+ 46 - 0
fs-service/src/main/java/com/fs/wxcid/dto/message/SendImageResponse.java

@@ -0,0 +1,46 @@
+package com.fs.wxcid.dto.message;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fs.wxcid.dto.common.BaseResponse;
+import com.fs.wxcid.dto.common.StringWrapper;
+import lombok.Data;
+
+/**
+ * 发送图片消息时 resp 字段的响应结构(SendImageNewMessage 接口返回)
+ */
+@Data
+public class SendImageResponse {
+
+    @JSONField(name = "baseResponse")
+    private BaseResponse baseResponse;
+
+    @JSONField(name = "msgId")
+    private Long msgId;
+
+    @JSONField(name = "clientImgId")
+    private StringWrapper clientImgId;
+
+    @JSONField(name = "fromUserName")
+    private StringWrapper fromUserName;
+
+    @JSONField(name = "toUserName")
+    private StringWrapper toUserName;
+
+    @JSONField(name = "totalLen")
+    private Long totalLen;
+
+    @JSONField(name = "startPos")
+    private Long startPos;
+
+    @JSONField(name = "dataLen")
+    private Long dataLen;
+
+    @JSONField(name = "createTime")
+    private Long createTime;
+
+    @JSONField(name = "newMsgId")
+    private Long newMsgId;
+
+    @JSONField(name = "msgSource")
+    private String msgSource;
+}

+ 3 - 3
fs-service/src/main/java/com/fs/wxcid/service/MessageService.java

@@ -1,13 +1,13 @@
 package com.fs.wxcid.service;
 
 
-import com.fs.wxcid.dto.common.ApiResponseCommon;
 import com.fs.wxcid.dto.message.*;
 
 import java.util.List;
 
 public interface MessageService {
-    ApiResponseCommon<List<SendMessageResult>> sendTextMessage(Long accountId, String txt);
-    ApiResponseCommon<List<SendMessageResult>> sendImageMessage(Long accountId, String imgUrl);
+    List<SendMessageResult> sendTextMessage(Long accountId, String txt);
+    List<SendImageMessageResult> sendImageMessage(Long accountId, String imgUrl, String toUser);
+    RevokeMsgResult revokeMessage(Long accountId, Long msgId, String toUserName);
 
 }

+ 30 - 10
fs-service/src/main/java/com/fs/wxcid/service/impl/MessageServiceImpl.java

@@ -7,6 +7,9 @@ import com.fs.wxcid.ServiceUtils;
 import com.fs.wxcid.dto.common.ApiResponseCommon;
 import com.fs.wxcid.dto.login.RequestBaseVo;
 import com.fs.wxcid.dto.message.MsgItem;
+import com.fs.wxcid.dto.message.RevokeMsgRequest;
+import com.fs.wxcid.dto.message.RevokeMsgResult;
+import com.fs.wxcid.dto.message.SendImageMessageResult;
 import com.fs.wxcid.dto.message.SendMessageResult;
 import com.fs.wxcid.dto.message.SendTextMessageRequest;
 import com.fs.wxcid.service.MessageService;
@@ -24,7 +27,7 @@ public class MessageServiceImpl implements MessageService {
     private ServiceUtils serviceUtils;
 
     @Override
-    public ApiResponseCommon<List<SendMessageResult>> sendTextMessage(Long accountId, String txt) {
+    public List<SendMessageResult> sendTextMessage(Long accountId, String txt) {
         SendTextMessageRequest request = new SendTextMessageRequest();
         List<MsgItem> list = new ArrayList<>();
         MsgItem msgItem = new MsgItem();
@@ -43,34 +46,51 @@ public class MessageServiceImpl implements MessageService {
             String errorMsg = "部分消息发送失败,失败接收人: " + String.join(", ", failedRecipients);
             throw new CustomException("发送文本消息部分失败: " + errorMsg);
         }
-        return response;
+        return response.getData();
     }
 
     @Override
-    public ApiResponseCommon<List<SendMessageResult>> sendImageMessage(Long accountId, String imgUrl) {
+    public List<SendImageMessageResult> sendImageMessage(Long accountId, String imgUrl, String toUser) {
         SendTextMessageRequest request = new SendTextMessageRequest();
         List<MsgItem> list = new ArrayList<>();
         MsgItem msgItem = new MsgItem();
         try {
+            msgItem.setMsgType(0);
             msgItem.setImageContent(ImageToBase64Util.convertImageUrlToBase64(imgUrl));
+            msgItem.setToUserName(toUser);
         }catch (Exception e){
             log.error("发送消息时,图片转换base64错误", e);
             throw new CustomException("图片消息发送失败");
         }
+        list.add(msgItem);
         request.setMsgItem(list);
-        ApiResponseCommon<List<SendMessageResult>> response = serviceUtils.sendPost(BASE_URL + "SendImageNewMessage", RequestBaseVo.builder().accountId(accountId).data(request).build(), new TypeReference<ApiResponseCommon<List<SendMessageResult>>>() {});
-        // 第二层:检查每条消息是否真正发送成功
-        List<SendMessageResult> results = response.getData();
+        ApiResponseCommon<List<SendImageMessageResult>> response = serviceUtils.sendPost(BASE_URL + "SendImageNewMessage", RequestBaseVo.builder().accountId(accountId).data(request).build(), new TypeReference<ApiResponseCommon<List<SendImageMessageResult>>>() {});
+        // 第二层:检查每条消息是否真正发送成功(根据 resp.baseResponse.ret == 0 判断)
+        List<SendImageMessageResult> results = response.getData();
         List<String> failedRecipients = new ArrayList<>();
-        for (SendMessageResult result : results) {
+        for (SendImageMessageResult result : results) {
             if (!result.isSendSuccess()) {
                 failedRecipients.add(result.getToUserName());
             }
         }
         if (!failedRecipients.isEmpty()) {
-            String errorMsg = "部分消息发送失败,失败接收人: " + String.join(", ", failedRecipients);
-            throw new CustomException("发送文本消息部分失败: " + errorMsg);
+            String errorMsg = "部分图片消息发送失败,失败接收人: " + String.join(", ", failedRecipients);
+            throw new CustomException("发送图片消息部分失败: " + errorMsg);
+        }
+        return response.getData();
+    }
+
+    @Override
+    public RevokeMsgResult revokeMessage(Long accountId, Long msgId, String toUserName) {
+        RevokeMsgRequest request = new RevokeMsgRequest();
+        request.setMsgId(msgId);
+        request.setToUserName(toUserName);
+        ApiResponseCommon<RevokeMsgResult> response = serviceUtils.sendPost(BASE_URL + "RevokeMsgNew", RequestBaseVo.builder().accountId(accountId).data(request).build(), new TypeReference<ApiResponseCommon<RevokeMsgResult>>() {});
+        RevokeMsgResult result = response.getData();
+        if (result != null && !result.isSuccess()) {
+            String errorMsg = result.getSysWording() != null ? result.getSysWording() : "消息撤回失败";
+            throw new CustomException(errorMsg);
         }
-        return response;
+        return response.getData();
     }
 }

+ 8 - 0
fs-wx-task/src/main/java/com/fs/app/controller/CommonController.java

@@ -5,6 +5,7 @@ import com.fs.app.service.WxTaskService;
 import com.fs.common.core.domain.R;
 import com.fs.company.service.ICompanyWxAccountService;
 import com.fs.company.service.impl.CompanyWxServiceImpl;
+import com.fs.wxcid.service.MessageService;
 import io.swagger.annotations.Api;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -70,11 +71,18 @@ public class CommonController {
 
     @Autowired
     CompanyWxServiceImpl ccompanyWxService;
+    @Autowired
+    MessageService messageService;
 
     @GetMapping("mockAddWxSuccess/{clientId}")
     public void mockAddWxSuccess(@PathVariable("clientId") Long clientId) {
         ccompanyWxService.mockInterface(clientId);
     }
 
+    @GetMapping("sendImg")
+    public void mockAddWxSuccess(Long accountId, String imgUrl, String toUser) {
+        messageService.sendImageMessage(accountId, imgUrl, toUser);
+    }
+
 
 }