Sfoglia il codice sorgente

fix 微信公众号扫码登录

zoujiajian 3 anni fa
parent
commit
8496192b01

+ 1 - 0
netflix-common/src/main/java/com/cyksj/common/constant/TemplateEnum.java

@@ -22,6 +22,7 @@ public enum TemplateEnum {
 	SPOTIFY_PRD_TEMPLATE("Spotify注册正式环境模板", "PswFyVYMurzJbdV8weJW2kuSAGpS_fnAKJQR7qMNlQI", " "),
 	PLAT_ACCOUNT_UPDATE_PRD_TEMPLATE("账号修改密码正式环境通知模板", "krTse4JDgR-upgx3JiB7XNOqpTEFhwLnA-yD1u-BZlw", " "),
 	SPOTIFY_ACCOUNT_UN_LIMIT_SUCCESS_PRD_TEMPLATE("Spotify账号解除限制成功正式环境模板", "o51fvp6AriFaIzlweupK2qjR5afsnKy2JabKocX5wHU", " "),
+	WX_GZH_QR_CODE_LOGIN("微信公众号扫码登录正式环境模板", "t4YTQcMwjT9VYlPUGXxJuWSpXvVyqyq_8-xKBhuFBC8", "")
 
 	;
 	private String desc;

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/response/WxGzhQrCodeTicketRep.java

@@ -0,0 +1,30 @@
+package com.cyksj.model.response;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: WxGzhQrCodeTicketRep
+ *创建者: JavaZou
+ *创建时间:2023/1/30 14:30
+ */
+@Getter
+@Setter
+public class WxGzhQrCodeTicketRep {
+
+	/**
+	 * 场景值str
+	 */
+	private String sceneStr;
+
+	/**
+	 * gzh二维码
+	 */
+	private String qrCodeUrl;
+
+	/**
+	 * 过期时间
+	 */
+	private Long expireTime;
+}

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

@@ -593,6 +593,7 @@ public class RedisService {
         EMAIL_CODE_KEY("email_code_key:%s", "邮箱验证码", 60 * 3),
         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),
         ;
 
         private String name;

+ 5 - 0
netflix-service/src/main/java/com/cyksj/service/template/TemplateCommonService.java

@@ -16,4 +16,9 @@ public interface TemplateCommonService {
 	 * 发送新订单模板消息
 	 */
 	void newOderSendMsgByType(OrderDon order, GoodsDon goodsDon, GoodsDonSku sku, User user, String toPeople) throws Exception;
+
+	/**
+	 * 公众号扫描登录成功模板消息
+	 */
+	void sendWxGzhQrCodeSuccessMsg(User user) throws Exception;
 }

+ 19 - 0
netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.template.impl;
 
+import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.constant.TemplateEnum;
@@ -54,4 +55,22 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 		data.setRemark(new WxMpTemplateData("点击查看详情"));
 		weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
 	}
+
+	@Override
+	public void sendWxGzhQrCodeSuccessMsg(User user) throws Exception {
+		if (!EnvCommonService.active.equals(envCommonService.getEnv())) {
+			TemplateEnum templateEnum = TemplateEnum.WX_GZH_QR_CODE_LOGIN;
+			WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+					.setToUser(user.getOpenId())
+					.setTemplateId(templateEnum.getTemplateId())
+					//TODO
+					.setUrl(" ");
+			WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+			data.setFirst(new WxMpTemplateData("您已登录成功"));
+			data.setKeyword1(new WxMpTemplateData("银河录像局"));
+			data.setKeyword2(new WxMpTemplateData(DateUtil.format(DateTime.now(), "yyyy-MM-dd HH:mm:ss")));
+			data.setRemark(new WxMpTemplateData("欢迎使用银河录像局"));
+			weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
+		}
+	}
 }

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

@@ -2,6 +2,7 @@ package com.cyksj.service.wechat;
 
 
 import com.cyksj.model.dto.*;
+import com.cyksj.model.response.WxGzhQrCodeTicketRep;
 
 import java.math.BigDecimal;
 import java.util.Date;
@@ -71,4 +72,10 @@ public interface WeChatService {
      * @param refundMoney  退款金额
      */
     void refundWxOrder(String appId, String shopId, String transactionId, String outRefundNo, BigDecimal totalFee, BigDecimal refundMoney, String notifyUrl) throws Exception;
+
+    /**
+     * 获取公众号带参数的二维码
+     * @return
+     */
+    WxGzhQrCodeTicketRep getWxGzhQrCode() throws Exception;
 }

+ 34 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java

@@ -1,8 +1,11 @@
 package com.cyksj.service.wechat.impl;
 
+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.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.exception.BusinessRuntimeException;
@@ -16,6 +19,8 @@ import com.cyksj.mapper.channel.ShopConfigMapper;
 import com.cyksj.model.dto.*;
 import com.cyksj.model.entity.ShopConfig;
 import com.cyksj.model.entity.WxApp;
+import com.cyksj.model.response.WxGzhQrCodeTicketRep;
+import com.cyksj.redis.RedisService;
 import com.cyksj.service.wechat.WeChatService;
 import com.cyksj.service.wechat.WxMpAccountOps;
 import lombok.RequiredArgsConstructor;
@@ -60,6 +65,8 @@ public class WeChatServiceImpl implements WeChatService {
 
     private final ShopConfigMapper shopConfigMapper;
 
+    private final RedisService redisService;
+
     @Override
     public String createUrl(String state, String redirectUrl) {
         return createUrl(state,redirectUrl,weChatConfig.getAppid(), WeChatAuthRedirectUrl.BASE.getScope());
@@ -471,6 +478,33 @@ public class WeChatServiceImpl implements WeChatService {
         log.info("------------------- 调用微信申请退款 结束 -------------------");
     }
 
+    @Override
+    public WxGzhQrCodeTicketRep getWxGzhQrCode() 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);
+        DateTime dateTime = DateUtil.offsetSecond(DateTime.now(), 60);
+        String body = String.format("{\"expire_seconds\": %s, \"action_name\": \"%s\", \"action_info\": {\"scene\": {\"scene_str\": %s}}}",
+                60,
+                "QR_STR_SCENE",
+                scene_str);
+        HttpResponse<String> response = J11HttpC.custom()
+                .url(gzhQrCodeUrl)
+                .ofPost()
+                .body(HttpRequest.BodyPublishers.ofString(body))
+                .send(HttpResponse.BodyHandlers.ofString());
+        if (200 != response.statusCode()) {
+            throw BusinessRuntimeException.getInstance("获取微信登录二维码失败: " + response.body());
+        }
+
+        JSONObject re = Jsons.parseObject(response.body(), JSONObject.class);
+        String ticket = re.getStr("ticket");
+        WxGzhQrCodeTicketRep wxGzhQrCodeTicketRep = new WxGzhQrCodeTicketRep();
+        wxGzhQrCodeTicketRep.setQrCodeUrl(String.format("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s", ticket));
+        wxGzhQrCodeTicketRep.setSceneStr(scene_str);
+        wxGzhQrCodeTicketRep.setExpireTime(dateTime.getTime());
+        return wxGzhQrCodeTicketRep;
+    }
 
     /**
      * sha256_HMAC加密

+ 38 - 0
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -35,10 +35,12 @@ import com.cyksj.model.entity.User;
 import com.cyksj.model.entity.UserDistributeShared;
 import com.cyksj.model.request.LoginPhoneReq;
 import com.cyksj.model.response.LoginPhoneRep;
+import com.cyksj.model.response.WxGzhQrCodeTicketRep;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.authorization.AuthorizationService;
 import com.cyksj.service.market.task.TaskService;
 import com.cyksj.service.order.OrderDonService;
+import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.service.wechat.WeChatService;
 import com.cyksj.web.controller.mail.MailService;
@@ -101,6 +103,8 @@ public class AuthorizationController {
 
     private final MailService mailService;
 
+    private final TemplateCommonService templateCommonService;
+
     @GetMapping(value = "/weChat")
     public void base(String url,Long sharedId, String authType, HttpServletResponse response) throws Exception {
 
@@ -254,6 +258,40 @@ public class AuthorizationController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(wxAuthUrl);
     }
 
+    /**
+     * 网页扫描微信公众号二维码 临时凭证ticket  关注后登录
+     */
+    @GetMapping("/wx/gzh/login/qrCode")
+    public Result<WxGzhQrCodeTicketRep> getWxGzhQrCode() throws Exception {
+        //获取gzh带参数的二维码
+        WxGzhQrCodeTicketRep result = weChatService.getWxGzhQrCode();
+        return GatewayResponse.SUCCESS.newBuilder().toResult(result);
+    }
+
+    /**
+     * 根据公众号的场景值是否 已经扫码了公众号二维码
+     */
+    @GetMapping("/wx/gzh/sceneStr/checkQrCode")
+    public Result<String> checkQrCodeByGzhSceneStr(String sceneStr) throws Exception {
+        Long userId = (Long) redisService.get(RedisService.key.WX_GZH_QRCODE_LOGIN.getNameFormat(sceneStr));
+        if (userId == null) {
+            return GatewayResponse.SUCCESS.newBuilder().setMsg("用户未扫码").toResult();
+        }
+        User user = userService.getById(userId);
+        StpUserUtil.login(userId);
+        String token = StpUserUtil.getTokenValue();
+
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.putOpt("saToken", token);
+        jsonObject.putOpt("uid", userId);
+        jsonObject.putOpt("nickname", user.getNickname());
+        jsonObject.putOpt("img", user.getHeadimgurl());
+
+        //发送模板消息
+        templateCommonService.sendWxGzhQrCodeSuccessMsg(user);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(jsonObject.toString());
+    }
+
     /**
      * 网页微信用户登录授权后,重定向至web端
      */