APP分享到微信的流程(以及二次分享样式问题)

APP分享到微信的流程(以及二次分享样式问题)

如果要完成微信分享,还是有需要去微信官方开发文档看一下的。附上地址:

微信开发平台

微信公众平台开发文档

自己老年记忆力过段时间肯定会忘记如何去实现这个功能,所以记录一下。

因为自己不是写客户端的(Android、ios),所以前端代码并不能详细记录在这里,可以参考微信开发平台中的说明。后端服务是在客户端提供给我们一个接口的前提下进行开发的。

接口如下:

/**

* 分享

* type:1:仅分享到通讯2:仅分享到其他3:分享到通讯和其他,

* wxTitle:微信分享标题(type==2|3时,必输),

* wxDes:微信分享描述(type==2|3时,必输),

* wxLink:微信分享分享页面地址(type==2|3时,必输),

* wxThump:微信分享 缩略图,

* wxType:微信分享类型0:网页分享1:文本分享2:本地图片分享3:网络图片分享,

*/

function shareMsg(json){

window.SysClientJs.shareMsgTo(JSON.stringify(json));

}

ps:参数type是用来表示点击分享后都有哪几个分享选项供用户选择:

1:平台通讯(我们自己应用内的通讯)

2:只分享到微信(没有平台通讯选项)

3:平台通讯和微信都有

一、APP内容分享到微信

有了客户端给的方法,实现微信分享功能就比较简单了。

/*

* 封装传送的数据

*/

var json ={

type:'2',

wxTitle:'**银行代销基金产品',

wxDes:'我行代销各类基金产品,请点击查看详情',

wxLink:$rootScope.AppUrl+'fundListWXShare?ShareId='+data.ShareId

};

/*

* 调用分享方法

*/

$clientUtils.shareMsg(json);

到这里微信分享就结束了,wxThump不填,默认选择客户端已经定义的图片,wxType默认为1。

分享后的图片:

ps:图片并不是代码里边的基金产品,不过样式是一样的。

好的,终于可以把好东西分享给好友了,但是好友并点不开你的分享。还差一步,你分享的这个东西相当于一个链接,就是参数里边的wxLink。好友点击你分享的内容,就相当于在微信浏览器里边输入了一个地址,然后微信浏览器去服务器获取页面展示给用户。最后一步就是写个页面来响应浏览器的请求。

二、微信二次分享问题

问题复现流程:分享给好友->好友打开看了看感觉还不错就想分享给他的好友->点击微信浏览器右上角的三个点 ,->选择发送给朋友 ,ok 结果发现变样了(如下图)。

标题变了,摘要变了,图片也没了......

有问题就只能解决,之前试过WeixinJSBridge接口,但是没有效果,通过百度了解到微信为了整顿"诱导分享"的行为,关闭了WeixinJSBridge。

经过百度、看开发文档,总算找到了解决方法。

首先,你得有一个已经认证的微信公众号(企业公众号),没有是不行滴~。

要准备的东西:

1.APPID、appsecret(在微信公众号 开发->基本设置 能看到)

2.公众号要设置安全域名(在 微信公众号 设置->公众号设置 -> 功能设置 -> JS接口安全域名)

3.IP地址白名单

设置->安全中心->IP白名单(IP地址就是服务器地址,没有这个白名单获取token时 会报IP地址非法。)

下面开始撸代码:

1).从微信获取token

向微信给定的url(https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET)发GET请求,获取token和token的有效期,获取token只需要替换APPID和APPSECRET,grant_type的值不变。

/* accessToken 静态全局变量 保存上次获取的token

* tokenExpireTime 静态的全局变量 保存上次获取token的有效期

* getTokenTime 静态的全局变量 保存上次获取token的时间

*/

if(accessToken==null||("").equals(accessToken)||(now - getTokenTime > tokenExpireTime*1000)){

Map tokenInfo = getAccessToken();

if(tokenInfo != null){

accessToken = (String) tokenInfo.get("access_token");

tokenExpireTime = Long.parseLong(tokenInfo.get("expires_in")+"");

getTokenTime = System.currentTimeMillis();

}else{

logger.info("get token is failure!");

}

}

private Map getAccessToken(){

String requestUrl = accessTokenUrl.replace("APPID",appId).replace("APPSECRET",appSecret);

Map result = HttpUtil.doGet(requestUrl);//向微信发送get请求

return result ;

}

ps:token有每天的获取次数和获取频率,如果频繁获取将会触发限制。所以token要在本地缓存,上边的代码缓存简单的用static来存储,严格来说应该存在数据库,如果生产上有多台服务器,就必须要存在数据库了。

2).从微信获取ticket

跟获取token有一点不同,token是获取ticket的参数,最后我们只需要ticket。url如下:(https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi)只需要把ACCESS_TOKEN(就是我们第一步获取的token)替换就OK。

if(jsApiTicket==null||("").equals(jsApiTicket)||(now - getTiketTime > ticketExpireTime*1000)){

Map ticketInfo = getJsApiTicket();

if(ticketInfo!=null){

jsApiTicket = (String) ticketInfo.get("ticket");

ticketExpireTime = Long.parseLong(ticketInfo.get("expires_in")+"");

getTiketTime = System.currentTimeMillis();

}else{

logger.info("get ticket is failure!");

}

}

@SuppressWarnings("rawtypes")

private Map getJsApiTicket(){

String requestUrl = apiTicketUrl.replace("ACCESS_TOKEN", accessToken);

Map result = HttpUtil.doGet(requestUrl);

return result;

}

3).生成签名

下图是微信开发文档的签名算法,开发文档中还有微信给的简单示例(java、php...)。

实现代码:

public Map makeWXTicket(String jsApiTicket, String url) {

Map ret = new HashMap();

String nonceStr = createNonceStr();

String timestamp = createTimestamp();

String string1;

String signature = "";

string1 = "jsapi_ticket=" + jsApiTicket +

"&noncestr=" + nonceStr +

"×tamp=" + timestamp +

"&url=" + url;

try{

MessageDigest crypt = MessageDigest.getInstance("SHA-1");

crypt.reset();

crypt.update(string1.getBytes("UTF-8"));

signature = byteToHex(crypt.digest());

}catch (Exception e){

logger.error("WeChatController.makeWXTicket=====Start");

logger.error(e.getMessage(),e);

logger.error("WeChatController.makeWXTicket=====End");

}

ret.put("url", url);

ret.put("jsapi_ticket", jsApiTicket);

ret.put("nonceStr", nonceStr);

ret.put("timestamp", timestamp);

ret.put("signature", signature);

ret.put("appid", appId);

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);

}

4).前端校验

data是后端传过来的数据:包含appid、时间戳、随机字符串、签名、ticket、url。

wx.config({

debug: false,

appId: data.appid,

timestamp: data.timestamp,

nonceStr: data.nonceStr,

signature: data.signature,

jsApiList: [//需要用到的接口

'checkJsApi',

'onMenuShareTimeline',//分享到朋友圈的接口

'onMenuShareAppMessage'//分享给朋友的接口

]

});

如果验证成功,debug模式下会提示config:ok。一般情况下,不OK一般是因为url的问题。url的值就是分享微信时wxLink的值去掉#号后边的内容。一般url的取值在js中取:

url = location.href.split('#')[0].toString();

传到后端进行签名。这个url必须包含在js接口安全域名内。

5).分享到朋友圈、好友

分享到朋友圈、好友这两个接口只是众多接口中比较常用的两个。还有分享到qq、微博等接口。

wx.ready(function () {

wx.checkJsApi({//可要可不要,功能只是校验下都支持哪些接口

jsApiList:['onMenuShareTimeline','onMenuShareAppMessage'],

success:function(res){

}

});

wx.onMenuShareTimeline({

title: title,//自定义的标题

link: link,//自定义的链接

imgUrl: $rootScope.rootUrl+'share/assets/logo.jpg',//自定义的图片

trigger: function (res) {

},

success: function (res) {

},

cancel: function (res) {

},

fail: function (res) {

}

});

wx.onMenuShareAppMessage({

title: title,

desc: desc,

link: link,

imgUrl: $rootScope.rootUrl+'share/assets/logo.jpg',

type: 'link',

dataUrl: '',

success: function () {

},

cancel: function () {

}

});

wx.error(function (res) {

});

});

ok,效果图如下:

OK,问题到此,就解决完了。可以尽情分享给好友了。