Jelajahi Sumber

Merge branch 'auth_wx_login' into back_user_info_detail

zoujiajian 3 tahun lalu
induk
melakukan
e0c127ee59
36 mengubah file dengan 801 tambahan dan 160 penghapusan
  1. 15 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 12 0
      netflix-common/src/main/java/com/cyksj/common/util/SmsUtil.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/GroupsTripsDeleteRecordMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/GroupsTripsAccountReplaceRecordMapper.java
  5. 0 1
      netflix-dao/src/main/java/com/cyksj/model/dto/AuthRedirect.java
  6. 10 0
      netflix-dao/src/main/java/com/cyksj/model/entity/FrontProblemCollectRecord.java
  7. 20 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java
  8. 40 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GroupsTripsAccountReplaceRecord.java
  9. 26 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GroupsTripsDeleteRecord.java
  10. 31 0
      netflix-dao/src/main/java/com/cyksj/model/request/ReplaceTripsAccountReq.java
  11. 40 0
      netflix-dao/src/main/java/com/cyksj/model/views/GroupsAccountView.java
  12. 1 1
      netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeViews.java
  13. 12 9
      netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml
  14. 2 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  15. 1 0
      netflix-service/src/main/java/com/cyksj/service/authorization/AuthorizationService.java
  16. 11 0
      netflix-service/src/main/java/com/cyksj/service/authorization/impl/AuthorizationServiceImpl.java
  17. 4 5
      netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java
  18. 1 3
      netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonService.java
  19. 3 5
      netflix-service/src/main/java/com/cyksj/service/mange/CmsGroupService.java
  20. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java
  21. 35 0
      netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonServiceImpl.java
  22. 116 0
      netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java
  23. 36 14
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  24. 67 27
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java
  25. 27 20
      netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java
  26. 1 18
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  27. 5 0
      netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java
  28. 22 1
      netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java
  29. 86 0
      netflix-service/src/main/java/com/cyksj/task/Scheduler.java
  30. 35 12
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  31. 7 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java
  32. 24 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupController.java
  33. 23 0
      netflix-web/src/main/java/com/cyksj/web/controller/sys/FrontProblemCollectRecordController.java
  34. 51 43
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java
  35. 0 0
      netflix-web/src/main/resources/application-dev.yml
  36. 0 0
      netflix-web/src/main/resources/application-prd.yml

+ 15 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -88,4 +88,19 @@ public interface Constant {
 	 * chatGPT Plus指定规格限购
 	 */
 	String CHAT_GPT_PLUS_SKU_PURCHASE_LIMIT = "chat_gpt_plus_sku_purchase_limit";
+
+	//发给商务
+	String BUSINESS_CHANNEL_MSG = "你的渠道%s(id%s)分销数据已低于7天平均值的50%%,请尽快与渠道沟通。【银河录像局】";
+
+	/**
+	 * midJourney课程赠送车票规格ids
+	 */
+	String MIDJOURNEY_TICKET_SKU_IDS = "midJourney_ticket_sku_ids";
+
+	/**
+	 * 授权扫码登录公众号
+	 */
+	String QR_CODE_WX_APP_ID = "qr_code_wx_app_id";
+
+	String CHANGE_GROUPS_TRIPS_ACCOUNT = "您好,您购买的%s,账号已替换,请登陆网站https://nf.video/查看最新账号密码【银河录像局】";
 }

+ 12 - 0
netflix-common/src/main/java/com/cyksj/common/util/SmsUtil.java

@@ -23,6 +23,8 @@ public class SmsUtil {
 
     private static final String PASSWORD = "key-1bf2a2f243e18be640b2428ddf03ded9";
 
+    private static final String LVSINCO_PASSWORD = "key-246cd85eb5603c3d4924531e5d5c4edc";
+
     private static final String TENCENT_SMS_SECRET_ID = "AKIDBB3jEqR0Y95zpfTix1vd6fMqAIahc4Ka";
 
     private static final String TENCENT_SMS_SECRET_KEY = "c6YtNm63rcQ1QdiGmEbmEPSTPF3e4KQK";
@@ -49,6 +51,16 @@ public class SmsUtil {
         System.out.println(execute.body());
     }
 
+    public static void sendLuoKey2Msg(String mobile, String msg) {
+        HttpRequest request = new HttpRequest(URL);
+        request.setMethod(Method.POST);
+        request.basicAuth("api", LVSINCO_PASSWORD);
+        request.form("mobile", mobile);
+        request.form("message", msg);
+        HttpResponse execute = request.execute();
+        System.out.println(execute.body());
+    }
+
     public static void sendTencent(String mobile, String msg) {
         try {
             /* 必要步骤:

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GroupsTripsDeleteRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GroupsTripsDeleteRecord;
+
+/*
+ *项目名: netflix
+ *文件名: GroupsTripsDeleteRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/4/25 16:18
+ */
+public interface GroupsTripsDeleteRecordMapper extends BaseMapper<GroupsTripsDeleteRecord> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/GroupsTripsAccountReplaceRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GroupsTripsAccountReplaceRecord;
+
+/*
+ *项目名: netflix
+ *文件名: GroupsTripsAccountReplaceRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/5/8 14:00
+ */
+public interface GroupsTripsAccountReplaceRecordMapper extends BaseMapper<GroupsTripsAccountReplaceRecord> {
+}

+ 0 - 1
netflix-dao/src/main/java/com/cyksj/model/dto/AuthRedirect.java

@@ -37,5 +37,4 @@ public class AuthRedirect {
      * 推广id
      */
     private Long pid;
-
 }

+ 10 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/FrontProblemCollectRecord.java

@@ -13,4 +13,14 @@ import lombok.Setter;
 @Setter
 public class FrontProblemCollectRecord extends BaseEntity{
 	private String errorMsg;
+
+	/**
+	 * 调用轨迹
+	 */
+	private String track;
+
+	/**
+	 * 操作
+	 */
+	private String handle;
 }

+ 20 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java

@@ -100,6 +100,26 @@ public class GoodsDon extends BaseEntity {
      */
     private Integer virtualSold;
 
+    /**
+     * 最小规格价格
+     */
+    private BigDecimal minPrice;
+
+    /**
+     * 最小规格价格月份
+     */
+    private Integer minMonths;
+
+    /**
+     * 最大规格价格
+     */
+    private BigDecimal maxPrice;
+
+    /**
+     * 最大规格价格月份
+     */
+    private Integer maxMonths;
+
     @TableField(exist = false)
     @DbIgnore
     private BigDecimal price;

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GroupsTripsAccountReplaceRecord.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: GroupsTripsAccountReplaceRecord
+ *创建者: JavaZou
+ *创建时间:2023/5/8 13:56
+ */
+@Getter
+@Setter
+public class GroupsTripsAccountReplaceRecord extends BaseEntity{
+	private Long groupsId;
+
+	private Long oldAccountId;
+
+	private String oldAccount;
+
+	private String oldPassword;
+
+	private Date oldStartTime;
+
+	private Date oldExpiryTime;
+
+	private Long newAccountId;
+
+	private String newAccount;
+
+	private String newPassword;
+
+	private Date newStartTime;
+
+	private Date newExpiryTime;
+
+	private String operator;
+}

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GroupsTripsDeleteRecord.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: GroupsTripsDeleteRecord
+ *创建者: JavaZou
+ *创建时间:2023/4/25 16:16
+ */
+@Getter
+@Setter
+public class GroupsTripsDeleteRecord extends BaseEntity{
+	private Long accountId;
+
+	private String account;
+
+	private Long beforeGroupsId;
+
+	private Long beforeSkuId;
+
+	private Long afterGroupsId;
+
+	private Long afterSkuId;
+}

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/request/ReplaceTripsAccountReq.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/*
+ *项目名: netflix
+ *文件名: ReplaceTripsAccountReq
+ *创建者: JavaZou
+ *创建时间:2023/5/8 13:35
+ */
+@Getter
+@Setter
+public class ReplaceTripsAccountReq {
+
+	private Long adminId;
+
+	@NotNull(message = "请选择对应车队")
+	private Long groupsId;
+
+	@NotEmpty(message = "替换账号不能为空")
+	private String account;
+
+	@NotEmpty(message = "替换账号密码不能为空")
+	private String password;
+
+	private String remark;
+}

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GroupsAccountView.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: GroupsAccountView
+ *创建者: JavaZou
+ *创建时间:2023/5/8 13:47
+ */
+@Getter
+@Setter
+@SearchBean(tables = "groups_trips gt left join account a on a.id = gt.account_id")
+public class GroupsAccountView {
+	@DbField("gt.id")
+	private Long groupsId;
+
+	@DbField("gt.account_id")
+	private Long accountId;
+
+	@DbField("a.goods_id")
+	private Long goodsId;
+
+	@DbField("a.account")
+	private String account;
+
+	@DbField("a.password")
+	private String password;
+
+	@DbField("a.start_time")
+	private Date startTime;
+
+	@DbField("a.expiry_time")
+	private Date expiryTime;
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeViews.java

@@ -18,7 +18,7 @@ import java.util.Date;
 @Getter
 @Setter
 @SearchBean(tables = "user_distribute ud left join user_distribute_shared us on ud.user_id = us.shared_id" +
-		" left join order_don od on od.user_id = us.user_id and od.is_fixed_distribute = 1 and od.status not in ('noPayment', 'close') :time:",
+		" left join order_don od on od.user_id = us.user_id and od.is_fixed_distribute = 1 and od.status not in ('noPayment', 'close') and od.relation_id != 0 :time:",
 		where = "ud.deleted is true",
 		groupBy = "ud.id,ud.user_id,ud.business_id,ud.remark,ud.created_time,ud.update_time")
 public class UserDistributeViews {

+ 12 - 9
netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml

@@ -4,15 +4,18 @@
 
     <update id="updateExpiryTime">
         update groups_relation
-        set start_time   = null,
-            expiry_time  = null,
-            status       = #{entity.status},
-            renew_status = #{entity.renewStatus},
-            is_handle    = #{entity.isHandle},
-            user_id      = #{entity.userId},
-            account = #{entity.account},
-            customer_service = null
-        where id = #{entity.id} and expiry_time = #{expireTime}
+        set start_time = null,
+        expiry_time = null,
+        status = #{entity.status},
+        renew_status = #{entity.renewStatus},
+        is_handle = #{entity.isHandle},
+        user_id = #{entity.userId},
+        account = #{entity.account},
+        customer_service = null
+        where id = #{entity.id}
+        <if test="expireTime != null">
+            and expiry_time = #{expireTime}
+        </if>
     </update>
 
     <select id="getAccountIdsByUserIdOrNickNameOrSubmitAccount" resultType="java.lang.Long">

+ 2 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -602,6 +602,8 @@ public class RedisService {
         CMS_USER_PERMISSION_KEY("cms:user:permission:%s:", "user权限缓存前缀", 60 * 60 * 24L * 7),
         REPEAT_USER_KEY("repeat_user_key:%s:", "重复用户插入key", 60l),
         BUSINESS_FIRST_ORDER_USER_KEY("business_first_order_user_key:%s:", "商务分销首单提成key", 60l),
+        PC_WEB_CACHE("pc_web_cache", "官网首页平台缓存", 5 * 60),
+        H5_WEB_CACHE("h5_web_cache", "h5首页平台缓存", 5 * 60),
         ;
 
         private String name;

+ 1 - 0
netflix-service/src/main/java/com/cyksj/service/authorization/AuthorizationService.java

@@ -20,4 +20,5 @@ public interface AuthorizationService {
 
     JsSdkTicket getJsTicket(String appId, String url) throws Exception;
 
+    String createWxAuthLoginUrl(String state);
 }

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/authorization/impl/AuthorizationServiceImpl.java

@@ -2,6 +2,7 @@ package com.cyksj.service.authorization.impl;
 
 import com.cyksj.common.util.Codec;
 import com.cyksj.config.WeChatConfig;
+import com.cyksj.config.wxlogin.WxOpenPlatYHLXLoginConfig;
 import com.cyksj.enums.WeChatAuthRedirectUrl;
 import com.cyksj.model.dto.JsSdkTicket;
 import com.cyksj.service.authorization.AuthorizationService;
@@ -10,6 +11,9 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
 /**
  * @author chan
  * @className AuthorizationServiceImpl
@@ -25,6 +29,8 @@ public class AuthorizationServiceImpl implements AuthorizationService {
 
     private final WeChatConfig weChatConfig;
 
+    private final WxOpenPlatYHLXLoginConfig wxOpenPlatYHLXLoginConfig;
+
 
     @Override
     public String createUrl(String state, String authType) {
@@ -55,4 +61,9 @@ public class AuthorizationServiceImpl implements AuthorizationService {
         return jsSdkTicket;
     }
 
+    @Override
+    public String createWxAuthLoginUrl(String state) {
+        return weChatService.createWxAuthLoginUrl(state, wxOpenPlatYHLXLoginConfig.getAppId(), URLEncoder.encode(wxOpenPlatYHLXLoginConfig.getRedirectUri(), StandardCharsets.UTF_8));
+    }
+
 }

+ 4 - 5
netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java

@@ -20,7 +20,6 @@ import com.cyksj.model.dto.MsgEvent;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.entity.UserGzhRelation;
 import com.cyksj.model.entity.WxApp;
-import com.cyksj.model.entity.WxSyncLog;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.distribute.DistributeService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
@@ -109,9 +108,9 @@ public class EventMsgService implements GzhMsgService {
 		}
 		//迁移公众号之后同步授权后信息
 		//是否是迁移用户
-		WxSyncLog wxSyncLog = wxSyncLogMapper.selectOne(Wrappers.lambdaQuery(WxSyncLog.class)
-				.eq(WxSyncLog::getToAppid, weChatConfig.getAppid())
-				.eq(WxSyncLog::getNewOpenid, openId).last("limit 1"));
+//		WxSyncLog wxSyncLog = wxSyncLogMapper.selectOne(Wrappers.lambdaQuery(WxSyncLog.class)
+//				.eq(WxSyncLog::getToAppid, weChatConfig.getAppid())
+//				.eq(WxSyncLog::getNewOpenid, openId).last("limit 1"));
 
 		WxApp wxApp = wxAppMapper.selectOne(Wrappers.lambdaQuery(WxApp.class)
 				.eq(WxApp::getGzhOriginalId, msgEvent.getToUserName()).last("limit 1"));
@@ -119,7 +118,7 @@ public class EventMsgService implements GzhMsgService {
 			return false;
 		}
 		GzhUnionidUserinfo info = weChatService.getUserInfo2(weChatService.getAccessToken(wxApp.getAppId()), openId);
-		User user = userService.getSyncUser(info.getOpenid(), info.getUnionid(), wxSyncLog);
+		User user = userService.getSyncUser(info.getOpenid(), info.getUnionid(), null);
 
 		String state = redisService.getStr(RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getNameFormat(sceneKey));
 		GzhBodyDto gzhDto = null;

+ 1 - 3
netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonService.java

@@ -1,10 +1,7 @@
 package com.cyksj.service.mange;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.model.entity.GoodsDon;
-import org.springframework.stereotype.Service;
 
 /**
  * @author chan
@@ -12,4 +9,5 @@ import org.springframework.stereotype.Service;
  */
 public interface CmsGoodsDonService extends IService<GoodsDon> {
 
+	void updateGoodsSkuPrice(Long goodsId, GoodsDon goodsDon);
 }

+ 3 - 5
netflix-service/src/main/java/com/cyksj/service/mange/CmsGroupService.java

@@ -1,12 +1,8 @@
 package com.cyksj.service.mange;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.cyksj.mapper.GroupsMapper;
 import com.cyksj.model.entity.GroupsTrips;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
+import com.cyksj.model.request.ReplaceTripsAccountReq;
 
 /**
  * @author chan
@@ -19,4 +15,6 @@ public interface CmsGroupService extends IService<GroupsTrips> {
     void close(Long groupId);
 
     void setAccount(GroupsTrips groupsTrips);
+
+    void replaceTripsAccount(ReplaceTripsAccountReq req);
 }

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java

@@ -131,6 +131,17 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 
 		int accountSize = accountViews.size();
 
+		if (accountSize < customerSize) {
+			accountViews.forEach(account->{
+				int randomIndex = RandomUtil.randomInt(customerSize);
+				CmsUserVO customer = customers.get(randomIndex);
+				accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
+						.set(Account::getCustomerServiceId, customer.getId())
+						.eq(Account::getId, account.getId()));
+			});
+			return;
+		}
+
 		int num = accountSize / customerSize;
 
 		int remain = accountSize % customerSize;

+ 35 - 0
netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonServiceImpl.java

@@ -3,14 +3,49 @@ package com.cyksj.service.mange.goods;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.model.views.GoodsDonFrontSkuView;
 import com.cyksj.service.mange.CmsGoodsDonService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+import java.util.Optional;
+
 /**
  * @author chan
  * @date 2022/9/27 5:31 PM
  */
 @Service
+@RequiredArgsConstructor
 public class CmsGoodsDonServiceImpl extends ServiceImpl<GoodsDonMapper, GoodsDon> implements CmsGoodsDonService {
+	private final BeanSearcher beanSearcher;
+
+	private final GoodsDonMapper goodsDonMapper;
 
+	@Override
+	public void updateGoodsSkuPrice(Long goodsId, GoodsDon goods) {
+		goods = Optional.ofNullable(goods).orElse(goodsDonMapper.selectById(goodsId));
+		List<GoodsDonFrontSkuView> skuViews = beanSearcher.searchAll(GoodsDonFrontSkuView.class, MapUtils.builder()
+				.field(GoodsDonFrontSkuView::getGoodsId, goodsId)
+				.field(GoodsDonFrontSkuView::getStatus, true)
+				.orderBy(GoodsDonFrontSkuView::getPrice).asc().onlySelect(GoodsDonFrontSkuView::getPrice, GoodsDonFrontSkuView::getMonths).build());
+		if (!skuViews.isEmpty()) {
+			GoodsDonFrontSkuView min = skuViews.get(0);
+			if (skuViews.size() == 1) {
+				goods.setMinPrice(min.getPrice());
+				goods.setMinMonths(min.getMonths());
+				goods.setMaxPrice(min.getPrice());
+				goods.setMaxMonths(min.getMonths());
+			} else {
+				GoodsDonFrontSkuView max = skuViews.get(skuViews.size() - 1);
+				goods.setMinPrice(min.getPrice());
+				goods.setMinMonths(min.getMonths());
+				goods.setMaxPrice(max.getPrice());
+				goods.setMaxMonths(max.getMonths());
+			}
+			goodsDonMapper.updateById(goods);
+		}
+	}
 }

+ 116 - 0
netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java

@@ -2,12 +2,23 @@ package com.cyksj.service.mange.group;
 
 import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.common.util.SmsUtil;
 import com.cyksj.mapper.*;
+import com.cyksj.mapper.manage.GroupsTripsAccountReplaceRecordMapper;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
 import com.cyksj.model.entity.*;
+import com.cyksj.model.request.ReplaceTripsAccountReq;
+import com.cyksj.model.views.GroupsAccountView;
 import com.cyksj.service.mange.CmsGroupService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -34,6 +45,20 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
 
     private final AccountMapper accountMapper;
 
+    private final BeanSearcher beanSearcher;
+
+    private final GroupsTripsAccountReplaceRecordMapper replaceRecordMapper;
+
+    private final CmsUserMapper cmsUserMapper;
+
+    private final GoodsDonMapper goodsDonMapper;
+
+    private UserBindDetailMapper userBindDetailMapper;
+
+    private final UserMapper userMapper;
+
+    private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
+
 
     @Override
     public GroupsTrips issuance(GroupsTrips groups) {
@@ -108,4 +133,95 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
 
     }
 
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public void replaceTripsAccount(ReplaceTripsAccountReq req) {
+        Long groupsId = req.getGroupsId();
+        String account = req.getAccount().trim();
+        String password = req.getPassword().trim();
+        String remark = req.getRemark();
+        GroupsAccountView groupsAccountView = beanSearcher.searchFirst(GroupsAccountView.class, MapUtils.builder()
+                .field(GroupsAccountView::getGroupsId, groupsId)
+                .build());
+        if (groupsId == null) {
+            throw BusinessRuntimeException.getInstance("车队已不存在");
+        }
+        Long accountId = groupsAccountView.getAccountId();
+        if (accountId == null) {
+            throw BusinessRuntimeException.getInstance("该车队暂未配置账号");
+        }
+        Long goodsId = groupsAccountView.getGoodsId();
+        if (!account.contains("客服")) {
+            int count = accountMapper.selectCount(Wrappers.lambdaQuery(Account.class)
+                    .eq(Account::getAccount, account)
+                    .eq(Account::getGoodsId, goodsId));
+            if (count > 0) {
+                throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
+            }
+        }
+        //新增账号
+        Account replace = new Account();
+        replace.setAccount(account);
+        replace.setPassword(password);
+        replace.setGoodsId(goodsId);
+
+        replace.setStartTime(groupsAccountView.getStartTime());
+        replace.setExpiryTime(groupsAccountView.getExpiryTime());
+        replace.setRemark(remark);
+        accountMapper.insert(replace);
+
+        //替换车队账号
+        this.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
+                .set(GroupsTrips::getAccountId, replace.getId())
+                .eq(GroupsTrips::getId, groupsId));
+
+        //删除旧的账号
+        accountMapper.deleteById(accountId);
+
+        //保存替换记录
+        GroupsTripsAccountReplaceRecord replaceRecord = new GroupsTripsAccountReplaceRecord();
+        replaceRecord.setGroupsId(groupsId);
+        replaceRecord.setOldAccountId(accountId);
+        replaceRecord.setOldAccount(groupsAccountView.getAccount());
+        replaceRecord.setOldPassword(groupsAccountView.getPassword());
+        replaceRecord.setOldStartTime(groupsAccountView.getStartTime());
+        replaceRecord.setOldExpiryTime(groupsAccountView.getExpiryTime());
+
+        Long adminId = req.getAdminId();
+        Optional.ofNullable(cmsUserMapper.selectById(adminId)).ifPresent(admin -> replaceRecord.setOperator(admin.getNickname()));
+
+        replaceRecord.setNewAccountId(replace.getId());
+        replaceRecord.setNewAccount(replace.getAccount());
+        replaceRecord.setNewPassword(replace.getPassword());
+        replaceRecord.setNewStartTime(replace.getStartTime());
+        replaceRecord.setNewExpiryTime(replace.getExpiryTime());
+
+        replaceRecordMapper.insert(replaceRecord);
+
+        TASK_EXECUTOR.execute(() -> sendChangeAccountMsg(groupsId, goodsId));;
+    }
+
+    private void sendChangeAccountMsg(Long groupsId,Long goodsId) {
+        GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
+        List<GroupsRelation> groupsRelations = beanSearcher.searchAll(GroupsRelation.class, MapUtils.builder().field(GroupsRelation::getGroupsId, groupsId).build());
+        groupsRelations.forEach(relation->{
+            Long userId = relation.getUserId();
+            User user = userMapper.selectById(userId);
+            String phone = null;
+            if (user != null) {
+                phone = user.getLoginPhone();
+                if (StrUtil.isEmpty(phone)) {
+                    UserBindDetail userBindDetail = userBindDetailMapper.selectById(userId);
+                    if (userBindDetail != null) {
+                        phone = userBindDetail.getPhone();
+                    }
+                }
+            }
+            if (StrUtil.isNotBlank(phone)) {
+                String title = goodsDon != null ? goodsDon.getTitle() : "车票";
+                SmsUtil.sendLuoKey2Msg(phone, String.format(Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title));
+            }
+
+        });
+    }
 }

+ 36 - 14
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -248,11 +248,17 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 					}
 
 				} else {
-					//寻找差不多过期时间规格的车位
-					relation = groupRelationFrontService.getSimilarExpiredGroupRelation(sku.getId(), sku.getMonths(), null);
+					if (goodsDon.getId() != 18) {
+						//寻找差不多过期时间规格的车位
+						relation = groupRelationFrontService.getSimilarExpiredGroupRelation(sku.getId(), sku.getMonths(), null);
+					}
 					if (relation == null) {
 						//TODO 如果没指定座位,等待逻辑确认
-						GroupsTrips groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getSkuId, payRequest.getSkuId()).gt(GroupsTrips::getAvailableNum, 0).last("limit 1").orderByAsc(GroupsTrips::getAvailableNum));
+						LambdaQueryWrapper<GroupsTrips> queryWrapper = Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getSkuId, payRequest.getSkuId()).gt(GroupsTrips::getAvailableNum, 0).last("limit 1").orderByAsc(GroupsTrips::getAvailableNum);
+						if (goodsDon.getId() == 18) {
+							queryWrapper.isNull(GroupsTrips::getAccountId);
+						}
+						GroupsTrips groups = groupsMapper.selectOne(queryWrapper);
 						if (groups == null) {
 							relation = createNewGroupsTrips(sku);
 							isNew = true;
@@ -1411,6 +1417,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		payeeInfo.setIdentityType(TransferConstant.ALIPAY_LOGON_ID);
 		payeeInfo.setName(name);
 		model.setPayeeInfo(payeeInfo);
+		model.setRemark("分销提现转账");
 		transUniTransferRequest.setBizModel(model);
 		return transUniTransferRequest;
 	}
@@ -2159,19 +2166,34 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 	}
 
 	/**
-	 * 购买Midjourney课程 赠送Midjourney车票
+	 * 购买Midjourney课程 赠送车票
 	 */
 	private void sendMidjourneyTicketIfCourse(Long userId) {
-		Optional.ofNullable(goodsDonSkuMapper.selectById(185))
-				.ifPresent(sku -> {
-					GroupsRelation relation = exchangeCodeService.getRelationNoOrder(sku, userId);
-					if (relation.getExpiryTime() == null || relation.getStartTime() == null) {
-						DateTime now = DateTime.now();
-						relation.setStartTime(now);
-						relation.setExpiryTime(DateUtil.offsetMonth(now, sku.getMonths() * 1));
-						groupsRelationMapper.updateById(relation);
-					}
-				});
+		SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.MIDJOURNEY_TICKET_SKU_IDS).last("limit 1"));
+		if (config != null) {
+			String sysValue = config.getSysValue();
+			if (StrUtil.isNotBlank(sysValue)) {
+				try {
+					//Midjourney车票、ChatGPT独立规格车票
+					List<Long> skuIds = Jsons.parseList(sysValue, Long.class);
+					skuIds.forEach(skuId->{
+						GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
+						if (sku != null && sku.getStatus()) {
+							GroupsRelation relation = exchangeCodeService.getRelationNoOrder(sku, userId);
+							if (relation.getExpiryTime() == null || relation.getStartTime() == null) {
+								DateTime now = DateTime.now();
+								relation.setStartTime(now);
+								relation.setExpiryTime(DateUtil.offsetMonth(now, sku.getMonths() * 1));
+								groupsRelationMapper.updateById(relation);
+							}
+						}
+					});
+				} catch (Exception e) {
+					log.error("购买midJourney课程赠送车票错误,errMsg:{}", StringUtil.getErrorText(e));
+				}
+			}
+		}
 	}
 
 	/**

+ 67 - 27
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java

@@ -3,16 +3,19 @@ package com.cyksj.service.relation.impl;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.mapper.GroupsMapper;
 import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.GroupsTripsDeleteRecordMapper;
 import com.cyksj.mapper.UserTicketClearedRecordMapper;
-import com.cyksj.model.entity.GroupsRelation;
-import com.cyksj.model.entity.UserTicketClearedRecord;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.service.mange.CmsAccountService;
+import com.cyksj.service.mange.CmsGroupService;
 import com.cyksj.service.relation.GroupRelationClearService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Date;
 
@@ -34,42 +37,79 @@ public class GroupRelationClearServiceImpl implements GroupRelationClearService
 
 	private final UserTicketClearedRecordMapper userTicketClearedRecordMapper;
 
+	private final CmsGroupService groupService;
+
+	private final CmsAccountService accountService;
+
+	private final GroupsTripsDeleteRecordMapper groupsTripsDeleteRecordMapper;
+
+
 	@Override
+	@Transactional(rollbackFor = Throwable.class)
 	public void clearTicket(GroupsRelation relation, UserTicketClearedRecord.Source source) {
 		Long relationId = relation.getId();
-		Long userId = relation.getUserId();
-		Date startTime = relation.getStartTime();
-		Date expireTime = relation.getExpiryTime();
-		relation.setStartTime(null);
-		relation.setExpiryTime(null);
-		relation.setUserId(0l);
-		relation.setStatus(GroupsRelation.Status.none);
-		relation.setIsHandle(false);
-		relation.setRenewStatus(false);
-		relation.setAccount(null);
-		Integer success = groupsRelationMapper.updateExpiryTime(relation, expireTime);
-		if (success == 1) {
-			log.info("开始清除过期子账号,座位号:{}", relation.getId());
-			int count = groupsMapper.incrAvailableNum(relation.getGroupsId());
-			if (count == 0) {
-				log.error("车位异常 groupId:{}", relation.getGroupsId());
-				throw new BusinessRuntimeException("车位异常");
+		//记录用户被清除车票历史记录
+		GroupsRelationView groupsRelation = beanSearcher.searchFirst(GroupsRelationView.class,
+				MapUtils.builder().field(GroupsRelationView::getId, relationId).build());
+		if (groupsRelation != null) {
+			Long userId = relation.getUserId();
+			Date startTime = relation.getStartTime();
+			Date expireTime = relation.getExpiryTime();
+			relation.setStartTime(null);
+			relation.setExpiryTime(null);
+			Boolean isFlag = false;
+			//非chatGpt独立会员规格车队
+			if (!groupsRelation.getSkuId().equals(177l)) {
+				relation.setUserId(0l);
+				isFlag = true;
 			}
-			//记录用户被清除车票历史记录
-			GroupsRelationView groupsTrips = beanSearcher.searchFirst(GroupsRelationView.class,
-					MapUtils.builder().field(GroupsRelationView::getId, relationId).build());
-			if (groupsTrips != null) {
+			relation.setStatus(GroupsRelation.Status.none);
+			relation.setIsHandle(false);
+			relation.setRenewStatus(false);
+			relation.setAccount(null);
+			Integer success = groupsRelationMapper.updateExpiryTime(relation, expireTime);
+			if (success == 1) {
+				log.info("开始清除过期子账号,座位号:{}", relation.getId());
+				int count = groupsMapper.incrAvailableNum(relation.getGroupsId());
+				if (count == 0) {
+					log.error("车位异常 groupId:{}", relation.getGroupsId());
+					throw new BusinessRuntimeException("车位异常");
+				}
 				UserTicketClearedRecord userTicketClearedRecord = new UserTicketClearedRecord();
-				userTicketClearedRecord.setAccountId(groupsTrips.getAccountId());
-				userTicketClearedRecord.setAccount(groupsTrips.getTripsAccount());
+				userTicketClearedRecord.setAccountId(groupsRelation.getAccountId());
+				userTicketClearedRecord.setAccount(groupsRelation.getTripsAccount());
 				userTicketClearedRecord.setRelationId(relationId);
 				userTicketClearedRecord.setUserId(userId);
 				userTicketClearedRecord.setSource(source);
-				userTicketClearedRecord.setGoodsId(groupsTrips.getGoodsId());
-				userTicketClearedRecord.setSkuId(groupsTrips.getSkuId());
+				userTicketClearedRecord.setGoodsId(groupsRelation.getGoodsId());
+				userTicketClearedRecord.setSkuId(groupsRelation.getSkuId());
 				userTicketClearedRecord.setStartTime(startTime);
 				userTicketClearedRecord.setExpiryTime(expireTime);
 				userTicketClearedRecordMapper.insert(userTicketClearedRecord);
+				if (!isFlag) {
+					//清除之前规格的车队
+					groupService.close(groupsRelation.getGroupsId());
+					if (groupsRelation.getAccountId() != null) {
+						//生成10人月付新规格车队
+						Account account = accountService.getById(groupsRelation.getAccountId());
+						account.setSkuId(161l);
+						accountService.updateById(account);
+						GroupsTrips gt = new GroupsTrips();
+						gt.setSkuId(account.getSkuId());
+						gt.setAccountId(account.getId());
+						groupService.issuance(gt);
+
+						GroupsTripsDeleteRecord record = new GroupsTripsDeleteRecord();
+						record.setAccountId(gt.getAccountId());
+						record.setAccount(gt.getAccount());
+						record.setBeforeGroupsId(groupsRelation.getId());
+						record.setBeforeSkuId(groupsRelation.getSkuId());
+						record.setAfterGroupsId(gt.getId());
+						record.setAfterSkuId(gt.getSkuId());
+						groupsTripsDeleteRecordMapper.insert(record);
+						log.info("ChatGPT 独立会员账号车票过期,删除原先车队id:{}并生成一个10人月付规格的车队id:{}", groupsRelation.getId(), gt.getId());
+					}
+				}
 			}
 		}
 	}

+ 27 - 20
netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.constant.TemplateEnum;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
 import com.cyksj.config.WeChatConfig;
 import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.mapper.GoodsDonSkuMapper;
@@ -63,25 +64,27 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 	public void newOderSendMsgByType(OrderDon order, GoodsDon goodsDon, User user, String toPeople, Boolean isCustomer) throws Exception {
 		if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
 			String openId = toPeople;
-			WxAppTemplateView wxAppTemplateView = null;
-			if (isCustomer) {
-				wxAppTemplateView = this.getCustomerTemplateView(TemplateEnum.NEW_ORDER_TEMPLATE.getDesc());
-			} else {
-				wxAppTemplateView = this.getWxAppByUserId(openId, TemplateEnum.NEW_ORDER_TEMPLATE.getDesc());
-			}
-			if (wxAppTemplateView != null) {
-				WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
-						.setToUser(openId)
-						.setTemplateId(wxAppTemplateView.getTemplateId())
-						//TODO
-						.setUrl(" ");
-				WxMpTemplateMessage.TemplateData data = templateMessage.getData();
-				data.setFirst(new WxMpTemplateData("新订单通知!"));
-				data.setKeyword1(new WxMpTemplateData(order.getOrderNo()));
-				data.setKeyword2(new WxMpTemplateData(String.format("%s服务", goodsDon.getTitle())));
-				data.setKeyword3(new WxMpTemplateData(order.getMoney().divide(BigDecimal.valueOf(100)).toString()));
-				data.setRemark(new WxMpTemplateData(goodsDon.getType() == 1 && goodsDon.getSecondType() == 1 ? "需要联系客服邀请才可使用,请联系客服" : "点击查看详情"));
-				weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+			if (StrUtil.isNotBlank(openId)) {
+				WxAppTemplateView wxAppTemplateView = null;
+				if (isCustomer) {
+					wxAppTemplateView = this.getCustomerTemplateView(TemplateEnum.NEW_ORDER_TEMPLATE.getDesc());
+				} else {
+					wxAppTemplateView = this.getWxAppByUserId(openId, TemplateEnum.NEW_ORDER_TEMPLATE.getDesc());
+				}
+				if (wxAppTemplateView != null) {
+					WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+							.setToUser(openId)
+							.setTemplateId(wxAppTemplateView.getTemplateId())
+							//TODO
+							.setUrl(" ");
+					WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+					data.setFirst(new WxMpTemplateData("新订单通知!"));
+					data.setKeyword1(new WxMpTemplateData(order.getOrderNo()));
+					data.setKeyword2(new WxMpTemplateData(String.format("%s服务", goodsDon.getTitle())));
+					data.setKeyword3(new WxMpTemplateData(order.getMoney().divide(BigDecimal.valueOf(100)).toString()));
+					data.setRemark(new WxMpTemplateData(goodsDon.getType() == 1 && goodsDon.getSecondType() == 1 ? "需要联系客服邀请才可使用,请联系客服" : "点击查看详情"));
+					weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+				}
 			}
 		}
 	}
@@ -238,7 +241,11 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 				data.setKeyword2(new WxMpTemplateData(DateTime.now().toString("YYYY-MM-mm HH:mm:ss")));
 				data.setRemark(new WxMpTemplateData("您的账号密码已经更新,请到我的车票查看,长期用户请选择拼车/年付。\n" +
 						"如您不是在公众号购买,请在浏览器登录查看我的车票"));
-				weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+				try {
+					weChatService.sendTemplateMessage(weChatService.getAccessToken(wxAppTemplateView.getAppId()), Jsons.toJson(templateMessage));
+				} catch (Exception e) {
+					log.info("发送用户:{}车票账号修改密码模板消息错误,errorMsg:{}", user.getId(), StringUtil.getErrorText(e));
+				}
 			}
 		}
 	}

+ 1 - 18
netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java

@@ -72,11 +72,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         if (StrUtil.isEmpty(unionid)) {
             throw BusinessRuntimeException.getInstance("授权操作异常,请刷新页面");
         }
-        WxSyncLog wxSyncLog = wxSyncLogMapper.selectOne(Wrappers.lambdaQuery(WxSyncLog.class)
-                .eq(WxSyncLog::getToAppid, weChatConfig.getAppid())
-                .eq(WxSyncLog::getNewOpenid, info.getOpenid()).last("limit 1"));
 
-		User user = getSyncUser(info.getOpenid(), info.getUnionid(), wxSyncLog);
+		User user = getSyncUser(info.getOpenid(), info.getUnionid(), null);
 
 		user = Optional.ofNullable(user).orElseGet(() -> new User()
 				.setUnionid(unionid));
@@ -90,20 +87,6 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 		if (StrUtil.isEmpty(user.getHeadimgurl())) {
 			user.setHeadimgurl(info.getHeadimgurl());
 		}
-		if (!user.getUnionid().equals(unionid)) {
-			UserTransferLog log = new UserTransferLog();
-			if (wxSyncLog != null) {
-				log.setType("公众号迁移");
-			} else {
-				log.setType("绑定开发者账号");
-			}
-			log.setOldAppId(weChatConfig.getOldAppid());
-			log.setNewAppId(weChatConfig.getAppid());
-			log.setUserId(user.getId());
-			log.setOldUnionid(user.getUnionid());
-			log.setNewUnionid(info.getUnionid());
-			userTransferLogMapper.insert(log);
-		}
 		user.setUnionid(unionid);
 		user.setOpenId(info.getOpenid());
 		Boolean isNewUser = false;

+ 5 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java

@@ -88,4 +88,9 @@ public interface WeChatService {
      * 获取微信订单信息 校验订单是否已支付
      */
     Map<String, String> getWxOrderDetail(String shopId, String orderNo) throws Exception;
+
+    /**
+     * 获取微信网页授权url
+     */
+    String createWxAuthLoginUrl(String state, String appId, String redirectUri);
 }

+ 22 - 1
netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java

@@ -9,6 +9,7 @@ import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
 import cn.hutool.json.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.*;
 import com.cyksj.config.BaseWeChatConfig;
@@ -19,9 +20,11 @@ import com.cyksj.mapper.WxAppMapper;
 import com.cyksj.mapper.channel.ShopConfigMapper;
 import com.cyksj.model.dto.*;
 import com.cyksj.model.entity.ShopConfig;
+import com.cyksj.model.entity.SysConfig;
 import com.cyksj.model.entity.WxApp;
 import com.cyksj.model.response.WxGzhQrCodeTicketRep;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.service.wechat.WeChatService;
 import com.cyksj.service.wechat.WxMpAccountOps;
 import lombok.RequiredArgsConstructor;
@@ -65,6 +68,8 @@ public class WeChatServiceImpl implements WeChatService {
 
     private final RedisService redisService;
 
+    private final SysConfigService sysConfigService;
+
     @Override
     public String createUrl(String state, String redirectUrl) {
         return createUrl(state,redirectUrl,weChatConfig.getAppid(), WeChatAuthRedirectUrl.BASE.getScope());
@@ -478,7 +483,16 @@ public class WeChatServiceImpl implements WeChatService {
 
     @Override
     public WxGzhQrCodeTicketRep getWxGzhQrCode(Long sharedId, Integer dsType, Long popularizeId, String loginPhone) throws Exception {
-        String gzhQrCodeUrl = String.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", this.getAccessToken());
+        SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+                .eq(SysConfig::getSysKey, Constant.QR_CODE_WX_APP_ID).last("limit 1"));
+        String appid = null;
+        if (sysConfig != null) {
+            String sysValue = sysConfig.getSysValue();
+            if (StrUtil.isNotBlank(sysValue)) {
+                appid = sysValue;
+            }
+        }
+        String gzhQrCodeUrl = String.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", this.getAccessToken(appid));
         //scene_str:场景值ID(字符串形式的ID),字符串类型,长度限制为1到64
         String scene_str = RandomUtil.randomString(16);
         int expireTime = 60;
@@ -564,6 +578,13 @@ public class WeChatServiceImpl implements WeChatService {
         return orderSearch;
     }
 
+    @Override
+    public String createWxAuthLoginUrl(String state, String appId, String redirectUri) {
+        String authLoginUrl = String.format("https://open.weixin.qq.com/connect/qrconnect?" +
+                "appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect", appId, redirectUri, state);
+        return authLoginUrl;
+    }
+
     /**
      * sha256_HMAC加密
      * @param message 消息

+ 86 - 0
netflix-service/src/main/java/com/cyksj/task/Scheduler.java

@@ -7,17 +7,22 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.EnvCommonService;
+import com.cyksj.common.constant.Constant;
 import com.cyksj.common.constant.TemplateEnum;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.SmsUtil;
 import com.cyksj.dto.RedisKey;
 import com.cyksj.mapper.*;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
 import com.cyksj.mapper.manage.sys.WorkOrderMapper;
 import com.cyksj.model.dto.WxMpTemplateData;
 import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.views.CmsUserVO;
+import com.cyksj.model.views.UserDistributeViews;
 import com.cyksj.model.views.WxAppTemplateView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.mange.CmsAccountService;
@@ -38,7 +43,10 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 
 @Component
@@ -90,6 +98,10 @@ public class Scheduler {
 
         private final WorkOrderMapper workOrderMapper;
 
+        private final UserDistributeMapper userDistributeMapper;
+
+        private final CmsUserMapper cmsUserMapper;
+
 
     /**
      * 每5分钟清理过期账号
@@ -347,4 +359,78 @@ public class Scheduler {
             });
         }
     }
+
+    /**
+     * 推广者渠道昨天订单金额是否小于过去7天平均订单金额的一半
+     * 若小于 则发送短信到对应商务
+     */
+    @Scheduled(cron = "0 30 8 * * ?")
+    public void distributeOrderDetailAndSendMsgToBusiness() {
+	    Integer daysRule = 7;
+	    DateTime thisZero = DateUtil.beginOfDay(DateTime.now());
+
+	    DateTime yesZero = DateUtil.offsetDay(thisZero, -1);
+	    DateTime thePast7dZero = DateUtil.offsetDay(yesZero, -daysRule);
+
+	    DateTime twoYesZero = DateUtil.offsetDay(thisZero, -2);
+	    DateTime theTwoPast7dZero = DateUtil.offsetDay(twoYesZero, -daysRule);
+	    //总销量小于1000的 不算、建立天数低于7天的不算、 连续2天销量低于7天平均值的50%的 提醒
+	    List<UserDistributeViews> userDistributeViews = beanSearcher.searchAll(UserDistributeViews.class, MapUtils.builder()
+			    .field(UserDistributeViews::getCreatedTime, thePast7dZero).op(Operator.LessEqual)
+			    .field(UserDistribute::getBusinessId, 0).op(Operator.GreaterThan)
+			    .put("time", String.format("and od.created_time < '%s'", thisZero))
+			    .field(UserDistributeViews::getDistributeOrdersMoney, BigDecimal.valueOf(100000)).op(Operator.GreaterEqual)
+			    .build());
+	    String thePast7dTimeSql = String.format("and od.created_time >= '%s' and od.created_time < '%s'", thePast7dZero, yesZero);
+	    String yesTimeSql = String.format("and od.created_time >= '%s' and od.created_time < '%s'", yesZero, thisZero);
+
+	    String theTwoPast7dTimeSql = String.format("and od.created_time >= '%s' and od.created_time < '%s'", theTwoPast7dZero, twoYesZero);
+	    String twoYesTimeSql = String.format("and od.created_time >= '%s' and od.created_time < '%s'", twoYesZero, yesZero);
+
+	    Map<Long, String> phoneMap = new ConcurrentHashMap<>();
+	    userDistributeViews.forEach(data -> {
+		    //昨天过去7天总订单金额
+		    Number yesPastFtMoneySum = beanSearcher.searchSum(UserDistributeViews.class, MapUtils.builder()
+				    .field(UserDistributeViews::getUserId, data.getUserId())
+				    .put("time", thePast7dTimeSql).build(), "distributeOrdersMoney");
+		    //前天过去7天总订单金额
+		    Number towYesPastMoneySum = beanSearcher.searchSum(UserDistributeViews.class, MapUtils.builder()
+				    .field(UserDistributeViews::getUserId, data.getUserId())
+				    .put("time", theTwoPast7dTimeSql).build(), "distributeOrdersMoney");
+
+		    int theYes7dPastMoney = yesPastFtMoneySum.intValue();
+
+		    int theTwoYes7dPastMoney = towYesPastMoneySum.intValue();
+		    UserDistributeViews yesDistribute = beanSearcher.searchFirst(UserDistributeViews.class, MapUtils.builder()
+				    .field(UserDistributeViews::getUserId, data.getUserId())
+				    .put("time", yesTimeSql).build());
+
+		    UserDistributeViews twoYesDistribute = beanSearcher.searchFirst(UserDistributeViews.class, MapUtils.builder()
+				    .field(UserDistributeViews::getUserId, data.getUserId())
+				    .put("time", twoYesTimeSql).build());
+		    BigDecimal yesDistributeOrdersMoney = yesDistribute.getDistributeOrdersMoney();
+		    BigDecimal twoYesDistributeOrdersMoney = twoYesDistribute.getDistributeOrdersMoney();
+
+		    BigDecimal thePast7dAverage = BigDecimal.valueOf(theYes7dPastMoney).divide(BigDecimal.valueOf(daysRule).multiply(BigDecimal.valueOf(2)), 2, RoundingMode.HALF_DOWN);
+		    BigDecimal theTwoPast7dAverage = BigDecimal.valueOf(theTwoYes7dPastMoney).divide(BigDecimal.valueOf(daysRule).multiply(BigDecimal.valueOf(2)), 2, RoundingMode.HALF_DOWN);
+		    if (yesDistributeOrdersMoney.compareTo(thePast7dAverage) < 0 && twoYesDistributeOrdersMoney.compareTo(theTwoPast7dAverage) < 0) {
+			    User user = userMapper.selectById(data.getUserId());
+			    String msg = String.format(Constant.BUSINESS_CHANNEL_MSG, (user == null ? "用户" : user.getNickname()), data.getUserId());
+			    String phone = phoneMap.get(data.getUserId());
+			    if (StrUtil.isBlank(phone)) {
+				    CmsUser cmsUser = cmsUserMapper.selectById(data.getBusinessId());
+				    if (cmsUser != null) {
+					    phone = cmsUser.getPhone();
+					    phoneMap.putIfAbsent(data.getBusinessId(), phone);
+				    }
+			    }
+			    if (StrUtil.isNotBlank(phone)) {
+				    log.info("商务businessId:{}所下渠道用户id:{}分销数据已低于7天平均值的50%%", data.getBusinessId(), data.getUserId());
+				    //发短信
+				    SmsUtil.send(phone, msg);
+			    }
+			    return;
+		    }
+	    });
+    }
 }

+ 35 - 12
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -1,17 +1,20 @@
 package com.cyksj.web.controller.goods;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.RandomUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.*;
+import com.cyksj.redis.RedisService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
@@ -22,8 +25,9 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
-import java.math.BigDecimal;
-import java.util.*;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
 
 /**
  * @author chan
@@ -43,6 +47,8 @@ public class GoodsDonController {
 
     private final GoodsDonSkuMapper goodsDonSkuMapper;
 
+    private final RedisService redisService;
+
     /**
      * 获取商品列表
      */
@@ -148,11 +154,21 @@ public class GoodsDonController {
      * 官网首页 平台列表
      */
     @GetMapping("/get/list")
-    public Result<SearchResult<GoodsFrontListView>> getGoodsList() {
-        SearchResult<GoodsFrontListView> search = beanSearcher.search(GoodsFrontListView.class, MapUtils.flatBuilder(request.getParameterMap())
+    public Result<List<GoodsFrontListView>> getGoodsList() {
+        Object value = redisService.get(RedisService.key.PC_WEB_CACHE.getName());
+        if (value != null) {
+            try {
+                List<GoodsFrontListView> list = Jsons.parseObject(value, List.class);
+                if (CollUtil.isNotEmpty(list)) {
+                    return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+                }
+            } catch (Exception e) {
+            }
+        }
+        List<GoodsFrontListView> list = beanSearcher.searchAll(GoodsFrontListView.class, MapUtils.flatBuilder(request.getParameterMap())
                 .build());
         DateTime now = DateTime.now();
-        search.getDataList().forEach(data -> {
+        list.forEach(data -> {
             data.setSpecs(beanSearcher.searchFirst(GoodsDonSpec.class, MapUtils.builder().field(GoodsDonSpec::getGoodsId, data.getId()).build()));
             data.setSkuList(beanSearcher.searchAll(GoodsDonFrontSkuView.class, MapUtils.builder().field(GoodsDonFrontSkuView::getGoodsId, data.getId()).field(GoodsDonFrontSkuView::getStatus, true).orderBy(GoodsDonFrontSkuView::getPrice).asc().build()));
             Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
@@ -166,7 +182,6 @@ public class GoodsDonController {
                     data.setMonths(donFrontSkuView.getMonths());
                 }
             });
-
             OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
                     .eq(OrderDon::getGoodsId, data.getId())
                     .notIn(OrderDon::getStatus, Constant.noOrderStatus).select(OrderDon::getCreatedTime, OrderDon::getPayTime, OrderDon::getId)
@@ -202,7 +217,8 @@ public class GoodsDonController {
             notifyMsg.append("前有人购买");
             data.setNotifyMsg(notifyMsg.toString());
         });
-        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+        redisService.setNx(RedisService.key.PC_WEB_CACHE.getName(), list, RedisService.key.PC_WEB_CACHE.getTimeout());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(list);
     }
 
     /**
@@ -210,9 +226,18 @@ public class GoodsDonController {
      */
     @GetMapping("/get/homePage")
     public Result<List<GoodsHomePageView>> getGoodsHomePage() {
+        Object value = redisService.get(RedisService.key.H5_WEB_CACHE.getName());
+        if (value != null) {
+            try {
+                List<GoodsHomePageView> list = Jsons.parseObject(value, List.class);
+                if (CollUtil.isNotEmpty(list)) {
+                    return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+                }
+            } catch (Exception e) {
+            }
+        }
         List<GoodsHomePageView> dataList = beanSearcher.searchAll(GoodsHomePageView.class, MapUtils.flatBuilder(request.getParameterMap())
                 .build());
-        List<GoodsHomePageView> collect = new ArrayList<>();
         dataList.forEach(data -> {
             Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
                     .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
@@ -222,11 +247,9 @@ public class GoodsDonController {
                 data.setPrice(skuView.getPrice());
                 data.setMonths(skuView.getMonths());
             }
-            if (data.getPrice() != null && data.getPrice().compareTo(BigDecimal.ZERO) > 0) {
-                collect.add(data);
-            }
         });
-        return GatewayResponse.SUCCESS.newBuilder().toResult(collect);
+        redisService.setNx(RedisService.key.H5_WEB_CACHE.getName(), dataList, RedisService.key.H5_WEB_CACHE.getTimeout());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(dataList);
     }
 
 

+ 7 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java

@@ -217,7 +217,8 @@ public class CmsGoodsDonSkuController {
             goodsDonSkuService.save(goodsDonSku);
 
         }
-        
+        //给平台更新额外属性
+        goodsDonService.updateGoodsSkuPrice(goods.getId(), goods);
        return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 
@@ -229,6 +230,8 @@ public class CmsGoodsDonSkuController {
     @Log(module = "平台管理/编辑规格", businessType = BusinessType.PUT, isSaveRequestData = true)
     public Result<String> skuUpdate(@RequestBody GoodsDonSku sku){
         goodsDonSkuService.saveOrUpdate(sku);
+        //给平台更新额外属性
+        goodsDonService.updateGoodsSkuPrice(sku.getGoodsId(), null);
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 
@@ -241,6 +244,9 @@ public class CmsGoodsDonSkuController {
     @Log(module = "平台管理/删除规格", businessType = BusinessType.DELETE)
     public Result<String> skuDelete(@PathVariable Long skuId) {
         goodsDonSkuService.removeById(skuId);
+        //给平台更新额外属性
+        GoodsDonSku sku = goodsDonSkuService.getById(skuId);
+        goodsDonService.updateGoodsSkuPrice(sku.getGoodsId(), null);
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 

+ 24 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupController.java

@@ -1,6 +1,7 @@
 package com.cyksj.web.controller.manage.group;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.Log;
@@ -12,7 +13,9 @@ import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.GroupsTrips;
+import com.cyksj.model.entity.GroupsTripsAccountReplaceRecord;
 import com.cyksj.model.request.AccountGroupsReq;
+import com.cyksj.model.request.ReplaceTripsAccountReq;
 import com.cyksj.model.views.GoodsDonSkuView;
 import com.cyksj.model.views.GroupsTripsWaitingView;
 import com.cyksj.service.mange.CmsAccountService;
@@ -156,4 +159,25 @@ public class CmsGroupController {
         groupService.setAccount(groupsTrips);
         return GatewayResponse.SUCCESS.newBuilder().toResult("车队配置新账号成功");
     }
+
+
+    /**
+     * 车队替换账号
+     */
+    @PutMapping("/account/replace")
+    public Result<String> replaceTripsAccount(@RequestBody ReplaceTripsAccountReq req) {
+        long adminId = StpUtil.getLoginIdAsLong();
+        req.setAdminId(adminId);
+        groupService.replaceTripsAccount(req);
+        return GatewayResponse.SUCCESS.newBuilder().toResult("车队替换账号成功");
+    }
+
+    /**
+     * 车队替换账号记录
+     */
+    @GetMapping("/get/account/replace/record")
+    public Result<SearchResult<GroupsTripsAccountReplaceRecord>> getAccountReplaceRecord() {
+        SearchResult<GroupsTripsAccountReplaceRecord> search = beanSearcher.search(GroupsTripsAccountReplaceRecord.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
 }

+ 23 - 0
netflix-web/src/main/java/com/cyksj/web/controller/sys/FrontProblemCollectRecordController.java

@@ -32,8 +32,22 @@ public class FrontProblemCollectRecordController {
 	@PostMapping
 	public Result saveProblem(@RequestBody FrontProblemCollectRecord record) {
 		String errorMsg = record.getErrorMsg();
+		String track = record.getTrack();
+		String handle = record.getHandle();
+		Boolean isFlag = false;
 		if (StrUtil.isNotBlank(errorMsg)) {
 			record.setErrorMsg(StrUtil.subSufByLength(errorMsg, 2000));
+			isFlag = true;
+		}
+		if (StrUtil.isNotBlank(track)) {
+			record.setTrack(StrUtil.subSufByLength(track, 2000));
+			isFlag = true;
+		}
+		if (StrUtil.isNotBlank(handle)) {
+			record.setHandle(StrUtil.subSufByLength(handle, 2000));
+			isFlag = true;
+		}
+		if (isFlag) {
 			recordMapper.insert(record);
 		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
@@ -47,4 +61,13 @@ public class FrontProblemCollectRecordController {
 		SearchResult<FrontProblemCollectRecord> search = beanSearcher.search(FrontProblemCollectRecord.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
+
+	/**
+	 * 清空
+	 */
+	@DeleteMapping("/empty")
+	public Result<String> delete() {
+		recordMapper.delete(null);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 }

+ 51 - 43
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -49,8 +49,6 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
 import java.util.Date;
 
 /**
@@ -119,42 +117,9 @@ public class AuthorizationController {
      */
     @GetMapping(value = "/weChat/baseRedirect")
     public void redirect(String code, String state, HttpServletResponse response) throws Exception {
-
-        // 转跳参数
-        String json = Codec.DoBase64.custom().setData(state).decodeAsText();
-        AuthRedirect re = Jsons.parseObject(json, AuthRedirect.class);
-
         AuthToken token = weChatService.getAuthToken(code,weChatConfig.getAppid());
 
-        // 根据openid 与 access_token 获取用户信息
-        GzhOAuth2UserInfo userinfo = weChatService.getUserInfo(token.getAccessToken(), token.getOpenid());
-
-        //保存用户信息
-        User user = userService.saveAuth(userinfo, re.getSharedId(), re.getDsType(), re.getPid());
-        if (user == null) {
-            throw BusinessRuntimeException.getInstance("系统错误,请重新授权");
-        }
-
-        //写回登陆信息
-        StpUserUtil.login(user.getId());
-        response.addHeader("satoken-user",StpUserUtil.getTokenValue());
-
-        Cookie cookie = new Cookie("satoken-user",StpUserUtil.getTokenValue());
-        cookie.setMaxAge(31536000);
-        cookie.setPath("/");
-        response.addCookie(cookie);
-        JSONObject jsonObject = new JSONObject();
-        jsonObject.putOpt("uid",user.getId());
-        jsonObject.putOpt("nickName",user.getNickname());
-
-        Cookie userInfo = new Cookie("info",Base64.encode(jsonObject.toString()));
-        cookie.setMaxAge(31536000);
-        cookie.setPath("/");
-        response.addCookie(userInfo);
-        String url = redisService.getStr(re.getMappingId().toString());
-        redisService.del(re.getMappingId().toString());
-        log.info("微信授权转跳.url: {}",url);
-        response.sendRedirect(url.contains("?") ? url + "&t=" + StpUserUtil.getTokenValue() : url + "?t=" + StpUserUtil.getTokenValue());
+        baseRedirect(token, state, response);
     }
 
     /**
@@ -233,22 +198,30 @@ public class AuthorizationController {
     /**
      * 网页微信授权登录
      */
-    @GetMapping("/wx/login/authUrl")
-    public Result<String> wxAuthorize() throws Exception {
+    @GetMapping("/wx/authLogin")
+    public Result<String> wxAuthorize(Long sharedId, Integer dsType, Long popularizeId) throws Exception {
         String wxAuthUrl = redisService.getStr(RedisService.key.WX_LOGIN_AUTH_URI.getNameFormat(wxOpenPlatYHLXLoginConfig.getAppId()));
         Long mappingId = SEQUENCE.nextId();
         redisService.set(mappingId.toString(), wxOpenPlatYHLXLoginConfig.getLoginUrl(), 60 * 60 * 24L);
-        AuthRedirect redirect = new AuthRedirect().setMappingId(mappingId);
+        AuthRedirect redirect = new AuthRedirect().setMappingId(mappingId).setSharedId(sharedId).setDsType(dsType).setPid(popularizeId);
         String state = Codec.DoBase64.custom().setData(Jsons.toJson(redirect)).encodeAsText();
         if (StrUtil.isEmpty(wxAuthUrl)) {
-            wxAuthUrl = String.format("https://open.weixin.qq.com/connect/qrconnect?" +
-                            "appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect",
-                    wxOpenPlatYHLXLoginConfig.getAppId(),
-                    URLEncoder.encode(wxOpenPlatYHLXLoginConfig.getRedirectUri(), StandardCharsets.UTF_8), state);
+            wxAuthUrl = authorizationService.createWxAuthLoginUrl(state);
         }
         return GatewayResponse.SUCCESS.newBuilder().toResult(wxAuthUrl);
     }
 
+    /**
+     * 网页微信授权后跳转
+     */
+    @GetMapping("/wx/authLogin/baseRedirect")
+    public void wxAuthLoginRedirect(String code, String state, HttpServletResponse response) throws Exception {
+
+        AuthToken token = weChatService.getAuthToken(code, wxOpenPlatYHLXLoginConfig.getAppId());
+        //重定向
+        baseRedirect(token, state, response);
+    }
+
     /**
      * 网页扫描微信公众号二维码 临时凭证ticket  关注后登录
      */
@@ -444,4 +417,39 @@ public class AuthorizationController {
         LoginPhoneRep loginPhoneRep = new LoginPhoneRep(StpUserUtil.getTokenValue(), user.getId(), user.getNickname(), user.getHeadimgurl());
         return GatewayResponse.SUCCESS.newBuilder().toResult(loginPhoneRep);
     }
+
+    public void baseRedirect(AuthToken token, String state, HttpServletResponse response) throws Exception {
+        // 根据openid 与 access_token 获取用户信息
+        GzhOAuth2UserInfo userinfo = weChatService.getUserInfo(token.getAccessToken(), token.getOpenid());
+
+        // 转跳参数
+        String json = Codec.DoBase64.custom().setData(state).decodeAsText();
+        AuthRedirect re = Jsons.parseObject(json, AuthRedirect.class);
+        //保存用户信息
+        User user = userService.saveAuth(userinfo, re.getSharedId(), re.getDsType(), re.getPid());
+        if (user == null) {
+            throw BusinessRuntimeException.getInstance("系统错误,请重新授权");
+        }
+
+        //写回登陆信息
+        StpUserUtil.login(user.getId());
+        response.addHeader("satoken-user", StpUserUtil.getTokenValue());
+
+        Cookie cookie = new Cookie("satoken-user", StpUserUtil.getTokenValue());
+        cookie.setMaxAge(31536000);
+        cookie.setPath("/");
+        response.addCookie(cookie);
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.putOpt("uid", user.getId());
+        jsonObject.putOpt("nickName", user.getNickname());
+
+        Cookie userInfo = new Cookie("info", Base64.encode(jsonObject.toString()));
+        cookie.setMaxAge(31536000);
+        cookie.setPath("/");
+        response.addCookie(userInfo);
+        String url = redisService.getStr(re.getMappingId().toString());
+        redisService.del(re.getMappingId().toString());
+        log.info("微信授权转跳.url: {}", url);
+        response.sendRedirect(url.contains("?") ? url + "&t=" + StpUserUtil.getTokenValue() : url + "?t=" + StpUserUtil.getTokenValue());
+    }
 }

File diff ditekan karena terlalu besar
+ 0 - 0
netflix-web/src/main/resources/application-dev.yml


File diff ditekan karena terlalu besar
+ 0 - 0
netflix-web/src/main/resources/application-prd.yml


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini