java 自定义微信分享_玩玩微信公众号Java版之七:自定义微信分享

前面已经学会了微信网页授权,现在微信网页的功能也可以开展起来啦!

首先,我们先来学习一下分享,如何在自己的页面获取分享接口及让小伙伴来分享呢?

今天的主人公: 微信 JS-SDK, 对应官方链接为:微信JS-SDK说明文档

经过分析,要使用微信SJ-SDK需要完成如下工作:

4afe46c645b9d88b18b0f206ea5eb2c5.png

由以上分析,我们需要做服务器的注入验证,另外在需要分享的页面中引入js文件,这样就可以调用微信JS-SDK中的接口啦~

下面首先开始实现注入验证功能,主要分为如下几步:

第一步,获取access_token:

access_token是微信接口号开发的基本数据,建议存到数据库中保存。(第三篇中已实现,可参考)

第二步,获取jsapi_ticket:

由官方文档得知,只需Get方式调用接口:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

其中参数为第一步中获取的access_token,调用方法已在工具类中。另jsapi_ticket有效时间为2个小时,且每个页面均需用到接口验证,因此可参考access_token,

将jsapi_ticket 存至数据库,以便后续获取。

获取jsapi_ticket主方法可参考(请忽略注释问题):

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 * 获取微信 js-api-ticket3 *@return

4 */

5 publicJSAPITicket getJsApiTicket()6 {7

8 /*

9 * 第一步,查询数据库中ticket是否已过期 未过期则直接获取10 */

11 if(updateJSAPITicket())12 {13 returnmJSAPITicket;14 }15

16 /*第二步,获取当前有效的access_token*/

17 WeChatTokenService tWeChatTokenService = newWeChatTokenService();18 //此处获取测试账号的

19 String access_token =tWeChatTokenService.getToken(mAppid, mAppSecret).getToken();20

21 /*第三步,则通过https调用获取 jsapi_ticket*/

22 if (!getJSApiTicketbyhttps(access_token))23 {24 System.out.println("获取ticket失败!");25 return null;26 }27

28 returnmJSAPITicket;29 }

View Code

其中jsapi_ticket对应实体类为:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 * 微信 JS-API-Ticket类3 *@authorDamon4 */

5 public class JSAPITicket implementsCloneable6 {7

8 //微信 ticket流水号

9 private String ticketid = "";10

11 //微信jsapi_ticket

12 private String ticket = "";13

14 //有效时间

15 private int expires_in = 0;16

17 //微信appid

18 private String appid = "";19

20 //申请用户密钥

21 private String appsecret = "";22

23 //获取时间

24 private String createtime = "";25

26 publicString getTicketid()27 {28 returnticketid;29 }30

31 public voidsetTicketid(String ticketid)32 {33 this.ticketid =ticketid;34 }35

36 publicString getTicket()37 {38 returnticket;39 }40

41 public voidsetTicket(String ticket)42 {43 this.ticket =ticket;44 }45

46 public intgetExpires_in()47 {48 returnexpires_in;49 }50

51 public void setExpires_in(intexpires_in)52 {53 this.expires_in =expires_in;54 }55

56 publicString getAppid()57 {58 returnappid;59 }60

61 public voidsetAppid(String appid)62 {63 this.appid =appid;64 }65

66 publicString getCreatetime()67 {68 returncreatetime;69 }70

71 public voidsetCreatetime(String createtime)72 {73 this.createtime =createtime;74 }75

76 publicString getAppsecret()77 {78 returnappsecret;79 }80

81 public voidsetAppsecret(String appsecret)82 {83 this.appsecret =appsecret;84 }85

86 @Override87 public JSAPITicket clone() throwsCloneNotSupportedException88 {89 //TODO Auto-generated method stub

90 JSAPITicket cloneTicket = (JSAPITicket) super.clone();91 returncloneTicket;92 }93

94 }

View Code

对应表结构可以参考:

35c08c069ea32b568d27498fe8e6283a.png

对应的SQL脚本:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 drop table if existsWeChatJSAPITicket;2

3 /*==============================================================*/

4 /*Table: WeChatJSAPITicket*/

5 /*==============================================================*/

6 create tableWeChatJSAPITicket7 (8 ticketid varchar(60) not null,9 ticket varchar(300),10 expires_in int,11 appid varchar(60),12 appsecret varchar(60),13 createtime timestamp,14 primary key(ticketid)15 );

View Code

主方法调用的明细方法为:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 * 获取微信JS-API-Ticket信息3 *@return

4 */

5 private booleanupdateJSAPITicket()6 {7 //查询数据库数据,如果有则不用更新,无则需要更新

8 Connection con = null;9 PreparedStatement stmt = null;10 ResultSet rs = null;11 //判断当前token是否在有效时间内

12 String sql = " select * from wechatjsapiticket where appid ='" + mAppid + "' and appsecret ='" +mAppSecret13 + "' and ( current_timestamp -createtime)

16 {17 //创建数据库链接

18 con =DBConnPool.getConnection();19 //创建处理器

20 stmt =con.prepareStatement(sql);21 //查询Token,读取1条记录

22 rs =stmt.executeQuery();23 if(rs.next())24 {25 mJSAPITicket.setTicketid(rs.getString("ticketid"));26 mJSAPITicket.setTicket(rs.getString("ticket"));27 mJSAPITicket.setExpires_in(rs.getInt("expires_in"));28 mJSAPITicket.setAppid(rs.getString("appid"));29 mJSAPITicket.setAppsecret(rs.getString("appsecret"));30 }31 else

32 {33 System.out.println("未查询到对应ticket");34 return false;35 }36 }37 catch(Exception e)38 {39 //TODO: handle exception

40 return false;41 }42

43

44 return true;45 }46

47

48 /**

49 * 调用请求获取ticket50 *@paramaccess_token51 *@return

52 */

53 private booleangetJSApiTicketbyhttps(String access_token)54 {55

56 String current_time = new Date().getTime() + "";57

58 try

59 {60 //请求地址

61 String path = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";62 path = path.replace("ACCESS_TOKEN", access_token);63 String strResp = WeChatUtil.doHttpsGet(path, "");64 System.out.println(strResp);65

66 //解析获取的token信息

67 Map tMap =WeChatUtil.jsonToMap(strResp);68

69 System.out.println(tMap.toString());70

71 mJSAPITicket.setTicketid(WeChatUtil.getMaxJSAPITicketID());72 mJSAPITicket.setTicket((String) tMap.get("ticket"));73 mJSAPITicket.setExpires_in(Integer.parseInt((String) tMap.get("expires_in")));74 mJSAPITicket.setAppid(mAppid);75 mJSAPITicket.setAppsecret(mAppSecret);76 mJSAPITicket.setCreatetime(current_time);77

78 System.out.println(mJSAPITicket.getTicket());79

80 }81 catch(HttpException e)82 {83 //TODO Auto-generated catch block

84 e.printStackTrace();85 return false;86 }87 catch(IOException e)88 {89 //TODO Auto-generated catch block

90 e.printStackTrace();91 return false;92 }93

94 //存储JS-API-Ticket至数据库

95 if (!saveJSAPITicket(mJSAPITicket))96 {97 return false;98 }99

100 return true;101 }102

103 /**

104 * 将获取到的ticket信息存到数据库105 *@paramtJSAPITicket106 *@return

107 */

108 private booleansaveJSAPITicket(JSAPITicket tJSAPITicket)109 {110 PreparedStatement pst = null;111 Connection conn = null;112 try

113 {114 JSAPITicket ticket =tJSAPITicket.clone();115

116 System.out.println(ticket.getTicketid() +ticket.getTicket());117

118 conn =DBConnPool.getConnection();119 //创建预处理器

120 pst = conn.prepareStatement("insert into wechatjsapiticket(ticketid, ticket, expires_in,appid, appsecret,createtime) values (?,?,?,?,?,?)");121

122 pst.setString(1, ticket.getTicketid());123 pst.setString(2, ticket.getTicket());124 pst.setInt(3, ticket.getExpires_in());125 pst.setString(4, ticket.getAppid());126 pst.setString(5, ticket.getAppsecret());127 long now = newDate().getTime();128 pst.setTimestamp(6, newjava.sql.Timestamp(Long.parseLong(ticket.getCreatetime())));129 pst.execute();130

131 }132 catch(CloneNotSupportedException e)133 {134 //TODO Auto-generated catch block

135 e.printStackTrace();136 return false;137 }138 catch(SQLException e)139 {140 //TODO Auto-generated catch block

141 e.printStackTrace();142 return false;143 }144 catch(Exception e)145 {146 //TODO: handle exception

147 System.out.println("出现额外异常");148 return false;149 }150

151 return true;152 }

View Code

这样就方便我们获取access_ticket啦!

第三步,实现数据签名:

签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。

这里需要用到四个参数,具体分析如下:

参数

说明

noncestr

随机字符串,可用java.util.UUUID类实现

jsapi_ticket

调用前面方法获取

timestamp

当前时间戳

url

传入参数,每次由前端传入

另外,参数加密算法为SHA1加密,因此实现方法为:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 * ticket数据签名3 *@return

4 */

5 publicWeChatJSAPISign getSignTicket(String requestUrl)6 {7 //随机字符串

8 String noncestr = UUID.randomUUID().toString().replace("-", "");9 String jsapi_ticket =getJsApiTicket().getTicket();10 long timestamp = newDate().getTime();11

12 String params = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url="

13 +requestUrl;14 String signature = "";15

16 System.out.println("params:" +params);17

18 try

19 {20 MessageDigest crypt = MessageDigest.getInstance("SHA-1");21 crypt.reset();22 crypt.update(params.getBytes("UTF-8"));23 signature =WeChatUtil.byteToHex(crypt.digest());24 }25 catch(NoSuchAlgorithmException e)26 {27 e.printStackTrace();28 }29 catch(UnsupportedEncodingException e)30 {31 e.printStackTrace();32 }33

34 WeChatJSAPISign tChatJSAPISign = newWeChatJSAPISign();35

36 tChatJSAPISign.setAppId(mAppid);37 tChatJSAPISign.setNoncestr(noncestr);38 tChatJSAPISign.setTimestamp(timestamp);39 tChatJSAPISign.setSignature(signature);40

41 returntChatJSAPISign;42 }

View Code

返回定义的参数对象,定义如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 * // JS-API-Ticket 签名类3 *@authorDamon4 */

5 public classWeChatJSAPISign6 {7

8 //JS-API-Ticket appid

9 private String appId = "";10

11 //JS-API-Ticket 随机字符串

12 private String noncestr = "";13

14 //JS-API-Ticket 时间

15 private long timestamp = 0;16

17 //JS-API-Ticket 签名

18 private String signature = "";19

20 publicString getAppId()21 {22 returnappId;23 }24

25 public voidsetAppId(String appId)26 {27 this.appId =appId;28 }29

30 publicString getNoncestr()31 {32 returnnoncestr;33 }34

35 public voidsetNoncestr(String noncestr)36 {37 this.noncestr =noncestr;38 }39

40 public longgetTimestamp()41 {42 returntimestamp;43 }44

45 public void setTimestamp(longtimestamp)46 {47 this.timestamp =timestamp;48 }49

50 publicString getSignature()51 {52 returnsignature;53 }54

55 public voidsetSignature(String signature)56 {57 this.signature =signature;58 }59

60 }

View Code

到这,注入验证的服务器端功能就完成了。

下面也进行页面的编写和调用验证。

第一步,先写一个分享页面(基本的html页面即可),可参考(由于我的工程默认编码GBK,编码请注意):

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1

2

3

4

5

6

damon's share page

7

8

9

10

11

14

15 wx.config({16 debug:false,//开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。

17 appId:'${appid}',//必填,公众号的唯一标识

18 timestamp:'${timestamp}',//必填,生成签名的时间戳

19 nonceStr:'${noncestr}',//必填,生成签名的随机串

20 signature:'${signature}',//必填,签名,见附录1

21 jsApiList: ['onMenuShareTimeline','onMenuShareQQ','onMenuShareQZone']//必填,需要使用的JS接口列表,所有JS接口列表见附录2

22 });23

24 wx.ready(function(){25

26 //分享到朋友圈

27 wx.onMenuShareTimeline({28 title:'玩玩微信公众号Java版之六:微信网页授权',//分享标题

29 link:'http://www.cnblogs.com/cooldamon/p/7219400.html',//分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致

30 imgUrl:'http://damonhouse.iok.la/wechat/pic1.jpg' //分享图标

31 });32

33 //分享到QQ

34 wx.onMenuShareQQ({35 title:'玩玩微信公众号Java版之六:微信网页授权',//分享标题

36 desc:'分享测试',//分享描述

37 link:'http://www.cnblogs.com/cooldamon/p/7219400.html',//分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致

38 imgUrl:'http://damonhouse.iok.la/wechat/pic1.jpg' //分享图标

39 });40

41 //分享到QQ空间

42 wx.onMenuShareQZone({43 title:'玩玩微信公众号Java版之六:微信网页授权',//分享标题

44 desc:'分享QQ空间测试',//分享描述

45 link:'http://www.cnblogs.com/cooldamon/p/7219400.html',//分享链接

46 imgUrl:'http://damonhouse.iok.la/wechat/pic1.jpg' //分享图标

47 });48

49

50 });51

52 wx.error(function(res){53 //config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。

54 });55

56 functionshareMe()57 {58 //分享到QQ空间

59 wx.onMenuShareQZone({60 title:'玩玩微信公众号Java版之六:微信网页授权',//分享标题

61 desc:'分享QQ空间测试',//分享描述

62 link:'http://www.cnblogs.com/cooldamon/p/7219400.html',//分享链接

63 imgUrl:'http://damonhouse.iok.la/wechat/pic1.jpg' //分享图标

64 });65

66 }67

68

69

70

71 欢迎分享

72

73

View Code

另外这里对微信接口调用写了一个功能的方法,引入wechat_config.jsp

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1

2

3

4 //微信js-jdk 配置接口处理5 //第一步,获取参数6 %>

7

8

9

10 Stringurl=request.getRequestURL().toString();11 System.out.println(url);12 WeChatJSAPIService tWeChatJSAPIService= newWeChatJSAPIService();13

14 WeChatJSAPISign tWeChatJSAPISign=tWeChatJSAPIService.getSignTicket(url);15 System.out.println( tWeChatJSAPISign.getAppId());16 System.out.println( tWeChatJSAPISign.getNoncestr());17 System.out.println( tWeChatJSAPISign.getTimestamp());18 System.out.println( tWeChatJSAPISign.getSignature());19

20 request.setAttribute("appid", tWeChatJSAPISign.getAppId());21 request.setAttribute("noncestr", tWeChatJSAPISign.getNoncestr());22 request.setAttribute("timestamp", tWeChatJSAPISign.getTimestamp());23 request.setAttribute("signature", tWeChatJSAPISign.getSignature());24

25 %>

View Code

其中说明:

1、引入http://res.wx.qq.com/open/js/jweixin-1.2.0.j

2、验证接口中请注意参数名称(这里粗心弄错了,导致验证失败),另外验证错误原因可参考官方错误说明:附录5-常见错误及解决方法.

3、对应的接口功能,最终实现在左上角的更多按钮,请参考页面:

dde4d4f4562e8bdee80d33e82731b74c.png

4、最终实现效果如下(以分享到qq空间为例):

7d3f83d5705360ad4ae7ed4cc494cbfe.png

这里多出了【分享到手机QQ】和【分享到QQ空间】两个按钮,点击【分享到QQ空间】,可看到:

0639fe36da3b3de3b5706926d08188a0.png

恭喜你,成功做出了自己的分享页面! 继续加油吧~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值