最近在帮朋友做小程序项目,把之前的web的商城新增支持小程序,预计本周内做完。
今天把首页、商品列表、详情和登录做完了,记录一下登录的实现。
先上效果图啦!
不多说,直接上代码
一、小程序前端代码
/**
* 调用微信登录,获取sessionKey
*/
function loginByWeixin() {
let code = null;
return new Promise(function (resolve, reject) {
return login().then((res) => {
code = res.code;
return getUserInfo();
}).then((userInfo) => {
//登录远程服务器
wx.request({
url: "http://localhost:8080/api/wx/login",
data: {
code: code,
userInfo: userInfo
},
method: 'POST',
header: {
'Content-Type': 'application/json',
'X-Nideshop-Token': wx.getStorageSync('token')
},
success: function (res) {
console.log(res);
if (res.statusCode == 200) {
//存储用户信息
wx.setStorageSync('userInfo', res.data.data.userInfo);
wx.setStorageSync('token', res.data.data.token);
// 跳转登录页面
wx.switchTab({
url: '/pages/ucenter/index/index',
});
resolve(res);
} else {
reject(res.message);
}
},
fail: function (err) {
reject(err)
}
})
}).catch((err) => {
reject(err);
})
});
}
/**
* 调用微信登录生成code
*/
function login() {
return new Promise(function (resolve, reject) {
wx.login({
success: function (res) {
if (res.code) {
//登录远程服务器
resolve(res);
} else {
reject(res);
}
},
fail: function (err) {
reject(err);
}
});
});
}
/**
* 获取用户信息
*/
function getUserInfo() {
return new Promise(function (resolve, reject) {
wx.getUserInfo({
withCredentials: true,
success: function (res) {
resolve(res);
},
fail: function (err) {
reject(err);
}
})
});
}
二、Java后端代码
1、控制器代码
/**
* 微信用户登录详情
*/
@PostMapping("/api/wx/login")
@ResponseBody
public Result user_login(@RequestBody Map<String, Object> param) {
String code = (String) param.get("code");
Map<String, Object> userInfoMap = (Map<String, Object>) param.get("userInfo");
Map<String, Object> rawData = (Map<String, Object>) userInfoMap.get("userInfo");
String signature = (String) userInfoMap.get("signature");
String encrypteData = (String) userInfoMap.get("encryptedData");
String iv = (String) userInfoMap.get("iv");
// 用户非敏感信息:rawData
// 签名:signature
// 1.接收小程序发送的code
// 2.开发者服务器 登录凭证校验接口 appi + appsecret + code
JSONObject SessionKeyOpenId = WxUtil.getSessionKeyOrOpenId(code);
// 3.接收微信接口服务 获取返回的参数
String openid = SessionKeyOpenId.getString("openid");
String sessionKey = SessionKeyOpenId.getString("session_key");
// 4.校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey)
String signature2 = DigestUtils.sha1Hex(JSON.toJSONString(rawData) + sessionKey);
if (!signature.equals(signature2)) {
return ResultGenerator.genFailResult("签名校验失败");
}
// 5.根据返回的User实体类,判断用户是否是新用户,是的话,将用户信息存到数据库;不是的话,更新最新登录时间
User user = this.userService.findByOpenId(openid);
if (user == null) {
// 用户信息入库
String nickName = (String) rawData.get("nickName");
String avatarUrl = (String) rawData.get("avatarUrl");
user = new User();
user.setOpenId(openid);
user.setSkey(sessionKey);
user.setCreateTime(new Date());
user.setAvatar(avatarUrl);
user.setNickName(nickName);
String passwordMD5 = MD5Util.MD5Encode("123456", "UTF-8");
user.setPasswordMd5(passwordMD5);
user.setLoginName("wx用户" + System.currentTimeMillis());
this.userService.insertUser(user);
} else {
// 重新设置会话skey
user.setSkey(sessionKey);
userService.updateUserInfo(user, null);
}
//6. 把新的skey返回给小程序
Map<String, Object> result = new HashMap<>();
result.put("token", sessionKey);
result.put("userInfo", rawData);
return ResultGenerator.genSuccessResult("登录成功", result);
}
2、其他代码
pom.xml 部分代码
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
<!--base64加密解密-->
<!--shiro依赖和缓存-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<!-- http请求工具包依赖 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
HttpClientUtil.java
package com.example.mall.util;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author 言曌
* @date 2021/3/8 5:52 下午
*/
public class HttpClientUtil {
public static String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
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();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGet(String url) {
return doGet(url, null);
}
public static String doPost(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPost(String url) {
return doPost(url, null);
}
public static String doPostJson(String url, String json) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
}
WxUtil
package com.example.mall.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.shiro.codec.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* @author 言曌
* @date 2021/3/8 5:49 下午
*/
public class WxUtil {
/**
* 获得openID和sessionkey
*
* @param code
* @return
*/
public static JSONObject getSessionKeyOrOpenId(String code) {
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
Map<String, String> requestUrlParam = new HashMap<>();
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN
//小程序appId
requestUrlParam.put("appid", "wx818b2b43c52117f9");
//小程序secret
requestUrlParam.put("secret", "52877e406406b61b829a789fb2b68b3a");
//小程序端返回的code
requestUrlParam.put("js_code", code);
//默认参数
requestUrlParam.put("grant_type", "authorization_code");
//发送post请求读取调用微信接口获取openid用户唯一标识
JSONObject jsonObject = JSON.parseObject(HttpClientUtil.doPost(requestUrl, requestUrlParam));
return jsonObject;
}
/**
* 获取用户信息
*
* @param encryptedData
* @param sessionKey
* @param iv
* @return
*/
public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
// 被加密的数据
byte[] dataByte = Base64.decode(encryptedData);
// 加密秘钥
byte[] keyByte = Base64.decode(sessionKey);
// 偏移量
byte[] ivByte = Base64.decode(iv);
try {
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
// 初始化
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
parameters.init(new IvParameterSpec(ivByte));
cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
byte[] resultByte = cipher.doFinal(dataByte);
if (null != resultByte && resultByte.length > 0) {
String result = new String(resultByte, "UTF-8");
return JSON.parseObject(result);
}
} catch (Exception e) {
}
return null;
}
}
其他代码就没必要贴了
参考:https://www.jianshu.com/p/4e4db943bfb3
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏