微信转发带图片和描述——JAVA {errmsg:config: invalid signature}

  网上看了好多大佬的文章,发现都不太适合我这种小白来操作,so只能结合大部分代码来自己操作,捣鼓了2天终于可以实现转发带着图片和描述了,我认为的比较简单的整个流程是这样的(哪里不正确请大佬指教):通过api连接获得access_token>通过access_token来换取jsapi(ticket)>获取时间毫秒数/随即字符串/动态获取的url>把这四个参数放到str中并使用SHA1加密再传到前台即可,废话不多说,开始代码(servlet):

获取token和ticket的类:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;


/**
 * 获取token  获取ticket
 * @author Administrator
 *
 */
public class JsapiTicketUtil {

public static String sendGet(String url, String charset, int timeout)
    {
      String result = "";
      try
      {
        URL u = new URL(url);
        try
        {
          URLConnection conn = u.openConnection();
          conn.connect();
          conn.setConnectTimeout(timeout);
          BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
          String line="";
          while ((line = in.readLine()) != null)
          {       
            result = result + line;
          }
          in.close();
        } catch (IOException e) {
          return result;
        }
      }
      catch (MalformedURLException e)
      {
        return result;
      }
     
      return result;
    }
   /***
    * 获取acess_token 
    * @return
    */
   public static String getAccessToken(){
     //获取token
String acess_token ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=你自己的appid";
          String token = sendGet(acess_token, "utf-8", 10000);
          return token;
   }
  /***
    * 获取jsapiTicket
    */
  public static String getJSApiTicket(){ 
      JsonParser jsonparer = new JsonParser();
      JsonObject json = null;
      JsonObject json2 = null;
      //获取token
      String acess_token= getAccessToken(); 
      json = jsonparer.parse(acess_token).getAsJsonObject();
      String access_token = json.get("access_token").getAsString();
      
      //获取JsAPI
      String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";  
      String backData=sendGet(urlStr, "utf-8", 10000);  
      json2 = jsonparer.parse(backData).getAsJsonObject();
      String ticket = json2.get("ticket").getAsString();
      System.out.println(ticket);
      return  ticket;          
  }  
}

获得随机字符串类:

import java.util.UUID;

/**
 * 获取随即字符串
 * @author Administrator
 *
 */
public class Create_nonce_str {
public static String create_nonce_str() {
return UUID.randomUUID().toString();
}
}

SHA1加密类

import java.security.MessageDigest;
/**
 * SHA1加密
 * @author Administrator
 *
 */
public class SHA1 {
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',  
             '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};  
private static String getFormattedText(byte[] bytes) {  
       int len = bytes.length;  
       StringBuilder buf = new StringBuilder(len * 2);  
       // 把密文转换成十六进制的字符串形式  
       for (int j = 0; j < len; j++) {  
           buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);  
           buf.append(HEX_DIGITS[bytes[j] & 0x0f]);  
       }  
       return buf.toString();  
   }  
 
   public static String encode(String str) {  
       if (str == null) {  
           return null;  
       }  
       try {  
           MessageDigest messageDigest = MessageDigest.getInstance("SHA1");  
           messageDigest.update(str.getBytes());  
           return getFormattedText(messageDigest.digest());  
       } catch (Exception e) {  
           throw new RuntimeException(e);  
       }  
   }  

}

处理和发送到前台的dopost方法

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
String timestamp = Long.toString(System.currentTimeMillis() / 1000);

String nonceStr  =  Create_nonce_str.create_nonce_str();

               //这个url一定要动态获取,不能写死

String url="http://"+req.getServerName()+req.getContextPath()+"/";  
System.out.println("当前地址为:"+url);
String jsapi_ticket = JsapiTicketUtil.getJSApiTicket();
System.out.println("时间戳:"+timestamp+"随即串:"+nonceStr+"ticket:"+jsapi_ticket);
//所有参数必须小写且有序
String str = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonceStr +
                "&timestamp=" + timestamp +
                "&url=" + url;
//sha1加密
        String signature = SHA1.encode(str);
        System.out.println("生成的签名:"+signature);
        //将三个参数拼接成字符串到前台,再由逗号分割取出
        String data = timestamp+","+nonceStr+","+signature;
        out.print(data);
        out.flush();
        out.close();

}

前台代码(我是写在body中了):

<script type="text/javascript"
src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script type="text/javascript">

window.onload=function(){

                //定义全局变量  接收后台传递的三个参数

var timestamp;
var nonceStr;
var signature;
$.ajax({
type : "POST", 
dataType : "text", 
url : "${ctx}/GainWXServlet.do", 
success : function(data) {
if (data != null) {
var arr=data.split(",");
timestamp = arr[0];
nonceStr = arr[1];
signature = arr[2];
wx.config({
   debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
   appId: '你的id', // 必填,公众号的唯一标识
   timestamp: timestamp, // 必填,生成签名的时间戳
   nonceStr: nonceStr, // 必填,生成签名的随机串
   signature: signature,// 必填,签名
   jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'] // 必填,需要使用的JS接口列表
});
 wx.checkJsApi({
   jsApiList: ['chooseImage'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
   success: function(res) {
   // 以键值对的形式返回,可用的api值true,不可用为false
   // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
   }
});
 wx.onMenuShareTimeline({
   title: '分享标题', // 分享标题
   link: '分享链接', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
   imgUrl: '分享图标', // 分享图标
   success: function () {
   // 用户点击了分享后执行的回调函数
}});
wx.onMenuShareAppMessage({
title: '', // 分享标题
desc: '', // 分享描述
link: 'http://fifa.dlscanyin.com/', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: 'http://fifa.dlscanyin.com/images/logo.jpg', // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
// 用户点击了分享后执行的回调函数
}
});
} else {
alert("数据没有获取到哦~");
}
}
});
};

</script>


PS:如果发生

{errmsg:config: invalid signature}

首先检查去微信的这个链接:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign,将自己的代码中的数据和它的数据做对比,如果还有问题,请检查url错误,可能最后的一个"/"都能引起这个错误,最后说下,我的代码比较简单,里面肯定有很多不合理的地方,请大佬多多指教

猜你喜欢

转载自blog.csdn.net/danshumai2098/article/details/80666358