• Hbuilder本地调试微信H5项目(三)--调用微信接口获取用户信息


    摘要

    通过微信网页授权接口,获取用户信息(头像,昵称等)

    前置准备

    1. 安装nginx,用于后续同一域名的反向代理,代理到页面和后端接口 下载地址

    实现逻辑

    1. 通过nginx,将页面和后端接口,代理到同一域名下

    2. 前端部分,通过授权,获取通过微信重定向后带过来的用户code

    3. 通过code,调用后端接口,请求获得用户信息

    4. 展示用户信息

    具体实现

    修改web项目的接口

    之前我吧web项目的端口设置为了80,好让natapp,通过域名直接访问到web项目,现在将web项目的端口改成8081,然后用nginx反向代理访问到本地web项目

    修改web项目的基础路径

    基础路径有点类似后端的项目名,原来是http://localhost:8081/就能访问的页面,现在要通过http://localhost:8081/demo/来访问

    下载并配置nginx

    [下载地址](nginx: download)

    我本地是windows环境,就下了windoows版本了

    修改conf目录中的配置,添加一个自己的目录conf,里面放我们自己的nginx配置,在conf/nginx.conf中加入我们自己配置的目录地址

    意思就是,conf目录下所有后缀名为conf的文件纳入进来

    include      conf/*.conf;
    
    • 1

    我们自己的nginx配置

    这样,就可以通过域名http://xbjh.natapp1.cc/demo/访问到本地项目了,这个地址后面会用在微信开发者工具中

    server{
        listen 80;
        server_name xbjh.natapp1.cc;
        location / {
            index index.htm index.html index.php sign_in;
            root /home/app/prod/xbjh;
        }
    
        # web项目的代理
        location /demo/ {
            proxy_pass http://localhost:8081; # 设置代理目标
            proxy_set_header Host $host; # 设置代理请求头
            proxy_set_header X-Real-IP $remote_addr;
        }
    
        # 后端接口项目的代理
        location ~ /demoapi/(.*) {
            rewrite ^/demoapi/(.*) /wxtoken/$1 break; # 重写 URL
            proxy_pass http://localhost:10200; # 设置代理目标
            proxy_set_header Host $host; # 设置代理请求头
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            # 如果需要传递查询参数,可以添加以下一行:
            # proxy_set $args $args;
        }
    
        access_log /home/app/log/nginx/xbjh.log;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    项目改造

    调整首页信息和增加一个授权页面,授权页面就一个按钮,用于调用授权获取code

    网页授权 | 微信开放文档

    网页授权-获取用户信息 | 微信开放文档

    这块是服务端调用的接口

    idnex.vue

    <template>
        <view class="content">
            <template>
                <view class="logo-container">
                    <u-avatar class="avatar" :src="src" mode="square" :size ="100">u-avatar>
                    <p>昵称:{{nickname}}p>
                    br>
                view>
            template>
            <template>
                <view class="form-content">
                    <u-button type="primary" v-on:click="toauth()">授权页面u-button>
                    <template v-if="form.wx_code !== ''">
                        <u-form :model="form" ref="uForm" label-position="top" label-width="500">
                            <u-form-item label="微信Code"><u-input v-model="form.wx_code" />u-form-item>                        
                            <u-button type="primary" v-on:click="getUserInfo()">获取用户信息u-button>
                        u-form>
                    template>
                view>
            template>
        view>
    template>
    
    <script>
        export default {
            data() {
                return {
                    title: 'Hello',
                    form: {
                        wx_code: ''
                    },
                    src: 'https://gitee.com/flygoa/markdown-img/raw/master/markdown/729abc9a-3844-4498-b041-71e7f3e1a52d.jpeg',
                    nickname: ''
                }
            },
            onLoad(option) {
               //第二种
               this.paraString = window.location.href   //还可以  window.location.search.substring()
               if(this.getQueryVariable('code')){
                   this.form.wx_code = this.getQueryVariable('code') //code是url后面带的
               }
               console.log("wx_code",this.form.wx_code)
            },
            methods: {
                toauth:function(){
                    uni.navigateTo({
                        url:'/pages/auth/auth'
                    })
                },
                // 获取地址栏中的参数
                getQueryVariable(variable) {
                    var query = this.paraString;
                    var rooms = query.split('?');
                    for (var i = 0; i < rooms.length; i++) {
                        var pair = rooms[i].split('=');
                        if (pair[0] == variable) {
                            return (pair[1].split('&'))[0]
                        }
                    }
                    //或者拼接&后面的值
                    var vars = query.split('&')
                    for (var i = 0; i < vars.length; i++) {
                        var pair = vars[i].split('=')
                        if (pair[0] == variable) {
                            return pair[1]
                        }
                    }
                },
                // 获取用户信息
                getUserInfo(){
                    // 发送 GET 请求
                    uni.request({
                      url: 'http://xbjh.natapp1.cc/demoapi/api/weChat/getWxInfoByCode',// 请求的 URL
                      data: {
                          code: this.form.wx_code
                      },
                      method: 'GET', // 请求方法
                      success: (res) => {
                        // 请求成功时的回调函数
                        if(res.data.code == 10001){
                            console.log('请求成功', res.data);
                            if(res.data.data){
                                this.src = res.data.data.headimgurl
                                this.nickname = res.data.data.nickname
                            }
                        }
                      },
                      fail: (err) => {
                        console.error('请求失败', err);
                      }
                    });
                }
            }
        }
    script>
    
    <style>
        .content {
            margin: 0 50rpx;
        }
    
        .logo-container {
            text-align: center; /* 居中对齐 */
        }
    
        .logo {
            height: 200rpx;
            width: 200rpx;
            margin-top: 200rpx;
            margin-left: auto;
            margin-right: auto;
            margin-bottom: 50rpx;
        }
    
        .avatar {
            margin-top: 20rpx;
            margin-bottom: 20rpx;
            margin-left: auto;
            margin-right: auto;
        }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121

    auth.vue

    <template>
        <view class="content">
            <u-button class="auth" type="primary" v-on:click="auth()">点击授权u-button>
        view>
    template>
    
    <script>
        export default {
            data() {
                return {
                }
            },
            onLoad() {
            },
            methods: {
                auth:function(){
                    location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=自己的appidd&redirect_uri=http%3A%2F%2Fxbjh.natapp1.cc%2Fdemo%2F%23%2F&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect"
                }
            }
        }
    script>
    
    <style>
        .content {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            margin: 0 60rpx;
        }
    
        .auth {
            margin-top: 200rpx;
            margin-left: auto;
            margin-right: auto;
            margin-bottom: 50rpx;
        }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在微信公众平台中,配置网页授权域名

    如果不配置的话,会提示“redirect uri 参数错误”

    启动nginx,在微信开发者工具中访问域名网址

    这样就能拿到重定向回来的code

    后端代码

    获取用户信息,这步需要调用服务端接口

    因为appid和secret比较敏感,微信建议在服务端进行请求

    服务端是springboot实现,就加了一个controller

    有可能会提示IP未加入白名单,在微信公众平台将本地IP加入即可

    核心处理类:WeChatController.java

    package com.lc.wxtoken.business.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import com.lc.wxtoken.business.entity.R;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.http.converter.StringHttpMessageConverter;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.client.RestTemplate;
    
    import java.nio.charset.Charset;
    import java.util.Collections;
    
    /**
     * 微信access token 控制类
     */
    @Controller
    @RequestMapping("/api/weChat")
    public class WeChatController {
    
        @Value("${weixin.appid}")
        private String appId;
    
        @Value("${weixin.secret}")
        private String secret;
    
    
        /**
         * 网页授权
         * 通过code换取网页授权access_token(该AccessToken与基础AccessToken不一样)
         */
        public final static String WEB_GET_ACCESS_TOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    
        /**
         * 网页授权
         * 获取用户详细信息(scope为 snsapi_userinfo)
         */
        public final static String WEB_GET_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    
        /**
         * 网页授权
         * 通过code获取微信个人信息
         */
        @RequestMapping(value = "/getWxInfoByCode",method = {RequestMethod.POST,RequestMethod.GET})
        @ResponseBody
        public R getWxInfoByCode(@RequestParam(value = "code") String code){
            JSONObject resultObj  = null;
            String url = WEB_GET_ACCESS_TOKEN.replace("APPID", appId).replace("SECRET", secret).replace("CODE", code);
            JSONObject accessTokenObj = getJsonData(url);
    
            if(accessTokenObj != null && accessTokenObj.get("access_token") != null ){
                String accessToken = accessTokenObj.getString("access_token");
                String openId =  accessTokenObj.getString("openid");
                if(accessToken != null){
                    String webGetUserInfoUrl = WEB_GET_USER_INFO.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
                    resultObj = getJsonData(webGetUserInfoUrl);
                }
            }
            return R.successData(resultObj);
        }
    
        /**
         * 发起get请求
         * @param url
         * @return
         */
        public JSONObject getJsonData(String url) {
            RestTemplate restTemplate = new RestTemplate();
            // 设置 HTTP 头部信息
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Accept-Charset", "UTF-8");
            // 创建 StringHttpMessageConverter 并设置编码方式为 UTF-8
            StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
            stringHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
            restTemplate.getMessageConverters().add(0, stringHttpMessageConverter);
            // 发送 GET 请求,并将响应映射为 JSONObject
            ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
            // 获取响应中的 JSONObject
            JSONObject jsonObject = JSONObject.parseObject(responseEntity.getBody());
            return jsonObject;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    R.java 响应类

    package com.lc.wxtoken.business.entity;
    
    import com.alibaba.fastjson.JSON;
    
    /**
     * 返回对象
     *
     * @author ASUS
     */
    public class R {
        /**
         * 成功的编码
         */
        public static final int CODE_SUCCESS = 10001;
        /**
         * 失败的编码
         */
        public static int CODE_FAIL = 10002;
        /**
         * 微信未授权的错误编码
         */
        public static int WECHAT_FAIL = 10004;
        /**
         * 执行成功的消息
         */
        public static String MSG_SUCCESS = "执行成功!";
        /**
         * 执行失败的消息
         */
        public static String MSG_FAIL = "执行失败!";
    
        /**
         * 编码
         */
        public int code;
    
        /**
         * 数据
         */
        public Object data;
    
        /**
         * 消息
         */
        public String msg;
    
    
    
        public R() {
    
        }
    
        public R(int code, String msg, Object data) {
            this.code = code;
            this.msg = msg;
            this.data = data;
        }
    
    
        /**
         * 默认成功返回
         *
         * @return
         */
        public static R success() {
            return new R(CODE_SUCCESS, MSG_SUCCESS, null);
        }
    
        /**
         * 微信未授权返回
         * @return
         */
        public static R wechatNo(Object data) {return new R(WECHAT_FAIL,"未授权",data);}
    
        /**
         * 默认失败返回
         *
         * @return
         */
        public static R fail() {
            return new R(CODE_FAIL, MSG_FAIL, null);
        }
    
        /**
         * 成功返回,附带数据
         *
         * @return
         */
        public static R successData(Object data) {
            return new R(CODE_SUCCESS, MSG_SUCCESS, data);
        }
    
    
        /**
         * 失败返回,附带消息
         *
         * @return
         */
        public static R failMsg(String msg) {
            return new R(CODE_FAIL, msg, null);
        }
    
        /**
         * 成功返回
         *
         * @param data
         * @return
         */
        public static String successResultObj(Object data) {
            return JSON.toJSONString(new R(R.CODE_SUCCESS, R.MSG_SUCCESS, data));
        }
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public Object getData() {
            return data;
        }
    
        public void setData(Object data) {
            this.data = data;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136

    代码地址

    Hbuilder上微信H5开发示例代码:

    其中demo3部分

  • 相关阅读:
    生产经验篇(2)——真实环境的MySQL机器配置规划
    web前端-html-css-HACK(CSS Hack 实际上指的就是一个特殊的代码,这段代码只在某些特殊的浏览器中可以识别)
    LeetCode2562
    数据结构与算法-Btree&B+Tree
    【在Spring MVC框架和Spring Boot项目中,控制器的响应结果】
    【Java 进阶篇】JavaScript二元运算符详解
    安卓案例:利用URLConnection下载图片
    分享几种 Java8 中通过 Stream 对列表进行去重的方法
    操作符详解
    020线上线下融合商业模式 新零售系统定制开发
  • 原文地址:https://blog.csdn.net/flygoa/article/details/133632691