微信公众号登录网站

2024 年 8 月 17 日 星期六(已编辑)
13
摘要
本文介绍了如何在微信公众号中实现用户登录并获取用户信息的步骤。首先,确保公众号已经认证,并准备好服务器接收微信服务器的回调。接下来,获取微信公众号的appid和appsecret,并配置服务器以响应微信的请求,确保按照微信的要求进行token的验证。然后,通过获取access_token来访问微信资源,并生成带有ticket的二维码,返回给前端展示。用户扫码后,服务器接收到事件推送,前端通过轮询查询登录状态,最终实现用户登录。

微信公众号登录网站

需求:微信公众号登录网站,获取用户信息

前提条件

  1. 微信公众号已经认证
  2. 拥有服务器,可以接收微信服务器的回调

步骤

1、获取微信公众号的appid和appsecret

2、接入服务器,接收微信服务器的回调,需要有域名,可以使用内网穿透工具,例如cpolar

首先需要准备好图中的资源

说明:

  • URL表示微信验证服务端是否存在,需要按照要求进行配置,例如我这里的地址是

    https://13a34511.r1.cpolar.top/api/user/wxcheck

    所以必须在自己的服务上准备好响应的接口

    //外层还有/user
    @GetMapping("wxcheck")
    public String  wxCheck(@RequestParam("signature") String signature,
                                        @RequestParam("timestamp") String timestamp,
                                        @RequestParam("nonce") String nonce,
                                        @RequestParam("echostr") String echostr) {
        if (userService.wxCheck(signature, timestamp, nonce, wxOpenConfig.getToken())) {
            return echostr;
        } else {
            return "error";
        }
    }

    需要按照微信的要求返回数据,要求如下:

    1)将token、timestamp、nonce三个参数进行字典序排序

    2)将三个参数字符串拼接成一个字符串进行sha1加密

    3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

    @Override
    public Boolean wxCheck(String signature, String timestamp, String nonce, String token) {
        // 微信公众号接入校验
        // 将token、timestamp、nonce三个参数进行字典序排序
        String[] arr = new String[]{token, timestamp, nonce};
        Arrays.sort(arr);
        // 将三个参数字符串拼接成一个字符串进行sha1加密
        StringBuilder content = new StringBuilder();
        for (String s : arr) {
            content.append(s);
        }
        String tmpStr = MYDigestUtils.sha1DigestAsHex(content.toString());
    
        log.info("微信公众号接入校验,signature = {}, tmpStr = {}", signature, tmpStr);
        return signature.equals(tmpStr);
    }

    接着提交上面的表单后会提示验证通过

3、接下来就是获取access_token了

java

@Override public String getAccessToken() { // 获取access_token String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", wxOpenConfig.getAppId(), wxOpenConfig.getAppSecret()); // 发送请求 String result = restTemplate.getForObject(url, String.class); log.info("获取access_token,result = {}", result); return result; } ```

4、生成带 Ticket 二维码

@Override
public String getQRCode(String accessToken) {
    // 获取二维码
    String url = String.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", accessToken);
    // 5分钟过期
    String body = WXUtils.getQRCodeBody("300", "QR_STR_SCENE");
    String result = restTemplate.postForObject(url, body, String.class);
    log.info("获取二维码,result = {}", result);
    return result;
}

5、将二维码的ticket返回给前端,前端请求到二维码图片展示给用户

6、用户扫码后会将响应的事件推送给上面的URL,只是将GET请求转换位POST请求,格式为:

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[FromUser]]></FromUserName>
  <CreateTime>123456789</CreateTime>
  <MsgType><![CDATA[event]]></MsgType>
  <Event><![CDATA[subscribe]]></Event>
  <EventKey><![CDATA[qrscene_123123]]></EventKey>
  <Ticket><![CDATA[TICKET]]></Ticket>
</xml>

当然有很多事件类型,我们可以定义策略模式分别处理

@Slf4j
public class DispatchEventHandle {

    private final Map<String, EventHandle> eventHandleMap = new HashMap<>();

    {
        eventHandleMap.put("subscribe", new SubscribeEventHandle());
        eventHandleMap.put("SCAN", new ScanEventHandle());
    }

    public  void dispatch(JSONObject jsonObject) {
        String eventType = jsonObject.getJSONObject("xml").getStr(WxEventHandleConstants.EVENT_TYPE_KEY);
        log.info("事件类型:{}", eventType);
        EventHandle eventHandle = eventHandleMap.get(eventType);
        if (eventHandle == null) {
            log.error("未找到对应的事件处理器");
            return;
        }
        eventHandle.handle(jsonObject);

    }
}

接收请求的接口定义为

@PostMapping("wxcheck")
public String  event(@RequestBody String xml) {
    String msgType = WXUtils.getMsgType(xml);
    if ("event".equals(msgType)) {
        DispatchEventHandle dispatchEventHandle = new DispatchEventHandle();
        dispatchEventHandle.dispatch(JSONUtil.xmlToJson(xml));
    }
    return xml;
}

7、前端在展示二维码后记得要轮询服务端,看是否已经扫描,后端可以在处理完成后将ticket作为key,JWT作为值缓存,前端请求查询到后顺利登录;

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...