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的注解,前后端分离时候,为前后知道接口作用和要传的参数用的













