背景
最近在工作中需要接入微信运动,获取微信步数。由于微信官方demo包里只有node、python、C++、php的代码,所以此处记录一下Java后端的代码。
1、微信官方文档地址:
微信运动:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/werun/wx.getWeRunData.html
2、核心步骤:
1、前端先调用wx.login(Object object)接口获取code,然后调用wx.getWeRunData(Object object)接口,获取加密数据encryptedData和加密算法的初始向量iv参数。
2、后端用code获取sessionKey,然后解密前端数据。
3、核心代码【屏蔽了公司业务代码】:
入参对象
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 微信运动记录
*
* @author Haixing
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MemberSportRecordWechatSaveDTO {
/**
* code
*/
@NotBlank(message = "code不能为空")
private String code;
/**
* 加密数据
*/
@NotBlank(message = "加密数据不能为空")
private String encryptedData;
/**
* 加密算法的初始向量
*/
@NotBlank(message = "加密算法的初始向量不能为空")
private String iv;
}
用的是hutool的解密工具包
import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
/**
* 开发者后台校验与解密开放数据工具类
*
* @author Haixing
*/
public class WXBizDataCryptUtil {
/**
* 解密
*
* @author Haixing
*/
@SneakyThrows
public static JSONObject decode(String sessionKey, String encryptedData, String iv, String appId) {
byte[] sessionKeyBytes = Base64.decode(sessionKey);
byte[] encryptedDataBytes = Base64.decode(encryptedData);
byte[] ivBytes = Base64.decode(iv);
// 创建AES实例
AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, sessionKeyBytes, ivBytes);
// 解密
String decrypted = aes.decryptStr(encryptedDataBytes);
JSONObject data = JSONUtil.parseObj(decrypted);
JSONObject watermark = data.getJSONObject("watermark");
// 验证appid
if (!appId.equals(watermark.getStr("appid"))) {
throw new RuntimeException("解密验证异常");
}
return data;
}
}
返回结果对象
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class Code2Session {
/**
* 错误码
*/
@JSONField(name = "errcode")
private String errCode;
/**
* 错误信息
*/
@JSONField(name = "errmsg")
private String errMsg;
/**
* 用户唯一标识
*/
@JSONField(name = "openid")
private String openId;
/**
* 会话密钥
*/
@JSONField(name = "session_key")
private String sessionKey;
/**
* 用户在开放平台的唯一标识符
*/
@JSONField(name = "unionid")
private String unionId;
}
业务service处理逻辑
/**
* 记录微信步数
*
* @author Haixing
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void saveBatchWechatSportRecord(MemberSportRecordWechatSaveDTO param) {
// 解密数据
Code2Session code2Session = getCode2Session(param.getCode());
JSONObject jSONObject = WXBizDataCryptUtil.decode(code2Session.getSessionKey(), param.getEncryptedData(), param.getIv(), "换成自己的appid");
}
获取sessionKey
/**
* code2Session
*
* @author Haixing
*/
@Override
public Code2Session getCode2Session(String code) {
// 地址是"https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
String url = String.format(SecurityConstants.MINI_APP_AUTHORIZATION_CODE_URL, "换成自己的appid", "换成自己的AppSecret", code);
String resultStr = HttpUtil.get(url);
Code2Session result = JSONObject.parseObject(resultStr, Code2Session.class);
if (!StringUtils.isEmpty(result.getErrCode())) {
// 公司框架的业务异常,需要转换成自己的失败处理逻辑或错误代码
throw new CheckedException(result.getErrMsg());
}
return result;
}
微信运动解析后的结果数据
{
"stepInfoList": [
{
"timestamp": 1445866601,
"step": 100
},
{
"timestamp": 1445876601,
"step": 120
}
]
}