一.大致实现思路

        1.给微信图标绑定一个触发事件,实现微信登录,然后再调用小程序的API。

    

        2.调用wx.getUserProfile()方法,这个方法是微信自带的,关于是否微信获取用户信息的权限。

        3.用户同意后,在wx.getUserProfile()的回调中再次调用wx.login()这个API。会返回一个code 这个code每次调用都会刷新一次,(注意:不能携带code进行两次请求,否则会报错,40029)

        4. 然后前端发送请求携带code到后端,你也可以携带用户信息对象,在下面代码会演示。

        5.后端开始根据这个code和你的小程序的AppId和Appsecret调用微信的服务器来获得openId(这是每个用户登录的唯一id,后期可以根据openid查询登录信息,而不会重复)

        6.获取到openid后就可以进行自定义业务逻辑了。

二.下面开始演示代码

        前端:uniapp

        2.1 首先给微信图标绑定事件

<image @click="weixinLo()" class="icon" src="../../static/微信.png" ></image>

        2.2 js代码:主要思路

                1.主要逻辑是先判断是否含有token,这个是验证登录的标识         

                2.判断是否用户收授权登录       

                3.用户同意后调用wx.login()方法,返回code和登录对象信息返回给后端接口。

weixinLo(){
				let that = this
				let token = uni.getStorageSync('token')
				wx.showLoading({
					title: '加载中',
				})
				console.log(token)
				if(token){
					//如果已经有token,说明用户已经登录,跳转到指定页面
					wx.reLaunch({
						url: "../index/index"
					})
				}else{
					// 未登录
					wx.getUserProfile({
						desc: '用于完善用户资料',
						success(res) {
							that.userInfo = res.userInfo
							if (res.errMsg == "getUserProfile:ok") {
								let code = null
								wx.login({
									success(e) {
										code = e.code
										let params = {};
										params.code = code; //用户code  注:用户的code每次登录都是随机的,所以不需要进行存储
										params.avatar = res.userInfo.avatarUrl; //用户头像
										params.nickname = res.userInfo.nickName; //用户微信名
										params.sex = res.userInfo.gender; //用户性别 0为未知,1为男,2为女
										wx.request({
											url: 'http://localhost:8010/educmsl/api/ucenterstu/wx/login',
											method: 'POST',
											data: params,
											success(res) {
												if(res.data.success){
													 //存储用户信息
													uni.setStorageSync('token', res.data.data.token);
													uni.reLaunch({
														url: '../my/my'
													})
												}else{
													console.log(res.data.message)
												}
											}
										})
									}
								})
							}
						}
					})
				}
			},

 后端:  java

         2.3. 写接口先得预备工作,先获得小程序的appid与密钥

                主要思路:  创建一个获取小程序appid与密钥的类

                实现步骤: 通过springboot的组件@Component注解,然后类实现 InitializingBean 这个接口(是用来初始化bean对象的作用)。

                注意:这里使用了@Component注解,最好在启动类上加上             @ComponentScan(basePackages={"com.laoyang"})这个注解,用来扫描我们自己的组件。

package com.laoyang.educms.utils;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author:Kevin
 * @create: 2022-11-03 15:00
 * @Description: 小程序密钥与id
 */
@Component
public class Wxmini implements InitializingBean {

    @Value("${wxMini.appId}")
    private String appid;

    @Value("${wxMini.secret}")
    private String secret;

    public static String APPID;

    public static String SECRET;

    @Override
    public void afterPropertiesSet() throws Exception {
        APPID = appid;
        SECRET = secret;

    }
}

        2.3.1:然后还要在配置文件添加appid与密钥

                      

uniapp ios微信登陆 uniapp微信登录demo_微信

        2.4:主要接口开发

主要思路:

                1.  后台接收到前端的code,然后携带appid和密钥发送请求到微信的服务器。

                2.  然后响应获得openid,实现自定义逻辑,说下我的逻辑。

                3.  先new用户对象,将前端授权获得的信息封装到此对象中,然后根据opendi查询是否有这个对象,有就执行更新信息操作,没有就添加信息。然后生成token返回给前端。

https://api.weixin.qq.com/sns/jscode2session?appid=" + Wxmini.APPID + "&secret=" + Wxmini.SECRET + "&js_code=" + code + "&grant_type=authorization_code";
package com.laoyang.educms.controller;

import com.alibaba.fastjson.JSONObject;
import com.laoyang.CommonUtils.JwtUtils;
import com.laoyang.CommonUtils.R;
import com.laoyang.educms.entity.UcenterMember;
import com.laoyang.educms.service.UcenterMemberService;
import com.laoyang.educms.utils.WeChatUtil;
import com.laoyang.educms.utils.Wxmini;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * @author:Kevin
 * @create: 2022-11-03 12:26
 * @Description: 微信小程序登录与退出
 */
@RestController //注意这里没有配置 @RestController
@RequestMapping("/educmsl/api/ucenterstu/wx")
public class WxApiStuController {

    @Autowired
    private UcenterMemberService memberService;


    @PostMapping("/login")
    public R wxlogin(@RequestBody UcenterMember user){

        String code = user.getCode();
        if (code == "" || "".equals(code)){
            return R.error("code不能为空!");
        }else {
            //微信接口服务,通过调用微信接口服务中jscode2session接口获取到openid和session_key
                String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + Wxmini.APPID + "&secret=" + Wxmini.SECRET + "&js_code=" + code + "&grant_type=authorization_code";
            String str = WeChatUtil.httpRequest(url, "GET", null); //调用工具类解密
            JSONObject jsonObject= JSONObject.parseObject(str);
            String openid = (String) jsonObject.get("openid");
            if(openid != null && !"".equals(openid)){
                //登录成功
                UcenterMember member = new UcenterMember();
                member.setNickname(user.getNickname());
                member.setOpenid(openid);
                member.setAvatar(user.getAvatar());
                member.setGmtCreate(new Date());
                member.setGmtModified(new Date());

                UcenterMember mymember = memberService.getByOPenId(openid);
                if (mymember == null){
                    //就是第一次登录,向数据库插入信息
                    //向数据库中插入一条记录
                    memberService.save(member);
                }else {
                    //更新数据
                    member.setId(mymember.getId());
                    memberService.updateById(member);

                }

                //使用jwt生成token,
                String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());

                return R.ok().data("token",jwtToken);
            }


        }




        return R.error("登录失败");
    }
}

        小结:

                首先说下我开发中遇到的问题,希望大家避坑,

        1.在写Controller时没有添加@RestController,返回前端json格式的注解,所以刚开始时后台响应成功了,前端却报404.

        2.code因为是一次性的,所以不能在请求里的请求携带code,否则微信服务器会响应40029的报错代码信息。因此就在wx.login()的回调函数中请求后端接口并携带code就ok了。