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

目录

1. 现在比较简单的方式

-> 接口名

---> 功能描述

-> 调用方式

---> HTTPS 调用

---> 第三方调用

---> 请求参数

---> 返回参数

2. 实现方式

1. 加入fastjson依赖 

2. http请求类

3. Json串工具类

4.接口方法

3.另外介绍一点access_token


1. 现在比较简单的方式

统一封装最新文章地址(可跳过): 微信小程序02: 使用手机号快速验证获取手机号(新版)

下面(旧版)的可以直接使用, 上面的文章(最新)进行了同一封装

-> 接口名

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_tokenstring接口调用凭证,该参数为 URL 参数,非 Body 参数。使用access_token或者authorizer_access_token
codestring手机号获取凭证

---> 返回参数

属性类型说明
errcodenumber错误码
errmsgstring错误信息
phone_infoobject用户手机号信息
属性类型说明
phoneNumberstring用户绑定的手机号(国外手机号会有区号)
purePhoneNumberstring没有区号的手机号
countryCodestring区号
watermarkobject数据水印
属性类型说明
timestampnumber用户获取手机号操作的时间戳
appidstring小程序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次/月

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
要在Java获取微信小程序用户手机号,需要使用微信开放平台提供的接口。具体步骤如下: 1. 在微信开放平台创建小程序,并获取小程序的AppID和AppSecret。 2. 在小程序中获取用户授权,包括获取用户手机号的授权。 3. 在Java中发起HTTPS请求,请求微信提供的接口,获取用户手机号。 以下是示例代码: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class GetPhoneNumber { public static void main(String[] args) throws IOException { String appid = "your_appid"; String secret = "your_appsecret"; String js_code = "user_js_code"; String grant_type = "authorization_code"; // 发起HTTPS请求,获取openid和session_key String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + js_code + "&grant_type=" + grant_type; URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("GET"); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); // 解析返回的JSON数据,获取openid和session_key JSONObject jsonObject = new JSONObject(response.toString()); String openid = jsonObject.getString("openid"); String session_key = jsonObject.getString("session_key"); // 发起HTTPS请求,获取用户手机号 String encryptedData = "user_encrypted_data"; String iv = "user_iv"; url = "https://api.weixin.qq.com/wxa/getphonenumber?access_token=" + access_token; String data = "encryptedData=" + URLEncoder.encode(encryptedData, "UTF-8") + "&iv=" + URLEncoder.encode(iv, "UTF-8") + "&session_key=" + session_key; obj = new URL(url); con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("POST"); con.setDoOutput(true); DataOutputStream wr = new DataOutputStream(con.getOutputStream()); wr.writeBytes(data); wr.flush(); wr.close(); in = new BufferedReader(new InputStreamReader(con.getInputStream())); response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); // 解析返回的JSON数据,获取用户手机号 jsonObject = new JSONObject(response.toString()); String phoneNumber = jsonObject.getString("phoneNumber"); System.out.println(phoneNumber); } } ``` 注意:以上示例代码仅供参考,具体实现需要根据实际情况进行调整。同时,获取用户手机号需要用户授权,因此需要在小程序中获取用户授权并获取用户手机号

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pingzhuyan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值