微信小程序获取手机号:前后端源码示例,解决47001这个错误提示

小程序中自动获取手机号为很常见的一个功能点,可以减少用户输入,目前小程序规则是不允许系统直接自动获取,需要用户手动触发
本文中的实现方式:前端使用uniapp生成小程序,后端使用springboot

首先,上效果图
效果图

1、前端uniapp代码

小程序原生代码类似,可以看微信开放平台官网示例

<u-form-item  :label-position="labelPosition"
 label="手机号码" prop="phone" label-width="150">
	<u-input :border="border" placeholder="请输入手机号" v-model="model.phone" type="number" :disabled="false"></u-input>
	<!-- #ifndef H5 -->
		<u-button slot="right" type="success" size="mini" open-type="getPhoneNumber"  @getphonenumber="getPhoneNumber">获取手机号
		</u-button>
	<!-- #endif -->
</u-form-item>

目前获取手机号不需要先做登录授权

// 获取微信小程序绑定的手机号
getPhoneNumber(e) {
	let data1 = {};
	data1.code = e.detail.code;
	data1.iv=e.detail.iv;
	data1.encryptedData=e.detail.encryptedData;
	
	_this._post_form('system/phone', data1, (result) => {
		if (result && result != null && result.code=='200'){
			uni.setStorageSync('user_phone', result.data.phone);
			console.info(result.data.phone);
			_this.model.phone = result.data.phone;
		}else{
			uni.showModal({
				showCancel: false,
				title: '错误',
				content: "获取手机号失败,请联系管理员处理",
			}); 
		}
	});
}

2、后端代码

注意:
1、这里后端不再使用旧版的解密方式获取手机号,而是直接请求微信获取
相关说明见微信公众平台API说明
2、这里的代码,最有用的是,使用post请求的时候,参数需要为raw的形式,否则,微信会返回47001的错误

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

import org.apache.commons.collections4.map.HashedMap;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
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 com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.WxDecPhone;
import com.ruoyi.common.enums.BusinessType;

/**
 * 获取微信手机号Controller
 * 
 * @author 
 * @date 2022-03-23
 */
@RestController
@RequestMapping("/system/phone")
public class WxController extends BaseController {
	
	// 小程序appid
    @Value("${APP_ID}")
    private String APP_ID;
    // 小程序的app secret
    @Value("${APPSECRET}")
    private String APPSECRET;
	
	@Log(title = "解密手机号", businessType = BusinessType.INSERT)
	@PostMapping
	public AjaxResult deciphering(@RequestBody WxDecPhone wxDecPhone) {
		String code = wxDecPhone.getCode();//code 为getPhoneNumber(e)后的e.detail.code
		String phone = "";
		String access_token = getAccess_token();
		System.out.println("code:" + code);
		System.out.println("access_token:" + access_token);

		String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + access_token;
		JSONObject body = new JSONObject();
		body.put("code", code);
		try {
			String ret = httpPostRaw(url, body.toString(), null, null);
			if(ret != null && !"".equals(ret)) {
				JSONObject json = JSONObject.parseObject(ret);
				JSONObject phone_info = json.getJSONObject("phone_info");
				phone = phone_info.getString("phoneNumber");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		Map<String, Object> data = new HashedMap<String, Object>();
		data.put("phone", phone);
		AjaxResult ajax = AjaxResult.success(data);
		return ajax;
	}

	/**
	 * 微信接口请求令牌:生产环境下 要用redis缓存起来
	 * @return
	 */
	public String getAccess_token() {
		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
				+ APP_ID + "&secret=" + APPSECRET;
		String accessToken = null;
		try {
			URL urlGet = new URL(url);
			HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
			http.setRequestMethod("GET"); // 必须是get方式请求
			http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
			http.setDoOutput(true);
			http.setDoInput(true);
			System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
			System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
			http.connect();
			InputStream is = http.getInputStream();
			int size = is.available();
			byte[] jsonBytes = new byte[size];
			is.read(jsonBytes);
			String message = new String(jsonBytes, "UTF-8");
			JSONObject demoJson = JSONObject.parseObject(message);
			accessToken = demoJson.getString("access_token");
			is.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return accessToken;
	}

	/**
	 * 参数以raw的方式做post请求
	 * 
	 * @param url
	 * @param stringJson
	 * @param headers
	 * @param encode
	 * @return
	 */
	public static String httpPostRaw(String url, String stringJson, Map<String, String> headers, String encode) {
		String str = "";
		if (encode == null) {
			encode = "utf-8";
		}
		// HttpClients.createDefault()等价于 HttpClientBuilder.create().build();
		CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
		HttpPost httpost = new HttpPost(url);

		// 设置header
		httpost.setHeader("Content-type", "application/json");
		if (headers != null && headers.size() > 0) {
			for (Map.Entry<String, String> entry : headers.entrySet()) {
				httpost.setHeader(entry.getKey(), entry.getValue());
			}
		}
		// 组织请求参数
		StringEntity stringEntity = new StringEntity(stringJson, encode);
		httpost.setEntity(stringEntity);
		String content = null;
		CloseableHttpResponse httpResponse = null;
		try {
			// 响应信息
			httpResponse = closeableHttpClient.execute(httpost);
			HttpEntity entity = httpResponse.getEntity();
			content = EntityUtils.toString(entity, encode);
			System.out.println(content);
			str = content;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				httpResponse.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try { // 关闭连接、释放资源
			closeableHttpClient.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return str;
	}

}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值