当前位置:   article > 正文

微信小程序授权登录,JAVA后台获取用户手机号_java 后台获取微信小程序手机号

java 后台获取微信小程序手机号

步骤:

  1. 前端通过微信小程序官方定义的方法获取code
  2. 前端将获取的code传到后台服务器
  3. 后台调用 https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
    appId, appSecret 获取token
  4. 最后调用 https://api.weixin.qq.com/wxa/business/getuserphonenumber"
    + “?access_token=” + accessToken 获取到手机号

代码:

前端部分

1、html

在button标签中定义 open-type=“getPhoneNumber” @getphonenumber=“getPhoneNumber” (小程序官方自带的方法)

<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">一键登录</button>
  • 1

2、JS

getPhoneNumber(res) {
			uni.showLoading({
				title: '加载中...'
			});
			const that = this;
			this.getNumber(res.detail.code)
		},
// 获取手机号
async getNumber(code){
			const data = await this.$api.user.getPhoneNumber(code)
			if(data.statusCode==200){
				this.phone_number = data.data.phone_info.phoneNumber;
			}
		},
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

JAVA后台

在 pom文件中添加依赖

<!--JSON-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.10</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.1</version>
    <scope>provided</scope>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

JsonUtil工具类

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;

@Slf4j
public class JsonUtil {

    /**
     * 定义映射对象
     */
    public static ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 日期格式化
     */
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    static {
        //对象的所有字段全部列入
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //取消默认转换timestamps形式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        //忽略空Bean转json的错误
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
        objectMapper.setDateFormat(new SimpleDateFormat(DATE_FORMAT));
        //忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    }

    /**
     * string转JsonNode
     *
     * @param jsonString
     * @return com.fasterxml.jackson.databind.JsonNode
     */
    public static JsonNode stringToJsonNode(String jsonString) throws JsonProcessingException {

        return objectMapper.readTree(jsonString);

    }

    /**
     * 对象转json字符串
     *
     * @param obj
     * @param <T>
     */
    public static <T> String objToString(T obj) {

        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.warn("Parse Object to String error : {}", e.getMessage());
            return null;
        }
    }

    /**
     * 对象转格式化的字符串字符串
     *
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> String objToPrettyString(T obj) {
        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.warn("Parse Object to String error : {}", e.getMessage());
            return null;
        }
    }

    /**
     * json字符串转对象
     *
     * @param jsonString
     * @param cls
     * @param <T>
     */
    public static <T> T stringToObj(String jsonString, Class<T> cls) {
        if (StringUtils.isEmpty(jsonString) || cls == null) {
            return null;
        }
        try {
            return cls.equals(String.class) ? (T) jsonString : objectMapper.readValue(jsonString, cls);
        } catch (JsonProcessingException e) {
            log.warn("Parse String to Object error : {}", e.getMessage());
            return null;
        }
    }

    /**
     * json字符串转对象(复杂泛型类型)
     *
     * @param jsonString
     * @param typeReference
     * @param <T>
     * @return
     */
    public static <T> T stringToObj(String jsonString, TypeReference<T> typeReference) {
        if (StringUtils.isEmpty(jsonString) || typeReference == null) {
            return null;
        }
        try {
            return typeReference.getType().equals(String.class) ? (T) jsonString : objectMapper.readValue(jsonString, typeReference);
        } catch (JsonProcessingException e) {
            log.warn("Parse String to Object error : {}", e.getMessage());
            return null;
        }
    }
}
  • 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

HttpClientSslUtils工具类

import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.MDC;
import org.springframework.http.HttpStatus;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * HTTP/HTTPS 请求封装: GET / POST
 * 默认失败重试3次
 * @author admin
 */
@Slf4j
public class HttpClientSslUtils {

    /**
     * 默认的字符编码格式
     */
    private static final String DEFAULT_CHAR_SET = "UTF-8";
    /**
     * 默认连接超时时间 (毫秒)
     */
    private static final Integer DEFAULT_CONNECTION_TIME_OUT = 2000;
    /**
     * 默认socket超时时间 (毫秒)
     */
    private static final Integer DEFAULT_SOCKET_TIME_OUT = 3000;

    /** socketTimeOut上限 */
    private static final Integer SOCKET_TIME_OUT_UPPER_LIMIT = 10000;

    /** socketTimeOut下限 */
    private static final Integer SOCKET_TIME_OUT_LOWER_LIMIT = 1000;

    private static CloseableHttpClient getHttpClient() {
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIME_OUT)
                .setConnectTimeout(DEFAULT_CONNECTION_TIME_OUT).build();
        return HttpClients.custom().setDefaultRequestConfig(requestConfig)
                .setRetryHandler(new DefaultHttpRequestRetryHandler()).build();
    }

    private static CloseableHttpClient getHttpClient(Integer socketTimeOut) {
        RequestConfig requestConfig =
                RequestConfig.custom().setSocketTimeout(socketTimeOut).setConnectTimeout(DEFAULT_CONNECTION_TIME_OUT)
                        .build();
        return HttpClients.custom().setDefaultRequestConfig(requestConfig)
                .setRetryHandler(new DefaultHttpRequestRetryHandler()).build();
    }

    public static String doPost(String url, String requestBody) throws Exception {
        return doPost(url, requestBody, ContentType.APPLICATION_JSON);
    }

    public static String doPost(String url, String requestBody, Integer socketTimeOut) throws Exception {
        return doPost(url, requestBody, ContentType.APPLICATION_JSON, null, socketTimeOut);
    }

    public static String doPost(String url, String requestBody, ContentType contentType) throws Exception {
        return doPost(url, requestBody, contentType, null);
    }

    public static String doPost(String url, String requestBody, List<BasicHeader> headers) throws Exception {
        return doPost(url, requestBody, ContentType.APPLICATION_JSON, headers);
    }

    public static String doPost(String url, String requestBody, ContentType contentType, List<BasicHeader> headers)
            throws Exception {
        return doPost(url, requestBody, contentType, headers, getHttpClient());
    }

    public static String doPost(String url, String requestBody, ContentType contentType, List<BasicHeader> headers,
                                Integer socketTimeOut) throws Exception {
        if (socketTimeOut < SOCKET_TIME_OUT_LOWER_LIMIT || socketTimeOut > SOCKET_TIME_OUT_UPPER_LIMIT) {
            log.error("socketTimeOut非法");
            throw new Exception();
        }
        return doPost(url, requestBody, contentType, headers, getHttpClient(socketTimeOut));
    }


    /**
     * 通用Post远程服务请求
     * @param url
     * 	请求url地址
     * @param requestBody
     * 	请求体body
     * @param contentType
     * 	内容类型
     * @param headers
     * 	请求头
     * @return String 业务自行解析
     * @throws Exception
     */
    public static String doPost(String url, String requestBody, ContentType contentType, List<BasicHeader> headers,
                                CloseableHttpClient client) throws Exception {

        // 构造http方法,设置请求和传输超时时间,重试3次
        CloseableHttpResponse response = null;
        long startTime = System.currentTimeMillis();
        try {
            HttpPost post = new HttpPost(url);
            if (!CollectionUtils.isEmpty(headers)) {
                for (BasicHeader header : headers) {
                    post.setHeader(header);
                }
            }
            StringEntity entity =
                    new StringEntity(requestBody, ContentType.create(contentType.getMimeType(), DEFAULT_CHAR_SET));
            post.setEntity(entity);
            response = client.execute(post);
            if (response.getStatusLine().getStatusCode() != HttpStatus.OK.value()) {
                log.error("业务请求返回失败:{}", EntityUtils.toString(response.getEntity()));
                throw new Exception();
            }
            String result = EntityUtils.toString(response.getEntity());
            return result;
        } finally {
            releaseResourceAndLog(url, requestBody, response, startTime);
        }
    }

    /**
     * 暂时用于智慧园区业务联调方式
     * @param url 业务请求url
     * @param param 业务参数
     * @return
     * @throws Exception
     */
    public static String doPostWithUrlEncoded(String url,
                                              Map<String, String> param) throws Exception {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = getHttpClient();
        CloseableHttpResponse response = null;
        long startTime = System.currentTimeMillis();
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建参数列表
            if (param != null) {
                List<org.apache.http.NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, DEFAULT_CHAR_SET);
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() != HttpStatus.OK.value()) {
                log.error("业务请求返回失败:{}" , EntityUtils.toString(response.getEntity()));
                throw new Exception();
            }
            String resultString = EntityUtils.toString(response.getEntity(), DEFAULT_CHAR_SET);
            return resultString;
        } finally {
            releaseResourceAndLog(url, param == null ? null : param.toString(), response, startTime);
        }
    }

    private static void releaseResourceAndLog(String url, String request, CloseableHttpResponse response, long startTime) {
        if (null != response) {
            try {
                response.close();
                recordInterfaceLog(startTime, url, request);
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }

    public static String doGet(String url) throws Exception {
        return doGet(url, ContentType.DEFAULT_TEXT);
    }

    public static String doGet(String url, ContentType contentType) throws Exception {
        return doGet(url, contentType, null);
    }

    public static String doGet(String url, List<BasicHeader> headers) throws Exception {
        return doGet(url, ContentType.DEFAULT_TEXT, headers);
    }

    /**
     * 通用Get远程服务请求
     * @param url
     * 	请求参数
     * @param contentType
     * 	请求参数类型
     * @param headers
     * 	请求头可以填充
     * @return String 业务自行解析数据
     * @throws Exception
     */
    public static String doGet(String url, ContentType contentType, List<BasicHeader> headers) throws Exception {
        CloseableHttpResponse response = null;
        long startTime = System.currentTimeMillis();
        try {
            CloseableHttpClient client = getHttpClient();
            HttpGet httpGet = new HttpGet(url);
            if (!CollectionUtils.isEmpty(headers)) {
                for (BasicHeader header : headers) {
                    httpGet.setHeader(header);
                }
            }
            if(contentType != null){
                httpGet.setHeader("Content-Type", contentType.getMimeType());
            }
            response = client.execute(httpGet);
            if (response.getStatusLine().getStatusCode() != HttpStatus.OK.value()) {
                log.error("业务请求返回失败:{}", EntityUtils.toString(response.getEntity()));
                throw new Exception();
            }
            String result = EntityUtils.toString(response.getEntity());
            return result;
        } finally {
            releaseResourceAndLog(url, null, response, startTime);
        }
    }

    private static void recordInterfaceLog(long startTime, String url, String request) {
        long endTime = System.currentTimeMillis();
        long timeCost = endTime - startTime;
        MDC.put("totalTime", String.valueOf(timeCost));
        MDC.put("url", url);
        MDC.put("logType", "third-platform-service");
        log.info("HttpClientSslUtils 远程请求:{} 参数:{} 耗时:{}ms", url, request, timeCost);
    }
}
  • 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
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245

这里将调用官方提供的方法也封装在自定义工具类里面

@Slf4j
public class UtilClass {
    /**
     * 获取手机号
     *
     * @param code
     * @param appId
     * @param appSecret
     * @return
     */
    public static JSONObject getPhoneNumber(String code, String appId, String appSecret) {
        JSONObject phone;
        // 获取token
        String token_url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
                appId, appSecret);
        try {
            JSONObject token = JSON.parseObject(HttpClientSslUtils.doGet(token_url));
            if (token == null) {
                log.info("获取token失败");
                return null;
            }
            String accessToken = token.getString("access_token");
            if (StringUtils.isEmpty(accessToken)) {
                log.info("获取token失败");
                return null;
            }
            log.info("token : {}", accessToken);
            //获取phone
            String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"
                    + "?access_token=" + accessToken;
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", code);
            String reqJsonStr = JsonUtil.objToString(jsonObject);
            phone = JSON.parseObject(HttpClientSslUtils.doPost(url, reqJsonStr));

            if (phone == null) {
                log.info("获取手机号失败");
                return null;
            }
            return phone;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
  • 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

根据官方要求小程序appId和appSecret不能作为参数传递给后台,因此将这两个参数放到后台yaml文件中保存

appInfo:
 appId: XXXXXX
 appSecret: XXXXXX
  • 1
  • 2
  • 3

创建一个获取数据的配置类

@Component
@ConfigurationProperties(prefix = "appInfo")
@Data
public class AppInfoConfig {
    private String appId;
    private String appSecret;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Controller层

@Slf4j
@RestController
@Api(tags = "用户信息接口")
@RequestMapping("login")
public class LoginController {
    @Resource
    private AppInfoConfig appInfoConfig;
    
    @ApiOperation("获取手机号")
    @GetMapping("getPhoneNumber")
    public JSONObject getPhoneNumber(String code) {
        return UtilClass.getPhoneNumber(code, appInfoConfig.getAppId(), appInfoConfig.getAppSecret());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

最后返回给前端的结果

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/388014
推荐阅读
相关标签
  

闽ICP备14008679号