微信扫描自定义二维码关注公众号并登录(一)PC端网站的设计与实现 - 大确幸_新社交_新生活_快速脱单_一个聚合百万单身年青的社群 #hi大确幸#

微信扫描自定义二维码关注公众号并登录(一)PC端网站的设计与实现

青峰加油 1年前 ⋅ 3454 阅读

业务需求

大确幸网站实现扫描二维码关注微信公众号,如果已经关注公众号就自动登陆网站并获取其微信昵称,头像等信息,如果用户未关注就等用户关注公众号后自动登陆网站

--如果用户已关注公众号,网站端直接自动登陆,如果没有关注,就等用户关注公众号之后网站端自动登陆

(目前已经完成了这个功能,示例网址:https://love.daquexing.com/  大确幸-新社交,新生活,一个聚合百万单身年青的社群。大确幸是一个有温度的社区,宗旨是帮更多适龄单身青年解决单身问题。)

做微信扫码登陆,生成二维码必须是微信公众号中绑定的域这个域名,网站生成不了二维码(网站与微信服务器不是同一个域名) ,而是调用微信系统的接口获取二维码,用户扫码后也是请求微信服务器 。

ok 以上内容参考引用出自:

网站实现扫描二维码关注微信公众号,自动登陆网站并获取其信息

方案优化:网站实现扫描二维码关注微信公众号,自动登陆网站并获取其信息

网上还有一篇文章推荐:

微信扫描自定义二维码关注公众号

如果以上三篇你都看懂了, 下面就简单, 或者你都不用看了。

微信公众平台技术文档:

获取access_token

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

生成带参数的二维码

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542

前端页面实现相关js

https://love.daquexing.com/theme/default/js/modules/authc.js

前端获取二维码方法:

@RequestMapping(value = "/qrcode", method = RequestMethod.GET)
public @ResponseBody
Data getqrcode(@RequestParam(value = "f") String f) {
Data data = Data.failure("操作失败");

Map<String, String> map = new HashMap<>();
String timestamp = System.currentTimeMillis() + "";
if ("m".equals(f)) {
timestamp = "m" + timestamp;
}
map.put("timestamp", timestamp);

// 获取二维码链接
String result = HttpKit.get(env.getProperty("api.url.wx_get_qrcode") + timestamp);
if (StringUtils.isNotEmpty(result)) {
JSONObject res = JSON.parseObject(result);
map.put("ticket", res.get("ticket").toString());
}

return Data.success(map);
}


/**
 * 登录
 *
 * @param username
 * @param timestamp
 * @return
 */
@RequestMapping(value = "/wechat", method = RequestMethod.POST)
public @ResponseBody
Data wechatlogin(String username, String timestamp) throws Exception {
    Data data = Data.failure("操作失败");

    //重置序列化
    redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

    if (StringUtils.isBlank(username) || StringUtils.isBlank(timestamp)) {
        return data;
    }
    // 获取用户
    if (redisTemplate.opsForValue().get("wechat_" + timestamp) == null) {
        data.setMessage("获取用户失败");
        return data;
    }
   //  其他登录逻辑
  。。。。。。。

}

后台服务的websocket 实现

package com.lotres.mp.controller;

import net.sf.json.JSONObject;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Hashtable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@Component
@ServerEndpoint("/websocket/wechat/{timestamp}")
public class WebSocketController {

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    //private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();
    private static ConcurrentMap<String, WebSocketController> webSocketMap = new ConcurrentHashMap<String, WebSocketController>();
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    /**
     * 连接建立成功调用的方法
     *
     * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam("timestamp") String timestamp, Session session) {
        this.session = session;
        webSocketMap.put(timestamp, this);
        //在线数加1
        System.out.println("唯一key为:" + timestamp);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("timestamp") String timestamp) {
        webSocketMap.remove(timestamp);//从map中删除
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("来自客户端的消息:" + message);

        JSONObject jsonobject = JSONObject.fromObject(message);
        Hashtable params = (Hashtable) JSONObject.toBean(jsonobject, Hashtable.class);

        //群发消息
        WebSocketController webSocketController = webSocketMap.get(params.get("equipmentType"));
        try {
            webSocketController.sendMessage((String) params.get("nickname"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }

    /**
     * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }
}

公众号后台配置

后台服务程序参考

https://github.com/binarywang/weixin-java-mp-demo-springboot

!!!好了,微信扫码关注公众号登录基本就实现了。 本系统实现直接使用了websocket 机制, 没有使用js 轮询检测用户是否已经扫码关注的方法。 轮询方法实现就是当系统生成带参数二维码后,获取到了后台生成的timestamp参数,前端js就开始轮询(例如:每三秒请求一次)。

致谢: 前面参考的几篇文章作者。

顺便提一下,我们系统使用了开源 https://gitee.com/mtons/mblog.  在此表示感谢!

最后,希望本文对你有帮助,欢迎体验一下

https://love.daquexing.com/login

如果你还有其他疑问,可以加我微信咨询

预告:《微信扫描自定义二维码关注公众号并登录(二)移动端/微信端的设计与实现

 


注意:本文归作者所有,未经作者允许,不得转载

全部评论: 0

      请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
    我有话说: