1.获取过程及需要的参数,图已经很明显,这个是在网上拿别人的图,写的很好很到位,就不一一解释,比较我也是菜鸟
2,在小程序这边,我们需要用 wx.login来给后台传code(因为微信小程序,不支持在小程序页面使用appid和secret,防止你的信息丢失,所以正式版只能从后台调用接口),注意code只有十分钟有效期,而且每次访问code都是变化的(微信这么写的)
后台代码
public class WxStepController {
private String appid = "你的appid";
private String secret = "你的secret";
private String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=";
private String url0 = "&grant_type=authorization_code";
//我自己的注入,------------------------------------
@Autowired
private MemberMapper ms;
@Autowired 虚线内的你们可以不要
private WalkStepMapper ws;
------------------------------------------------------
protected static final Logger logger = LoggerFactory.getLogger(WxStepController.class);
@ApiOperation(value = "微信登录")
@ApiImplicitParam(name = "code",value = "微信code",required = true, dataType = "int") //两行为swagger的注解,可以不要
@RequestMapping("/onlogin")
public String login(String code){
String oppid="";
JSONObject oppidObj=null;
try {
oppid = new HttpRequestor().doGet(url+code+url0); //url+code+url0
oppidObj =JSONObject.fromObject(oppid);
System.out.println(oppidObj);
} catch (Exception e) {
e.printStackTrace();
}
logger.debug("获取到的json串"+oppid);
Gson gson = new Gson();
return gson.toJson(oppidObj);
}
这样的话,就能获取到用户session_key,openid(对于一个公众号唯一),
获取到的json,这些数据都是临时,并对公众号唯一,所以你们拿去也没用
3.这时候,我们需要用wx.getWeRunData来获取微信运动的数据,以及加密方式等,用来解密微信运动数据数据
其中,token是用来验证用户是否登录,和传递用户信息的,相信很多都用,因为我这个是app跳小程序,所以传token,如果只是小程序的,传openid即可,因为这就是唯一标识符,openid在上面的json已经获取到
解密方法类AES,直接copy别人的
POM依赖
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.2</version>
</dependency>
<dependency>
<groupId>net.sf.ezmorph</groupId>
<artifactId>ezmorph</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.hynnet</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
<!--加密组件-->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.57</version>
</dependency>
<!--google转json-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
http请求工具类
import java.io.*;
import java.net.*;
import java.util.Iterator;
import java.util.Map;
/**
* Created by Administrator on 2018/5/24.
*/
public class HttpRequestor {
private String charset = "utf-8";
private Integer connectTimeout = null;
private Integer socketTimeout = null;
private String proxyHost = null;
private Integer proxyPort = null;
public HttpRequestor() {
}
public String doGet(String url) throws Exception {
URL localURL = new URL(url);
URLConnection connection = this.openConnection(localURL);
HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
httpURLConnection.setRequestProperty("Accept-Charset", this.charset);
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
StringBuffer resultBuffer = new StringBuffer();
String tempLine = null;
if(httpURLConnection.getResponseCode() >= 300) {
throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
} else {
try {
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
reader = new BufferedReader(inputStreamReader);
while((tempLine = reader.readLine()) != null) {
resultBuffer.append(tempLine);
}
} finally {
if(reader != null) {
reader.close();
}
if(inputStreamReader != null) {
inputStreamReader.close();
}
if(inputStream != null) {
inputStream.close();
}
}
return resultBuffer.toString();
}
}
public String doPost(String url, Map parameterMap) throws Exception {
StringBuffer parameterBuffer = new StringBuffer();
if(parameterMap != null) {
Iterator iterator = parameterMap.keySet().iterator();
String key = null;
String value = null;
while(iterator.hasNext()) {
key = (String)iterator.next();
if(parameterMap.get(key) != null) {
value = (String)parameterMap.get(key);
} else {
value = "";
}
parameterBuffer.append(key).append("=").append(value);
if(iterator.hasNext()) {
parameterBuffer.append("&");
}
}
}
System.out.println("POST parameter : " + parameterBuffer.toString());
URL localURL = new URL(url);
URLConnection connection = this.openConnection(localURL);
HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Accept-Charset", this.charset);
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(parameterBuffer.length()));
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
StringBuffer resultBuffer = new StringBuffer();
String tempLine = null;
try {
outputStream = httpURLConnection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write(parameterBuffer.toString());
outputStreamWriter.flush();
if(httpURLConnection.getResponseCode() >= 300) {
throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
}
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
reader = new BufferedReader(inputStreamReader);
while((tempLine = reader.readLine()) != null) {
resultBuffer.append(tempLine);
}
} finally {
if(outputStreamWriter != null) {
outputStreamWriter.close();
}
if(outputStream != null) {
outputStream.close();
}
if(reader != null) {
reader.close();
}
if(inputStreamReader != null) {
inputStreamReader.close();
}
if(inputStream != null) {
inputStream.close();
}
}
return resultBuffer.toString();
}
private URLConnection openConnection(URL localURL) throws IOException {
URLConnection connection;
if(this.proxyHost != null && this.proxyPort != null) {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(this.proxyHost, this.proxyPort.intValue()));
connection = localURL.openConnection(proxy);
} else {
connection = localURL.openConnection();
}
return connection;
}
private void renderRequest(URLConnection connection) {
if(this.connectTimeout != null) {
connection.setConnectTimeout(this.connectTimeout.intValue());
}
if(this.socketTimeout != null) {
connection.setReadTimeout(this.socketTimeout.intValue());
}
}
public Integer getConnectTimeout() {
return this.connectTimeout;
}
public void setConnectTimeout(Integer connectTimeout) {
this.connectTimeout = connectTimeout;
}
public Integer getSocketTimeout() {
return this.socketTimeout;
}
public void setSocketTimeout(Integer socketTimeout) {
this.socketTimeout = socketTimeout;
}
public String getProxyHost() {
return this.proxyHost;
}
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
public Integer getProxyPort() {
return this.proxyPort;
}
public void setProxyPort(Integer proxyPort) {
this.proxyPort = proxyPort;
}
public String getCharset() {
return this.charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
}
AES解密工具类
import org.bouncycastle.jce.provider.BouncyCastleProvider;
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;
public class AES {
public static boolean initialized = false;
/**
* AES解密
* @param content 密文
* @return
* @throws InvalidAlgorithmParameterException
* @throws NoSuchProviderException
*/
public static 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;
}
}
这部分是解密以及存数据库的部分,肯在页面传值,确定要协调多少天数据
@ApiOperation(value = "获取微信运动步数,并存储到数据库,只校对最近三天的")
@ApiImplicitParams({
@ApiImplicitParam(name = "encryptedData", value = "加密数据", required = true, dataType = "string"),
@ApiImplicitParam(name = "iv", value = "加密方式", required = true, dataType = "string"),
@ApiImplicitParam(name = "sessionKey", value = "微信用code换的钥匙", required = true, dataType = "string"),
@ApiImplicitParam(name = "token", value = "用户token", required = true, dataType = "string"),
@ApiImplicitParam(name = "days", value = "需要协调的天数", required = true, dataType = "int")
})
@RequestMapping("/decrypt")
public String decrypt(String encryptedData, String iv, String sessionKey, String token,Integer days) throws Exception{
Map map = new HashMap();
try {
byte[] resultByte = AES.decrypt(Base64.decodeBase64(encryptedData),
Base64.decodeBase64(sessionKey),
Base64.decodeBase64(iv));
if(null != resultByte && resultByte.length > 0){
String userInfo = new String(resultByte, "UTF-8");
map.put("status", "1");
map.put("msg", "解密成功");
map.put("userInfo", userInfo);
//获取当前调接口用户的信息
List<TMemberBase> user=null;
if(token!=null) {
user = ms.findAllByToken(token);
}else{
map.put("errormsg","token不能为空");
}
//将微信运动的数据,转换为list
JSONObject userinfo = JSONObject.fromObject(userInfo);
String stepInfoList = userinfo.getString("stepInfoList");
Gson gson = new Gson();
List<WxStep> list = gson.fromJson(stepInfoList, new TypeToken<List<WxStep>>() {}.getType());
int size=list.size();
for (int i = 0; i < days; i++) {
//判断最近三天的数据,有没有存储过,有就只改变步数,没就存储
List<TWalk> walk = ws.findAllByMemberIdAndRecordDate(user.get(0).getMemberId(), DateKit.converIntToYYYYMMDD(list.get(size-i-1).getTimestamp()));
System.out.println("shuzu---"+walk);
int size1= walk.size();
if(size1>0&&walk!=null) {
TWalk tWalk = walk.get(0);
tWalk.setStepNum(list.get(size - i - 1).getStep());
ws.save(tWalk);
}else{
TWalk tWalk1 = new TWalk();
tWalk1.setMemberId(user.get(0).getMemberId());
tWalk1.setMemberName(user.get(0).getMemberName());
tWalk1.setOrgId(user.get(0).getOrgId());
tWalk1.setOrgName(user.get(0).getOrgName());
tWalk1.setRecordTime(list.get(size - i - 1).getTimestamp());
tWalk1.setRecordDate(DateKit.converIntToYYYYMMDD(list.get(size - i - 1).getTimestamp()));
tWalk1.setStepNum(list.get(size - i - 1).getStep());
ws.save(tWalk1);
}
}
}else{
map.put("status", "0");
map.put("msg", "解密失败");
}
}catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Gson gson = new Gson();
String decodeJSON = gson.toJson(map);
return decodeJSON;
}
微信运动获取来的json串
这就算完成了,只需要把返回结果,放进data,然后页面调用就行,我把整体代码再贴一遍,免的你们看着乱
完整代码
在data中,加上 runData:{}即可
var that = this;
wx.login({
success: function(res) {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
//if (res.code) {
wx.request({
url: 'https://你的服务器地址/onlogin', //本地调试,是获取不到code的,所以要实现,还是得传服务
data: {
"code": res.code
},
header: {
'content-type': 'application/json' // 默认值
},
success: function (res) {
console.log(res.data)
console.log("sessionkey--" + res.data.session_key)
//2、调用小程序API: wx.getWeRunData获取微信运动数据(加密的);
wx.getWeRunData({
success(resRun) {
const encryptedData = resRun
console.info(resRun);
//3、解密步骤2的数据;
wx.request({
url: 'https://你的服务器地址/decrypt', //记得更改
data: {
encryptedData: resRun.encryptedData,
iv: resRun.iv,
sessionKey: res.data.session_key,
token:'用户token,如果你只是小程序开发,传openid即:res.data.openid',days: 3 //传要协调的天数
},
method: 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
// header: {}, // 设置请求的 header
success: function (resDecrypt) {
var runData = JSON.parse(resDecrypt.data.userInfo)
console.info(runData);
if (runData.stepInfoList) {
runData.stepInfoList = runData.stepInfoList.reverse()
for (var i in runData.stepInfoList) {
//给数据加上时间,格式呢,在你的util.js下面写,建微信小程序项目的时候就有,import进来就行,不要也可以
runData.stepInfoList[i].date = util.formatTime(new Date(runData.stepInfoList[i].timestamp * 1000))
}
that.setData({
runData: runData.stepInfoList
});
}
}
});
}
})
}
})
//} else {
// console.log('获取用户登录态失败!' + res.errMsg)
//}
}
})
页面显示部分(我只取了当天数据,所以下标是0,如果要显示30天数据,用wx:for-items={{runData}})
后台代码,上面都有,只需要把我的存储步数的类,换成你的即可 (TWalk)数据存储和查询部分,根据自己情况即可,第一次在这上面发,写的不好,大家见谅,有问题可以互动的哦,希望能帮到大家,方法上面那些@Api什么的,都是swagger的注解,前后端分离时候,为前后知道接口作用和要传的参数用的