赞
踩
在某些业务情况下,微信小程序开发者需要获取到用户的手机号,微信小程序官方为我们提供了该方法。
获取手机号的开发过程可以分为三部分:微信前端设置,微信js文件编写,服务器端程序开发.
其中微信前端最为简单,在获取手机号的过程中我们必须经过用户授权,在wxml文件中加入如下代码:
//声明了一个按钮,当用户点击该按钮后将进入授权界面,用户允许系统获取手机号后,js的getPhoneNumber将接受到用户手机号的相关信。
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">手机号</button>
然后我们需要编写js文件,当用户允许获取手机号后调用相关逻辑,将手机号加密信息发送给用户服务器,以便进行进一步的解密操作获取用户真正的是手机号信息。
getPhoneNumber(e) {
console.log(e.detail.errMsg) // 错误信息,如果获取失败则返回该信息
console.log(e.detail.iv) // iv用于解密操作
console.log(e.detail.encryptedData) // 密文,解密后可以获取手机号
//在真正的业务方向上应该将获取到的iv和encryptedData发送给用户服务器
},
服务器操作
获取手机号的重点以及难点在于多加密数据的解密操作。微信的加密使用了对称加密算法AES。AES工具类如下
import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; 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 org.bouncycastle.jce.provider.BouncyCastleProvider; /** * AES加密 */ public class AES { 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; } }
微信解密的直接接口如下:
import org.apache.commons.codec.binary.Base64; import org.springframework.stereotype.Component; import com.alibaba.fastjson.JSONObject; /** * 封装对外访问方法 */ @Component public class WXCore { private static final String WATERMARK = "watermark"; private static final String APPID = "appid"; /** * 解密 * @param appId --- 你的appId * @param encryptedData --- 加密的数据 * @param sessionKey --- 密钥(session_key) * @param iv * @return */ public static String decrypt(String appId, String encryptedData, String sessionKey, String iv){ String result = ""; try { AES aes = new AES(); byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv)); if(null != resultByte && resultByte.length > 0){ result = new String(WxPKCS7Encoder.decode(resultByte)); JSONObject jsonObject = JSONObject.parseObject(result); String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID); if(!appId.equals(decryptAppid)){ result = ""; } } } catch (Exception e) { result = ""; e.printStackTrace(); } return result; } }
如果需要解密,将上面两个类直接添加到你的项目中,WXCore类需要调用AES类中的相关方法。获取手机号的解密可以直接调用WXCore.decrype(String appId, String encryptedData, String sessionKey, String iv)方法。注意这几个参数对应的值,需要注意的是sessionKey,还记得微信小程序的登录吗,登录获取到的其中一个参数是session_key这里就将使用到他。调用方法如下:
//解密获取结果
String result = WXCore.decrypt(appId, encryptedData, sessionKey, iv);
JSONObject jsonObject = JSONObject.parseObject(result);
//防止空指针异常
if(jsonObject!=null) {
//获取的该手机号并不一定为非空,所以后面需要判断phone是否为null或者""
String phone = jsonObject.getString("phoneNumber");
}
总结
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。