正文 1.首先理一下流程,下面是微信开发文档中的一张图1.首先获取手机号需要认证企业资质的小程序
2.获取手机号需要一台服务器编写解密代码
下面是我自己写的流程
注意 微信官方文档-手机号获取
按照例程打印不出来code,看看答应e.detail的结果
{ errMsg: "getPhoneNumber:ok", encrypteddata: "/7uD9+GJ7qd0YBVX30Fg0Fj8W/2IXHbUhzZ3TfHv+LyRktBtZw…KKLFhmzK5jyiLxweSspezjVP7EEaifXPaAFeGG4fIl3u4GQ==", iv: "jfnSdhGbU4OS3JmwsoxL2Q==" }
只能获取encryptedData和iv因此我们需要从wx.login()中获取code
2.小程序代码1.在app.js的onLaunch()或index.js页面的onLoad()下面写wx.login()
App({ onLaunch: function () { // 1.获取临时登录凭证code wx.login({ success: res => { if(res.code){ console.log("code->", res.code) wx.setStorageSync('resCode', res.code) } } }) } })
将获取到的code保存在缓存里
2.由于getPhoneNumber现在不支持自动d出,需要用按钮去拉起,所以我们在wxml写上
并且在对应的js里写
Page({ // 获取手机号授权 getPhoneNumber (e) { // 用户拒绝授权 if(e.detail.errMsg == "getPhoneNumber:fail user deny") { wx.showToast({ icon: "none", title: '请允许获取手机号,否则功能不可用!', }) return } /// 用户允许授权 console.log("e.detail.errMsg="+e.detail.errMsg) console.log("e.detail.iv=->", e.detail.iv); //包括敏感数据在内的完整用户信息的加密数据,需要解密 console.log("e.detail.encryptedData->", e.detail.encryptedData); //加密算法的初始向量,解密需要用到 /// 获取手机号 let resCode = wx.getStorageSync('resCode'); console.log("resCode = " +resCode) console.log(" e.detail = " + e.detail) if(resCode){ this.getphone(resCode, e.detail.encryptedData, e.detail.iv); this.triggerEvent("isHiddenPopup"); } }, // 访问登录凭证校验接口获取session_key 并用session_key获取手机号 getphone: function(js_code, encryptedData, iv) { wx.request({ url: globalData.getSessionKeyUrl,//需要填写自己的服务器请求地址 data: { 'js_code': js_code, 'encryptedData' : encryptedData, 'iv':iv, 'sign': 'sign', }, method: 'GET', header: { 'content-type': 'application/json' }, // 设置请求的 header success: function(data) { console.log("获取手机号返回JSON数据 =", data.data) console.log("手机号 = "+data.data.phoneNumber) if(data.data==undefined){ wx.showToast({ icon: "none", title: '手机号获取失败,请重新登录!', }) return } if(data.statusCode == 200) { if(data.data.phoneNumber==undefined){ // 获取手机号失败 console.log("获取手机号失败"); return } // 4.跳转web-view页面 wx.switchTab({ url: "/pages/mine/mine" }) } }, fail: function(err) { console.log(err); wx.showToast({ icon: "none", title: 'session_key获取失败,请重新登录!', }) return } }) } })
至此小程序主要代码写完了
3.后台代码后台选择SpringBoot搭建,首先建一个基础工程,然后直接贴代码
1.pom.xml
4.0.0 org.springframework.boot spring-boot-starter-parent2.6.1 com.server server0.0.1-SNAPSHOT server server 1.8 org.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-devtoolsruntime true org.springframework.boot spring-boot-configuration-processortrue org.projectlombok lomboktrue org.springframework.boot spring-boot-starter-testtest org.apache.logging.log4j log4j-api2.11.1 commons-codec commons-codec1.15 org.bouncycastle bcprov-jdk161.46 org.springframework.boot spring-boot-maven-pluginorg.projectlombok lombok
2.ServerApplication.java
package com.server; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.server.data.globalData; import com.server.httpUtil.PostData; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.*; @RestController @SpringBootApplication public class ServerApplication { com.server.data.globalData globalData = new globalData(); public static void main(String[] args) { SpringApplication.run(ServerApplication.class, args); } //解析电话号码 @GetMapping("/getsessionkey") public Object getsessionkey(String js_code,String encryptedData, String iv) throws JsonProcessingException { PostData PostData = new PostData(); String responseData = PostData.PostData(globalData.url, globalData.appid, globalData.secret,js_code,globalData.grant_type); //获取SessionKey 和openid ObjectMapper mapper = new ObjectMapper(); JsonNode resData = mapper.readTree(responseData); try{ if(resData.get("session_key").asText()!=null) { String SessionKey = resData.get("session_key").asText(); String openid = resData.get("openid").asText(); System.out.println("SessionKey="+SessionKey); System.out.println("openid="+openid); System.out.println("encryptedData="+encryptedData); System.out.println("iv="+iv); String wxDecrypt = WechatUtils.wxDecrypt(encryptedData,SessionKey,iv); System.out.println(wxDecrypt); return wxDecrypt; }else { System.out.println("请求微信服务器异常"); } }catch (Exception e) { System.out.println("请求微信服务器异常"); } return 0; } }
3.WechatUtils.java解密工具类
package com.server; import java.security.*; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class WechatUtils { public static final String AES = "AES"; public static final String AES_CBC_PADDING = "AES/CBC/PKCS7Padding"; public static String wxDecrypt(String encrypted, String session_key, String iv) { String result = null; byte[] encrypted64 = org.apache.commons.codec.binary.base64.decodebase64(encrypted); byte[] key64 = org.apache.commons.codec.binary.base64.decodebase64(session_key); byte[] iv64 = org.apache.commons.codec.binary.base64.decodebase64(iv); try { init(); result = new String(decrypt(encrypted64, key64, generateIV(iv64))); } catch (Exception e) { e.printStackTrace(); } return result; } public static void init() throws Exception { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyGenerator.getInstance(AES).init(128); } public static AlgorithmParameters generateIV(byte[] iv) throws Exception { // iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0 // Arrays.fill(iv, (byte) 0x00); AlgorithmParameters params = AlgorithmParameters.getInstance(AES); params.init(new IvParameterSpec(iv)); return params; } public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv) throws Exception { Key key = new SecretKeySpec(keyBytes, AES); Cipher cipher = Cipher.getInstance(AES_CBC_PADDING); // 设置为解密模式 cipher.init(Cipher.DECRYPT_MODE, key, iv); return cipher.doFinal(encryptedData); } }
4.HttpRestUtils.java http请求工具类
package com.server.httpUtil; import org.springframework.http.*; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import java.io.IOException; public class HttpRestUtils { public static String post(String url, MultiValueMapparams) throws IOException { return httpRestClient(url, HttpMethod.POST, params); } public static String get(String url, MultiValueMap params) throws IOException { return httpRestClient(url, HttpMethod.GET, params); } private static String httpRestClient(String url, HttpMethod method, MultiValueMap params) throws IOException { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setConnectTimeout(10*1000); requestFactory.setReadTimeout(10*1000); RestTemplate client = new RestTemplate(requestFactory); HttpHeaders headers = new HttpHeaders(); // 以表单的方式提交 headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // headers.setContentType(MediaType.APPLICATION_JSON_UTF8);//不好使,不能用get方法 HttpEntity > requestEntity = new HttpEntity >(params, headers); // 执行HTTP请求 ResponseEntity response = null; try{ response = client.exchange(url, HttpMethod.POST, requestEntity, String.class); System.out.println("response="+response); return response.getBody(); } catch (HttpClientErrorException e){ System.out.println( "------------- 出现异常 HttpClientErrorException -------------"); System.out.println(e.getMessage()); System.out.println(e.getStatusText()); System.out.println( "-------------responseBody-------------"); System.out.println( e.getResponseBodyAsString()); e.printStackTrace(); return ""; } catch (Exception e) { System.out.println( "------------- HttpRestUtils.httpRestClient() 出现异常 Exception -------------"); System.out.println(e.getMessage()); return ""; } } }
5.PostData.java http请求业务类
package com.server.httpUtil; import org.springframework.http.HttpMethod; import org.springframework.util.linkedMultiValueMap; import org.springframework.util.MultiValueMap; public class PostData { public String PostData(String url ,String appid,String appSecret,String code,String authorization_code) { try { //post请求 HttpMethod method = HttpMethod.GET; // 封装参数,千万不要替换为Map与HashMap,否则参数无法传递 MultiValueMapparams = new linkedMultiValueMap (); params.add("appid",appid); params.add("secret",appSecret); params.add("js_code",code); params.add("grant_type",authorization_code); System.out.print("发送数据:" + params.toString()+"n"); //发送http请求并返回结果 String result = HttpRestUtils.get(url, params); System.out.print("接收反馈:" + result+"n"); return result; } catch (Exception e) { System.out.println("------------- " + this.getClass().toString() + ".PostData() : 出现异常 Exception -------------"); System.out.println(e.getMessage()); return ""; } } }
6.globalData.java 全局变量
package com.server.data; public class globalData { public String url = "https://api.weixin.qq.com/sns/jscode2session";//微信服务器接口 public String appid = "xxxxxx填自己小程序的xxxxx"; public String secret = "xxxxxx填自己小程序的xxxxx"; public String grant_type = "authorization_code";//这样写就行 }
至此前后台就ok了,可以获取用户手机号了
后台数据打印如下
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)