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);
        }
    }

posted @ 2024-10-30 10:36  鱼鱼寡欢  阅读(3)  评论(0编辑  收藏  举报