微信公众号H5页面跳转小程序 Java

后台生成并返回前端所需参数

1:jsapi_ticket

jsapi_ticket是公众号用于调用js接口的临时票据。有效期7200秒,跟公众号普通access_token一样,必须全局缓存起来,因为这个ticket获取次数有限,超过次数将无法使用。

1.1获取access_token

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

1.2获取jsapi_ticket

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

2:生成签名

签名规则:
1、参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分)。
2、对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序,sort()即可)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串(string)。
3、使用sha1加密拼接成的字符串string。
注意:字段名和字段值都要使用原值,不要进行url转义

参与的字段:

noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=调用js接口的安全域名

2.1:校验签名

https://work.weixin.qq.com/api/jsapisign

3:后端完整代码

 public  net.sf.json.JSONObject getConfig(String url){
        //url为前端动态入参
        net.sf.json.JSONObject object = new net.sf.json.JSONObject();
        String access_token = redisStringService.get("AccessToken");
        String jsapi_ticket = redisStringService.get("JsapiTicket");
        if(StringUtils.isEmpty(access_token)){
            //获取access_token
            String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
                    + wxConfigYml.getWxAppId()
                    + "&secret="
                    + wxConfigYml.getWxSecret();
            String result = HttpUtil.sendGet(tokenUrl);
            JSONObject accessObj = JSON.parseObject(result);
            String accessToken = accessObj.getString("access_token");
            redisStringService.put("AccessToken", accessToken, 7180);
        }
        if (StringUtils.isEmpty(jsapi_ticket)) {
            //获取jsapi
            String jsapiStr  = HttpUtil.sendGet("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi");
            net.sf.json.JSONObject jsapi = net.sf.json.JSONObject.fromObject(JSON.parseObject(jsapiStr));
            jsapi_ticket = jsapi.getString("ticket");
            redisStringService.put("JsapiTicket",jsapi_ticket,7180);
        }
        //获取签名signature
        String noncestr = IdGen.uuid();
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String str = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + noncestr +
                "×tamp=" + timestamp +
                "&url=" + url;
        //sha1加密
        String signature = WechatConfig.sha1(str);
        object.put("noncestr",noncestr);
        object.put("timestamp",timestamp);
        object.put("signature",signature);
        object.put("jsapi_ticket",jsapi_ticket);
        log.info("jsapi_ticket="+jsapi_ticket);
        log.info("noncestr="+noncestr);
        log.info("timestamp="+timestamp);
        log.info("url="+url);
        log.info("signature="+signature);
        return object;
    }
3.1加密方法
    public static String sha1(String str) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(str.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
3.2httpUtil
public class HttpUtil {

    private static  CloseableHttpClient httpclient = HttpClients.createDefault();

    /**
     * 发送HttpGet请求
     * @param url
     * @return
     */
    public static String sendGet(String url) {

        HttpGet httpget = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpget);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        String result = null;
        try {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发送HttpPost请求,参数为map
     * @param url
     * @param map
     * @return
     */
    public static String sendPost(String url, Map map) {
        List formparams = new ArrayList();
        for (Map.Entry entry : map.entrySet()) {
            formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
        HttpPost httppost = new HttpPost(url);
        httppost.setEntity(entity);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httppost);
        } catch (IOException e) {
            e.printStackTrace();
        }
        HttpEntity entity1 = response.getEntity();
        String result = null;
        try {
            result = EntityUtils.toString(entity1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 发送不带参数的HttpPost请求
     * @param url
     * @return
     */
    public static String sendPost(String url) {
        HttpPost httppost = new HttpPost(url);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httppost);
        } catch (IOException e) {
            e.printStackTrace();
        }
        HttpEntity entity = response.getEntity();
        String result = null;
        try {
            result = EntityUtils.toString(entity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String post(String url, String jsonString) {
        CloseableHttpResponse response = null;
        BufferedReader in = null;
        String result = "";
        try {
            HttpPost httpPost = new HttpPost(url);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
            httpPost.setConfig(requestConfig);
            httpPost.setConfig(requestConfig);
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            httpPost.setHeader("Accept", "application/json");
            httpPost.setEntity(new StringEntity(jsonString, Charset.forName("UTF-8")));
            response = httpclient.execute(httpPost);
            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuffer sb = new StringBuffer("");
            String line = "";
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                sb.append(line + NL);
            }
            in.close();
            result = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != response) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

4.常见问题

1、前端wx.config配置中的nonceStr字段名称的's'是大写。但是后台生成签名的noncestr字段 的‘s'是小写,千万要注意
2、时间戳(timestamp)值要记住精确到秒,不是毫秒。
3、生成签名的url(使用jssdk的页面地址,这个页面地址可以在浏览器访问),包含“?”号后面的所有参数,不包含“#”号后面的值。
如果是静默授权或者授权页面同意授权后跳转到的页面,页面路径会添加两个参数:code和state。
即授权后跳转页面为http://redirect.page.com,则完整路径为
http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE。
那么生成签名的url必须为授权后跳转页面的完整路径。前端获取这个路径:location.href.split('#')[0]

你可能感兴趣的:(微信公众号H5页面跳转小程序 Java)