微信分享功能开发

微信分享功能开发

用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路。

一、服务器端程序

[java] view plain copy
  1. package com.wiimedia.controller;  
  2.    
  3.    
  4. import java.io.IOException;  
  5. import java.security.MessageDigest;  
  6. import java.security.NoSuchAlgorithmException;  
  7. import java.text.ParseException;  
  8. import java.text.SimpleDateFormat;  
  9. import java.util.Arrays;  
  10. import java.util.Date;  
  11.    
  12. import javax.servlet.http.HttpServletRequest;  
  13. import javax.servlet.http.HttpServletResponse;  
  14.    
  15. import org.springframework.beans.factory.annotation.Autowired;  
  16. import org.springframework.stereotype.Controller;  
  17. import org.springframework.web.bind.annotation.RequestMapping;  
  18.    
  19. import com.google.gson.Gson;  
  20. import com.wiimedia.model.Ticket;  
  21. import com.wiimedia.service.ArticleSolrService;  
  22. import com.wiimedia.service.TicketRepository;  
  23. import com.wiimedia.service.TicketRepositorySolr;  
  24. import com.wiimedia.utils.GetRandomStr;  
  25. import com.wiimedia.utils.SignatureBean;  
  26. import com.wiimedia.utils.weixin.WeixinUtil;  
  27. /** 
  28.  *  
  29.  *  
  30.  *<p>Project:mryl_phone_v2</p>  
  31.  *  
  32.  *<p>Package:com.wiimedia.controller</p>  
  33.  *  
  34.  *<p>Description:微信分享Controller</p> 
  35.  * 
  36.  *<p>Company:Wiimedia</p> 
  37.  * 
  38.  *@Athor:SongJia 
  39.  * 
  40.  *@Date:2016-7-15 上午09:34:10 
  41.  * 
  42.  */  
  43.    
  44. @Controller  
  45. @RequestMapping("/WeixinshareController/Api/Inteface")  
  46. public class WeixinshareController {  
  47.  @Autowired  
  48.  private TicketRepositorySolr ticketRepositorySolr;  
  49.    
  50.  @RequestMapping("/getSignature")  
  51.  public String getSignature( HttpServletRequest request,  
  52.    HttpServletResponse response) throws IOException, ParseException{  
  53.   //获取签名页面链接  
  54.   String url = request.getParameter("url");  
  55.   SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  56.   //从数据库中获取标签,并检查标签是否过期  
  57.   Ticket oldticket = ticketRepositorySolr.getTicketById("20160114wiimediamrylsong1152");  
  58.   if(oldticket==null){//第一次访问,标签不存在。  
  59.    executeTicket(response,"1",url,format);  
  60.    return null;  
  61.   }else{//标签存在,判断标签是否超时  
  62.    String oldAcquiretime = oldticket.getAcquiretime();  
  63.    long difference=format.parse(format.format(new Date())).getTime()-format.parse(oldAcquiretime).getTime();  
  64.    if(difference>7100000){//标签超时,重新到微信服务器请求标签超时时间为7200秒(7200000毫秒)  
  65.     executeTicket(response,"2",url,format);  
  66.     return null;   
  67.    }else{//标签未超时  
  68.     /**  
  69.      * 注意事项            
  70.      * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。 
  71.      * 2.签名用的url必须是调用JS接口页面的完整URL。       
  72.      * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。  
  73.      *  
  74.      ****根据第1点要求   signature 配置的时候很容易出错,需要把生成 Ticket的 noncestr和 timestamp传给客户端*** 
  75.      */  
  76.     String signature = signature(oldticket.getTicket(),oldticket.getTimestamp(),oldticket.getNoncestr(),url);  
  77.     SignatureBean signatureBean = new SignatureBean();  
  78.     signatureBean.setNoncestr(oldticket.getNoncestr());  
  79.     signatureBean.setSignature(signature);  
  80.     signatureBean.setTimestamp(oldticket.getTimestamp());  
  81.     signatureBean.setUrl(url);  
  82.     response.setContentType("text/html;charset=UTF-8");  
  83.     response.getWriter().print(new Gson().toJson(signatureBean));  
  84.     return null;   
  85.    }   
  86.   }  
  87.    
  88.    
  89.  }  
  90.  /** 
  91.   *  
  92.   *<p>Project:mryl_phone_v2</p>  
  93.   *  
  94.   *<p>:mryl_phone_v2</p>  
  95.   *  
  96.   *<p>Description:更新和获取ticket的方法,因为用的solr所以更新和新增是一样的ID无则添加,有责更新</p> 
  97.   * 
  98.   *<p>Company:Wiimedia</p> 
  99.   * 
  100.   *@Athor:SongJia 
  101.   * 
  102.   *@Date:2016-7-15 上午09:45:00  
  103.   * 
  104.   */  
  105.  public void executeTicket(HttpServletResponse response,String flag,String url,SimpleDateFormat format) throws IOException{  
  106.    
  107.   //获取签名随即字符串  
  108.   GetRandomStr randomStr = new GetRandomStr();  
  109.   String noncestr = randomStr.getRandomString(15);  
  110.   //获取签名时间戳  
  111.   String timestamp = Long.toString(System.currentTimeMillis());  
  112.   //请求accessToken  
  113.   String accessTokenUrl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=您的APPID&secret=您的密匙";  
  114.   String tokenJson = WeixinUtil.httpRequest(accessTokenUrl, "GET"null);  
  115.   Gson gson = new Gson();  
  116.   ShareAccess_Token token = gson.fromJson(tokenJson, ShareAccess_Token.class);  
  117.   String to= token.getAccess_token();  
  118.   //获取标签  
  119.   String urlTicket ="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+to+"&type=jsapi";  
  120.   String ticketJson = WeixinUtil.httpRequest(urlTicket, "GET"null);  
  121.   Ticket ticket = gson.fromJson(ticketJson, Ticket.class);  
  122.   String t = ticket.getTicket();  
  123.   //String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");  
  124.   //我的Ticket ID是写死的  
  125.   String acquiretime = format.format(new Date());  
  126.   ticket.setTid("20160114wiimediamrylsong1152");  
  127.   ticket.setAcquiretime(acquiretime);  
  128.   ticket.setTimestamp(timestamp);  
  129.   ticket.setNoncestr(noncestr);  
  130.   //因为用的SOLR所以更新和添加的方法是一样的,可以根据自己具体需求进行修改,本文不再贴出代码.  
  131.   if(flag.equals("2")){  
  132.    ticketRepositorySolr.addTicketToSolr(ticket);   
  133.   }else{  
  134.    ticketRepositorySolr.addTicketToSolr(ticket);  
  135.   }  
  136.   /**  
  137.    * 注意事项            
  138.    * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。 
  139.    * 2.签名用的url必须是调用JS接口页面的完整URL。       
  140.    * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。  
  141.    *  
  142.    *根据第1点要求   signature 配置的时候很容易出错,需要把生成 Ticket的 noncestr和 timestamp传给客户端* 
  143.    */  
  144.   String signature = signature(t,timestamp,noncestr,url);  
  145.   SignatureBean signatureBean = new SignatureBean();  
  146.   signatureBean.setNoncestr(noncestr);  
  147.   signatureBean.setSignature(signature);  
  148.   signatureBean.setTimestamp(timestamp);  
  149.   signatureBean.setUrl(url);  
  150.   response.setContentType("text/html;charset=UTF-8");  
  151.   response.getWriter().print(new Gson().toJson(signatureBean));  
  152.  }  
  153.    
  154.  /** 
  155.   *  
  156.   *<p>Project:mryl_phone_v2</p>  
  157.   *  
  158.   *<p>:mryl_phone_v2</p>  
  159.   *  
  160.   *<p>Description:根据标签,时间戳,密匙,URL进行签名</p> 
  161.   * 
  162.   *<p>Company:Wiimedia</p> 
  163.   * 
  164.   *@Athor:SongJia 
  165.   * 
  166.   *@Date:2016-7-15 上午09:37:13  
  167.   * 
  168.   */  
  169.  private String signature(String jsapi_ticket, String timestamp, String noncestr, String url) {  
  170.   jsapi_ticket = "jsapi_ticket=" + jsapi_ticket;  
  171.   timestamp = "timestamp=" + timestamp;  
  172.   noncestr = "noncestr=" + noncestr;  
  173.   url = "url=" + url;  
  174.   String[] arr = new String[] { jsapi_ticket, timestamp, noncestr, url };  
  175.   // 将token、timestamp、nonce,url参数进行字典序排序  
  176.   Arrays.sort(arr);  
  177.   StringBuilder content = new StringBuilder();  
  178.   for (int i = 0; i < arr.length; i++) {  
  179.    content.append(arr[i]);  
  180.    if (i != arr.length - 1) {  
  181.     content.append("&");  
  182.    }  
  183.   }  
  184.   MessageDigest md = null;  
  185.   String tmpStr = null;  
  186.    
  187.   try {  
  188.    md = MessageDigest.getInstance("SHA-1");  
  189.    // 将三个参数字符串拼接成一个字符串进行sha1加密  
  190.    byte[] digest = md.digest(content.toString().getBytes());  
  191.    tmpStr = byteToStr(digest);  
  192.   } catch (NoSuchAlgorithmException e) {  
  193.    e.printStackTrace();  
  194.   }  
  195.    
  196.   content = null;  
  197.   return tmpStr;  
  198.  }  
  199.  /** 
  200.   * 将字节转换为十六进制字符串 
  201.   *  
  202.   * @param mByte 
  203.   * @return 
  204.   */  
  205.  private static String byteToHexStr(byte mByte) {  
  206.    
  207.   char[] Digit = { '0''1''2''3''4''5''6''7''8''9''A''B''C''D''E''F' };  
  208.   char[] tempArr = new char[2];  
  209.   tempArr[0] = Digit[(mByte >>> 4) & 0X0F];  
  210.   tempArr[1] = Digit[mByte & 0X0F];  
  211.    
  212.   String s = new String(tempArr);  
  213.   return s;  
  214.  }  
  215.  /** 
  216.   * 将字节数组转换为十六进制字符串 
  217.   *  
  218.   * @param byteArray 
  219.   * @return 
  220.   */  
  221.  private static String byteToStr(byte[] byteArray) {  
  222.   String strDigest = "";  
  223.   for (int i = 0; i < byteArray.length; i++) {  
  224.    strDigest += byteToHexStr(byteArray[i]);  
  225.   }  
  226.   return strDigest;  
  227.  }  
  228.    
  229.    
  230.  class ShareAccess_Token{  
  231.   private String access_token;  
  232.   private String expires_in;  
  233.   public String getAccess_token() {  
  234.    return access_token;  
  235.   }  
  236.   public void setAccess_token(String accessToken) {  
  237.    access_token = accessToken;  
  238.   }  
  239.   public String getExpires_in() {  
  240.    return expires_in;  
  241.   }  
  242.   public void setExpires_in(String expiresIn) {  
  243.    expires_in = expiresIn;  
  244.   }  
  245.    
  246.  }  
  247. }  
二、客户端代码.

[javascript] view plain copy
  1. <script type="text/javascript">  
  2.    var url = window.location.href;  
  3.    var articleId = "";  
  4.    var shareTitle="明日医疗资讯";  
  5.    var shareImgUrl="";  
  6.    var userinfo = localStorage.getItem("_userinfo");  
  7.    var timestamp;  
  8.    var noncestr;  
  9.    var signature;  
  10.    //获取签名  
  11.     $.ajax({  
  12.       type: "GET",  
  13.       url: "WeixinshareController/Api/Inteface/getSignature",  
  14.       //data:{timestamp:timestamp,noncestr:noncestr,url:url},  
  15.       data:{url:url},  
  16.       success: function(data){  
  17.         var objData=JSON.parse(data);   
  18.         timestamp=objData.timestamp;   
  19.         noncestr=objData.noncestr;   
  20.         signature=objData.signature;  
  21.          console.log(objData);  
  22.          wxShare();  
  23.       }  
  24.      });  
  25.    function wxShare(){  
  26.    wx.config({  
  27.     debug: false// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。  
  28.     appId: '您的appid'// 和获取Ticke的必须一样------必填,公众号的唯一标识  
  29.     timestamp:timestamp, // 必填,生成签名的时间戳  
  30.     nonceStr: noncestr, // 必填,生成签名的随机串  
  31.     signature: signature,// 必填,签名,见附录1  
  32.     jsApiList: [  
  33.     'onMenuShareAppMessage'  
  34.     ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2  
  35.    });  
  36.    }  
  37.    wx.ready(function(){  
  38.      //config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,  
  39.      //config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关  
  40.      //接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。  
  41.    
  42.     //----------“分享给朋友”  
  43.     wx.onMenuShareAppMessage({  
  44.      title: "明日医疗资讯"// 分享标题  
  45.      desc: shareTitle, // 分享描述  
  46.      link: url, // 分享链接  
  47.      imgUrl: shareImgUrl, // 分享图标  
  48.      type: ''// 分享类型,music、video或link,不填默认为link  
  49.      dataUrl: ''// 如果type是music或video,则要提供数据链接,默认为空  
  50.      success: function () {   
  51.       // 用户确认分享后执行的回调函数、  
  52.      },  
  53.      cancel: function () {   
  54.       // 用户取消分享后执行的回调函数  
  55.      }  
  56.     });  
  57.     //------------"分享到朋友圈"  
  58.     wx.onMenuShareTimeline({  
  59.      title: '明日医疗资讯'// 分享标题  
  60.      link: ''// 分享链接  
  61.      imgUrl: shareImgUrl, // 分享图标  
  62.      success: function () {   
  63.       // 用户确认分享后执行的回调函数  
  64.      },  
  65.      cancel: function () {   
  66.       // 用户取消分享后执行的回调函数  
  67.      }  
  68.     });  
  69.     //-------------分享到QQ  
  70.     wx.onMenuShareQQ({  
  71.      title: '明日医疗资讯'// 分享标题  
  72.      desc: shareTitle, // 分享描述  
  73.      link: ''// 分享链接  
  74.      imgUrl: shareImgUrl, // 分享图标  
  75.      success: function () {   
  76.       // 用户确认分享后执行的回调函数  
  77.      },  
  78.      cancel: function () {   
  79.       // 用户取消分享后执行的回调函数  
  80.      }  
  81.     });  
  82.     //-------------分享到QQ空间  
  83.     wx.onMenuShareQZone({  
  84.      title: '明日医疗资讯'// 分享标题  
  85.      desc: shareTitle, // 分享描述  
  86.      link: ''// 分享链接  
  87.      imgUrl: shareImgUrl, // 分享图标  
  88.      success: function () {   
  89.       // 用户确认分享后执行的回调函数  
  90.      },  
  91.      cancel: function () {   
  92.       // 用户取消分享后执行的回调函数  
  93.      }  
  94.     });  
  95.    
  96.    });  

三、服务器需要的工具类和Model

① Ticket

[java] view plain copy
  1. package com.wiimedia.model;  
  2.    
  3.    
  4. public class Ticket{  
  5.  private String tid;  
  6.  private String ticket;   
  7.  private String errcode;  
  8.  private String errmsg;   
  9.  private String expires_in;  
  10.  private String acquiretime;  
  11.  private String noncestr;  
  12.  private String timestamp;  
  13.    
  14.  public Ticket(String tid, String ticket, String errcode, String errmsg,  
  15.    String expiresIn, String acquiretime, String noncestr,  
  16.    String timestamp) {  
  17.   super();  
  18.   this.tid = tid;  
  19.   this.ticket = ticket;  
  20.   this.errcode = errcode;  
  21.   this.errmsg = errmsg;  
  22.   expires_in = expiresIn;  
  23.   this.acquiretime = acquiretime;  
  24.   this.noncestr = noncestr;  
  25.   this.timestamp = timestamp;  
  26.  }  
  27.  public String getTid() {  
  28.   return tid;  
  29.  }  
  30.  public void setTid(String tid) {  
  31.   this.tid = tid;  
  32.  }  
  33.  public String getTicket() {  
  34.   return ticket;  
  35.  }  
  36.  public void setTicket(String ticket) {  
  37.   this.ticket = ticket;  
  38.  }  
  39.  public String getErrcode() {  
  40.   return errcode;  
  41.  }  
  42.  public void setErrcode(String errcode) {  
  43.   this.errcode = errcode;  
  44.  }  
  45.  public String getErrmsg() {  
  46.   return errmsg;  
  47.  }  
  48.  public void setErrmsg(String errmsg) {  
  49.   this.errmsg = errmsg;  
  50.  }  
  51.  public String getExpires_in() {  
  52.   return expires_in;  
  53.  }  
  54.  public void setExpires_in(String expiresIn) {  
  55.   expires_in = expiresIn;  
  56.  }  
  57.  public String getAcquiretime() {  
  58.   return acquiretime;  
  59.  }  
  60.  public void setAcquiretime(String acquiretime) {  
  61.   this.acquiretime = acquiretime;  
  62.  }  
  63.  public String getNoncestr() {  
  64.   return noncestr;  
  65.  }  
  66.  public void setNoncestr(String noncestr) {  
  67.   this.noncestr = noncestr;  
  68.  }  
  69.  public String getTimestamp() {  
  70.   return timestamp;  
  71.  }  
  72.  public void setTimestamp(String timestamp) {  
  73.   this.timestamp = timestamp;  
  74.  }  
  75.    
  76.    
  77. }  
② 添加到数据库的业务根据自己需要进行实现. 
③ GetRandomStr

[java] view plain copy
  1. package com.wiimedia.utils;  
  2.    
  3. import java.util.Random;  
  4.    
  5. public class GetRandomStr {  
  6.  /** 
  7.   *  
  8.   *<p>Project:mryl_phone_v2</p>  
  9.   *  
  10.   *<p>:mryl_phone_v2</p>  
  11.   *  
  12.   *<p>Description:生成随即字符串 </p> 
  13.   * 
  14.   *<p>Company:Wiimedia</p> 
  15.   * 
  16.   *@Athor:SongJia 
  17.   * 
  18.   *@Date:2016-7-14 上午11:14:46  
  19.   * 
  20.   */  
  21.  public String getRandomString(int length) {  
  22.   String base = "abcdefghijklmnopqrstuvwxyz0123456789";   
  23.   Random random = new Random();   
  24.   StringBuffer sb = new StringBuffer();   
  25.   for (int i = 0; i < length; i++) {   
  26.    int number = random.nextInt(base.length());   
  27.    sb.append(base.charAt(number));   
  28.   }   
  29.   return sb.toString();   
  30.   }  
  31. }  
④ SignatureBean
[java] view plain copy
  1. package com.wiimedia.utils;  
  2.    
  3. public class SignatureBean {  
  4.  private String noncestr;  
  5.  private String url;  
  6.  private String timestamp;  
  7.  private String signature;  
  8.  public String getNoncestr() {  
  9.   return noncestr;  
  10.  }  
  11.  public void setNoncestr(String noncestr) {  
  12.   this.noncestr = noncestr;  
  13.  }  
  14.  public String getUrl() {  
  15.   return url;  
  16.  }  
  17.  public void setUrl(String url) {  
  18.   this.url = url;  
  19.  }  
  20.  public String getTimestamp() {  
  21.   return timestamp;  
  22.  }  
  23.  public void setTimestamp(String timestamp) {  
  24.   this.timestamp = timestamp;  
  25.  }  
  26.  public String getSignature() {  
  27.   return signature;  
  28.  }  
  29.  public void setSignature(String signature) {  
  30.   this.signature = signature;  
  31.  }  
  32.    
  33. }  
⑤ WeixinUtil
[java] view plain copy
  1. package com.wiimedia.utils.weixin;  
  2. import java.io.BufferedReader;  
  3. import java.io.InputStream;  
  4. import java.io.InputStreamReader;  
  5. import java.io.OutputStream;  
  6. import java.net.ConnectException;  
  7. import java.net.URL;  
  8.    
  9. import javax.net.ssl.HttpsURLConnection;  
  10. import javax.net.ssl.SSLContext;  
  11. import javax.net.ssl.SSLSocketFactory;  
  12. import javax.net.ssl.TrustManager;  
  13.    
  14. /** 
  15.   *  
  16.   *<p>Project:mryl_phone_v2</p>  
  17.   *  
  18.   *<p>:mryl_phone_v2</p>  
  19.   *  
  20.   *<p>Description:公众平台接口工具类</p> 
  21.   * 
  22.   *<p>Company:Wiimedia</p> 
  23.   * 
  24.   *@Athor:SongJia 
  25.   * 
  26.   *@Date:2016-7-15 上午09:37:13  
  27.   * 
  28.   */  
  29. public class WeixinUtil {  
  30.    
  31.  /**  
  32.   * 发起https请求并获取结果  
  33.   *  
  34.   * @param requestUrl 请求地址  
  35.   * @param requestMethod 请求方式(GET、POST)  
  36.   * @param outputStr 提交的数据  
  37.   * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)  
  38.   */  
  39.  public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {   
  40.    
  41.   StringBuffer buffer = new StringBuffer();   
  42.   try {   
  43.    // 创建SSLContext对象,并使用我们指定的信任管理器初始化   
  44.    TrustManager[] tm = { new MyX509TrustManager() };   
  45.    SSLContext sslContext = SSLContext.getInstance("SSL""SunJSSE");   
  46.    sslContext.init(null, tm, new java.security.SecureRandom());   
  47.    // 从上述SSLContext对象中得到SSLSocketFactory对象   
  48.    SSLSocketFactory ssf = sslContext.getSocketFactory();   
  49.    
  50.    URL url = new URL(requestUrl);   
  51.    HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();   
  52.    httpUrlConn.setSSLSocketFactory(ssf);   
  53.    
  54.    httpUrlConn.setDoOutput(true);   
  55.    httpUrlConn.setDoInput(true);   
  56.    httpUrlConn.setUseCaches(false);   
  57.    // 设置请求方式(GET/POST)   
  58.    httpUrlConn.setRequestMethod(requestMethod);   
  59.    
  60.    if ("GET".equalsIgnoreCase(requestMethod))   
  61.     httpUrlConn.connect();   
  62.    
  63.    // 当有数据需要提交时   
  64.    if (null != outputStr) {   
  65.     OutputStream outputStream = httpUrlConn.getOutputStream();   
  66.     // 注意编码格式,防止中文乱码   
  67.     outputStream.write(outputStr.getBytes("UTF-8"));   
  68.     outputStream.close();   
  69.    }   
  70.    
  71.    // 将返回的输入流转换成字符串   
  72.    InputStream inputStream = httpUrlConn.getInputStream();   
  73.    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");   
  74.    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);   
  75.    
  76.    String str = null;   
  77.    while ((str = bufferedReader.readLine()) != null) {   
  78.     buffer.append(str);   
  79.    }   
  80.    bufferedReader.close();   
  81.    inputStreamReader.close();   
  82.    // 释放资源   
  83.    inputStream.close();   
  84.    inputStream = null;   
  85.    httpUrlConn.disconnect();   
  86.    return buffer.toString();   
  87.   } catch (ConnectException ce) {   
  88.    ce.printStackTrace();   
  89.   } catch (Exception e) {   
  90.    e.printStackTrace();  
  91.   }   
  92.   return "";   
  93.  }  
  94. }  

四、至此,分享功能已经开发完成,但是,在生成signature的时候会遇到很多问题,这里提供一些wx.config失败的排错方法。

① 确认自己的生成的signature是否正确 
在微信提供的http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign进行校验

② wx.config中使用的noncestr, timestamp与用以签名中的对应noncestr, timestamp是否一致一致…如上面(一.服务器代码) 
(有可能因为JS页面加载顺序问题,服务器生成的signature,noncestr,timestamp在wx.config中没有获取到)。

③ 确认url是页面完整的url,包括GET参数部分 
需要去掉#后面的部分

④ config 中的 appid 与用来获取 jsapi_ticket 的 appid 是否一致

⑤ 报错{errmsg:config:ok}是debug的正常返回把调试模式关掉就OK 
wx.config debug: false, 

以上就是本文的全部内容,希望对大家的学习有所帮助

微信分享功能开发