java调用微信开发(微信开发文档)报错:errMsg config invalid signature

package com.hy.utils.wechat;

import com.hy.common.redis.RedisPublicManager;
import com.hy.common.utils.Constant;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 微信开发相关工具
 * 
 */
public class WechatUtils {


    private static Logger log  = LoggerFactory.getLogger(WechatUtils.class);

    private static final String jsApi_Url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
    //普通access_token_url
    private static final String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    //通过普通access_token获取公众号关注者个人信息
    private static final String token_userinfo_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    //授权code_url
    private static final String oauth_code_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
    //授权access_token_url
    private static final String oauth_access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    //根据授权access_token获取用户信息
    private static final String oauth_token_userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    
    /**
     * 获取微信授权access_token
     * @param appId
     * @param appsecret
     * @param code
     * @return
     * @throws Exception
     */
    public static com.alibaba.fastjson.JSONObject getWxOauthToken(String appId,String appsecret,String code) throws Exception {
        String url= oauth_access_token_url.replace("APPID",appId).replace("SECRET", appsecret).replace("CODE", code);
        String  result = httpRequest(url,"GET",null);
        com.alibaba.fastjson.JSONObject jsonresult = com.alibaba.fastjson.JSONObject.parseObject(result);
        log.info("oauth access_token:{} ", jsonresult);
        return jsonresult;
    }
    
    /**
     * 获取公众号关注者的个人信息
     * @param appId
     * @param appsecret
     * @param code
     * @return
     * @throws Exception
     */
    public static com.alibaba.fastjson.JSONObject getWxOfficialUserInfo(String officialAccessToken,String openid) throws Exception {
    	String url= token_userinfo_url.replace("ACCESS_TOKEN",officialAccessToken).replace("OPENID", openid);
        String  result = httpRequest(url,"GET",null);
        com.alibaba.fastjson.JSONObject jsonresult = com.alibaba.fastjson.JSONObject.parseObject(result);
        log.info("official user info :{} ", jsonresult);
        return jsonresult;
    }
    
    /**
     * 根据授权access_token获取用户信息
     * @param oauthAccessToken
     * @param openid
     * @return
     * @throws Exception
     */
    public static com.alibaba.fastjson.JSONObject getWxOauthUserInfo(String oauthAccessToken,String openid) throws Exception {
        String url= oauth_token_userinfo_url.replace("ACCESS_TOKEN",oauthAccessToken).replace("OPENID", openid);
        String  result = httpRequest(url,"GET",null);
        com.alibaba.fastjson.JSONObject jsonresult = com.alibaba.fastjson.JSONObject.parseObject(result);
        log.info("oauth user info:{} ", jsonresult);
        return jsonresult;
    }
    
    
    
    public static String getWxJsTicket(String appId,String appsecret) throws Exception {

        String accessToken = RedisPublicManager.get(Constant.WECHAT_TOKEN_REDIS);
        if(StringUtils.isEmpty(accessToken)) {
            accessToken = getAccessToken(appId,appsecret);
        }
        String url= jsApi_Url.replace("ACCESS_TOKEN",accessToken);
        String  result = httpRequest(url,"GET",null);
        JSONObject jsonresult = JSONObject.fromObject(result);
        System.out.println("getWxJsTicket:="+jsonresult.toString());
        String ticket = null;
        if(jsonresult.getInt("errcode")==0) {
            ticket = jsonresult.getString("ticket");
        }
        log.info("ticket jsapi_ticket:{} ", ticket);
        return ticket;
    }

    public static String getAccessToken(String appId,String appSecret) {
        AccessToken accessToken = null;
        String requestUrl = access_token_url.replace("APPID", appId).replace("APPSECRET",appSecret);
        JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
        System.out.println("jsonObject:"+jsonObject);
        // 如果请求成功
        if (null != jsonObject) {
            try {
                accessToken = new AccessToken();
                String token = jsonObject.getString("access_token");
                accessToken.setToken(token);
                accessToken.setExpiresIn(jsonObject.getInt("expires_in"));

                //设置缓存
                RedisPublicManager.add(Constant.WECHAT_TOKEN_REDIS,token);

            } catch (Exception e) {
                accessToken = null;
                e.printStackTrace();
                // 获取token失败
                log.info("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return accessToken.getToken();
    }

    public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
        try {

            URL url = new URL(requestUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            //对浏览返回的对象进行重新编码
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            //读取对象
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            //用于存放读取对象结果的
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                //读取对象将结果读取出来
                buffer.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            return buffer.toString();
        } catch (ConnectException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonObject;
    }

    public static String getJsapiSign(String noncestr,String jsapi_ticket,String timestamp,String url){
        JSONObject jsonObject = new JSONObject();     
        jsonObject.put("jsapi_ticket",jsapi_ticket);
        jsonObject.put("noncestr",noncestr);
        jsonObject.put("timestamp",timestamp);
        jsonObject.put("url",url);
        jsonObject = sortJsonObject(jsonObject);
        String body = "";
        // 获取body信息拼接字符串
        Iterator it = jsonObject.keys();
        while(it.hasNext()){
            String key = (String) it.next();
            String  value= jsonObject.getString(key);
            body += "&"+key +"="+value;
        }
        body = body.substring(1);
        System.out.println("body=====>"+body);
        String signature = getSha1(body);
        System.out.println("signature===>"+signature);
        return signature;
    }

    public static JSONObject sortJsonObject(JSONObject obj) {
        Map map = new TreeMap();
        Iterator<String> it = obj.keys();
        while (it.hasNext()) {
            String key = it.next();
            Object value = obj.get(key);
            if (value instanceof JSONObject) {
                map.put(key, sortJsonObject(JSONObject.fromObject(value)));
            } else {
                map.put(key, value);
            }
        }
        return JSONObject.fromObject(map);
    }

    public static String getSha1(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};

        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            return null;
        }
    }


    public static Map<String, String> getSignature(String appId,String appsecret, String url) throws Exception {
         String jsapiTicket = getWxJsTicket(appId, appsecret);
        Map<String, String> ret = new HashMap<String, String>();
        String nonceStr = createNonceStr();
        String timestamp = createTimestamp();
        String signature = "";

        //注意这里参数名必须全部小写,且必须有序
        String string1 = "jsapi_ticket=" + jsapiTicket +
                "&noncestr=" + nonceStr +
                "×tamp=" + timestamp +
                "&url=" + url;
        System.out.println(string1);

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapiTicket", jsapiTicket);
        ret.put("nonceStr", nonceStr);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash){
          formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private static String createNonceStr() {
        return UUID.randomUUID().toString();
    }

    private static String createTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}

调用:JSONObject result = WechatUtils.getWxOauthToken(Constant.appMobileId, Constant.appMobileSecret, code);

String officialAccessToken = WechatUtils.getAccessToken(Constant.appId, Constant.appsecret);

踩的坑:报错   errMsg config invalid signature
因为一开始是订阅号。用 wx-open-launch-weapp必须用服务号

得到服务号后。把域名添加上

点击js接口安全域名的设置后出现如下,把MP_verify_KuEMpGwqo3AMxFP2.txt下载下来,放到项目的根目录,放好后才能点击保存,如果放的目录正确那会弹出提交成功。

然后在浏览器里的url栏用域名/MP_verify_KuEMpGwqo3AMxFP2.txt 能正常访问就是成功了。
还要添加IP白名单。就是把测试正式环境的ip添加到白名单,点击查看有修改的按钮。

还是报错   errMsg config invalid signature
看的测试环境的日志发现前端传的url有%号

处理一下。不要有% 正常显示就成功了。

 

微信公众号官网:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html


生成的签 名和以下链接生成的一样就代表是对的
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

 

 

Guess you like

Origin blog.csdn.net/weixin_43075758/article/details/117331258