微信小程序獲取手機(jī)號(hào),后端JAVA解密流程代碼
小程序獲取手機(jī)號(hào),后端JAVA解密流程代碼
微信官方文檔獲取手機(jī)號(hào)流程地址,先看下最好方便理解下面步驟
實(shí)現(xiàn)思路,步驟如下
1.前端需先調(diào)用官方wx.login接口獲取登錄憑證code。
2.后端接收code 調(diào)用官方接口地址獲取用戶秘鑰 sessionKey。
3.前端通過官方getPhoneNumber獲取encryptedData,iv
4.前端通過參數(shù)**【encryptedData】 、【iv】 、【sessionKey】** 發(fā)送請(qǐng)求后端接口,解密用戶手機(jī)號(hào)
小程序獲取sessionkey詳細(xì)接口文檔
后端工作如下,
- 1.參數(shù)code 解密出sessionKey
- {“session_key”:“eF9PAi5P7ZbSaQqkGzEY5g==”,“openid”:“otJ1I4zMSFGDtk7C33O_h6U3IRK8”}
- 2.參數(shù)sessionKey,iv,encryptedData 解密出手機(jī)號(hào)
代碼如下:
下面工具類很全,放心代碼必須全,良心教程。
業(yè)務(wù)代碼Controller
package com.df.detection.controller; import com.df.detection.base.entity.ResultBean; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import org.apache.commons.codec.binary.Base64; import org.json.JSONException; import org.springframework.web.bind.annotation.*; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import org.json.JSONObject; /** * @Author Songzhongjin * @Date 2020/7/15 10:09 * @Version 1.0 */ @Api(value = "小程序登錄授權(quán) Controller",tags = {"小程序登錄授權(quán)接口"}) @RestController @RequestMapping("/app") public class APPController { /** * 微信小程序登錄獲取 * 獲取session_key * @param * @return */ @ResponseBody @PostMapping("/initWxLogin") @ApiImplicitParams({ @ApiImplicitParam(name = "js_code", value = "登錄時(shí)獲取的code",paramType = "form", dataType = "string", required = true) }) public ResultBeaninitWxLogin(@RequestParam(value = "js_code", required = true) String js_code) throws JSONException { //測(cè)試數(shù)據(jù)code // js_code = "081ZQ3f91fr9VM1HYdb91y93f91ZQ3fU"; //微信獲取session_key接口地址 String wxLoginUrl = "https://api.weixin.qq.com/sns/jscode2session"; //接口參數(shù) String param = "appid=小程序id&secret=小程序secret&js_code=" + js_code + "&grant_type=authorization_code"; //調(diào)用獲取session_key接口 請(qǐng)求方式get String jsonString = GetPostUntil.sendGet(wxLoginUrl, param); System.out.println(jsonString); //因?yàn)閖son字符串是大括號(hào)包圍,所以用JSONObject解析 JSONObject json = new JSONObject(jsonString); //json解析session_key值 String session_key = json.getString("session_key"); System.out.println("session_key:" + session_key); //返回給前端 return ResultBean.success("session_key",session_key); } /** * 解密小程序用戶敏感數(shù)據(jù) * * @param encryptedData 明文 * @param iv 加密算法的初始向量 * @param sessionKey 用戶秘鑰 * @return */ @ResponseBody @PostMapping(value = "/decodeUserInfo") @ApiImplicitParams({ @ApiImplicitParam(name = "encryptedData", value = "包括敏感數(shù)據(jù)在內(nèi)的完整用戶信息的加密數(shù)據(jù)",paramType = "form", dataType = "string", required = true), @ApiImplicitParam(name = "iv", value = "加密算法的初始向量",paramType = "form", dataType = "string", required = true), @ApiImplicitParam(name = "sessionKey", value = "用戶秘鑰",paramType = "form", dataType = "string", required = true) }) public ResultBean decodeUserInfo(@RequestParam(required = true, value = "encryptedData") String encryptedData, @RequestParam(required = true, value = "iv") String iv, @RequestParam(required = true, value = "sessionKey") String sessionKey ) throws UnsupportedEncodingException, InvalidAlgorithmParameterException, JSONException { //AESUtils微信獲取手機(jī)號(hào)解密工具類 AESUtils aes = new AESUtils(); //調(diào)用AESUtils工具類decrypt方法解密獲取json串 byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv)); //判斷返回參數(shù)是否為空 if (null != resultByte && resultByte.length > 0) { String jsons = new String(resultByte, "UTF-8"); System.out.println(jsons); JSONObject json = new JSONObject(jsons); //json解析phoneNumber值 String phoneNumber = json.getString("phoneNumber"); System.out.println("phoneNumber:" + phoneNumber); return ResultBean.success("手機(jī)號(hào)", phoneNumber); } return ResultBean.error(500,"session_key:失敗"); } }
工具類代碼如下
package com.df.detection.controller; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; /** * @Author Songzhongjin * @Date 2020/7/15 10:37 * @Version 1.0 */ public class GetPostUntil { /** * 向指定URL發(fā)送GET方法的請(qǐng)求 * * @param url * 發(fā)送請(qǐng)求的URL * @param param * 請(qǐng)求參數(shù),請(qǐng)求參數(shù)應(yīng)該是 name1=value1&name2=value2 的形式。 * @return URL 所代表遠(yuǎn)程資源的響應(yīng)結(jié)果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打開和URL之間的連接 URLConnection connection = realUrl.openConnection(); // 設(shè)置通用的請(qǐng)求屬性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立實(shí)際的連接 connection.connect(); // 獲取所有響應(yīng)頭字段 Map<String, List<String>> map = connection.getHeaderFields(); // 遍歷所有的響應(yīng)頭字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定義 BufferedReader輸入流來讀取URL的響應(yīng) in = new BufferedReader(new InputStreamReader( connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("發(fā)送GET請(qǐng)求出現(xiàn)異常!" + e); e.printStackTrace(); } // 使用finally塊來關(guān)閉輸入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 發(fā)送POST方法的請(qǐng)求 * * @param url * 發(fā)送請(qǐng)求的 URL * @param param * 請(qǐng)求參數(shù),請(qǐng)求參數(shù)應(yīng)該是 name1=value1&name2=value2 的形式。 * @return 所代表遠(yuǎn)程資源的響應(yīng)結(jié)果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打開和URL之間的連接 URLConnection conn = realUrl.openConnection(); // 設(shè)置通用的請(qǐng)求屬性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 發(fā)送POST請(qǐng)求必須設(shè)置如下兩行 conn.setDoOutput(true); conn.setDoInput(true); // 獲取URLConnection對(duì)象對(duì)應(yīng)的輸出流 out = new PrintWriter(conn.getOutputStream()); // 發(fā)送請(qǐng)求參數(shù) out.print(param); // flush輸出流的緩沖 out.flush(); // 定義BufferedReader輸入流來讀取URL的響應(yīng) in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("發(fā)送 POST 請(qǐng)求出現(xiàn)異常!"+e); e.printStackTrace(); } //使用finally塊來關(guān)閉輸出流、輸入流 finally{ try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } }
AESUtils工具類 解密手機(jī)號(hào)
package com.df.detection.controller; import org.apache.tomcat.util.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.xml.transform.Result; import java.security.*; /** * @Author Songzhongjin * @Date 2020/7/15 11:46 * @Version 1.0 */ public class AESUtils { public static boolean initialized = false; /** * AES解密 * @param content 密文 * @return * @throws InvalidAlgorithmParameterException * @throws NoSuchProviderException */ public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException { initialize(); try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); Key sKeySpec = new SecretKeySpec(keyByte, "AES"); cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化 byte[] result = cipher.doFinal(content); return result; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static void initialize(){ if (initialized) { return; } Security.addProvider(new BouncyCastleProvider()); initialized = true; } //生成iv public static AlgorithmParameters generateIV(byte[] iv) throws Exception { AlgorithmParameters params = AlgorithmParameters.getInstance("AES"); params.init(new IvParameterSpec(iv)); return params; } }
接口返回對(duì)象ResultBean定義工具類 防止有些朋友發(fā)現(xiàn)沒有這個(gè)類
package com.df.detection.base.entity; import io.swagger.annotations.ApiModelProperty; /** * @author Liu Yaoguang * @Classname aaa * @Description * @Date 2019/12/06 09:22 */ public class ResultBean<T> { @ApiModelProperty(value = "返回碼",dataType = "int") private int code; @ApiModelProperty(value = "返回描述信息",dataType = "string") private String message; @ApiModelProperty(value = "返回?cái)?shù)據(jù)") private T data; @ApiModelProperty(value = "口令",dataType = "string") private String token; private ResultBean() { } public static ResultBean error(int code, String message) { ResultBean resultBean = new ResultBean(); resultBean.setCode(code); resultBean.setMessage(message); return resultBean; } public static<T> ResultBean error(int code, String message,T data) { ResultBean resultBean = new ResultBean(); resultBean.setCode(code); resultBean.setMessage(message); resultBean.setData(data); return resultBean; } public static ResultBean success(String message) { ResultBean resultBean = new ResultBean(); resultBean.setCode(200); resultBean.setMessage(message); return resultBean; } public static<T> ResultBean success(String message,T data) { ResultBean resultBean = new ResultBean(); resultBean.setCode(200); resultBean.setMessage(message); resultBean.setData(data); return resultBean; } public static ResultBean success(String message,Object data,String token) { ResultBean resultBean = new ResultBean(); resultBean.setCode(200); resultBean.setMessage(message); resultBean.setData(data); resultBean.setToken(token); return resultBean; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } }
以上就是微信小程序獲取手機(jī)號(hào),后端JAVA解密流程代碼的詳細(xì)內(nèi)容,更多關(guān)于微信小程序獲取手機(jī)號(hào)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
玩轉(zhuǎn)spring boot MVC應(yīng)用(2)
玩轉(zhuǎn)spring boot,如何快速搭建一個(gè)MCV程序?這篇文章為大家詳細(xì)主要介紹了一個(gè)MCV程序的快速搭建過程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01Spring中的動(dòng)態(tài)數(shù)據(jù)源解讀
這篇文章主要介紹了關(guān)于Spring中的動(dòng)態(tài)數(shù)據(jù)源解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Java SSM框架(Spring+SpringMVC+MyBatis)搭建過程
最近一段時(shí)間搭建了ssm環(huán)境,并測(cè)試了幾個(gè)小項(xiàng)目,下面小編通過圖文并茂的形式給大家分享Java SSM框架(Spring+SpringMVC+MyBatis)搭建過程,需要的朋友參考下吧2017-11-11java實(shí)現(xiàn)輸出任意整數(shù)的每一位
這篇文章主要介紹了java實(shí)現(xiàn)輸出任意整數(shù)的每一位,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01SpringMVC解析post請(qǐng)求參數(shù)詳解
今天小編就為大家分享一篇解決SpringMVC接收不到ajaxPOST參數(shù)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-08-08Spring ApplicationListener的使用詳解
這篇文章主要介紹了Spring ApplicationListener的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06