java开发-微信二次分享

java

今天踩了一个很大的坑。。我发现微信坑真多啊。微信做的东西真的不屑于评论啊。刚开始坑公众号开发,然后坑微信支付开发,然后坑小程序开发。我真的走不出来了。。。。关键还没办法。

今天给大家分享一下app的二次分享问题吧。

是不是挺好玩的。这个时候就说了为什么变成这个样子,因为他分享H5没有写微信的二次分享。

二次分享操作流程:

  1. 打开某app然后分享到朋友某一个篇文章。
  2. 然后朋友打开,觉得写得不错,然后呢也分享了,然后就出现了下图的现象。。
  3. 所有参数都暴露了不说,关键是难看啊。你看上图。

画个图图告诉你什么是二次分享:

代码流程炒鸡简单。我给你们也画一个流程图。

老规矩:

点我快速进入分享sdk官方文档

直接上代码吧。代码有些糙 不喜欢勿喷。

	前段需要引入的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 + "&timestamp=" + 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);

}

}

微信的签名算法逻辑。

微信分享-常见错误及解决方法

调用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换成测试了 一直报签名错误,对比了很长时间,自己生成的和官网的一模一样就是报错。提示就是签名报错 他也不说哪里错了。

前几天有人问我怎么申请测试公众号,只能用于开发。

我把微信官方的地址给大家一下: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)

以上是 java开发-微信二次分享 的全部内容, 来源链接: utcz.com/z/395087.html

回到顶部