Springboot小程序相关
记录一些与小程序相关的内容,例如登录,发送订阅消息等
1. 登录相关
1.1. 获取openid
/**
* code:由小程序生成
* appid:小程序id
* secret:密钥
**/
public String getOpenid(String code) {
String data = "appid=" + appid + "&" +
"secret=" + secret + "&" +
"js_code=" + code + "&" +
"grant_type=" + "authorization_code";
JSONObject jsonObject = JSONObject.parseObject(HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session?" + data));
return jsonObject.getString("openid");
}
1.2. 登录
这块主要是获取openid后,查询是否存在与该openid绑定的账号,有则调用登录,返回登录信息,如果没有,则直接注册新用户
1.3. 获取手机号
手机号登录与openid直接登录相同,我这边写的是,先调用openid登录,如果当前用户未注册,则先不注册,将openid存入redis,返回openidToken,前端调起手机号选择,用户选择手机号后,调用手机号登录,将code与openidToken返回,后端获取手机号就可以获取到用户手机号了,现在可以创建新用户,存入openid与手机号
public String getPhone(String code) {
// 获取token
String appletToken = String.valueOf(getAccessToken());
// 构建参数
Map<String,Object> paramMap = new HashMap<>();
paramMap.put("code",code);
String res = HttpRequest.post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + appletToken)
.header("Content-Type", "application/json").body(JSONUtils.toJSONString(paramMap)).execute().body();
return JSONObject.parseObject(res).getJSONObject("phone_info").getString("phoneNumber");
}
public String getAccessToken() {
String result;
if (redisUtil.hasKey("AppletToken")) {
return redisUtil.get("AppletToken").toString();
}
try {
String baseUrl = "https://api.weixin.qq.com/cgi-bin/token";
HashMap<String, Object> requestParam = new HashMap<>();
requestParam.put("grant_type", "client_credential");
// 小程序唯一凭证id appid
requestParam.put("appid", appid);
// 小程序 appSecret
requestParam.put("secret", secret);
// 发送GET请求读取调用微信接口获取openid用户唯一标识
result = HttpUtil.get(baseUrl, requestParam);
} catch (Exception e) {
throw new ServiceException(GENERATE_TOKEN_ERROR);
}
String token = JSON.parseObject(result).getString("access_token");
//将token存到redis,有效期100分钟。官方接口返回的token有效期120分钟
redisUtil.set("AppletToken", token, 100 * MyConstants.MINUTER);
return token;
}
2. 发送订阅消息
2.1. 创建参数
public Map<String, Object> createParams(String name,String phone,String time,String reason){
Map<String, Object> objMap = new HashMap<>(5);
Map<String, String> map = new HashMap<>(1);
map.put("value", name);
objMap.put("thing1", map);
map = new HashMap<>(1);
map.put("value", phone);
objMap.put("phone_number7", map);
map = new HashMap<>(1);
map.put("value", time);
objMap.put("time2", map);
map = new HashMap<>(1);
map.put("value", reason);
objMap.put("thing11", map);
return objMap;
}
2.2. 发送订阅消息
public void msgSend(String templateId, String page, Map<String, Object> data,String openId) {
try {
// getAccessToken()在上面有贴过,这里就不贴了,直接调用
String accessToken = getAccessToken();
// region 推送小程序信息
String msgUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
// 请求参数处理
Map<String, Object> params = new HashMap<>(6);
// 目标用户
params.put("touser", openId);
// 这个templateId需要在微信公众号中创建模板,之后使用模板id发送,与短信类似
params.put("template_id", templateId);
// page则为用户收到消息后点击消息跳转的页面,例如/index
params.put("page", page);
params.put("lang", "zh_CN");
params.put("miniprogram_state", "formal");
// 模板参数,2.1调用生成后传入当前方法
params.put("data", data);
String res = HttpRequest.post(msgUrl)
.header("Content-Type", "application/json")
// 这个toJSONString很关键
.body(JSONUtils.toJSONString(params)).execute().body();
JSONObject msgResultObject = JSONObject.parseObject(res);
if (!"0".equals(msgResultObject.get("errcode").toString())) {
throw new RuntimeException("发送订阅消息失败," + msgResultObject.get("errmsg"));
}
} catch (Exception e) {
throw new RuntimeException("发送订阅消息失败," + e);
}
}