Bläddra i källkod

企业微信引流功能

zoujiajian 1 år sedan
förälder
incheckning
3edd6cb831
26 ändrade filer med 686 tillägg och 30 borttagningar
  1. 15 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpWxYlFollowConfigMapper.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpWxYlRecordMapper.java
  4. 1 2
      netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponUserMapper.java
  5. 10 0
      netflix-dao/src/main/java/com/cyksj/model/dto/UserWhoami.java
  6. 18 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpWxYlFollowConfig.java
  7. 16 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpWxYlRecord.java
  8. 2 1
      netflix-dao/src/main/java/com/cyksj/model/entity/CouponUser.java
  9. 1 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserBenefits.java
  10. 37 0
      netflix-dao/src/main/java/com/cyksj/model/request/TempCorpFollowCodeReq.java
  11. 4 2
      netflix-dao/src/main/java/com/cyksj/model/request/corp/CorpFollowContact.java
  12. 24 0
      netflix-dao/src/main/java/com/cyksj/model/response/UserInfoResp.java
  13. 122 0
      netflix-dao/src/main/java/com/cyksj/model/views/CouponDetailView.java
  14. 1 2
      netflix-dao/src/main/resources/mapper/CouponUserMapper.xml
  15. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  16. 16 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpUserFrontService.java
  17. 2 0
      netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java
  18. 131 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpUserFrontServiceImpl.java
  19. 19 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java
  20. 2 2
      netflix-service/src/main/java/com/cyksj/service/coupon/CouponFontService.java
  21. 8 4
      netflix-service/src/main/java/com/cyksj/service/coupon/impl/CouponFontServiceImpl.java
  22. 41 11
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  23. 86 4
      netflix-web/src/main/java/com/cyksj/web/controller/coupon/CouponFrontController.java
  24. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  25. 86 0
      netflix-web/src/main/java/com/cyksj/web/controller/user/CorpUserFrontController.java
  26. 16 1
      netflix-web/src/main/java/com/cyksj/web/controller/user/UserBenefitsFrontController.java

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

@@ -517,4 +517,19 @@ public interface Constant {
 	 * 第三方分类id
 	 */
 	Long THIRD_CATEGORY = 6l;
+
+	/**
+	 * 企业微信添加引流客服ids key
+	 */
+	String CORP_WX_YL_FOLLOW_IDS_KEY = "corp_wx_yl_follow_ids_key";
+
+	/**
+	 * 企业微信引流前缀标识key
+	 */
+	String CORP_WX_YL_PREFIX = "qywxyl_";
+
+	/**
+	 * 引流新人优惠券id
+	 */
+	String YL_NEW_WELFARE_COUPON_ID = "yl_new_welfare_coupon_id";
 }

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.corp;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpWxYlFollowConfig;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpWxYlFollowConfigMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/3/14 17:40
+ */
+public interface CorpWxYlFollowConfigMapper extends BaseMapper<CorpWxYlFollowConfig> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.corp;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpWxYlRecord;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpWxYlRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/3/12 16:20
+ */
+public interface CorpWxYlRecordMapper extends BaseMapper<CorpWxYlRecord> {
+}

+ 1 - 2
netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponUserMapper.java

@@ -1,6 +1,5 @@
 package com.cyksj.mapper.manage.coupon;
 
-import cn.hutool.core.date.DateTime;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -28,7 +27,7 @@ public interface CouponUserMapper extends BaseMapper<CouponUser> {
 
 	Page<CouponUserView> couponPersonalList(@Param("userId") Long userId, @Param("page") Page<CouponUserView> page, @Param("couponId") Long couponId);
 
-	CouponUserView getNewUserWelfareCouponsByUserId(@Param("userId") long userId, @Param("channel") CouponUser.Channel channel, @Param("now") DateTime now);
+	CouponUserView getNewUserWelfareCouponsByUserId(@Param("userId") long userId, @Param("couponId") Long couponId);
 
 	CouponUser getCouponByCouponUserId(Long couponUserId);
 

+ 10 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/UserWhoami.java

@@ -41,4 +41,14 @@ public class UserWhoami implements Serializable {
     private String bindPhone;
 
     private String bindEmail;
+
+    /**
+     * 是否添加过企业微信
+     */
+    private Boolean isJoinWx = false;
+
+    /**
+     * 是否是未下单的用户
+     */
+    private Boolean isPay;
 }

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpWxYlFollowConfig.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpWxYlFollowConfig
+ * 创建者: JavaZou
+ * 创建时间:2025/3/14 17:40
+ */
+@Getter
+@Setter
+public class CorpWxYlFollowConfig extends BaseEntity{
+	private String configId;
+
+	private Boolean deleted;
+}

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpWxYlRecord.java

@@ -0,0 +1,16 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpWxYlRecord
+ * 创建者: JavaZou
+ * 创建时间:2025/3/12 16:20
+ */
+@Getter
+@Setter
+public class CorpWxYlRecord extends BaseEntity{
+	private String state;
+}

+ 2 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/CouponUser.java

@@ -72,7 +72,8 @@ public class CouponUser extends BaseEntity {
 		new_welfare("new_welfare", "新人福利"),
 		corp_active_code("corp_active_code", "企业微信活码"),
 		customer_link("customer_link", "获客链接"),
-		student_cert("student_cert","大学生认证")
+		student_cert("student_cert","大学生认证"),
+		yl("yl", "企业微信引流"),
 		;
 		private String channel;
 		private String desc;

+ 1 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserBenefits.java

@@ -75,6 +75,7 @@ public class UserBenefits extends BaseEntity {
 		RENEW("续费减免"),
 		CERT("大学生认证"),
 		COMBO("套餐优惠"),
+		WELFARE("福利放送"),
 		;
 		private String desc;
 	}

+ 37 - 0
netflix-dao/src/main/java/com/cyksj/model/request/TempCorpFollowCodeReq.java

@@ -0,0 +1,37 @@
+package com.cyksj.model.request;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: TempCorpFollowCodeReq
+ * 创建者: JavaZou
+ * 创建时间:2025/3/11 16:38
+ */
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class TempCorpFollowCodeReq {
+	private Long goodsId;
+
+	private Long userId;
+
+	/**
+	 * 引流标识
+	 */
+	private Boolean yl;
+
+	/**
+	 * 用户无登录授权token
+	 */
+	private String t;
+
+	/**
+	 * 登录方式
+	 * 0.微信
+	 * 1.其他
+	 */
+	private Integer s;
+}

+ 4 - 2
netflix-dao/src/main/java/com/cyksj/model/request/corp/CorpFollowContact.java

@@ -48,7 +48,8 @@ public class CorpFollowContact {
 	 */
 	private List<Integer> party;
 
-	private boolean is_temp;
+	@JsonProperty("is_temp")
+	private boolean isTemp;
 
 	private Integer expires_in;
 
@@ -56,7 +57,8 @@ public class CorpFollowContact {
 
 	private String unionid;
 
-	private boolean is_exclusive;
+	@JsonProperty("is_exclusive")
+	private boolean isExclusive;
 
 	private Conclusions conclusions;
 

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/response/UserInfoResp.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.response;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: UserInfoResp
+ * 创建者: JavaZou
+ * 创建时间:2025/3/11 17:45
+ */
+@Getter
+@Setter
+public class UserInfoResp {
+	/**
+	 * 是否添加过企业微信
+	 */
+	private Boolean isJoinWx;
+
+	/**
+	 * 是否是未下单的用户
+	 */
+	private Boolean isPay;
+}

+ 122 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CouponDetailView.java

@@ -0,0 +1,122 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.Coupon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CouponDetailView
+ * 创建者: JavaZou
+ * 创建时间:2025/3/17 14:06
+ */
+@Getter
+@Setter
+@SearchBean(tables = "coupon c left join coupon_classification cc on cc.id = c.classification_id")
+public class CouponDetailView {
+	/**
+	 * 优惠券id
+	 */
+	@DbField("c.id")
+	private Long couponId;
+
+	/**
+	 * 优惠券名称
+	 */
+	@DbField("c.name")
+	private String name;
+
+	@DbField("cc.id")
+	private Long classificationId;
+
+	@DbField("cc.name")
+	private String couponClassificationName;
+
+	/**
+	 * 优惠券平台类型
+	 */
+	@DbField("c.goods_type")
+	private Coupon.GoodsType goodsType;
+
+	/**
+	 * 优惠券类型
+	 */
+	@DbField("c.type")
+	private Coupon.Type type;
+
+	/**
+	 * 可用满减卷金额条件
+	 */
+	@DbField("c.reduce_condition")
+	private BigDecimal reduceCondition;
+
+	/**
+	 * 抵扣金额
+	 */
+	@DbField("c.reduce_money")
+	private BigDecimal reduceMoney;
+
+	/**
+	 * 折扣
+	 */
+	@DbField("c.discount")
+	private BigDecimal discount;
+
+	/**
+	 * 领取人范围
+	 */
+	@DbField("c.scope")
+	private Coupon.Scope scope;
+
+	/**
+	 * 平台规格集合
+	 */
+	@DbField("c.goods_sku_ids")
+	private String goodsSkuIds;
+
+	@DbIgnore
+	private String goodsSkuStr;
+
+	@DbIgnore
+	private List<GoodsDonSkuView> skuViewList;
+
+	/**
+	 * 是否是有效时间
+	 */
+	@DbField("c.is_valid_time")
+	private Boolean isValidTime;
+
+	/**
+	 * 起始有效时间
+	 */
+	@DbField("c.valid_start_time")
+	private Date validStartTime;
+
+	/**
+	 * 截止有效时间
+	 */
+	@DbField("c.valid_end_time")
+	private Date validEndTime;
+
+	/**
+	 * 领取有效天数
+	 */
+	@DbField("c.valid_days")
+	private Integer validDays;
+
+	@DbField("c.valid_hours")
+	private Integer validHours;
+
+	/**
+	 * 使用范围
+	 */
+	@DbField("c.use_scope")
+	private Coupon.UseScope useScope;
+}

+ 1 - 2
netflix-dao/src/main/resources/mapper/CouponUserMapper.xml

@@ -199,9 +199,8 @@
                      valid_end_time,
                      status as couponUserStatus
               from `coupon_user`
-              where channel = #{channel}
+              where coupon_id = #{couponId}
                 and user_id = #{userId}
-                and valid_end_time > #{now}
                  and status = 'unused' limit 1) cu
                  inner join coupon c on c.id = cu.coupon_id
     </select>

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

@@ -854,6 +854,7 @@ public class RedisService {
         USER_MIRROR_SHOP_ADVERTISE_CACHE_KEY("user_mirror_shop_advertise_cache_key:", "用户镜像店铺广告缓存key", 60 * 60 * 12),
         NETFLIX_CHANGE_TICKET_KEY("netflix_change_ticket_key:", "奈飞更换车票key", 60l),
         CORP_KF_ACCOUNT_URL("corp_kf_account_url:", "微信客服url:", 60 * 60 * 6),
+        CORP_WX_YL_KEY("corp_wx_yl_key:", "企业微信引流", 60 * 30),
         ;
 
         private String name;

+ 16 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpUserFrontService.java

@@ -0,0 +1,16 @@
+package com.cyksj.service.corp;
+
+import com.cyksj.model.request.TempCorpFollowCodeReq;
+import com.cyksj.model.response.UserInfoResp;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpUserFrontService
+ * 创建者: JavaZou
+ * 创建时间:2025/3/11 16:29
+ */
+public interface CorpUserFrontService {
+	UserInfoResp getUserInfoResp(long userId, Integer type);
+
+	String generateTempCorpFollowCode(TempCorpFollowCodeReq tempCorpFollowCodeReq) throws Exception;
+}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java

@@ -265,4 +265,6 @@ public interface WxCorpOps {
 	 * 获取素材
 	 */
 	String getMedia(String corpId, String mediaId) throws Exception;
+
+	String generateTempCorpFollowCode(CorpFollowContact corpFollowContact) throws Exception;
 }

+ 131 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpUserFrontServiceImpl.java

@@ -0,0 +1,131 @@
+package com.cyksj.service.corp.impl;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Codec;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.corp.CorpWxYlFollowConfigMapper;
+import com.cyksj.mapper.corp.CorpWxYlRecordMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
+import com.cyksj.mapper.sys.SysConfigMapper;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.TempCorpFollowCodeReq;
+import com.cyksj.model.request.corp.CorpFollowContact;
+import com.cyksj.model.response.UserInfoResp;
+import com.cyksj.model.views.CorpUserFollowView;
+import com.cyksj.service.corp.CorpUserFrontService;
+import com.cyksj.service.corp.WxCorpOps;
+import com.cyksj.service.user.UserBindRelationService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpUserFrontServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2025/3/11 16:29
+ */
+@Service
+@RequiredArgsConstructor
+public class CorpUserFrontServiceImpl implements CorpUserFrontService {
+	private final UserBindDetailMapper userBindDetailMapper;
+
+	private final BeanSearcher beanSearcher;
+
+	private final UserMapper userMapper;
+
+	private final WxCorpOps wxCorpOps;
+
+	private final SysConfigMapper sysConfigMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final OrderDonMapper orderDonMapper;
+
+	private final CorpWxYlRecordMapper corpWxYlRecordMapper;
+
+	private final CorpWxYlFollowConfigMapper corpWxYlFollowConfigMapper;
+
+	@Override
+	public UserInfoResp getUserInfoResp(long userId, Integer type) {
+		UserInfoResp userInfoResp = new UserInfoResp();
+		User user = userMapper.selectById(userId);
+		if (type == 0 || type == 1) {
+			String unionId = user.getUnionid();
+			if (StrUtil.isEmpty(unionId)) {
+				//获取绑定的微信用户id
+				UserBindDetail bindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+						.and(qr -> qr.eq(UserBindDetail::getPhoneUserId, user.getId()).or().eq(UserBindDetail::getEmailUserId, user.getId()))
+						.last("limit 1"));
+				if (bindDetail != null && bindDetail.getUserId() != null) {
+					User wxUser = userMapper.selectById(bindDetail.getUserId());
+					if (wxUser != null) {
+						unionId = wxUser.getUnionid();
+					}
+				}
+			}
+			if (StrUtil.isEmpty(unionId)) {
+				userInfoResp.setIsJoinWx(false);
+			} else {
+				CorpUserFollowView corpUserFollowView = beanSearcher.searchFirst(CorpUserFollowView.class, MapUtils.builder()
+						.field(CorpUserFollowView::getUnionId, unionId)
+						.field(CorpUserFollowView::getStatus, 1).build());
+				if (corpUserFollowView != null) {
+					userInfoResp.setIsJoinWx(true);
+				} else userInfoResp.setIsJoinWx(false);
+			}
+		}
+		//是否下过单
+		if (type == 0 || type == 2) {
+			List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, user);
+			Integer selectCount = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
+					.in(OrderDon::getUserId, userIdList)
+					.notIn(OrderDon::getStatus, Constant.noOrderStatus));
+			userInfoResp.setIsPay(selectCount > 0);
+		}
+		return userInfoResp;
+	}
+
+	@Override
+	public String generateTempCorpFollowCode(TempCorpFollowCodeReq tempCorpFollowCodeReq) throws Exception {
+		CorpFollowContact corpFollowContact = new CorpFollowContact();
+		tempCorpFollowCodeReq.setYl(true);
+		String state = Codec.DoBase64.custom().setData(Jsons.toJson(tempCorpFollowCodeReq)).encodeAsText();
+		CorpWxYlRecord corpWxYlRecord = new CorpWxYlRecord();
+		corpWxYlRecord.setState(state);
+		corpWxYlRecordMapper.insert(corpWxYlRecord);
+		//场景,1-在小程序中联系,2-通过二维码联系
+		corpFollowContact.setScene(2);
+		corpFollowContact.setState(Constant.CORP_WX_YL_PREFIX + corpWxYlRecord.getId());
+		corpFollowContact.setTemp(false);
+		corpFollowContact.setExclusive(true);
+		corpFollowContact.setSkip_verify(true);
+		//系统配置
+		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.CORP_WX_YL_FOLLOW_IDS_KEY)
+				.last("limit 1"));
+		if (sysConfig == null || StrUtil.isEmpty(sysConfig.getSysValue())) {
+			throw BusinessRuntimeException.getInstance("获取错误,请刷新重试");
+		}
+		corpFollowContact.setUser(Jsons.parseList(sysConfig.getSysValue(), String.class));
+		//联系方式类型,1-单人, 2-多人
+		corpFollowContact.setType(corpFollowContact.getUser().size() > 1 ? 2 : 1);
+		String re = wxCorpOps.generateTempCorpFollowCode(corpFollowContact);
+		JSONObject jsonObject = Jsons.parseObject(re, JSONObject.class);
+		//记录下 删除
+		String configId = jsonObject.getStr("config_id");
+		CorpWxYlFollowConfig followConfig= new CorpWxYlFollowConfig();
+		followConfig.setConfigId(configId);
+		corpWxYlFollowConfigMapper.insert(followConfig);
+		return jsonObject.getStr("qr_code");
+	}
+}

+ 19 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java

@@ -1221,4 +1221,23 @@ public class WxCorpOpsImpl implements WxCorpOps {
 		FileUtil.del(tempFile);
 		return result.getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
 	}
+
+	@Override
+	public String generateTempCorpFollowCode(CorpFollowContact corpFollowContact) throws Exception {
+		//配置
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_contact_way?access_token=" + getAccessToken(null);
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(corpFollowContact), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		JSONObject jsonObject = Jsons.parseObject(body, JSONObject.class);
+		if (jsonObject.getInt("errcode") != 0) {
+			throw BusinessRuntimeException.getInstance("获取客服二维码错误,请联系客服");
+		}
+		return body;
+	}
 }

+ 2 - 2
netflix-service/src/main/java/com/cyksj/service/coupon/CouponFontService.java

@@ -65,9 +65,9 @@ public interface CouponFontService {
 	/**
 	 * 新用户福利优惠券
 	 */
-	CouponUserView getNewUserWelfareCoupons(long userId, DateTime now);
+	CouponUserView getNewUserWelfareCoupons(long userId, Long couponId);
 
 	CouponUserView getCouponDetailById(long userId, Long couponId);
 
-	CouponUserView receiveCoupon(long userId, Long couponId);
+	CouponUserView receiveCoupon(long userId, Long couponId, CouponUser.Channel channel);
 }

+ 8 - 4
netflix-service/src/main/java/com/cyksj/service/coupon/impl/CouponFontServiceImpl.java

@@ -6,6 +6,7 @@ import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.Jsons;
@@ -13,6 +14,7 @@ import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.channel.ChannelPopularizeMapper;
 import com.cyksj.mapper.manage.coupon.*;
+import com.cyksj.mapper.sys.SysConfigMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.ChannelPopularizeCouponReq;
 import com.cyksj.model.request.CouponCollectReq;
@@ -61,6 +63,8 @@ public class CouponFontServiceImpl implements CouponFontService {
 
 	private final UserMapper userMapper;
 
+	private final SysConfigMapper sysConfigMapper;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void collectCoupon(CouponCollectReq couponCollectReq, Long userId) {
@@ -361,8 +365,8 @@ public class CouponFontServiceImpl implements CouponFontService {
 	}
 
 	@Override
-	public CouponUserView getNewUserWelfareCoupons(long userId, DateTime now) {
-		return couponUserMapper.getNewUserWelfareCouponsByUserId(userId, CouponUser.Channel.new_welfare, now);
+	public CouponUserView getNewUserWelfareCoupons(long userId,Long couponId) {
+		return couponUserMapper.getNewUserWelfareCouponsByUserId(userId, couponId);
 	}
 
 	@Override
@@ -376,9 +380,9 @@ public class CouponFontServiceImpl implements CouponFontService {
 	}
 
 	@Override
-	public CouponUserView receiveCoupon(long userId, Long couponId) {
+	public CouponUserView receiveCoupon(long userId, Long couponId, CouponUser.Channel channel) {
 		try {
-			receiveCouponUser(couponId, userId, CouponUser.Channel.manual);
+			receiveCouponUser(couponId, userId, channel);
 		} catch (Exception e) {
 			return null;
 		}

+ 41 - 11
netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java

@@ -28,6 +28,7 @@ import com.cyksj.mapper.station.CollegeStudentStationUserRelateMapper;
 import com.cyksj.model.dto.*;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.LoginReq;
+import com.cyksj.model.views.CorpUserFollowView;
 import com.cyksj.model.views.RenewalView;
 import com.cyksj.model.views.UserCertInfoView;
 import com.cyksj.model.views.UserTicketView;
@@ -135,6 +136,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
 	private final UserStudentCertRecordMapper userStudentCertRecordMapper;
 
+	private final OrderDonMapper orderDonMapper;
+
 	private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
 	@Override
@@ -189,10 +192,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 			//发放新用户福利
 			final Long fUid = user.getId();
 			TASK_POOL.execute(() -> {
-				try {
-					sendNewUserWelfare(fUid);
-				} catch (Exception e) {
-				}
+//				try {
+//					sendNewUserWelfare(fUid);
+//				} catch (Exception e) {
+//				}
 				//去关联对应企业微信用户
 				relateCorpUserAndSengWelfare(fUid, unionid);
 			});
@@ -265,7 +268,34 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 		    type = 2;
 	    }
 	    userWhoami.setType(type);
-
+		//是否加过企业微信
+		String unionId = user.getUnionid();
+		if (StrUtil.isEmpty(unionId)) {
+			//获取绑定的微信用户id
+			UserBindDetail bindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+					.and(qr -> qr.eq(UserBindDetail::getPhoneUserId, user.getId()).or().eq(UserBindDetail::getEmailUserId, user.getId()))
+					.last("limit 1"));
+			if (bindDetail != null && bindDetail.getUserId() != null) {
+				User wxUser = userMapper.selectById(bindDetail.getUserId());
+				if (wxUser != null) {
+					unionId = wxUser.getUnionid();
+				}
+			}
+		}
+		if (StrUtil.isNotBlank(unionId)) {
+			CorpUserFollowView corpUserFollowView = beanSearcher.searchFirst(CorpUserFollowView.class, MapUtils.builder()
+					.field(CorpUserFollowView::getUnionId, unionId)
+					.field(CorpUserFollowView::getStatus, 1).build());
+			if (corpUserFollowView != null) {
+				userWhoami.setIsJoinWx(true);
+			}
+		}
+		//是否下过单
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, user);
+		Integer selectCount = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
+				.in(OrderDon::getUserId, userIdList)
+				.notIn(OrderDon::getStatus, Constant.noOrderStatus));
+		userWhoami.setIsPay(selectCount > 0);
 	    return userWhoami;
     }
 
@@ -529,12 +559,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 			}
 			//发放新用户福利
 			final Long fUid = user.getId();
-			TASK_POOL.execute(() -> {
-				try {
-					sendNewUserWelfare(fUid);
-				} catch (Exception e) {
-				}
-			});
+//			TASK_POOL.execute(() -> {
+//				try {
+//					sendNewUserWelfare(fUid);
+//				} catch (Exception e) {
+//				}
+//			});
 			final String login_email = user.getEmail();
 			final String login_phone = user.getLoginPhone();
 			UserBindDetail bindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)

+ 86 - 4
netflix-web/src/main/java/com/cyksj/web/controller/coupon/CouponFrontController.java

@@ -2,9 +2,11 @@ package com.cyksj.web.controller.coupon;
 
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.cyksj.common.annotation.NoSubmit;
+import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
@@ -23,6 +25,7 @@ import com.cyksj.model.request.CouponCollectReq;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.coupon.CouponFontService;
+import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
@@ -31,6 +34,7 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -65,6 +69,10 @@ public class CouponFrontController {
 
 	private final UserMapper userMapper;
 
+	private final HttpServletRequest request;
+
+	private final SysConfigService sysConfigService;
+
 	/**
 	 * 优惠券领取中心列表
 	 */
@@ -357,10 +365,20 @@ public class CouponFrontController {
 	 * 新用户福利 优惠券详情展示
 	 */
 	@GetMapping("/get/newUser/welfare")
-	public Result<CouponUserView> getNewUserWelfare() {
+	public Result<Object> getNewUserWelfare() {
 		long userId = StpUserUtil.getLoginIdAsLong();
-		DateTime now = DateTime.now();
-		CouponUserView couponUserView = couponFontService.getNewUserWelfareCoupons(userId, now);
+		SysConfig one = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.YL_NEW_WELFARE_COUPON_ID)
+				.last("limit 1"));
+		if (one == null || StrUtil.isEmpty(one.getSysValue())) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		String couponId = one.getSysValue();
+		CouponUserView couponUserView = couponFontService.getNewUserWelfareCoupons(userId, Long.valueOf(couponId));
+		if (couponUserView == null) {
+			CouponDetailView couponDetailView = beanSearcher.searchFirst(CouponDetailView.class, MapUtils.flatBuilder(request.getParameterMap()).field(CouponDetailView::getCouponId, couponId).build());
+			return GatewayResponse.SUCCESS.newBuilder().toResult(couponDetailView);
+		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult(couponUserView);
 	}
 
@@ -377,7 +395,71 @@ public class CouponFrontController {
 	@PostMapping("/receive/coupon/{couponId}")
 	public Result<CouponUserView> receiveCoupon(@PathVariable Long couponId) {
 		long userId = StpUserUtil.getLoginIdAsLong();
-		CouponUserView couponUserView = couponFontService.receiveCoupon(userId, couponId);
+		CouponUserView couponUserView = couponFontService.receiveCoupon(userId, couponId, CouponUser.Channel.manual);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(couponUserView);
+	}
+
+	/**
+	 * 优惠券详情
+	 */
+	@GetMapping("/get/detail/{couponId}")
+	public Result<CouponDetailView> getCouponDetail(@PathVariable Long couponId) {
+		CouponDetailView couponDetailView = beanSearcher.searchFirst(CouponDetailView.class, MapUtils.flatBuilder(request.getParameterMap()).field(CouponDetailView::getCouponId, couponId).build());
+		String str = couponSkuMapper.selectGoodsSkuStr(couponDetailView.getCouponId());
+		couponDetailView.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
+		List<CouponSkuView> couponSkus = couponSkuMapper.getGoodsSkuByCouponId(couponDetailView.getCouponId());
+		try {
+			couponDetailView.setGoodsSkuIds(Jsons.toJson(couponSkus));
+		} catch (Exception e) {
+
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(couponDetailView);
+	}
+
+	/**
+	 * 引流新人优惠券详情
+	 */
+	@GetMapping("/get/yl/welfare/coupon/detail")
+	@Deprecated
+	public Result<CouponDetailView> getYlWelfareCouponDetail() {
+		SysConfig one = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.YL_NEW_WELFARE_COUPON_ID)
+				.last("limit 1"));
+		if (one == null || StrUtil.isEmpty(one.getSysValue())) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		String couponId = one.getSysValue();
+		CouponDetailView couponDetailView = beanSearcher.searchFirst(CouponDetailView.class, MapUtils.flatBuilder(request.getParameterMap()).field(CouponDetailView::getCouponId, couponId).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(couponDetailView);
+	}
+
+	/**
+	 * 领取新人优惠券
+	 */
+	@PostMapping("/receive/newWelfare")
+	public Result<CouponUserView> receiveNewWelfareCoupon() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		SysConfig one = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.YL_NEW_WELFARE_COUPON_ID)
+				.last("limit 1"));
+		if (one == null || StrUtil.isEmpty(one.getSysValue())) {
+			throw BusinessRuntimeException.getInstance("暂无新人优惠券活动");
+		}
+		String couponId = one.getSysValue();
+		CouponUserView couponUserView = couponFontService.receiveCoupon(userId, Long.valueOf(couponId), CouponUser.Channel.new_welfare);
+		if (couponUserView == null) {
+			couponUserView = beanSearcher.searchFirst(CouponUserView.class, MapUtils.flatBuilder(request.getParameterMap()).field(CouponNewUserView::getUserId, userId).field(CouponUserView::getCouponId, couponId).build());
+		}
+		if (couponUserView != null) {
+			String str = couponSkuMapper.selectGoodsSkuStr(couponUserView.getCouponId());
+			couponUserView.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
+			List<CouponSkuView> couponSkus = couponSkuMapper.getGoodsSkuByCouponId(couponUserView.getCouponId());
+			try {
+				couponUserView.setGoodsSkuIds(Jsons.toJson(couponSkus));
+			} catch (Exception e) {
+			}
+		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult(couponUserView);
 	}
 }
+

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -199,7 +199,7 @@ public class GroupRelationController {
     }
 
     /**
-     * 查询是否加入了企业微信
+     * 查询是否加入了企业微信 并是否买了奈飞
      */
     @GetMapping("/check/joinCorpWx")
     public Result<Boolean> isJoinCorpWx() {

+ 86 - 0
netflix-web/src/main/java/com/cyksj/web/controller/user/CorpUserFrontController.java

@@ -0,0 +1,86 @@
+package com.cyksj.web.controller.user;
+
+import cn.hutool.core.util.StrUtil;
+import com.cyksj.common.util.Codec;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.corp.CorpWxYlRecordMapper;
+import com.cyksj.model.entity.CorpWxYlRecord;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.request.TempCorpFollowCodeReq;
+import com.cyksj.model.response.UserInfoResp;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.corp.CorpUserFrontService;
+import com.cyksj.web.util.StpUserUtil;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpUserFrontController
+ * 创建者: JavaZou
+ * 创建时间:2025/3/11 16:26
+ */
+@RestController
+@RequestMapping("/applets/user")
+@RequiredArgsConstructor
+public class CorpUserFrontController {
+	private final CorpUserFrontService corpUserFrontService;
+
+	private final RedisService redisService;
+
+	private final CorpWxYlRecordMapper corpWxYlRecordMapper;
+
+	private final UserMapper userMapper;
+
+	/**
+	 * 获取用户添加企业微信和下单 情况
+	 */
+	@GetMapping("/get/situation")
+	public Result<UserInfoResp> getUserInfoResp(@RequestParam(defaultValue = "0") Integer type) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		UserInfoResp resp = corpUserFrontService.getUserInfoResp(userId, type);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(resp);
+	}
+
+	/**
+	 * 获取添加客服 临时二维码
+	 */
+	@PostMapping("/post")
+	public Result<String> generateTempCorpFollowCode(@RequestBody TempCorpFollowCodeReq tempCorpFollowCodeReq) throws Exception {
+		String keyName = RedisService.key.CORP_WX_YL_KEY.getName();
+		long userId = StpUserUtil.getLoginIdAsLong();
+		keyName += userId;
+		if (tempCorpFollowCodeReq.getGoodsId() != null) {
+			keyName += ":" + tempCorpFollowCodeReq.getGoodsId();
+		}
+		String codeUrl = redisService.getStr(keyName);
+		if (StrUtil.isEmpty(codeUrl)) {
+			tempCorpFollowCodeReq.setUserId(userId);
+			User user = userMapper.selectById(userId);
+			tempCorpFollowCodeReq.setS(StrUtil.isEmpty(user.getUnionid()) ? 1 : 0);
+			codeUrl = corpUserFrontService.generateTempCorpFollowCode(tempCorpFollowCodeReq);
+			redisService.setNx(keyName, codeUrl, RedisService.key.CORP_WX_YL_KEY.getTimeout());
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(codeUrl);
+	}
+
+	/**
+	 * 引流用户授权跳转 详情
+	 * 非微信用户
+	 */
+	@GetMapping("/get/yl/redirect/detail")
+	public Result<String> getYlRedirectDetail(Long ylId) throws Exception {
+		CorpWxYlRecord corpWxYlRecord = corpWxYlRecordMapper.selectById(ylId);
+		if (corpWxYlRecord == null) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		String json = Codec.DoBase64.custom().setData(corpWxYlRecord.getState()).decodeAsText();
+		TempCorpFollowCodeReq re = Jsons.parseObject(json, TempCorpFollowCodeReq.class);
+		Long userId = re.getUserId();
+		User user = userMapper.selectById(userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(StrUtil.isEmpty(user.getLoginPhone()) ? user.getEmail() : user.getLoginPhone());
+	}
+}

+ 16 - 1
netflix-web/src/main/java/com/cyksj/web/controller/user/UserBenefitsFrontController.java

@@ -67,7 +67,7 @@ public class UserBenefitsFrontController {
 
 	private final UserActivityMapper userActivityMapper;
 
-	private final GroupsRelationMapper relationMapper;
+	private final UserMapper userMapper;
 
 
 	/**
@@ -219,6 +219,21 @@ public class UserBenefitsFrontController {
 					log.error("解析大学生认证json错误,:{}", StringUtil.getErrorText(e));
 				}
 			}
+			if (type == UserBenefits.Type.WELFARE) {
+				//是否添加过企业微信
+				User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
+						.in(User::getId, userIdList)
+						.ne(User::getUnionid, StrUtil.EMPTY)
+						.last("limit 1"));
+				if (user != null) {
+					CorpUserFollowView corpUserFollowView = beanSearcher.searchFirst(CorpUserFollowView.class, MapUtils.builder()
+							.field(CorpUserFollowView::getUnionId, user.getUnionid())
+							.field(CorpUserFollowView::getStatus, 1).build());
+					if (corpUserFollowView != null) {
+						fhCount = 1;
+					}
+				}
+			}
 			data.setIsFh(fhCount > 0);
 		}
 	}