1、wxml使用getPhoneNumber
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取用户手机号</button>
2、js向后台发起请求
注意这里要在发起wx.request给后台解密之前使用wx.login接口更新code(用于解密SessionKey),防止code过期,得到的SessionKey也是过期的,再拿去解密手机号会报错pad block corrupted。最好在每次获取手机号前先使用wx.login更新code。
Page({
data: {
code: "",//用于解密session_key和openid的code
phoneNumber:""
},
onLoad:function(e){
wx.login({
success:res=>{
this.setData({
code:res.code
})
}
})
},
getPhoneNumber(e){
//如果用户允许获取手机号则返回的数组长度为4
if(Object.getOwnPropertyNames(e.detail).length>1){
//检查code是否过期,如果过期更换新的code
wx.checkSession({
success: (res) => {
wx.login({
success:res=>{
this.setData({
code:res.code
})
}
})
},
})
//发起解密手机号请求
wx.request({
url: '后台连接',
method: 'POST',
data: {
code:this.data.code,
iv:e.detail.iv,
encryptedData:e.detail.encryptedData
},
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success(res){//控制台打印解密后的手机号
console.log(res.data)
}
})
}
}
})
3、SpringBoot获取手机号接口
pom.xml:
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.4.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
OpenIdAndSessionKey:
public class OpenIdAndSessionKey {
private String openid;
private String session_key;
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getSession_key() {
return session_key;
}
public void setSession_key(String session_key) {
this.session_key = session_key;
}
}
UserLoginController:
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.test.utils.AESUtil;
import com.test.utils.GetSessionKeyAndOpenId;
import org.springframework.web.bind.annotation.*;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidParameterSpecException;
@RestController
public class UserLoginController {
/*获取用户的openid*/
@PostMapping("/user/login/getOpenId")
public String getOpenId(@RequestParam("code")String code) throws IOException {
return new GetSessionKeyAndOpenId().getOpenIdAndSessionKey(code).getOpenid();
}
/*获取用户的手机号*/
@PostMapping("/user/login/getPhoneNumber")
public String getPhoneNumber(@RequestParam("code")String code,
@RequestParam("iv")String iv,
@RequestParam("encryptedData")String encryptedData)
throws IOException, InvalidParameterSpecException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
String sessionKey = new GetSessionKeyAndOpenId().getOpenIdAndSessionKey(code).getSession_key();
JSONObject jsonObject = AESUtil.decrypt(encryptedData,sessionKey,iv);
return jsonObject.get("phoneNumber").toString();
}
}
AESUtil:
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import static javax.crypto.Cipher.*;
public class AESUtil {
private static final String KEY_NAME = "AES";
public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
//生成iv
public static AlgorithmParameters generateIV(byte[] iv)
throws NoSuchAlgorithmException, InvalidParameterSpecException {
AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(KEY_NAME);
algorithmParameters.init(new IvParameterSpec(iv));
return algorithmParameters;
}
//初始化秘钥
public static void init() throws NoSuchAlgorithmException {
Security.addProvider(new BouncyCastleProvider());
KeyGenerator.getInstance(KEY_NAME).init(128);
}
//生成解密
public static JSONObject decrypt(String encryptedData, String sessionKey, String iv)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidParameterSpecException {
byte[] encrypted64 = Base64.decodeBase64(encryptedData.getBytes());
byte[] session64 = Base64.decodeBase64(sessionKey.getBytes());
byte[] iv64 = Base64.decodeBase64(iv.getBytes());
init();
AlgorithmParameters algorithmParameters = generateIV(iv64);
Key key = new SecretKeySpec(session64,KEY_NAME);
Cipher cipher = getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,key,algorithmParameters);
String json = new String(cipher.doFinal(encrypted64));
return JSONUtil.parseObj(json);
}
}
GetSessionKeyAndOpenId:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.model.OpenIdAndSessionKey;
import java.io.IOException;
public class GetSessionKeyAndOpenId {
private String appID = "自己的appID";
private String appSecret = "自己的appSecret";
public OpenIdAndSessionKey getOpenIdAndSessionKey(String code) throws IOException {
String result = "";
try{
result = HttpUtil.doGet(
"https://api.weixin.qq.com/sns/jscode2session?"
+ "appid=" + this.appID
+ "&secret=" + this.appSecret
+ "&js_code=" + code
+ "&grant_type=authorization_code",null);
} catch (
IOException e) {
e.printStackTrace();
}
ObjectMapper mapper = new ObjectMapper();
OpenIdAndSessionKey openIdJson = mapper.readValue(result, OpenIdAndSessionKey.class);
return openIdJson;
}
}
HttpUtil:
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.HttpStatus;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HttpUtil {
/*通过请求url连接和参数获取返回的内容并转为string*/
public static String doGet(String urlPath, HashMap<String,Object> params) throws IOException {
StringBuilder sb = new StringBuilder(urlPath);
//在请求的URL后面添加参数,用&分隔
if(params!=null && !params.isEmpty()){
sb.append("?");
Set<Map.Entry<String, Object>> set = params.entrySet();
for(Map.Entry<String,Object> entry:set){
String key = entry.getKey();
String value = "";
if(null!=entry.getValue()){
value = entry.getValue().toString();
value = URLEncoder.encode(value,"UTF-8");
}
sb.append(key).append("=").append(value).append("&");
}
sb.deleteCharAt(sb.length()-1);
}
URL url = new URL(sb.toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);//超时时间
conn.setRequestMethod("GET");
if(conn.getResponseCode()== HttpStatus.SC_OK){
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sbs = new StringBuilder();
String line;
while ((line=reader.readLine())!=null){
sbs.append(line);
}
return sbs.toString();
}
return null;
}
}
参考文章1:
https://www.jianshu.com/p/c80979950ce6?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
参考文章2:https://developers.weixin.qq.com/community/develop/doc/0004a8dfe288605a5188675c456000