Przeglądaj źródła

Merge branch 'pc_user_ticket_fuse'

# Conflicts:
#	netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java
zoujiajian 3 lat temu
rodzic
commit
34907998a4
18 zmienionych plików z 300 dodań i 103 usunięć
  1. 3 3
      netflix-dao/src/main/java/com/cyksj/mapper/market/task/UserBindDetailMapper.java
  2. 5 0
      netflix-dao/src/main/java/com/cyksj/model/dto/GzhBodyDto.java
  3. 2 1
      netflix-dao/src/main/java/com/cyksj/model/dto/UserWhoami.java
  4. 2 2
      netflix-dao/src/main/java/com/cyksj/model/entity/UserBindDetail.java
  5. 7 1
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java
  6. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  7. 23 0
      netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java
  8. 4 4
      netflix-service/src/main/java/com/cyksj/service/market/impl/MarketFrontServiceImpl.java
  9. 21 0
      netflix-service/src/main/java/com/cyksj/service/market/task/BindTaskService.java
  10. 87 0
      netflix-service/src/main/java/com/cyksj/service/market/task/impl/BindTaskServiceImpl.java
  11. 50 3
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  12. 17 14
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  13. 1 1
      netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java
  14. 5 3
      netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java
  15. 14 60
      netflix-web/src/main/java/com/cyksj/web/controller/market/TaskFrontController.java
  16. 30 5
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
  17. 23 1
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java
  18. 5 5
      netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

+ 3 - 3
netflix-dao/src/main/java/com/cyksj/mapper/market/task/UserBindPhoneMapper.java → netflix-dao/src/main/java/com/cyksj/mapper/market/task/UserBindDetailMapper.java

@@ -1,13 +1,13 @@
 package com.cyksj.mapper.market.task;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.cyksj.model.entity.UserBindPhone;
+import com.cyksj.model.entity.UserBindDetail;
 
 /*
  *项目名: netflix
- *文件名: UserBindPhoneMapper
+ *文件名: UserBindDetailMapper
  *创建者: JavaZou
  *创建时间:2022/12/29 13:54
  */
-public interface UserBindPhoneMapper extends BaseMapper<UserBindPhone> {
+public interface UserBindDetailMapper extends BaseMapper<UserBindDetail> {
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/GzhBodyDto.java

@@ -28,4 +28,9 @@ public class GzhBodyDto {
 	 * 分销类型id
 	 */
 	private Integer dsType;
+
+	/**
+	 * 登录手机号
+	 */
+	private String loginPhone;
 }

+ 2 - 1
netflix-dao/src/main/java/com/cyksj/model/dto/UserWhoami.java

@@ -5,7 +5,6 @@ import lombok.Setter;
 import lombok.experimental.Accessors;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 
 /**
  *
@@ -29,5 +28,7 @@ public class UserWhoami implements Serializable {
      */
     private String headimgurl;
 
+    private String loginPhone;
 
+    private String email;
 }

+ 2 - 2
netflix-dao/src/main/java/com/cyksj/model/entity/UserBindPhone.java → netflix-dao/src/main/java/com/cyksj/model/entity/UserBindDetail.java

@@ -5,13 +5,13 @@ import lombok.Setter;
 
 /*
  *项目名: netflix
- *文件名: UserBindPhone
+ *文件名: UserBindDetail
  *创建者: JavaZou
  *创建时间:2022/12/27 13:39
  */
 @Getter
 @Setter
-public class UserBindPhone extends BaseEntity{
+public class UserBindDetail extends BaseEntity{
 	private Long userId;
 
 	private String phone;

+ 7 - 1
netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java

@@ -15,7 +15,7 @@ import java.util.Date;
  */
 @Getter
 @Setter
-@SearchBean(tables = "user u left join user_bind_phone up on up.user_id = u.id" +
+@SearchBean(tables = "user u left join user_bind_detail up on up.user_id = u.id" +
         " left join channel_popularize cp on cp.id = u.popularize_id" +
         " left join channel c on c.id = cp.channel_id",
 where = ":otherPhone:")
@@ -45,6 +45,12 @@ public class UserView {
     @DbField("up.phone")
     private String bindPhone;
 
+    /**
+     * 绑定邮箱
+     */
+    @DbField("up.email")
+    private String bindEmail;
+
     /**
      * 头像
      */

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

@@ -594,6 +594,7 @@ public class RedisService {
         LOTTERY_KEY("lottery_key:%s", "抽奖key", 60 * 60 * 24l),
         TASK_TIME_LIMIT_KEY("task_time_limit:%s", "一次性任务key", 30),
         WX_GZH_QRCODE_LOGIN("wx_gzh_qrcode_login:%s", "微信公众号扫码登录key", 60),
+        WX_GZH_QRCODE_BIND("wx_gzh_qrcode_bind:%s", "pc手机用户购买车票绑定wx", 60),
         WX_GZH_QRCODE_SHARED_LOGIN("wx_gzh_qrcode_shared_login:%s", "微信公众号扫码分享邀请key", 60),
         EQUIPMENT_DISTRIBUTE_COUPON_KEY("equipment_distribute_coupon_key:%s", "实物设备分销新用户优惠券展示key", 60),
         CMS_USER_KEY("cms:user:%s:", "user缓存前缀", 60 * 60 * 24L * 7),

+ 23 - 0
netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.gzh.factory;
 
+import cn.hutool.core.lang.Validator;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -7,6 +8,7 @@ import com.cyksj.common.constant.Constant;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.Codec;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
 import com.cyksj.config.WeChatConfig;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.WxAppMapper;
@@ -22,6 +24,7 @@ import com.cyksj.model.entity.WxSyncLog;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.distribute.DistributeService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
+import com.cyksj.service.market.task.BindTaskService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
@@ -61,6 +64,8 @@ public class EventMsgService implements GzhMsgService {
 
 	private final WxSyncLogMapper wxSyncLogMapper;
 
+	private final BindTaskService bindTaskService;
+
 	private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
 	@Override
@@ -160,6 +165,8 @@ public class EventMsgService implements GzhMsgService {
 						userService.sendFixedCustomerCoupon(popularizeId, userId, info.getUnionid());
 					});
 				}
+				String loginPhone = gzhDto.getLoginPhone();
+				userBind(user.getId(), sceneKey, loginPhone);
 			}
 
 			saveGzhUserRelation(msgEvent, user.getId(), openId, info.getUnionid(), sceneKey, wxApp.getId());
@@ -170,6 +177,10 @@ public class EventMsgService implements GzhMsgService {
 				userMapper.updateById(user);
 			}
 			saveGzhUserRelation(msgEvent, user.getId(), openId, info.getUnionid(), sceneKey, wxApp.getId());
+			if (gzhDto != null) {
+				String loginPhone = gzhDto.getLoginPhone();
+				userBind(user.getId(), sceneKey, loginPhone);
+			}
 		}
 		//场景值扫描公众号二维码 登录
 		if (StrUtil.isNotEmpty(sceneKey)) {
@@ -213,4 +224,16 @@ public class EventMsgService implements GzhMsgService {
 
 		}
 	}
+
+	public void userBind(Long userId, String sceneKey, String loginPhone) {
+		if (StrUtil.isNotBlank(loginPhone) && Validator.isMobile(loginPhone)) {
+			log.info("pc端用户phone:{}购买车票后,微信扫描公众号二维码进行用户信息绑定", loginPhone);
+			try {
+				bindTaskService.bindPhone(userId, loginPhone, null, false);
+				redisService.set(RedisService.key.WX_GZH_QRCODE_BIND.getNameFormat(sceneKey), userId, RedisService.key.WX_GZH_QRCODE_BIND.getTimeout());
+			} catch (Exception e) {
+				log.info(StringUtil.getErrorText(e));
+			}
+		}
+	}
 }

+ 4 - 4
netflix-service/src/main/java/com/cyksj/service/market/impl/MarketFrontServiceImpl.java

@@ -24,7 +24,7 @@ import com.cyksj.mapper.market.sign.SignUserMapper;
 import com.cyksj.mapper.market.sign.UserPointsRecordMapper;
 import com.cyksj.mapper.market.task.TaskFollowPlatVerifyMapper;
 import com.cyksj.mapper.market.task.TaskUserCompleteRecordMapper;
-import com.cyksj.mapper.market.task.UserBindPhoneMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.LuckyDrawReq;
@@ -91,7 +91,7 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 
 	private final UserDistributeSharedMapper userDistributeSharedMapper;
 
-	private final UserBindPhoneMapper userBindPhoneMapper;
+	private final UserBindDetailMapper UserBindDetailMapper;
 
 	private final RedisService redisService;
 
@@ -562,8 +562,8 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 				}
 			}
 		} else if (TaskTypeEnum.bind_phone.getDesc().equals(data.getTypeName())) {
-			UserBindPhone bindPhone = userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-					.eq(UserBindPhone::getUserId, userId).last("limit 1"));
+			UserBindDetail bindPhone = UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+					.eq(UserBindDetail::getUserId, userId).last("limit 1"));
 			if (bindPhone != null) {
 				data.setPhone(bindPhone.getPhone());
 			}

+ 21 - 0
netflix-service/src/main/java/com/cyksj/service/market/task/BindTaskService.java

@@ -0,0 +1,21 @@
+package com.cyksj.service.market.task;
+
+/*
+ *项目名: netflix
+ *文件名: BindTaskService
+ *创建者: JavaZou
+ *创建时间:2023/4/13 9:53
+ */
+public interface BindTaskService {
+
+	/**
+	 *
+	 * @param userId 用户id
+	 * @param phone 绑定手机号
+	 * @param code 验证码
+	 * @param isCode 是否需要验证码 true需要
+	 */
+	void bindPhone(Long userId, String phone, String code, Boolean isCode);
+
+	void updateBindPhone(Long userId, String phone, String code);
+}

+ 87 - 0
netflix-service/src/main/java/com/cyksj/service/market/task/impl/BindTaskServiceImpl.java

@@ -0,0 +1,87 @@
+package com.cyksj.service.market.task.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.TaskTypeEnum;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.market.task.TaskTypeMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
+import com.cyksj.model.entity.TaskType;
+import com.cyksj.model.entity.UserBindDetail;
+import com.cyksj.service.market.task.BindTaskService;
+import com.cyksj.service.market.task.TaskService;
+import com.cyksj.service.phone.PhoneCodeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+/*
+ *项目名: netflix
+ *文件名: BindTaskServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/4/13 9:53
+ */
+@Service
+@RequiredArgsConstructor
+public class BindTaskServiceImpl implements BindTaskService {
+	private final TaskService taskService;
+
+	private final TaskTypeMapper taskTypeMapper;
+
+	private final PhoneCodeService phoneCodeService;
+
+	private final UserBindDetailMapper UserBindDetailMapper;
+
+
+	@Override
+	public void bindPhone(Long userId, String phone, String code, Boolean isCode) {
+		UserBindDetail other = UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+				.eq(UserBindDetail::getPhone, phone).ne(UserBindDetail::getUserId, userId).select(UserBindDetail::getId).last("limit 1"));
+		if (other != null) {
+			throw BusinessRuntimeException.getInstance("该手机号已被绑定");
+		}
+		UserBindDetail bindPhone = Optional.ofNullable(UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+				.eq(UserBindDetail::getUserId, userId).last("limit 1"))).orElse(new UserBindDetail());
+		if (StrUtil.isNotBlank(bindPhone.getPhone())) {
+			throw BusinessRuntimeException.getInstance("您已绑定手机号");
+		}
+		if (isCode) {
+			//校验
+			phoneCodeService.checkPhone(phone, code);
+		}
+		bindPhone.setUserId(userId);
+		bindPhone.setPhone(phone);
+		try {
+			if (bindPhone.getId() == null) {
+				UserBindDetailMapper.insert(bindPhone);
+			} else {
+				UserBindDetailMapper.updateById(bindPhone);
+			}
+		} catch (DuplicateKeyException e) {
+
+		}
+		TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
+				.eq(TaskType::getName, TaskTypeEnum.bind_phone.getDesc()).last("limit 1"));
+		//完成任务
+		taskService.completeTask(taskType, userId);
+	}
+
+	@Override
+	public void updateBindPhone(Long userId, String phone, String code) {
+		UserBindDetail bindPhone = UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+				.eq(UserBindDetail::getUserId, userId).last("limit 1"));
+		if (bindPhone == null || StrUtil.isEmpty(bindPhone.getPhone())) {
+			throw BusinessRuntimeException.getInstance("您未绑定手机号");
+		}
+		UserBindDetail other = UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+				.eq(UserBindDetail::getPhone, phone).ne(UserBindDetail::getUserId, userId).select(UserBindDetail::getId).last("limit 1"));
+		if (other != null) {
+			throw BusinessRuntimeException.getInstance("该手机号已被绑定");
+		}
+		phoneCodeService.checkPhone(phone, code);
+		bindPhone.setPhone(phone);
+		UserBindDetailMapper.updateById(bindPhone);
+	}
+}

+ 50 - 3
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -16,6 +16,7 @@ import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
 import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
 import com.alipay.api.response.AlipayTradeQueryResponse;
 import com.alipay.api.response.AlipayTradeRefundResponse;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.EnvCommonService;
@@ -45,6 +46,7 @@ import com.cyksj.mapper.manage.coupon.CouponSkuMapper;
 import com.cyksj.mapper.manage.coupon.CouponUserMapper;
 import com.cyksj.mapper.manage.distribute.*;
 import com.cyksj.mapper.market.task.TaskTypeMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
 import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.dto.CouponPopularizeDto;
 import com.cyksj.model.dto.H5JsPayParams;
@@ -197,6 +199,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final UserBusinessFrontService userBusinessFrontService;
 
+	private final UserBindDetailMapper userBindDetailMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -591,7 +595,15 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				GroupsRelation groupsRelation = groupsRelationMapper.selectById(orderDon.getRelationId());
 				if (groupsRelation != null) {
 					if (!groupsRelation.getUserId().equals(orderDon.getUserId())) {
-						throw new BusinessRuntimeException("订单用户与车位用户不匹配!");
+						TASK_POOL.execute(()->{
+							orderDon.setStatus(OrderDon.Status.close);
+							updateById(orderDon);
+						});
+						User user = userMapper.selectById(orderDon.getUserId());
+						if (user != null) {
+							checkIsSameUser(groupsRelation.getUserId(), orderDon.getUserId(), user.getOpenId(), user.getLoginPhone());
+						}
+						//throw new BusinessRuntimeException("订单用户与车位用户不匹配!");
 					} else {
 						if (GroupsRelation.Status.locking.equals(groupsRelation.getStatus())) {
 							log.info("清理用户userId:{}未支付订单", orderDon.getUserId());
@@ -658,7 +670,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 		//todo 多账号同一用户绑定 续费
 		if (!relation.getUserId().equals(user.getId())) {
-			throw new BusinessRuntimeException("");
+			checkIsSameUser(relation.getUserId(), userId, user.getOpenId(), user.getLoginPhone());
 		}
         GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
 		if (groupsTrips == null) {
@@ -1521,7 +1533,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			log.info("虚物订单orderNo:{}开始更新车票信息", order.getOrderNo());
 			//修改车位状态
 			GroupsRelation relation = groupsRelationMapper.selectById(order.getRelationId());
-			if (order.getRelationId() != 0 && !relation.getUserId().equals(order.getUserId())) {
+			if (order.getRelationId() != 0 && !relation.getUserId().equals(order.getUserId()) && order.getOrderType() == 1) {
 				GroupsRelation relationNoOrder = exchangeCodeService.getRelationNoOrder(sku, order.getUserId());
 				if (relationNoOrder == null) {
 					log.error("用户userId:{}支付订单orderId:{}回调后,未分配车票", order.getUserId(), order.getId());
@@ -2097,4 +2109,39 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		return noPayment;
 	}
+
+	public void checkIsSameUser(Long relationUserId, Long userId, String openId, String loginPhone) {
+		//手机用户与微信用户
+		LambdaQueryWrapper<UserBindDetail> wrapper = Wrappers.lambdaQuery(UserBindDetail.class);
+		Boolean isPcUser = false;
+		if (StrUtil.isNotBlank(openId)) {
+			wrapper.eq(UserBindDetail::getUserId, userId);
+		} else {
+			isPcUser = true;
+			wrapper.eq(UserBindDetail::getPhone, loginPhone);
+		}
+		UserBindDetail userBindDetail = userBindDetailMapper.selectOne(wrapper.last("limit 1"));
+		if (userBindDetail == null) {
+			throw new BusinessRuntimeException("");
+		}
+		if (userBindDetail != null) {
+			if (isPcUser) {
+				if (!relationUserId.equals(userBindDetail.getUserId())) {
+					throw new BusinessRuntimeException("");
+				}
+			} else {
+				if (StrUtil.isEmpty(userBindDetail.getPhone())) {
+					throw new BusinessRuntimeException("");
+				}
+				User otherUser = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
+						.eq(User::getLoginPhone, userBindDetail.getPhone()).last("limit 1"));
+				if (otherUser == null) {
+					throw new BusinessRuntimeException("");
+				}
+				if (!relationUserId.equals(otherUser.getId())) {
+					throw new BusinessRuntimeException("");
+				}
+			}
+		}
+	}
 }

+ 17 - 14
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -10,7 +10,7 @@ import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.corp.CorpUserMapper;
-import com.cyksj.mapper.market.task.UserBindPhoneMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.GoodsDonViews;
 import com.cyksj.model.views.RenewalView;
@@ -37,7 +37,7 @@ import java.util.stream.Collectors;
 @RequiredArgsConstructor
 @Slf4j
 public class GroupRelationFrontServiceImpl implements GroupRelationFrontService {
-	private final UserBindPhoneMapper userBindPhoneMapper;
+	private final UserBindDetailMapper UserBindDetailMapper;
 
 	private final UserMapper userMapper;
 
@@ -61,29 +61,32 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 			return new ArrayList<>();
 		}
 		//是否绑定过手机号
-		LambdaQueryWrapper<UserBindPhone> wrapper = Wrappers.lambdaQuery(UserBindPhone.class).last("limit 1");
+		LambdaQueryWrapper<UserBindDetail> wrapper = Wrappers.lambdaQuery(UserBindDetail.class).last("limit 1");
 		if (isPcUser) {
-			wrapper.eq(UserBindPhone::getPhone, u.getLoginPhone());
+			wrapper.eq(UserBindDetail::getPhone, u.getLoginPhone());
 		} else {
-			wrapper.eq(UserBindPhone::getUserId, userId);
+			wrapper.eq(UserBindDetail::getUserId, userId);
 		}
-		UserBindPhone userBindPhone = userBindPhoneMapper.selectOne(wrapper);
+		UserBindDetail userBindDetail = UserBindDetailMapper.selectOne(wrapper);
 		Long otherUserId = 0l;
-		if (userBindPhone != null) {
+		if (userBindDetail != null) {
 			if (isPcUser) {
-				otherUserId = userBindPhone.getUserId();
+				otherUserId = userBindDetail.getUserId();
 			} else {
-				User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
-						.eq(User::getLoginPhone, userBindPhone.getPhone()).last("limit 1"));
-				if (user != null) {
-					if (user.getIsBlack()) {
-						return new ArrayList<>();
+				if (StrUtil.isNotBlank(userBindDetail.getPhone())) {
+					User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
+							.eq(User::getLoginPhone, userBindDetail.getPhone()).last("limit 1"));
+					if (user != null) {
+						if (user.getIsBlack()) {
+							return new ArrayList<>();
+						}
+						otherUserId = user.getId();
 					}
-					otherUserId = user.getId();
 				}
 			}
 		}
 		List<RenewalView> list = beanSearcher.searchAll(RenewalView.class, MapUtils.builder()
+				.field(RenewalView::getUserId, 0).op(Operator.GreaterThan)
 				.field(RenewalView::getUserId, userId, otherUserId).op(Operator.InList)
 				.field(RenewalView::getStatus, List.of("validity", "overdue")).op(Operator.InList)
 				.orderBy(RenewalView::getExpiryTime).asc()

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

@@ -77,7 +77,7 @@ public interface WeChatService {
      * 获取公众号带参数的临时二维码
      * @return
      */
-    WxGzhQrCodeTicketRep getWxGzhQrCode(Long sharedId, Integer dsType, Long popularizeId) throws Exception;
+    WxGzhQrCodeTicketRep getWxGzhQrCode(Long sharedId, Integer dsType, Long popularizeId, String loginPhone) throws Exception;
 
     /**
      * 获取公众号带参数的永久二维码

+ 5 - 3
netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.CharsetUtil;
 import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
 import cn.hutool.json.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -476,7 +477,7 @@ public class WeChatServiceImpl implements WeChatService {
     }
 
     @Override
-    public WxGzhQrCodeTicketRep getWxGzhQrCode(Long sharedId, Integer dsType, Long popularizeId) throws Exception {
+    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());
         //scene_str:场景值ID(字符串形式的ID),字符串类型,长度限制为1到64
         String scene_str = RandomUtil.randomString(16);
@@ -493,11 +494,12 @@ public class WeChatServiceImpl implements WeChatService {
         if (200 != response.statusCode()) {
             throw BusinessRuntimeException.getInstance("获取微信登录二维码失败: " + response.body());
         }
-        if (sharedId != null || popularizeId != null) {
+        if (sharedId != null || popularizeId != null || StrUtil.isNotBlank(loginPhone)) {
             GzhBodyDto gzhBodyDto = new GzhBodyDto()
                     .setSharedId(sharedId)
                     .setPopularizeId(popularizeId)
-                    .setDsType(dsType);
+                    .setDsType(dsType)
+                    .setLoginPhone(loginPhone);
             String state = Codec.DoBase64.custom().setData(Jsons.toJson(gzhBodyDto)).encodeAsText();
             redisService.set(RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getNameFormat(scene_str), state, RedisService.key.WX_GZH_QRCODE_SHARED_LOGIN.getTimeout());
         }

+ 14 - 60
netflix-web/src/main/java/com/cyksj/web/controller/market/TaskFrontController.java

@@ -4,22 +4,18 @@ import cn.hutool.core.lang.Validator;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.NoSubmit;
-import com.cyksj.common.constant.TaskTypeEnum;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.mapper.market.task.TaskTypeMapper;
-import com.cyksj.mapper.market.task.UserBindPhoneMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
 import com.cyksj.model.entity.TaskFollowPlatVerify;
-import com.cyksj.model.entity.TaskType;
-import com.cyksj.model.entity.UserBindPhone;
+import com.cyksj.model.entity.UserBindDetail;
 import com.cyksj.model.request.LoginPhoneReq;
 import com.cyksj.model.request.TaskFollowReq;
 import com.cyksj.model.views.TaskFrontView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.market.MarketFrontService;
-import com.cyksj.service.market.task.TaskService;
-import com.cyksj.service.phone.PhoneCodeService;
+import com.cyksj.service.market.task.BindTaskService;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -49,16 +45,12 @@ public class TaskFrontController {
 
 	private final HttpServletRequest request;
 
-	private final UserBindPhoneMapper userBindPhoneMapper;
-
-	private final PhoneCodeService phoneCodeService;
-
-	private final TaskService taskService;
-
-	private final TaskTypeMapper taskTypeMapper;
+	private final UserBindDetailMapper UserBindDetailMapper;
 
 	private final RedisService redisService;
 
+	private final BindTaskService bindTaskService;
+
 	/**
 	 * 任务列表
 	 */
@@ -90,33 +82,7 @@ public class TaskFrontController {
 	@NoSubmit
 	public Result<String> bindPhone(@RequestBody LoginPhoneReq phoneReq) {
 		Long userId = StpUserUtil.getLoginIdAsLong();
-		UserBindPhone other = userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-				.eq(UserBindPhone::getPhone, phoneReq.getPhone()).ne(UserBindPhone::getUserId, userId).select(UserBindPhone::getId).last("limit 1"));
-		if (other != null) {
-			throw BusinessRuntimeException.getInstance("该手机号已被绑定");
-		}
-		UserBindPhone bindPhone = Optional.ofNullable(userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-				.eq(UserBindPhone::getUserId, userId).last("limit 1"))).orElse(new UserBindPhone());
-		if (StrUtil.isNotBlank(bindPhone.getPhone())) {
-			throw BusinessRuntimeException.getInstance("您已绑定手机号");
-		}
-		//校验
-		phoneCodeService.checkPhone(phoneReq.getPhone(), phoneReq.getCode());
-		bindPhone.setUserId(userId);
-		bindPhone.setPhone(phoneReq.getPhone());
-		try {
-			if (bindPhone.getId() == null) {
-				userBindPhoneMapper.insert(bindPhone);
-			}else {
-				userBindPhoneMapper.updateById(bindPhone);
-			}
-		} catch (DuplicateKeyException e) {
-
-		}
-		TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
-				.eq(TaskType::getName, TaskTypeEnum.bind_phone.getDesc()).last("limit 1"));
-		//完成任务
-		taskService.completeTask(taskType, userId);
+		bindTaskService.bindPhone(userId, phoneReq.getPhone(), phoneReq.getCode(), true);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("绑定手机号成功");
 	}
 
@@ -129,13 +95,13 @@ public class TaskFrontController {
 		if (!Validator.isEmail(phoneReq.getEmail())) {
 			throw BusinessRuntimeException.getInstance("请输入正确的邮箱");
 		}
-		UserBindPhone other = userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-				.eq(UserBindPhone::getEmail, phoneReq.getEmail()).ne(UserBindPhone::getUserId, userId).select(UserBindPhone::getId).last("limit 1"));
+		UserBindDetail other = UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+				.eq(UserBindDetail::getEmail, phoneReq.getEmail()).ne(UserBindDetail::getUserId, userId).select(UserBindDetail::getId).last("limit 1"));
 		if (other != null) {
 			throw BusinessRuntimeException.getInstance("该邮箱已被绑定");
 		}
-		UserBindPhone bindPhone = Optional.ofNullable(userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-				.eq(UserBindPhone::getUserId, userId).last("limit 1"))).orElse(new UserBindPhone());
+		UserBindDetail bindPhone = Optional.ofNullable(UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+				.eq(UserBindDetail::getUserId, userId).last("limit 1"))).orElse(new UserBindDetail());
 		if (StrUtil.isNotBlank(bindPhone.getEmail())) {
 			throw BusinessRuntimeException.getInstance("您已绑定邮箱");
 		}
@@ -150,9 +116,9 @@ public class TaskFrontController {
 		bindPhone.setUserId(userId);
 		try {
 			if (bindPhone.getId() == null) {
-				userBindPhoneMapper.insert(bindPhone);
+				UserBindDetailMapper.insert(bindPhone);
 			}else {
-				userBindPhoneMapper.updateById(bindPhone);
+				UserBindDetailMapper.updateById(bindPhone);
 			}
 		} catch (DuplicateKeyException e) {
 
@@ -168,19 +134,7 @@ public class TaskFrontController {
 	@PutMapping("/put/bind/phone")
 	public Result<String> updateBindPhone(@RequestBody LoginPhoneReq phoneReq) {
 		Long userId = StpUserUtil.getLoginIdAsLong();
-		UserBindPhone bindPhone = userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-				.eq(UserBindPhone::getUserId, userId).last("limit 1"));
-		if (bindPhone == null || StrUtil.isEmpty(bindPhone.getPhone())) {
-			throw BusinessRuntimeException.getInstance("您未绑定手机号");
-		}
-		UserBindPhone other = userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-				.eq(UserBindPhone::getPhone, phoneReq.getPhone()).ne(UserBindPhone::getUserId, userId).select(UserBindPhone::getId).last("limit 1"));
-		if (other != null) {
-			throw BusinessRuntimeException.getInstance("该手机号已被绑定");
-		}
-		phoneCodeService.checkPhone(phoneReq.getPhone(), phoneReq.getCode());
-		bindPhone.setPhone(phoneReq.getPhone());
-		userBindPhoneMapper.updateById(bindPhone);
+		bindTaskService.updateBindPhone(userId, phoneReq.getPhone(), phoneReq.getCode());
 		return GatewayResponse.SUCCESS.newBuilder().toResult("更换手机号成功");
 	}
 

+ 30 - 5
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -15,12 +15,13 @@ import com.cyksj.config.zfb.BaseZfbConfig;
 import com.cyksj.config.zfb.ZfbProductCode;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.BusinessType;
+import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.OrderDonWaybillMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
-import com.cyksj.mapper.market.task.UserBindPhoneMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
 import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.dto.H5JsPayParams;
 import com.cyksj.model.entity.*;
@@ -77,7 +78,7 @@ public class OrderController {
     private OrderDonMapper orderDonMapper;
 
     @Autowired
-    private UserBindPhoneMapper userBindPhoneMapper;
+    private UserBindDetailMapper userBindDetailMapper;
 
     @Autowired
     private UserMapper userMapper;
@@ -432,6 +433,27 @@ public class OrderController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
+    /**
+     * 电脑端手机号注册 购买车票是否绑定了微信用户
+     */
+    @GetMapping("/isBindWx")
+    public Result<Boolean> isBindWx() {
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        User user = userMapper.selectById(userId);
+        if (user == null) {
+            throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
+        }
+        if (StrUtil.isEmpty(user.getLoginPhone())) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult(true);
+        }
+        UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+                .eq(UserBindDetail::getPhone, user.getLoginPhone()));
+        if (userBindDetail == null) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult(false);
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult(true);
+    }
+
     /**
      * 是否绑定了邮箱或手机号
      */
@@ -439,12 +461,15 @@ public class OrderController {
     public Result<Boolean> isBindPhoneOrEmail() {
         Long userId = StpUserUtil.getLoginIdAsLong();
         User user = userMapper.selectById(userId);
+        if (user == null) {
+            throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
+        }
         if (StrUtil.isEmpty(user.getOpenId())) {
             return GatewayResponse.SUCCESS.newBuilder().toResult(true);
         }
-        UserBindPhone userBindPhone = userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-                .eq(UserBindPhone::getUserId, userId));
-        if (userBindPhone == null) {
+        UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+                .eq(UserBindDetail::getUserId, userId));
+        if (userBindDetail == null) {
             return GatewayResponse.SUCCESS.newBuilder().toResult(false);
         }
         return GatewayResponse.SUCCESS.newBuilder().toResult(true);

+ 23 - 1
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -255,7 +255,16 @@ public class AuthorizationController {
     @GetMapping("/wx/gzh/login/qrCode")
     public Result<WxGzhQrCodeTicketRep> getWxGzhQrCode(Long sharedId, Integer dsType, Long popularizeId) throws Exception {
         //获取gzh带参数的二维码
-        WxGzhQrCodeTicketRep result = weChatService.getWxGzhQrCode(sharedId, dsType, popularizeId);
+        WxGzhQrCodeTicketRep result = weChatService.getWxGzhQrCode(sharedId, dsType, popularizeId, null);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(result);
+    }
+
+    /**
+     * pc端公众号二维码绑定微信账号信息
+     */
+    @GetMapping("/wx/gzh/qrCode")
+    public Result<WxGzhQrCodeTicketRep> getWxGzhBindQrcode(String loginPhone) throws Exception {
+        WxGzhQrCodeTicketRep result = weChatService.getWxGzhQrCode(null, null, null, loginPhone);
         return GatewayResponse.SUCCESS.newBuilder().toResult(result);
     }
 
@@ -287,6 +296,19 @@ public class AuthorizationController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(jsonObject.toString());
     }
 
+    /**
+     * pc用户是否 已通过二维码 扫码关注公众号
+     */
+    @GetMapping("/wx/gzh/subscribe")
+    public Result<Boolean> isSubscribeWxGzh(String sceneStr) {
+        String key = RedisService.key.WX_GZH_QRCODE_BIND.getNameFormat(sceneStr);
+        Object value = redisService.get(key);
+        if (value == null) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult(false);
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult(true);
+    }
+
     /**
      * 网页微信用户登录授权后,重定向至web端
      */

+ 5 - 5
netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

@@ -6,12 +6,12 @@ import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.manage.coupon.CouponUserMapper;
-import com.cyksj.mapper.market.task.UserBindPhoneMapper;
+import com.cyksj.mapper.market.task.UserBindDetailMapper;
 import com.cyksj.model.dto.UserWhoami;
 import com.cyksj.model.entity.CouponUser;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.entity.User;
-import com.cyksj.model.entity.UserBindPhone;
+import com.cyksj.model.entity.UserBindDetail;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.ExchangeCodeTicket;
 import com.cyksj.model.request.ReceiveBenefitsReq;
@@ -49,7 +49,7 @@ public class UserController {
 
     private final OrderDonMapper orderDonMapper;
 
-    private final UserBindPhoneMapper userBindPhoneMapper;
+    private final UserBindDetailMapper UserBindDetailMapper;
 
     private final UserRealOrderBenefitsService userRealOrderBenefitsService;
 
@@ -98,8 +98,8 @@ public class UserController {
                 .eq(OrderDon::getUserId, userId)
                 .eq(OrderDon::getStatus, OrderDon.Status.noPayment).last("limit 1"));
         personalView.setIsNoPayment(orderDon != null ? true : false);
-        UserBindPhone bindPhone = userBindPhoneMapper.selectOne(Wrappers.lambdaQuery(UserBindPhone.class)
-                .eq(UserBindPhone::getUserId, userId).last("limit 1"));
+        UserBindDetail bindPhone = UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
+                .eq(UserBindDetail::getUserId, userId).last("limit 1"));
         //手机号
         if (bindPhone != null) {
             personalView.setPhone(bindPhone.getPhone());