微信小程序: java实现获取手机号方式

目录

1. 现在比较简单的方式

-> 接口名

---> 功能描述

-> 调用方式

---> HTTPS 调用

---> 第三方调用

---> 请求参数

---> 返回参数

2. 实现方式

1. 加入fastjson依赖 

扫描二维码关注公众号,回复: 15585892 查看本文章

2. http请求类

3. Json串工具类

4.接口方法

3.另外介绍一点access_token


1. 现在比较简单的方式

微信官方文档介绍: 

-> 接口名

getPhoneNumber

---> 功能描述

该接口需配合手机号快速填写组件能力一起使用,当用户点击并同意之后,可以通过 bindgetphonenumber 事件回调获取到动态令牌code,再调用该接口将code换取用户手机号。

注意:每个code只能使用一次,code的有效期为5min。

-> 调用方式

---> HTTPS 调用


POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN 

---> 第三方调用

  • 调用方式以及出入参和HTTPS相同,仅是调用的token不同

  • 该接口所属的权限集id为:18

  • 服务商获得其中之一权限集授权后,可通过使用authorizer_access_token代商家进行调用

---> 请求参数

属性 类型 必填 说明
access_token string 接口调用凭证,该参数为 URL 参数,非 Body 参数。使用access_token或者authorizer_access_token
code string 手机号获取凭证

---> 返回参数

属性 类型 说明
errcode number 错误码
errmsg string 错误信息
phone_info object 用户手机号信息
属性 类型 说明
phoneNumber string 用户绑定的手机号(国外手机号会有区号)
purePhoneNumber string 没有区号的手机号
countryCode string 区号
watermark object 数据水印
属性 类型 说明
timestamp number 用户获取手机号操作的时间戳
appid string 小程序appid

2. 实现方式

1. 加入fastjson依赖 

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>

2. http请求类

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);
	}
}

3. Json串工具类

import com.alibaba.fastjson.TypeReference;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
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;
        }
    }

}

4.接口方法

 @PostMapping("/getPhone")
    public ResultResponse getPhone(@RequestBody @Valid WxMiniGetPhone param) {
        JSONObject wxJson;
        // 获取token
        String token_url = null;

        /**
         * appid切换
         */
        if (param.getWxAppletType() == 1) {
            token_url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", bAppID, bAppSecret);
        } else if (param.getWxAppletType() == 2) {
            token_url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", aAppId, aSecret);
        } else {
            throw new UserServiceException("异常");
        }


        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", param.getCode());
            String reqJsonStr = JsonUtil.objToString(jsonObject);
            wxJson = JSON.parseObject(HttpClientSslUtils.doPost(url, reqJsonStr));

            if (wxJson == null) {
                log.info("获取手机号失败");
                return ResultResponse.error("获取手机号失败!");
            }
            return ResultResponse.ok("获取成功!").setData(wxJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultResponse.error("获取失败,请重试!");
    }

3.另外介绍一点access_token

access_token是有次数限制的 一天2000次 超过了需要刷新accessToken限制次数,10次/月

猜你喜欢

转载自blog.csdn.net/pingzhuyan/article/details/131143111
今日推荐