小程序登录
整体流程如下:
- 1.获取code
- 2.用步骤1获取到的临时code换取用户唯一标识OpenId和会话密钥 session_key
- 3.获取用户手机号,用进行登录
请求参数:
请求参数:
返回值:
开发前准备(必须)
appid:wx4c1d53****7a671
appsecret:fc9f99c08dcb2a0****eb26376c65eae
小程序代码:
login.js
// pages/login/login.wxml.jsconst app = getApp();Page({
/** * 页面的初始数据 */ data: { // 判断小程序的API,回调,参数,组件等是否在当前版本可用。 canIUse: wx.canIUse('button.open-type.getPhoneNumber'), wechat: '微信快捷登录', isShow: false },
/** * 生命周期函数--监听页面加载 */ onLoad: function (options) { // 从缓存中取手机号 console.log("获取手机号!") try { var value = wx.getStorageSync('phoneNumber') if (value) { // 说明已登录 跳转 页面 console.log("获取缓存:"+value) wx.navigateTo({ url: '../login?param=' + value }) }else{// 未登录 显示 微信授权页面 this.setData({ isShow: true }) } } catch (e) {
} // 解决第一次获取手机号失败问题 wx.login({ success: res => { if(res.code){ console.log("code->", res.code) } } }) },
// 0.获取手机号授权 getPhoneNumber: function(e) { // 用户拒绝授权 if(e.detail.errMsg == "getPhoneNumber:fail user deny") { wx.showToast({ icon: "none", title: '请允许获取手机号,否则功能不可用!', }) return } // console.log("e->detail", e.detail) /// 用户允许授权 // console.log("iv->", e.detail.iv); //包括敏感数据在内的完整用户信息的加密数据,需要解密 // console.log("encryptedData->", e.detail.encryptedData); //加密算法的初始向量,解密需要用到
/// 获取手机号 // 1.获取临时登录凭证code wx.login({ success: res => { if(res.code){ this.code = res.code; console.log("code->", res.code) console.log("encryptedData->", encodeURIComponent(e.detail.encryptedData)) console.log("iv->", e.detail.iv) this.getSessionKey(res.code, e.detail.encryptedData, e.detail.iv); } } }) }, // 2.访问登录凭证校验接口获取session_key(后续改成后台实现) getSessionKey: function(js_code, encryptedData, iv) { // 3. 解密获取手机号 wx.request({ url: 'http://localhost:8082/wechat/appletLogin', data: { 'encryptedData': encodeURIComponent(encryptedData),//需要进行编码 'iv': iv, 'jscode': js_code }, method: 'POST', header: { 'content-type': 'application/json' }, // 设置请求的 header success: function(data2) { var data = data2.data console.log(data) if(data.resultCode == 200) { if(data.data.user.phone==undefined){ // 获取手机号失败 跳转到 常规 用户登录页面(通过webview) wx.navigateTo({ url: '用户登录页' }) return } // 存储数据到缓存 wx.setStorage({ key:"phoneNumber", data:data.data.user.phone }) // 4.跳转页面 } }, fail: function(err) { console.log(err); wx.showToast({ icon: "none", title: '获取手机号失败,请重试!', }) } }) },
/** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () {
},
/** * 生命周期函数--监听页面显示 */ onShow: function () {
},
/** * 生命周期函数--监听页面隐藏 */ onHide: function () {
},
/** * 生命周期函数--监听页面卸载 */ onUnload: function () {
},
/** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () {
},
/** * 页面上拉触底事件的处理函数 */ onReachBottom: function () {
},
/** * 用户点击右上角分享 */ onShareAppMessage: function () {
}})
login.json
{ "usingComponents": {}}
login.wxml
<!--pages/login.wxml--><view class="modal-mask" catchtouchmove="preventTouchMove" wx:if="{{isShow}}"></view> <view class="modal-dialog" wx:if="{{isShow}}"> <view class="modal-content"> <view><image src='../images/show.png' class='show'></image></view> <!-- <view>绑定手机号</view> <view>请先绑定手机号在进行此操作</view> --> <button class="show" type="primary" lang="zh_CN" open-type='getPhoneNumber' bindgetphonenumber="getPhoneNumber" > 微信用户一键登录 </button> </view></view>
login.wxss
/* pages/login/login.wxml.wxss */.show{ display: block; border-radius: 8rpx; margin: 20rpx 20rpx 20rpx 20rpx; font-size: 35rpx;}
.container{ position: fixed; /*关键属性,设置为fixed*/ display: flex; flex-direction: column; width: 100%; height: 100%;}
后端代码
WxLoginController.java
public class WxLoginController {
private Logger logger = LoggerFactory.getLogger(WxLoginController.class); UserDao userDao; private String appid; private String appsecret; private Map<String, Object> userMap = new HashMap<>(); public ResultBean appletLogin(String encryptedData, String iv, String jscode) { System.out.println(encryptedData); ResultBean resultBean = new ResultBean(); // jscode if (StringUtils.isEmpty(jscode)) { resultBean.setResultCode(-10001); resultBean.setResultMessage("鉴权失败!"); return resultBean; } // sign if (StringUtils.isEmpty(encryptedData)) { resultBean.setResultCode(-10001); resultBean.setResultMessage("鉴权失败!"); return resultBean; } if(StringUtils.isBlank(iv)) { resultBean.setResultCode(-10002); resultBean.setResultMessage("鉴权失败!"); return resultBean; }
// 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault(); String resultString = ""; CloseableHttpResponse response = null; String url =WxContants.url.replace(WxContants.APPID, appid). replace(WxContants.SECRET, appsecret).replace(WxContants.JSCODE, jscode);
try { // 创建uri URIBuilder builder = new URIBuilder(url); URI uri = builder.build();
// 创建http GET请求 HttpGet httpGet = new HttpGet(uri);
// 执行请求 response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); } } catch (Exception e) { e.printStackTrace(); }
// 解析json JSONObject jsonObject = (JSONObject) JSONObject.parse(resultString); String session_key = jsonObject.getString("session_key"); String openid = jsonObject.getString("openid");
System.out.println("session_key:"+session_key + ",openid:"+openid); if (StringUtils.isEmpty(session_key)) { resultBean.setResultCode(-10003); resultBean.setResultMessage("获取sessionkey失败!"); return resultBean; }
// 解码 try { encryptedData = URLDecoder.decode(encryptedData,"UTF-8"); } catch (UnsupportedEncodingException e) { logger.error("encryptedData,decode失败!", e); resultBean.setResultCode(-10003); resultBean.setResultMessage("encryptedData,decode失败!"); return resultBean; } String decryptData = WechatDecryptDataUtil.decryptData(encryptedData, session_key, iv); JSONObject userInfo = JSONObject.parseObject(decryptData); // 存入redis+数据库,判断是否存在redis中,存在直接从redis返回 // 本地使用Map模拟 if (!userMap.containsKey(openid)) { // 判断用户是否存在系统中 String phoneNumber = userInfo.getString("phoneNumber"); User user = userDao.findByPhone(phoneNumber); if (user == null) { resultBean.setResultCode(200); resultBean.setResultMessage("此用户不存在,请先注册!"); return resultBean; } user.setOpenId(openid); userDao.save(user); userMap.put(openid, user); } User user = (User) userMap.get(openid); resultBean.setResultCode(200); resultBean.setResultMessage("成功!"); resultBean.setData(user); return resultBean; }}
UserDao.java
public interface UserDao extends JpaRepository<User, Long> {
User findByPhone(String phone);
User findByOpenId(String openId);}
User.java:
public class User {
private Long id; private String openId; private String phone;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getOpenId() { return openId; }
public void setOpenId(String openId) { this.openId = openId; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }}
WechatDecryptDataUtil.java
public class WechatDecryptDataUtil { private static Logger logger = LogManager.getLogger(WechatDecryptDataUtil.class);
public static void main(String[] args) { String result = decryptData( "BLY05rL1qLzGdqn+m4s4KfnM9CbMCm2sTZmgIcUJUpoOVeZkKKYh06ATVm2BgX8HUsH1a93811fhwr70MTh2Pk2qw9rPBzvos3husUJdVfaZgBk3Afp6wNFS0/kcoyt+7q2eMrIHMe6wkc4J0hgbbkxdUwZag/pyKXwe4pUzSQfta7dfBHy3DLu+REvwHiDNfvI3KJbZ0l8/9vRjfSmT4Q==", "C9Z59YjFkCDT8+9NQ3OxcA==", "oOWTpbZ80evG/GQqRdUu3w==" ); System.out.println("result = " + result); }
public synchronized static String decryptData(String encryptDataB64, String sessionKeyB64, String ivB64) { String res = null; try { res = new String( decryptOfDiyIV( Base64.decode(encryptDataB64), Base64.decode(sessionKeyB64), Base64.decode(ivB64) ) ); } catch (Exception e) { logger.error("encryptDataB64:"+encryptDataB64+"\n"+"sessionKeyB64:"+sessionKeyB64+"\n"+"ivB64:"+ivB64); }
return res; }
private static final String KEY_ALGORITHM = "AES"; private static final String ALGORITHM_STR = "AES/CBC/PKCS7Padding"; private static Key key; private static Cipher cipher;
private static void init(byte[] keyBytes) { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if (keyBytes.length % base != 0) { int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0); byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length); keyBytes = temp; } // 初始化 Security.addProvider(new BouncyCastleProvider()); // 转化成JAVA的密钥格式 key = new SecretKeySpec(keyBytes, KEY_ALGORITHM); try { // 初始化cipher cipher = Cipher.getInstance(ALGORITHM_STR, "BC"); } catch (Exception e) { e.printStackTrace(); } }
/** * 解密方法 * * @param encryptedData 要解密的字符串 * @param keyBytes 解密密钥 * @param ivs 自定义对称解密算法初始向量 iv * @return 解密后的字节数组 */ private static byte[] decryptOfDiyIV(byte[] encryptedData, byte[] keyBytes, byte[] ivs) { byte[] encryptedText = null; init(keyBytes); try { cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivs)); encryptedText = cipher.doFinal(encryptedData); } catch (Exception e) { e.printStackTrace(); } return encryptedText; }
}
WxContants.java
public interface WxContants {
String APPID = "APPID"; String SECRET = "SECRET"; String JSCODE = "JSCODE"; String TRADE_TYPE = "JSAPI"; String url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";}
简单的Java小程序
(一)简单的java程序publicclassMyFirstApp{publicstaticvoidmain(String[]args){System.out.print(He...
延伸阅读
本文来自投稿,不代表本人立场,如若转载,请注明出处:http://lnbdc.com/article/7214.html