文档章节

java开发的微信分享到朋友圈功能

千元机爱好者
 千元机爱好者
发布于 2016/12/12 18:03
字数 1303
阅读 766
收藏 3
点赞 3
评论 0

微信分享到朋友圈其实是微信中的一个内置功能,但当我们想自定义分享的内容的时候,就得自己写js代码调用微信的jsapi。

过程大体分为两步:

一、当你打开一个页面(你项目中需要加入分享朋友圈功能的页面)时,会执行一段js代码,这段js代码中实现了一个微信注入权限的功能,因为只有注入权限之后你才可以调用微信的分享朋友圈的功能,微信注入权限接口的js代码如下所示:

$(function(){
	    ajaxConfig();
	}); 

	function ajaxConfig(){
	$.ajax({
	        type:"post",
	        dataType: "json",
	        data: {
	           url : location.href.split('#')[0]
	        },
	        url: "${pageContext.request.contextPath }/wxUser/testConfig.shtml",
	        success: function(obj){
	            if(obj.result == "success"){
	                //微信注入权限接口
	                wx.config({
	                  debug: false,
	                  appId: obj.appId,
	                  timestamp: obj.timestamp,
	                  nonceStr: obj.nonceStr,
	                  signature: obj.signature,
	                  jsApiList: [
	                    'onMenuShareTimeline',  //分享到朋友圈                 
	                  ]
	              });
	            }else{
	                alert("加载数据错误");
	            }
	        },
	        error:function(){
	            alert("系统请求异常!");
	        }
	    });
	}

如果接口权限注入成功,这个接口需要5个重要的参数,公众号的appid,时间戳timestamp,随机字符串nonceStr,以及加密签名signature,这四个参数通过ajax的回调函数进行接收,后台代码的实现如下:

@RequestMapping("/testConfig")
	public void testConfig(String url,Model model,HttpServletResponse response) throws IOException{
        String jsapi_ticket = JsapiTicketTimeTask.jsapi_ticket;
        String result;
        if("".equals(jsapi_ticket)){
            result = "error";
        }
        //进行数据的加密(url,jsapi_ticket,nonceStr,timestamp)等参数进行SHA1加密
        Map<String, String> ret = Sign.sign(jsapi_ticket, url);
        String appId=WxConfigure.getAPPID();
        String timestamp = ret.get("timestamp");
        String nonceStr = ret.get("nonceStr");
        String signature = ret.get("signature");
        result = "success";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("timestamp", timestamp);
        jsonObject.put("nonceStr", nonceStr);
        jsonObject.put("signature", signature);
        jsonObject.put("result", result);
        jsonObject.put("appId", appId);
        response.setContentType("application/json;charset=utf-8");
		response.setHeader("Access-Control-Allow-Origin", "*");
     	response.getWriter().write(jsonObject.toString());
    }

二、当你点击你页面的一个按钮时(携带有点击事件的标签,不一定非得是按钮),会弹出一个页面指向右上角提示你分享朋友圈(因为微信不能实现自定义的按钮直接分享到朋友圈,所以只能这样提示),会调用微信分享朋友圈的js代码,微信分享到朋友圈的js代码如下所示:

$("#share").on("click", function() {
	    $("#shareit").show();
	    wx.onMenuShareTimeline({
	    	title: '欢迎来到慧聪网产业带性格色彩测试',
	        link: 'https://rong580.com/wzh/wxUser/toTestChoice.shtml',
	        imgUrl: '../img/zp-header.png',
	        trigger: function (res) {
	        },
	        success: function (res) {
	          alert('已分享');
	          window.location.href="toIndex.shtml?tag4="+4;
	        },
	        cancel: function (res) {
	          alert('已取消');
	          window.location.href="toIndex.shtml";
	        },
	        fail: function (res) {
	          alert(JSON.stringify(res));
	        }
	      });
	});
$("#shareit").on("click", function(){
	  $("#shareit").hide(); 
	})

这时候你点击分享朋友圈按钮,就可以将你自定义的内容分享到朋友圈了,这里的shareit就是你指引你分享到朋友圈的图片,通过点击事件可以控制它的显示与隐藏,这个图片你可以自定义,大概是这样的:

以上就是分享到朋友圈的功能实现;

在这个功能中会实现遇到一个问题,就是jsapiticket的获取,因为微信官方规定jsapiticket每天的获取次数是有限的,一旦超过次数就无法获取,这样就会影响到项目的正常功能,这里可以写一个定时器每小时获取一次就可以了。定时器利用spring的定时器来实现,直接在spring的配置文件中配置即可:

<bean id="jsapiTask" class="chan.ye.dai.wexin.JsapiTicketTimeTask" />
    <bean id="jobDetail"
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="jsapiTask" />
        <property name="targetMethod" value="getTicket" />
        <property name="concurrent" value="false" />
    </bean>
     <bean id="simpleTrigger"
        class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail" />
        <property name="startDelay" value="1000" />
        <property name="repeatInterval" value="3600000" />
    </bean>
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="simpleTrigger" />
            </list>
        </property>
    </bean>

这里要注意一个问题,spring3和spring4中所使用的定时器是不一样的;

接下来附上相关的代码:

获取jsapiticket的类:

package chan.ye.dai.wexin;
import chan.ye.dai.http.Con2http;
import net.sf.json.JSONObject;
/**
 * 
* @ClassName: JsapiTicketTimeTask 
* @Description: TODO(jsapi_ticket类) 
* @author anyou
* @date 2016年12月9日 上午8:29:19 
*
 */
public class JsapiTicketTimeTask {
    public static String jsapi_ticket = "";
  /**
   * 
  * @Title: getTicket 
  * @Description: TODO(每隔一个小时调用一次微信获取jsapi的接口的任务调用器,在spring配置里面调用) 
  * @param     设定文件 
  * @return void    返回类型 
  * @throws
   */
    public static void getTicket() {
        //调用微信接口获取access_token凭证
        //Constant.ACCESS_TOKEN = https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
        String _url = WexinUrlConst.WEXIN_USER_ACCESS_TOKEN.replace("APPID", WxConfigure.getAPPID()).replace("SECRET", WxConfigure.getAPPSECRET());
        String resp = new Con2http().httpsRequest(_url, "GET", null);
        if (!resp.contains("errcode")) {
			JSONObject object = JSONObject.fromObject(resp);
			String access_token = (String) object.get("access_token");
			 if(access_token != null && !"".equals(access_token)){
	                //如果可以获取access_token,即可以调用jsapi_tiket的凭证了
	                String ticketUrl = WexinUrlConst.JSAPI_TICKET.replace("ACCESS_TOKEN", access_token);   //Constant.JSAPI_TICKET = https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
	                String ticketStr = new Con2http().httpsRequest(ticketUrl, "GET", null);
	                JSONObject ticketJson = JSONObject.fromObject(ticketStr);
	                String errmsg = (String) ticketJson.get("errmsg");
	                //如果调用成功,返回ok
	                if("ok".equals(errmsg)){
	                    jsapi_ticket = (String) ticketJson.get("ticket");	
	                 
	                }
			}
		}
    
    }
}

sign类:

package chan.ye.dai.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class Sign {
	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);
    }
}

 

 

© 著作权归作者所有

共有 人打赏支持
千元机爱好者
粉丝 9
博文 33
码字总数 34685
作品 0
焦作
后端工程师
Sharding-JDBC 3.0 即将发布,更名 Sharding-Sphere !

8日下午,知名开源数据库中间件 Sharding-JDBC 创始人张亮在朋友圈中发布了一个动态,表示 Sharding-JDBC 3.0 将于近期发布。 从该动态我们可以知道,从 3.0 开始,Sharding-JDBC 将更名为 ...

雨田桑 ⋅ 05/08 ⋅ 16

Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!

前几天写了一篇 Java 8 即将在 2019 年停止免费向企业提供更新的文章,企图迫使用户向更新一代的 Java 版本升级,但让人遗憾的是,小编今天收到了 Oracle Java 版本的升级推送,装完居然是 ...

Java技术栈 ⋅ 04/27 ⋅ 0

为什么大批的JAVA程序员都是在转大数据

前言 首先JAVA的精密,强大,拥有其它语言不可替代的性能和可维护性,早已经是成为最受欢迎的编程语言之一,很多人想进入IT行业,首选的第一门语言就是JAVA。但是,在未来10年肯定是大数据的...

JAVA丶学习 ⋅ 04/18 ⋅ 0

Java程序员必读书单,家族又添新成员

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书。 ——异步小编 有些革命出其不意地吸引了全世界的眼球。Twitter、Linux操作系统和...

异步社区 ⋅ 05/09 ⋅ 0

升级到JDK9的一个BUG,你了解吗

概述 前几天在一个群里看到一个朋友发了一个demo,说是JDK的bug,昨天在JVM的一个群里又有朋友发了,觉得挺有意思,分享给大家,希望大家升级JDK的版本的时候注意下是否存在这样的代码,如果...

你假笨 ⋅ 06/06 ⋅ 0

Java 8 停止维护,Java 9 难产,IDEA 2018 发布,还有……

祝大家五一劳动节快乐,工作顺利! 又到了总结上个月干货的时候了,这个月我们带来了各种Java技术干货,各种送书抽奖福利,各种面试题分享,各种最新动态资讯等。 - 5.1重磅活动 区块链免费送...

Java技术栈 ⋅ 04/30 ⋅ 0

Java开发学习之三版本简介 java编程

  Java编程语言,在更迭迅速的互联网领域多年屹立不倒,足以得见Java这门语言旺盛的生命力,因此,会有很多想要进入互联网领域的朋友,想要学Java来转行开发。但是,所谓“隔行如隔山”,j...

老男孩Linux培训 ⋅ 06/05 ⋅ 0

面试中关于Java虚拟机(jvm)的问题看这篇就够了

最近看书的过程中整理了一些面试题,面试题以及答案都在我的文章中有所提到,希望你能在以问题为导向的过程中掌握虚拟机的核心知识。面试毕竟是面试,核心知识我们还是要掌握的,加油~~~ 下面...

snailclimb ⋅ 05/12 ⋅ 0

java思维导图90天训练营第一期,向架构师前进一步

作者寄语 嗨,大家好,我是java思维导图的小编吕一明。这次训练营为期90天,主要针对有些java基础,但是项目经验比较缺乏的程序员。内容涵盖了主流的spring,redis,rabbitmq,MongoDB等技术...

java思维导图 ⋅ 04/26 ⋅ 0

关注这些技术号,你将拥有半个互联网圈

“ IT 行业技术变更周期越来越快,作为技术人最重要的是持续学习,现在的学习途径有很多,我们到底该如何做出选择? 我觉得最重要有两方面:第一,需要保持良好的技术视野,持续关注行业内技...

g6u8w7p06dco99fq3 ⋅ 04/18 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

BS与CS的联系与区别【简】

C/S是Client/Server的缩写。服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统,如Oracle、Sybase、InFORMix或 SQL Server。客户端需要安装专用的客户端软件。 B/S是Brower/...

anlve ⋅ 56分钟前 ⋅ 0

发生了什么?Linus 又发怒了?

在一个 Linux 内核 4.18-rc1 的 Pull Request 中,开发者 Andy Shevchenko 表示其在对设备属性框架进行更新时,移除了 union 别名,这引发了 Linus 的暴怒。 这一次 Linus Torvalds 发怒的原...

问题终结者 ⋅ 今天 ⋅ 0

在树莓派上搭建一个maven仓库

在树莓派上搭建一个maven仓库 20180618 lambo init 项目说明 家里有台树莓派性能太慢。想搭建一个maven私服, 使用nexus或者 jfrog-artifactory 运行的够呛。怎么办呢,手写一个吧.所在这个...

林小宝 ⋅ 今天 ⋅ 0

Spring发展历程总结

转自与 https://www.cnblogs.com/RunForLove/p/4641672.html 目前很多公司的架构,从Struts2迁移到了SpringMVC。你有想过为什么不使用Servlet+JSP来构建Java web项目,而是采用SpringMVC呢?...

onedotdot ⋅ 今天 ⋅ 0

Python模块/包/库安装(6种方法)

Python模块/包/库安装(6种方法) 冰颖机器人 2016-11-29 21:33:26 一、方法1: 单文件模块 直接把文件拷贝到 $python_dir/Lib 二、方法2: 多文件模块,带setup.py 下载模块包(压缩文件zip...

cswangyx ⋅ 今天 ⋅ 0

零基础学习大数据人工智能,学习路线篇!系统规划大数据之路?

大数据处理技术怎么学习呢?首先我们要学习Python语言和Linux操作系统,这两个是学习大数据的基础,学习的顺序不分前后。 Python:Python 的排名从去年开始就借助人工智能持续上升,现在它已经...

董黎明 ⋅ 今天 ⋅ 0

openJdk和sun jdk的区别

使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的OpenJDK, 那么到底什么是OpenJDK,它与SUN JDK有什么关系和区别呢? 历史上的原因是,Ope...

jason_kiss ⋅ 今天 ⋅ 0

梳理

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 它是JS的状态容器,是一种解决问题的方式,所以即可以用于 react 也可以用于 vue。 需要理解其思想及实现方式。 应用中所有的 stat...

分秒 ⋅ 今天 ⋅ 0

Java 后台判断是否为ajax请求

/** * 是否是Ajax请求 * @param request * @return */public static boolean isAjax(ServletRequest request){return "XMLHttpRequest".equalsIgnoreCase(((HttpServletReques......

JavaSon712 ⋅ 今天 ⋅ 0

Redis 单线程 为何却需要事务处理并发问题

Redis是单线程处理,也就是命令会顺序执行。那么为什么会存在并发问题呢? 个人理解是,虽然redis是单线程,但是可以同时有多个客户端访问,每个客户端会有 一个线程。客户端访问之间存在竞争...

码代码的小司机 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部