Springboot小程式相關

鱼鱼寡欢發表於2024-10-30

記錄一些與小程式相關的內容,例如登入,傳送訂閱訊息等

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

相關文章