今天踩了一个很大的坑。。我发现微信坑真多啊。微信作的东西真的不屑于评论啊。刚开始坑公众号开发,而后坑微信支付开发,而后坑小程序开发。我真的走不出来了。。。。关键还没办法。php
今天给你们分享一下app的二次分享问题吧。html
是否是挺好玩的。这个时候就说了为何变成这个样子,由于他分享H5没有写微信的二次分享。前端
二次分享操做流程:java
画个图图告诉你什么是二次分享:web
代码流程炒鸡简单。我给大家也画一个流程图。
老规矩:ajax
点我快速进入分享sdk官方文档redis
直接上代码吧。代码有些糙 不喜欢勿喷。算法
前段须要引入的js <!--微信分享js --> <script src="http://res2.wx.qq.com/open/js/jweixin-1.4.0.js"></script> <script src="static/js/wx_share.js"></script 前端的代码:我用的el表达式,jsp页面。别的可根据本身进行修改。 <input type="hidden"value="${shareDate.nonceStr }" id="nonceStr"> <input type="hidden"value="${shareDate.timestamp }" id="timestamp"> <input type="hidden"value="${shareDate.signature }" id="signature"> <input type="hidden"value="${shareDate.appid }" id="appid"> <input type="hidden"value="${shareDate.share_title }" id="share_title"> <input type="hidden"value="${shareDate.share_detail }" id="share_detail"> <input type="hidden"value="${shareDate.share_image }" id="share_image"> <input type="hidden"value="${shareDate.share_url }" id="share_url"> 本身的封装的wx_share.js $(function() { var timestamp = $("#timestamp").val(); var nonceStr = $("#nonceStr").val();//随机串 var signature = $("#signature").val();//签名 var appid = $("#appid").val(); var title = $("#share_title").val(); var desc = $("#share_detail").val(); var link = $("#share_url").val(); var imgUrl = $("#share_image").val(); wx.config({ debug : true, // 开启调试模式,调用的全部api的返回值会在客户端alert出来,若要查看传入的参数,能够在pc端打开,参数信息会经过log打出,仅在pc端时才会打印。 appId : appid, // 必填,公众号的惟一标识 timestamp : timestamp, // 必填,生成签名的时间戳 nonceStr : nonceStr, // 必填,生成签名的随机串 signature : signature,// 必填,签名,见附录1 jsApiList : [ 'onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo' ] // 必填,须要使用的JS接口列表,全部JS接口列表见附录2 }); wx.ready(function(){ wx.onMenuShareTimeline({ title: title, link: link, imgUrl: imgUrl, success: function () { // 用户确认分享后执行的回调函数 alert('分享到朋友圈成功'); }, cancel: function () { // 用户取消分享后执行的回调函数 alert('你没有分享到朋友圈'); } }); wx.onMenuShareAppMessage({ title: title, desc: desc, link: link, imgUrl: imgUrl, success: function (res) { alert('分享给朋友成功'); }, cancel: function (res) { alert('你没有分享给朋友'); }, }); wx.onMenuShareQQ({ title: title, desc: desc, link: link, imgUrl: imgUrl, success: function () { // 用户确认分享后执行的回调函数 alert('分享给朋友成功'); }, cancel: function () { // 用户取消分享后执行的回调函数 } }); wx.onMenuShareWeibo({ title: title, desc: desc, link: link, imgUrl: imgUrl, success: function () { // 用户确认分享后执行的回调函数 alert('分享给朋友成功'); }, cancel: function () { // 用户取消分享后执行的回调函数 } }); wx.onMenuShareQZone({ title: title, desc: desc, link: link, imgUrl: imgUrl, success: function () { // 用户确认分享后执行的回调函数 alert('分享给朋友成功'); }, cancel: function () { // 用户取消分享后执行的回调函数 } }); }); }); /** * 分享数据test * * @return * @throws Exception */ @RequestMapping(value = "/share_date", method = RequestMethod.GET) public ModelAndView share_date() throws Exception { ModelAndView modelAndView = this.getModelAndView(); PageData pd = new PageData(); pd = this.getPageData(); try { PageData shareDate = commonService.wx_share_date("test", "hehe", "xxxx.img", "xxx"); modelAndView.addObject("shareDate", shareDate); modelAndView.setViewName("xx/xxx/xxx"); } catch (Exception e) { e.printStackTrace(); logBefore(logger, e.toString()); throw e; } return modelAndView; } /** * 封装二次分享数据返回前台 * * @param share_title 分享标题 * @param share_detail 分享描述 * @param share_image 分享图片 * @param share_url 分享打开链接 * @return * @throws Exception */ public PageData wx_share_date(String share_title, String share_detail, String share_image, String share_url) throws Exception { //微信所须要的数据 PageData wxDate = Sign.retSign(wechatShareUtil.getJsapiTicket(), share_url); wxDate.put("appid", WeChatUtil.WEIXIN_APPID); //分享所须要数据 wxDate.put("share_title", share_title); wxDate.put("share_detail", share_detail); wxDate.put("share_image", share_image); wxDate.put("share_url", share_url); return wxDate; } package cn.cnbuilder.util; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import cn.cnbuilder.dao.redis.RedisDao; import cn.cnbuilder.entity.AccessToken; import cn.cnbuilder.entity.TicketJson; import cn.cnbuilder.util.weixin.WeChatUtil; import net.sf.json.JSONException; import net.sf.json.JSONObject; @Component public class WechatShareUtil { @Resource(name = "redisDaoImpl") private RedisDao redisDaoImpl; private static Logger log = LoggerFactory.getLogger(WeChatUtil.class); /** * 获取微信jsapi_ticket * * * @param pd * @throws Exception */ public String getJsapiTicket() { // 先获取jsapi_ticket在redis中是否存在 String gzh_jsapiTicket = redisDaoImpl.get("jsapiTicket"); if (Tools.isEmpty(gzh_jsapiTicket)) { String accessToken = getAccessToken(); // 获取jsapi_ticket并保存到redis中 TicketJson ticketJson = getJsapiTicket(accessToken); gzh_jsapiTicket = ticketJson.getTicket(); if (Tools.notEmpty(gzh_jsapiTicket)) { redisDaoImpl.addString("jsapiTicket", gzh_jsapiTicket, ticketJson.getExpires_in()); } } return gzh_jsapiTicket; } /** * 获取微信accessToken * * @param pd * @throws Exception */ public String getAccessToken() throws JSONException { // 先获取accessToken在redis中是否存在 String gzh_accessToken = redisDaoImpl.get("accessToken"); if (Tools.isEmpty(gzh_accessToken)) { // 获取accessToken并保存到redis中 AccessToken accessToken = getAccessTokenByWechat(); if (accessToken != null) { gzh_accessToken = accessToken.getToken(); redisDaoImpl.addString("accessToken", gzh_accessToken, accessToken.getExpiresIn()); } } return gzh_accessToken; } /** * @Description: 经过微信获取token */ public AccessToken getAccessTokenByWechat() throws JSONException { String requestUrl = WeChatUtil.access_Token_Url.replace("APPID", WeChatUtil.WEIXIN_APPID).replace("APPSECRET", WeChatUtil.WEIXIN_APPSECRET); JSONObject jsonObject = WeChatUtil.httpRequest(requestUrl, "GET", null); AccessToken accessToken = new AccessToken(); // 若是请求成功 if (null != jsonObject) { try { accessToken.setToken(jsonObject.getString("access_token")); accessToken.setExpiresIn(jsonObject.getInt("expires_in")); log.info("获取access_token成功,有效时长{}秒 token:{}", accessToken.getExpiresIn(), accessToken.getToken()); } catch (JSONException e) { // 获取token失败 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } return accessToken; } /** * @Description: 不经过判断,直接生成锌的token */ public TicketJson getJsapiTicket(String token) throws JSONException { String requestUrl = WeChatUtil.get_jsticket.replace("ACCESS_TOKEN", token); JSONObject jsonObject = WeChatUtil.httpRequest(requestUrl, "GET", null); TicketJson ticketJson = new TicketJson(); // 若是请求成功 if (null != jsonObject) { try { ticketJson.setErrcode(jsonObject.getInt("errcode")); ticketJson.setErrmsg(jsonObject.getString("errmsg")); ticketJson.setExpires_in(jsonObject.getInt("expires_in")); ticketJson.setTicket(jsonObject.getString("ticket")); log.info("获取jsapi_ticket成功,有效时长{}秒 token:{}", ticketJson.getExpires_in(), ticketJson.getTicket()); } catch (JSONException e) { // 获取token失败 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } return ticketJson; } } package cn.cnbuilder.entity; import java.io.Serializable; /** * 微信通用接口凭证 * * @author KingYiFan * @date 2015-12-13 */ public class AccessToken implements Serializable{ /** * */ private static final long serialVersionUID = -553323547802220881L; // 获取到的凭证 private String token; // 凭证有效时间,单位:秒 private int expiresIn; public String getToken() { return token; } public void setToken(String token) { this.token = token; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } } package cn.cnbuilder.entity; import java.io.Serializable; /** * 微信通用接口凭证 * * @author KingYiFan * @date 2015-12-13 */ public class TicketJson implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private int errcode; private String errmsg; private String ticket; private int expires_in; public int getErrcode() { return errcode; } public void setErrcode(int errcode) { this.errcode = errcode; } public String getErrmsg() { return errmsg; } public void setErrmsg(String errmsg) { this.errmsg = errmsg; } public String getTicket() { return ticket; } public void setTicket(String ticket) { this.ticket = ticket; } public int getExpires_in() { return expires_in; } public void setExpires_in(int expires_in) { this.expires_in = expires_in; } } 。。。wechatUtils package cn.cnbuilder.util.weixin; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.ConnectException; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Formatter; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.annotation.Resource; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import cn.cnbuilder.dao.redis.RedisDao; import cn.cnbuilder.entity.AccessToken; import cn.cnbuilder.entity.TicketJson; import cn.cnbuilder.util.MyX509TrustManager; import cn.cnbuilder.util.PageData; import cn.cnbuilder.util.Tools; import cn.cnbuilder.util.wxpay.Sign; import net.sf.json.JSONException; import net.sf.json.JSONObject; /** * 公众平台通用接口工具类 */ public class WeChatUtil { @Resource(name = "redisDaoImpl") private RedisDao redisDaoImpl; private static Logger log = LoggerFactory.getLogger(WeChatUtil.class); public static String WEIXIN_APPID = "xxxx"; public static String WEIXIN_APPSECRET = "xxxx"; // 获取access_token的接口地址(GET) 限200(次/天) public final static String access_Token_Url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + WEIXIN_APPID + "&secret=" + WEIXIN_APPSECRET; // 拉取用户信息(需scope为 snsapi_userinfo) ACCESS_TOKEN 是网页受权的ACCESS_TOKEN public final static String user_Info_Url_login = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID"; // 获取用户基本信息(包括UnionID机制) public final static String user_Info_Url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; // 用户赞成受权,获取code public final static String scope_Code_Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WEIXIN_APPID + "&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"; // 经过code换取网页受权access_token public final static String scope_OpenId_Url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WEIXIN_APPID + "&secret=" + WEIXIN_APPSECRET + "&code=CODE&grant_type=authorization_code"; // 因为access_token拥有较短的有效期,当access_token超时后,可使用refresh_token进行刷新,refresh_token有效期为30天,当refresh_token失效以后,须要用户从新受权。 public final static String refresh_token_Url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + WEIXIN_APPID + "&grant_type=refresh_token&refresh_token=REFRESH_TOKEN"; // 获取用户code值 public final static String get_code_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WEIXIN_APPID + "&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; //获取jsticket public final static String get_jsticket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; /** * 经过code获取网页受权 和用户openid * * @param code * @return */ public static Map<String, Object> getOpenId(String code) { Map<String, Object> resMap = new HashMap<>(); String openId = null; String accessToken = null; String refreshToken = null; String url = scope_OpenId_Url.replace("CODE", code); JSONObject jsonObject = httpRequest(url, "POST", null); log.info("WeChatUtil getOpenId=" + jsonObject); if (null != jsonObject) { if (!jsonObject.containsKey("errcode")) { openId = jsonObject.getString("openid"); accessToken = jsonObject.getString("access_token"); refreshToken = jsonObject.getString("refresh_token"); resMap.put("openId", openId); resMap.put("accessToken", accessToken); resMap.put("refresh_token", refreshToken); return resMap; } else { int errorCode = jsonObject.getInt("errcode"); String errorMsg = jsonObject.getString("errmsg"); log.info("经过code换取网页受权失败errorCode:{" + errorCode + "},errmsg:{" + errorMsg + "}"); System.out.println("经过code换取网页受权失败errorCode:{" + errorCode + "},errmsg:{" + errorMsg + "}"); } } return resMap; } /** * 经过openId和accessToken获取当前用户的基本信息 * * @param openId * @param accessToken * @return */ public static JSONObject getUserInfo2(String openId, String accessToken) { String url = user_Info_Url.replace("OPENID", openId).replace("ACCESS_TOKEN", accessToken); JSONObject jsonObject = httpRequest(url, "POST", null); log.info("WeChatUtil getUserInfo=" + jsonObject); return jsonObject; } /** * 经过appId和appSecretId获取accessToken * * @date 2018年3月6日 * @return */ public static String getAccessToken() { String url = access_Token_Url.replace("WEIXIN_APPID", WEIXIN_APPID).replace("WEIXIN_APPSECRET", WEIXIN_APPSECRET); JSONObject jsonObject = httpRequest(url, "GET", null); log.info("WeChatUtil getAccessToken=" + jsonObject); return jsonObject.getString("access_token"); } /** * 获取用户code值 */ public static String getCodeUrl(String redirect_uri) { String url = get_code_url.replace("REDIRECT_URI", redirect_uri); return url; } /** * 刷新token有效期 * * @date 2018年3月6日 * @return */ public static String refreshToken(String REFRESH_TOKEN) { String url = refresh_token_Url.replace("REFRESH_TOKEN", REFRESH_TOKEN); JSONObject jsonObject = httpRequest(url, "GET", null); log.info("WeChatUtil refreshToken=" + jsonObject); return jsonObject.getString("access_token"); } /** * 获取jsticket * * @date 2018年3月6日 * @return */ public static String getJsTicket(String accessToken) { String url = get_jsticket.replace("ACCESS_TOKEN", accessToken); JSONObject jsonObject = httpRequest(url, "GET", null); return jsonObject.getString("ticket"); } /** * URL编码(utf-8) * * @param source * @return */ public static String urlEncodeUTF8(String source) { String result = source; try { result = java.net.URLEncoder.encode(source, "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); log.error("urlEncodeUTF8出现异常!\n" + e.getMessage()); } return result; } public static String getWEIXIN_APPID() { return WEIXIN_APPID; } public static void setWEIXIN_APPID(String wEIXIN_APPID) { WEIXIN_APPID = wEIXIN_APPID; } public static String getWEIXIN_APPSECRET() { return WEIXIN_APPSECRET; } public static void setWEIXIN_APPSECRET(String wEIXIN_APPSECRET) { WEIXIN_APPSECRET = wEIXIN_APPSECRET; } /** * 发起https请求并获取结果 * * @param requestUrl 请求地址 * @param requestMethod 请求方式(GET、POST) * @param outputStr 提交的数据 * @return JSONObject(经过JSONObject.get(key)的方式获取json对象的属性值) */ public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject = null; StringBuffer buffer = new StringBuffer(); 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 httpUrlConn = (HttpsURLConnection) url.openConnection(); httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 设置请求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 当有数据须要提交时 if (null != outputStr) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意编码格式,防止中文乱码 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 将返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); jsonObject = JSONObject.fromObject(buffer.toString()); } catch (ConnectException ce) { ce.printStackTrace(); log.error("Weixin server connection timed out."); } catch (Exception e) { e.printStackTrace(); log.error("https request error:{}", e); } return jsonObject; } public static Map<String, String> sign(String jsapi_ticket, String url) { Map<String, String> ret = new HashMap<String, String>(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String string1; String signature = ""; // 注意这里参数名必须所有小写,且必须有序 string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×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("jsapi_ticket", jsapi_ticket); ret.put("nonceStr", nonce_str); 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 create_nonce_str() { return UUID.randomUUID().toString(); } private static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); } } 加密 package cn.cnbuilder.util.wxpay; import java.util.UUID; import cn.cnbuilder.util.PageData; import java.util.Map; import java.util.Formatter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.io.UnsupportedEncodingException; public class Sign { public static void main(String[] args) { String jsapi_ticket = "jsapi_ticket"; // 注意 URL 必定要动态获取,不能 hardcode String url = "http://baidu.com"; Map<String, String> ret = retSign(jsapi_ticket, url); }; public static PageData retSign(String jsapi_ticket, String url) { PageData ret = new PageData(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String string1; String signature = ""; //注意这里参数名必须所有小写,且必须有序 string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url; 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("jsapi_ticket", jsapi_ticket); ret.put("nonceStr", nonce_str); 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 create_nonce_str() { return UUID.randomUUID().toString(); } private static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); } }
微信的签名算法逻辑。 spring
微信分享-常见错误及解决方法 调用config 接口的时候传入参数 debug: true 能够开启debug模式,页面会alert出错误信息。如下为常见错误及解决方法: 1.invalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,仅支持80(http)和443(https)两个端口,所以不须要填写端口号(一个appid能够绑定三个有效域名,见 ]目录1.1.1)。 2.invalid signature签名错误。建议按以下顺序检查: 1.确认签名算法正确,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。 2.确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。 3.确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。 4.确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。 5.确保必定缓存access_token和jsapi_ticket。 6.确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。若是是html的静态页面在前端经过ajax将url传到后台签名,前端须要用js获取当前页面除去'#'hash部分的连接(可用location.href.split('#')[0]获取,并且须要encodeURIComponent),由于页面一旦分享,微信客户端会在你的连接末尾加入其它参数,若是不是动态获取当前连接,将致使分享后的页面签名失败。 3.the permission value is offline verifying这个错误是由于config没有正确执行,或者是调用的JSAPI没有传入config的jsApiList参数中。建议按以下顺序检查: 1.确认config正确经过。 2.若是是在页面加载好时就调用了JSAPI,则必须写在wx.ready的回调中。 3.确认config的jsApiList参数包含了这个JSAPI。 4.permission denied该公众号没有权限使用这个JSAPI,或者是调用的JSAPI没有传入config的jsApiList参数中(部分接口须要认证以后才能使用)。 5.function not exist当前客户端版本不支持该接口,请升级到新版体验。 6.为何6.0.1版本config:ok,可是6.0.2版本以后不ok(由于6.0.2版本以前没有作权限验证,因此config都是ok,但这并不意味着你config中的签名是OK的,请在6.0.2检验是否生成正确的签名以保证config在高版本中也ok。) 7.在iOS和Android都没法分享(请确认公众号已经认证,只有认证的公众号才具备分享相关接口权限,若是确实已经认证,则要检查监听接口是否在wx.ready回调函数中触发) 8.服务上线以后没法获取jsapi_ticket,本身测试时没问题。(由于access_token和jsapi_ticket必需要在本身的服务器缓存,不然上线后会触发频率限制。请确保必定对token和ticket作缓存以减小2次服务器请求,不只能够避免触发频率限制,还加快大家本身的服务速度。目前为了方便测试提供了1w的获取量,超过阀值后,服务将再也不可用,请确保在服务上线前必定全局缓存access_token和jsapi_ticket,二者有效期均为7200秒,不然一旦上线触发频率限制,服务将再也不可用)。 9.uploadImage怎么传多图(目前只支持一次上传一张,多张图片需等前一张图片上传以后再调用该接口) 10.无法对本地选择的图片进行预览(chooseImage接口自己就支持预览,不须要额外支持) 11.经过a连接(例如先经过微信受权登陆)跳转到b连接,invalid signature签名失败(后台生成签名的连接为使用jssdk的当前连接,也就是跳转后的b连接,请不要用微信登陆的受权连接进行签名计算,后台签名的url必定是使用jssdk的当前页面的完整url除去'#'部分) 12.出现config:fail错误(这是因为传入的config参数不全致使,请确保传入正确的appId、timestamp、nonceStr、signature和须要使用的jsApiList) 13.如何把jsapi上传到微信的多媒体资源下载到本身的服务器(请参见文档中uploadVoice和uploadImage接口的备注说明) 14.Android经过jssdk上传到微信服务器,第三方再从微信下载到本身的服务器,会出现杂音(微信团队已经修复此问题,目先后台已优化上线) 15.绑定父级域名,是否其子域名也是可用的(是的,合法的子域名在绑定父域名以后是彻底支持的) 16.在iOS微信6.1版本中,分享的图片外链不显示,只能显示公众号页面内链的图片或者微信服务器的图片,已在6.2中修复 17.是否须要对低版本本身作兼容(jssdk都是兼容低版本的,不须要第三方本身额外作更多工做,但有的接口是6.0.2新引入的,只有新版才可调用) 18.该公众号支付签名无效,没法发起该笔交易(请确保你使用的jweixin.js是官方线上版本,不只能够减小用户流量,还有可能对某些bug进行修复,拷贝到第三方服务器中使用,官方将不对其出现的任何问题提供保障,具体支付签名算法可参考 JSSDK微信支付一栏) 19.目前Android微信客户端不支持pushState的H5新特性,因此使用pushState来实现web app的页面会致使签名失败,此问题已在Android6.2中修复 20.uploadImage在chooseImage的回调中有时候Android会不执行,Android6.2会解决此问题,若需支持低版本能够把调用uploadImage放在setTimeout中延迟100ms解决 21.require subscribe错误说明你没有订阅该测试号,该错误仅测试号会出现 22.getLocation返回的坐标在openLocation有误差,由于getLocation返回的是gps坐标,openLocation打开的腾讯地图为火星坐标,须要第三方本身作转换,6.2版本开始已经支持直接获取火星坐标 23.查看公众号(未添加): "menuItem:addContact"不显示,目前仅有从公众号传播出去的连接才能显示,来源必须是公众号 24.ICP备案数据同步有一天延迟,因此请在第二日绑定
今天我踩的坑是这样的,我用的redis而后保存到根据正式的token和ticket 而后我appid换成测试了 一直报签名错误,对比了很长时间,本身生成的和官网的如出一辙就是报错。提示就是签名报错 他也不说哪里错了。json
前几天有人问我怎么申请测试公众号,只能用于开发。
我把微信官方的地址给你们一下:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index 直接用微信登陆就能够 只能用于微信公众号开发。
下面我给你你们截图一下个人测试号。
微信公众号必不可少的工具。 下载地址:https://mp.weixin.qq.com/wiki?action=doc&id=mp1455784140&t=0.20035047813405238#5
因为有公司信息我部分打码,请你们理解。
这就是微信二次分享,哪里不懂能够私信我哦!
鼓励做者写出更好的技术文档,就请我喝一瓶哇哈哈哈哈哈哈哈。。
微信:
支付宝:
感谢一路支持个人人。。。。。 Love me and hold me QQ:69673804(16年老号) EMAIL:69673804@qq.com 友链交换 若是有兴趣和本博客交换友链的话,请按照下面的格式在评论区进行评论,我会尽快添加上你的连接。
网站名称:KingYiFan’S Blog 网站地址:http://blog.cnbuilder.cn 网站描述:年少是你未醒的梦话,风华是燃烬的彼岸花。 网站Logo/头像:[头像地址](https://blog.cnbuilder.cn/upload/2018/7/avatar20180720144536200.jpg)