Java通过webSocket实现微信扫码后通过微信小程序授权登录Web端

 

1.web端向服务器发送请求获取二维码,服务器同时返回webSocket id

参考:JAVA获取小程码_qq_43019699的博客-CSDN博客

注意:本次返回返回的二维码,同时将webSocke ID一同给前端。

    /**
     * 获取二维码
     * @return 二维码字符串
     */
    public Map getQRCode() {
        Map map = new HashMap();
        String webSocketId = String.valueOf(System.currentTimeMillis());
        String accessToken = getCustomerAccessToken();
        String postUrl ="https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+accessToken;
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("scene", webSocketId);     //将webSocketId 作为参数传给扫码跳转后页面
        jsonObject.put("page", "pages/weChat_login/weChat_login"); //扫码后跳转页面
        jsonObject.put("check_path", false); //是否检查跳转页面存不存在
        jsonObject.put("env_version", "develop"); //版本
        byte[] string = null;
        try {
            string = sendPostJsonImge(postUrl, jsonObject.toJSONString());
        } catch (IOException e) {
            logger.info(String.valueOf("获取二维码时出现异常"));
        }
        String base64Str = Base64.getEncoder().encodeToString(string);
        map.put("base64Str",base64Str);
        map.put("webSocketId",webSocketId);
        return map;
    }

2.前端接收到WebSocket ID时,开启WebSocket

 web端代码

// 获取二维码
    getSignQRCode() {
      ApiService.get(
        guaranteeLoginApi.getSignQRCode.url,
        {},
        ApiService.createBasicHeaders()
      ).then(response => {
        console.log(response);
        if (response.code === ResponseType.SUCCESS.code) {
          // const buffer = Buffer.from(response.data.base64Str, "base64");
          this.dataBuffer = "data:image/png;base64," + response.data.base64Str;
          this.webSocketId = response.data.webSocketId;
          this.initWebSocket();
        } else {
          this.$message.error(response.msg);
        }
      });
    },
    initWebSocket() {
      const wsurl = process.env.VUE_APP_WEBSOCKET_URL + this.webSocketId;
      this.websock = new WebSocket(wsurl);
      console.log(this.websock);
      this.websock.onopen = this.websocketonopen;
      this.websock.onerror = this.websocketonerror;
      this.websock.onmessage = this.websocketonmessage;
      this.websock.onclose = this.websocketclose;
    },
    websocketonopen() {
      console.log("推送服务连接成功");
      // this.websocketsend('连接进行中', 'INITIAL');
    },
    websocketonerror() {
      // 错误
      // info(this, '推送服务连接失败');
      console.log("推送服务连接失败");
    },
    websocketonmessage(evt) {
      // 数据接收
      console.log(evt);
      const msg = eval("(" + evt.data + ")");
      console.log(msg);
      const params = {
        username: msg.unionid,
        password: msg.unionid,
        loginType: "web",
        authType: "4"
      };
      this.Login(params);
    },

3.手机端扫码跳转页面,并且获取到WebSocket ID

微信小程序页面代码

<template>
	<!-- <view class="content" :style="{backgroundImage: `url(${baseImgUrl}/static/img/login_b.png)`}"> -->
		<!-- 标头 -->
		<view class="content_header">
			<view class="avatar">
				<image style="width: 84rpx; height: 84rpx;" src="../../static/img/u192.png"></image>
			</view>
			<text style="font-size: 45rpx; color: #FFFFFF;margin-left: 20rpx;">xx服务平台</text>
		</view>
		<view class="wx_w">
			<view class="wx_w_v">
				<text class="szc-fw-5 szc-fs-30">申请获取以下权限</text>
			</view>
			<view class="wx_w_v">
				<text class="szc-fc-999 szc-fs-28">获取你的公开信息(昵称,头像等)</text>
			</view>
		</view>
		<!-- 微信登陆 -->
		<view class="wx_all">
			<button class="wx_v" @click.stop="$noMultipleClicks(wxLogin)" plain>
				<text class="szc-fs-30 szc-fc-white szc-fw-5">授权登陆</text>
			</button>
		</view>
		<!-- 弹出确认 -->
		<uni-popup ref="popup" type="success" :animation="false" :isMaskClick="false">
			<view class="popup_c">
				<view class="popup_c_t">
					<view class="t-icon-a-16x16_wancheng" style="width: 160rpx;height: 160rpx;"></view>
					<text class="szc-fs-36" style="margin-top: 20px;">授权成功</text>
				</view>
				<view class="popup_btn">
					<navigator open-type="exit" target="miniProgram" style="width: 550rpx;" class="popup_btn2 flex-center">确认</navigator>
				</view>
			</view>
		</uni-popup>
	</view>
</template>

<script>
	import { setAccessToken } from '../../service/auth.js'
	import ValidateUtil from '@/public/js/ValidateUtil.js'
	export default {
		data() {
			return {
				noClick: true,
				baseImgUrl: this.BASE_IMG_URL,
				code: '',
				scene: ''
			};
		},
		onLoad (query) {
			// scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene,webS
			this.scene = decodeURIComponent(query.scene);
			this.wxAuthorize();
		},
		methods: {
			// 获取用户信息
			wxAuthorize() {
				var _this = this
				uni.login({
					provider: 'weixin',
					onlyAuthorize: true,
					success(res) {
						if (res.code) {
							_this.code = res.code;
						}
					}
				})
			},
			// 微信登陆
			wxLogin() {
				uni.showLoading({
					title: "授权登录中",
					mask: true
				});
				this.WechatLogin();
			},
			WechatLogin() {
				var _this = this
				uni.getUserProfile({
					desc: '微信登录获取用户数据',
					success: async (obj) => {
						uni.setStorageSync('userInfo', JSON.stringify(obj.userInfo))
						// 调用 action ,请求登录接口
						const url = '/weChatApplet/getWxUserInfo';
						const query = {
							requestCode: _this.code,
							webSocketId: _this.scene
						}
						_this.$ApiService.get(url, query, {}).then(res => {
							if (res.data.code == '0000') {
								uni.hideLoading();
							    this.open();
							} else {
								uni.hideLoading();
								uni.showToast({
									icon: 'none',
									title: res.data.msg
								});
							}
						}).catch(err => {
							uni.hideLoading();
							uni.showToast({
								icon: 'none',
								title: err
							});
						});
					},
					fail: (err) => {
						uni.showToast({
							title: '登录已取消',
							icon: 'error',
							mask: true,
						});
					},
					complete: () => {}
				});
			},
			open() {
				this.$refs.popup.open('success');
			}
		}
	}
</script>

<style lang="scss" scoped>
	.content {
		background-size: 100% 450rpx;
		background-repeat: no-repeat;
	}

	.avatar {
		background-color: #FFFFFF;
		border-radius: 10rpx;
		width: 96rpx;
		height: 96rpx;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	.content_header {
		width: 100%;
		height: 38vh;
		display: flex;
		justify-content: center;
		align-items: center;
	}
	.wx_w {
		width: 100%;
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
	}
	.wx_w_v {
		width: 85%;
		height: 5vh;
	}

	.wx_all {
		width: 100%;
		height: 12vh;
		display: flex;
		justify-content: center;
		align-items: center;
	}
	.wx_v {
		display: flex;
		align-items: center;
		justify-content: center;
		height: 80rpx;
		width: 85%;
		background-color: #339800;
		border-width: 0;
		border-radius: 50rpx;
	}
</style>

 4.点击【授权登录】之后调用后台,获取用户信息,再通过webSocket将用户信息发送到web端

 /**
     * 微信扫码获取用户信息
     * @param code
     * @param id
     * @return
     */
    @Override
    public ResponseEntity getWxUserInfo(String code, String id) {
        WxAuthorizeResponse wxWebAuthorizeResponse = null;
        BeanCopyUtils beanCopyUtils = SpringUtil.getBean(BeanCopyUtils.class);
        try {
            //通过 code,appid,appSecret获取 openid 和 unionid
            wxWebAuthorizeResponse = callApiForDecrypt(code,appid,appSecret);
        }catch (Exception e){
            log.error("微信登录凭证校验异常!appId:{},code:{}", clientAppid, code, e);
            SysExceptionUtil.insert(e);
            throw new SystemServiceException(SystemStatus.CHECK_ERROR_EXCEPTION).reason("存在问题");
        }
        // 根据openid获取数据库中的用户信息
        CustomerUsers customerUsers = customerUsersMapper.findByApOpenId(wxWebAuthorizeResponse.getOpenid());
        if(customerUsers == null){
            throw new SystemServiceException(SystemStatusCode.PARAM_ERROR_EXCEPTION).reason("您尚未绑定微信账号。");
        }
        CustomerUsersRespVo customerUsersRespVo = beanCopyUtils.convertTo(customerUsers, CustomerUsersRespVo.class);
        //向webSocket发送用户信息
        try {
            WebSocketServer webSocketServer = SpringUtil.getBean("webSocketServer", WebSocketServer.class);
            webSocketServer.sendMessage(id, customerUsersRespVo);
        } catch (Exception e) {
            log.error("WebSocket消息提醒异常,消息内容为:{}", customerUsersRespVo, e);
            return ResponseEntity.Failure(BaseStatus.SERVICE_FAILURE, "未拿到webSocket中的uuid");
        }
        return ResponseEntity.Success(null).OK();
    }

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.concurrent.ConcurrentHashMap;

/**
 * @description: WebSocketServer
 * @author: 
 * @create: 
 **/

@Slf4j
//@ConditionalOnClass(value = WebSocketConfig.class)
@ServerEndpoint("/ws/{id}")
@Component
public class WebSocketServer {

    /**
     * 客户端ID
     */
    private String id = "";

    /**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 用来存储当前在线的客户端(此map线程安全)
     */
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();


    /**
     * 连接建立成功后调用
     */
    @OnOpen
    public void onOpen(@PathParam(value = "id") String id, Session session) {
        this.session = session;
        // 接收到发送消息的客户端编号
        this.id = id;
        // 加入map中
        webSocketMap.put(id, this);
        log.info("用户连接:{}", this.id);

    }

    /**
     * 连接关闭时调用
     */
    @OnClose
    public void onClose() {
        // 从map中删除
        webSocketMap.remove(this);
        log.info("用户退出:{}", this.id);
    }

    /**
     * 收到客户端消息后调用
     *
     * @param message 客户端发送过来的消息<br/>
     *                消息格式:内容 - 表示群发,内容|X - 表示发给id为X的客户端
     * @param session 用户信息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("用户消息:{},报文:{}", this.id, message);
        String[] messages = message.split("[|]");
        try {
            if (messages.length > 1) {
                sendToUser(messages[0], messages[1]);
            } else {
                sendToAll(messages[0]);
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 发生错误时回调
     *
     * @param session 用户信息
     * @param error   错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:{},原因:{}", this.id, error.getMessage());
        error.printStackTrace();
    }

    /**
     * 推送信息给指定ID客户端
     *
     * @param message 客户端发来的消息
     * @param id      客户端ID
     */
    public void sendToUser(String message, String id) throws IOException {
        if (StringUtils.isBlank(message)) {
            log.error("发送报文为空!id:{}", id);
            return;
        }
        log.info("发送消息到:{},报文:{}", id, message);
        if (StringUtils.isNotBlank(id) && webSocketMap.containsKey(id)) {
            webSocketMap.get(id).sendMessage(message);
        } else {
            log.error("用户{}不在线!", id);
        }
    }

    /**
     * 群送发送信息给所有人
     *
     * @param message 要发送的消息
     */
    public void sendToAll(String message) throws IOException {
        if (StringUtils.isBlank(message)) {
            log.error("群发报文为空!");
            return;
        }
        log.info("群发消息到所有客户端,消息:{}", message);
        for (String key : webSocketMap.keySet()) {
            webSocketMap.get(key).sendMessage(message);
        }
    }

    /**
     * 发送消息
     *
     * @param message 要发送的消息
     */
    private void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * 发送消息 消息内容为json格式
     *
     * @param id
     * @param msgObj
     */
    public void sendMessage(String id, Object msgObj) {
        String message = null;
        if (msgObj instanceof String) {
            message = String.valueOf(msgObj);
        } else {
            message = JSON.toJSONString(msgObj);
        }
        try {
            this.sendToUser(message, id);
        } catch (IOException e) {
            log.error("websocket发送消息失败!id:{},message:{}", id, message, e);
        }
    }


}

5.最后web前端根据返回的用户信息登录。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
客户: 1. 在小程序页面中引入socket.io-client库,用于与服务建立websocket连接。 ```javascript import io from '../../utils/socket.io-client'; const socket = io('wss://yourserver.com'); // 建立websocket连接 ``` 2. 在页面加载时,监听socket连接事件,连接成功后发送加入房间的请求。 ```javascript onLoad: function() { socket.on('connect', () => { console.log('连接成功'); socket.emit('join room', { roomId: 'yourRoomId' }); // 发送加入房间请求 }); }, ``` 3. 监听服务发送的消息,将消息展示在聊天界面中。 ```javascript socket.on('message', (data) => { console.log('收到消息', data); // 将消息展示在聊天界面中 }); ``` 4. 发送消息,将消息通过socket发送给服务。 ```javascript sendMessage: function() { const message = this.data.inputValue; socket.emit('message', { message }); this.setData({ inputValue: '' }); }, ``` 服务: 1. 在Node.js中引入socket.io库,创建websocket服务器。 ```javascript const server = require('http').createServer(); const io = require('socket.io')(server, { cors: { origin: '*', }, }); io.on('connection', (socket) => { console.log('有客户连接', socket.id); // 监听客户加入房间请求 socket.on('join room', ({ roomId }) => { console.log(`客户 ${socket.id} 加入房间 ${roomId}`); socket.join(roomId); }); // 监听客户发送的消息 socket.on('message', ({ message }) => { console.log(`客户 ${socket.id} 发送消息 ${message}`); io.to('yourRoomId').emit('message', { message }); // 将消息发送给所有房间成员 }); }); server.listen(3000, () => { console.log('websocket服务器启动成功'); }); ``` 2. 监听客户连接事件,建立连接后处理加入房间请求。 3. 监听客户发送的消息,将消息发送给房间中的所有成员。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值