• 问题与需求:h5页面的内容在微信分享分享的内容无法定制,要自定义分享内容为该h5页面的标题,内容,图片等。  实现与排错:由于本人技术有限,基本都是参照网络上大神们... java开发微信分享到朋友圈功能 http:/

                问题与需求:h5页面的内容在微信分享后分享的内容无法定制,要自定义分享内容为该h5页面的标题,内容,图片等。

                实现与排错:由于本人技术有限,基本都是参照网络上大神们提供的源码,在部分地方做了简单修改。感谢大神们的无私奉献!主要参考链接和实现代码如下:

                                        java开发微信分享到朋友圈功能  http://www.jb51.net/article/88690.htm
                                        微信公众平台开发:JS-SDK之分享功能整理(Java)http://blog.csdn.net/dcb_ripple/article/details/52066708

                                        实现】步骤一:参考微信公众平台的开发者文档https://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html了解开发步骤

                                                    步骤二:为了描述方便,我先把h5页面的js代码贴出,再描述其实现所依赖的java代码。

    1.1h5页面的js代码

           h5页面:(获取该页面中的title-标题 discuss-内容 传入wx.config中实现分享内容的定制)                                  
          
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    <script>
        var url = window.location.href;
        var discuss ;
        var title ;
        var shareImgUrl="";
        var timestamp;
        var noncestr;
        var signature;
        var topicid = getUrlParameter('topicid');
        var userid =  getUrlParameter('userid');
        $.ajax({
            type: 'GET',
            url:  'topic/get?topicid=' + topicid+ '&userid=' + userid
        }).then(function successCallback(response) {
            var data = jsonToObj(response);
            discuss=data.data.discuss;
            title=data.data.title;
        }, function errorCallback(response) {
            console.log("error");
        });
    </script>
    <script src="js/weshare.js"></script>

           ps.由于我的页面用了angularjs,在js中如果通过document.getElementById拿值总是为空所以在js中再次使用了ajax向后台取值!!很影响性能的做法,在js中如何拿到angularjs渲染后的值呢?还希望有知道的朋友指点一下。
           weshare.js代码:
          
    
    //获取签名
    $.ajax({
        type: "GET",
        url: "wshare/getSignature",
        data:{url:url},
        success: function(data){
            console.log("success");
            var objData=JSON.parse(data);
            timestamp=objData.timestamp;
            noncestr=objData.noncestr;
            signature=objData.signature;
            console.log(objData);
            wxShare();
        },
        statusCode: {404: function(){
            alert('page not found');
        }}
    });
    function wxShare(){
        wx.config({
            debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: 'wxca57e6589ccebff0', // 和获取Ticke的必须一样------必填,公众号的唯一标识
            timestamp:timestamp, // 必填,生成签名的时间戳
            nonceStr: noncestr, // 必填,生成签名的随机串
            signature: signature,// 必填,签名,见附录1
            jsApiList: [
                'onMenuShareAppMessage','onMenuShareTimeline','onMenuShareTimeline','onMenuShareQQ','onMenuShareQZone'
            ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
        });
    }
    wx.ready(function(){
        //config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,
        //config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关
        //接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
    
        //----------“分享给朋友”
        wx.onMenuShareAppMessage({
            title:title, // 分享标题
            desc:discuss, // 分享描述
            link: url, // 分享链接
            imgUrl: shareImgUrl, // 分享图标
            success: function () {
                // 用户确认分享后执行的回调函数、
            },
            cancel: function () {
                // 用户取消分享后执行的回调函数
            }
        });
        //------------"分享到朋友圈"
        wx.onMenuShareTimeline({
            title: title, // 分享标题
            desc: discuss, // 分享描述
            link: url, // 分享链接
            imgUrl: shareImgUrl, // 分享图标
            type: '', // 分享类型,music、video或link,不填默认为link
            dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
            success: function () {
                // 用户确认分享后执行的回调函数、
            },
            cancel: function () {
                // 用户取消分享后执行的回调函数
            }
        });
        //-------------分享到QQ
        wx.onMenuShareQQ({
            title: title, // 分享标题
            desc: discuss, // 分享描述
            link: url, // 分享链接
            imgUrl: shareImgUrl, // 分享图标
            type: '', // 分享类型,music、video或link,不填默认为link
            dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
            success: function () {
                // 用户确认分享后执行的回调函数、
            },
            cancel: function () {
                // 用户取消分享后执行的回调函数
            }
        });
        //-------------分享到QQ空间
        wx.onMenuShareQZone({
            title: title, // 分享标题
            desc: discuss, // 分享描述
            link: url, // 分享链接
            imgUrl: shareImgUrl, // 分享图标
            type: '', // 分享类型,music、video或link,不填默认为link
            dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
            success: function () {
                // 用户确认分享后执行的回调函数、
            },
            cancel: function () {
                // 用户取消分享后执行的回调函数
            }
        });
    
    });
    wx.error(function(res){
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
        console.log(res);
    });
    
    


    1.2java后台实现代码
          1.2.1 weixin.controller
          
    package com.weixin.controller;
    
    import java.io.IOException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Arrays;
    import java.util.Date;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.weixin.util.WeixinUtil;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import com.google.gson.Gson;
    import com.weixin.model.Ticket;
    import com.weixin.util.GetRandomStr;
    import com.weixin.util.SignatureBean;
    
    
    
    /**
     * Created by Administrator on 2017/1/9.
     */
    @Controller
    @RequestMapping("/wshare")
    public class WeixinshareController {
    
            private static Ticket aticket = null;
    
            @RequestMapping("/getSignature")
            public String getSignature( HttpServletRequest request,
                                        HttpServletResponse response) throws IOException, ParseException{
                //获取签名页面链接
                String url = request.getParameter("url");
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                //获取标签,并检查标签是否过期
                if(aticket==null){//第一次访问,标签不存在。
                    aticket = executeTicket(response,"1",url,format);
                    return null;
                }else{//标签存在,判断标签是否超时
                    String oldAcquiretime = aticket.getAcquiretime();
                    long difference=format.parse(format.format(new Date())).getTime()-format.parse(oldAcquiretime).getTime();
                    if(difference>7100000){//标签超时,重新到微信服务器请求标签超时时间为7200秒(7200000毫秒)
                        aticket = executeTicket(response,"2",url,format);
                        return null;
                    }else{//标签未超时
                        /**
                         * 注意事项
                         * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
                         * 2.签名用的url必须是调用JS接口页面的完整URL。
                         * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。
                         *
                         ****根据第1点要求   signature 配置的时候很容易出错,需要把生成 Ticket的 noncestr和 timestamp传给客户端***
                         */
                        System.out.print("ticket:"+aticket.getTicket());
                        String signature = signature(aticket.getTicket(),aticket.getTimestamp(),aticket.getNoncestr(),url);
                        SignatureBean signatureBean = new SignatureBean();
                        signatureBean.setNoncestr(aticket.getNoncestr());
                        signatureBean.setSignature(signature);
                        signatureBean.setTimestamp(aticket.getTimestamp());
                        signatureBean.setUrl(url);
                        response.setContentType("text/html;charset=UTF-8");
                        response.getWriter().print(new Gson().toJson(signatureBean));
                        return null;
                    }
                }
    
    
            }
            /**
             更新和获取ticket的方法,因为用的solr所以更新和新增是一样的ID无则添加,有则更新
             */
            public Ticket executeTicket(HttpServletResponse response,String flag,String url,SimpleDateFormat format) throws IOException{
    
                //获取签名随机字符串
                GetRandomStr randomStr = new GetRandomStr();
                String noncestr = randomStr.getRandomString(15);
                //获取签名时间戳
                String timestamp = Long.toString(System.currentTimeMillis());
                //请求accessToken
                String accessTokenUrl ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxca57e6589ccebff0&secret=b7d7c5df24644563be32bd84b90c8bf6";
                String tokenJson = WeixinUtil.httpRequest(accessTokenUrl, "GET", null);
                Gson gson = new Gson();
                ShareAccess_Token token = gson.fromJson(tokenJson, ShareAccess_Token.class);
                String to= token.getAccess_token();
                //获取标签
                String urlTicket ="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+to+"&type=jsapi";
               String ticketJson = WeixinUtil.httpRequest(urlTicket, "GET", null);
                Ticket ticket = gson.fromJson(ticketJson, Ticket.class);
                String t = ticket.getTicket();
                //String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
                //我的Ticket ID是写死的 20160114wiimediamrylsong1152
                String acquiretime = format.format(new Date());
                ticket.setTid("20160114wiimediamrylsong1152");
                ticket.setAcquiretime(acquiretime);
                ticket.setTimestamp(timestamp);
                ticket.setNoncestr(noncestr);
    
                /**
                 * 注意事项
                 * 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
                 * 2.签名用的url必须是调用JS接口页面的完整URL。
                 * 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。
                 *
                 *根据第1点要求   signature 配置的时候很容易出错,需要把生成 Ticket的 noncestr和 timestamp传给客户端*
                 */
    
                String signature = signature(t,timestamp,noncestr,url);
                System.out.print("ticket: "+t);
                SignatureBean signatureBean = new SignatureBean();
                signatureBean.setNoncestr(noncestr);
                signatureBean.setSignature(signature);
                signatureBean.setTimestamp(timestamp);
                signatureBean.setUrl(url);
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().print(new Gson().toJson(signatureBean));
    
                return ticket;
            }
    
            /**
             *
             *

    Project:mryl_phone_v2

    * *

    :mryl_phone_v2

    * *

    Description:根据标签,时间戳,密匙,URL进行签名

    * *

    Company:Wiimedia

    * *@Athor:SongJia * *@Date:2016-7-15 上午09:37:13 * */ private String signature(String jsapi_ticket, String timestamp, String noncestr, String url) { jsapi_ticket = "jsapi_ticket=" + jsapi_ticket; timestamp = "timestamp=" + timestamp; noncestr = "noncestr=" + noncestr; url = "url=" + url; String[] arr = new String[] { jsapi_ticket, timestamp, noncestr, url }; // 将token、timestamp、nonce,url参数进行字典序排序 Arrays.sort(arr); StringBuilder content = new StringBuilder(); for (int i = 0; i < arr.length; i++) { content.append(arr[i]); if (i != arr.length - 1) { content.append("&"); } } MessageDigest md = null; String tmpStr = null; try { md = MessageDigest.getInstance("SHA-1"); // 将三个参数字符串拼接成一个字符串进行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } content = null; return tmpStr; } /** * 将字节转换为十六进制字符串 * * @param mByte * @return */ private static String byteToHexStr(byte mByte) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } /** * 将字节数组转换为十六进制字符串 * * @param byteArray * @return */ private static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i < byteArray.length; i++) { strDigest += byteToHexStr(byteArray[i]); } return strDigest; } class ShareAccess_Token{ private String access_token; private String expires_in; public String getAccess_token() { return access_token; } public void setAccess_token(String accessToken) { access_token = accessToken; } public String getExpires_in() { return expires_in; } public void setExpires_in(String expiresIn) { expires_in = expiresIn; } } }
           原大神的实现中是将Ticket存入数据库中,但是考虑到TicketId已写死,Ticket只有一条数据,存入数据库,再从数据库中取值新等过于麻烦,故将Ticket作为static变量。第一次访问时创建,超时时给他赋新值。
          1.2.2weixin.util
          {CSDN:CODE:2126562
         
    package com.weixin.util;
    
    /**
     * Created by Administrator on 2017/1/9.
     */
    public class SignatureBean {
        private String noncestr;
        private String url;
        private String timestamp;
        private String signature;
        public String getNoncestr() {
            return noncestr;
        }
        public void setNoncestr(String noncestr) {
            this.noncestr = noncestr;
        }
        public String getUrl() {
            return url;
        }
        public void setUrl(String url) {
            this.url = url;
        }
        public String getTimestamp() {
            return timestamp;
        }
        public void setTimestamp(String timestamp) {
            this.timestamp = timestamp;
        }
        public String getSignature() {
            return signature;
        }
        public void setSignature(String signature) {
            this.signature = signature;
        }
    
    }
    

         
    package com.weixin.util;
    
    import java.util.Random;
    
    /**
     * Created by Administrator on 2017/1/9.
     * 获取随机字符串
     */
    
    public class GetRandomStr {
        public String getRandomString(int length) {
            String base = "abcdefghijklmnopqrstuvwxyz0123456789";
            Random random = new Random();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < length; i++) {
                int number = random.nextInt(base.length());
                sb.append(base.charAt(number));
            }
            return sb.toString();
        }
    }
    
      
         
    package com.weixin.util;
    
    import javax.net.ssl.X509TrustManager;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    /**
     * Created by Administrator on 2017/1/10.
     */
    public class MyX509TrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    
        }
    
        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    
        }
    
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
    

          ps.因为大神的注释写的很清楚,拉入我的项目中是可用滴,当然关于这个MyX509TrustManager我也不懂,百度之后还是不知道应该信任哪些证书,然后,干脆什么都没改,信任全部。当然网上也有很多不是通过Https请求的,然而根据微信现在的规定,好像都需要Https请求了。对于这个MyX509TrustManager大家有什么好的实现欢迎指教。
          1.2.3weixin.model     
         
    package com.weixin.model;
    
    /**
     * Created by Administrator on 2017/1/9.
     */
    public class Ticket {
        private String tid;
        private String ticket;
        private String errcode;
        private String errmsg;
        private String expires_in;
        private String acquiretime;
        private String noncestr;
        private String timestamp;
        public Ticket(String tid, String ticket, String errcode, String errmsg,
                      String expiresIn, String acquiretime, String noncestr,
                      String timestamp) {
            super();
            this.tid = tid;
            this.ticket = ticket;
            this.errcode = errcode;
            this.errmsg = errmsg;
            expires_in = expiresIn;
            this.acquiretime = acquiretime;
            this.noncestr = noncestr;
            this.timestamp = timestamp;
        }
        public String getTid() {
            return tid;
        }
        public void setTid(String tid) {
            this.tid = tid;
        }
        public String getTicket() {
            return ticket;
        }
        public void setTicket(String ticket) {
            this.ticket = ticket;
        }
        public String getErrcode() {
            return errcode;
        }
        public void setErrcode(String errcode) {
            this.errcode = errcode;
        }
        public String getErrmsg() {
            return errmsg;
        }
        public void setErrmsg(String errmsg) {
            this.errmsg = errmsg;
        }
        public String getExpires_in() {
            return expires_in;
        }
        public void setExpires_in(String expiresIn) {
            expires_in = expiresIn;
        }
        public String getAcquiretime() {
            return acquiretime;
        }
        public void setAcquiretime(String acquiretime) {
            this.acquiretime = acquiretime;
        }
        public String getNoncestr() {
            return noncestr;
        }
        public void setNoncestr(String noncestr) {
            this.noncestr = noncestr;
        }
        public String getTimestamp() {
            return timestamp;
        }
        public void setTimestamp(String timestamp) {
            this.timestamp = timestamp;
        }
    }
    

          最后,由于是在项目下新开的包,别忘了在Application.java中加入
    @ComponentScan(basePackages = {"com.mzqadmin","com.baidu","com.weixin"})
          另外,调试时把debug:true如果debug:ok却始终无法完成定制,一定是你的js代码有问题,后台验证已经通过了,看看你的js代码里参数是否带“”什么的。别问我怎么知道的,低级错误害死人呐~
          以上,是我做微信分享功能参考和实现的所有代码,有很多不足之处,还希望各位看官不吝赐教。
         
       
                




          
          
                            

                                                    

                                                    
      


                                            

                                                            

                                       

                                     

    展开全文
  • Java微信分享接口开发

    2019-08-06 17:31:14
    Java微信分享,步骤是 1、根据当前的url,获取signature,nonceStr,timestamp 和appId。 2、通过signature,nonceStr,timestamp 和appId来配置微信 wx.config。...3、通过wx.ready实现微信分享功能

    Java微信分享,步骤是

    1、根据当前的url,获取signature,nonceStr,timestamp 和appId。
    2、通过signature,nonceStr,timestamp 和appId来配置微信 wx.config。
    3、通过wx.ready实现微信分享功能。

    1、html端

    引入微信JS-SDK.

    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

    //分享核心js代码
    $(document).ready(function () {
    	//通过ajax,在页面加载的时候获取微信分享接口signature,nonceStr,timestamp 和appId
        $.ajax({
            type: "post",
            url: "/weixin/share",
            dataType: "json",
            data:"url="+window.location.href,
            success: function (data) {
                wx.config({
                    debug: false,
                    appId: data.appId,
                    timestamp: data.timestamp,
                    nonceStr: data.nonceStr,
                    signature: data.signature,
                    jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline', 'hideAllNonBaseMenuItem', 'showMenuItems']
                    // 功能列表,我们要使用JS-SDK的什么功能
                });
                wx.ready(function () {
                    // 获取“分享给朋友”按钮点击状态及自定义分享内容接口
                    wx.onMenuShareAppMessage({
                        title: "分享自定义标题", // 分享标题
                        desc: "分享自定义描述", // 分享描述
                        link: "http://localhost/weixin/share?openId=1",//分享点击之后的链接
                        imgUrl:'/images/photo/1.jpg', // 分享图标
                        type: 'link', // 分享类型,music、video或link,不填默认为link
                        success: function () {
    						//成功之后的回调
                        }
                    });
                    wx.hideAllNonBaseMenuItem();
                    wx.showMenuItems({
                        menuList: ['menuItem:share:appMessage', 'menuItem:share:timeline'] // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
                    });
                    wx.onMenuShareTimeline({
                        title: "分享自定义标题", // 分享标题
                        desc: "分享自定义描述", // 分享描述
                        link: "http://localhost/weixin/share?openId=1",//分享点击之后的链接
                        imgUrl:'/images/photo/1.jpg', // 分享图标
                        type: 'link', // 分享类型,music、video或link,不填默认为link
                        success: function () {
    						//成功之后的回调
                        }
                        cancel: function () {
                            // 用户取消分享后执行的回调函数
                        }
                    });
                });
                wx.error(function (res) {
                    //打印错误消息。及把 debug:false,设置为debug:ture就可以直接在网页上看到弹出的错误提示
                });
            }
        })
    });
    
    

    2、Java代码,获取 signature,nonceStr,timestamp 和appId

        @RequestMapping(value = "/share", method = RequestMethod.POST)
        @ResponseBody
        public Map<String, Object> share(HttpServletRequest request) {
            String urlTemp = "http://" + request.getServerName() + request.getContextPath();
            String urlpath = "http://" + request.getServerName();
            String appUrl = request.getParameter("url");
            if (request.getParameter("code") != null) {
                appUrl += "&code=" + request.getParameter("code");
            }
            if (request.getParameter("state") != null) {
                appUrl += "&state=" + request.getParameter("state");
            }
            return WxConfigUtil.getSignature(appUrl, ContentValues.APPID, ContentValues.SECRET, urlTemp, urlpath);
        }
    

    工具类我就把整个贴上来了,其中有些方法是没有用到的。

    getSignature()整个方法是微信分享中的核心方法,用来获取signature,nonceStr,timestamp 和appId这几个核心参数。

    package com.blog.common.util;
    
    import com.alibaba.fastjson.JSONObject;
    import com.blog.common.model.Token;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.ConnectException;
    import java.net.URL;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    
    
    /**
     * 公众平台通用接口工具类
     *
     * @author james
     * @date 2015-02-27
     */
    public class WxConfigUtil {
        // 获取access_token的接口地址(GET) 限2000(次/天)
        public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
        // 获取jsapi_ticket的接口地址(GET) 限2000(次/天)
        public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
        // 缓存添加的时间
        public static String cacheAddTime = null;
        // token,ticket缓存
        public static Map<String, Token> TOKEN_TICKET_CACHE = new HashMap<String, Token>();
        // token对应的key
        private static final String TOKEN = "token";
        // ticket对应的key
        private static final String TICKET = "ticket";
    
        /**
         * 外部获取签名入口类
         *
         * @param appUrl    应用的url
         * @return
         */
        public static Map<String, Object> getSignature(String appUrl, String appId, String secret, String url, String urlpath) {
            // 生成签名的随机串
            String noncestr = RandomUtil.getStringRandom(4);
            if (appUrl == null || "".equals(appUrl)) {
                return null;
            }
            String signature = null;
            Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
            Token accessTicket = getTicket(accessTocken.getToken(), System.currentTimeMillis() / 1000);
            signature = signature(accessTicket.getTicket(), cacheAddTime, noncestr, appUrl);
            System.out.println("-=-=-=-=-=-=-=-=appUrl:" + appUrl);
            System.out.println("-=-=-=-=-=-=-=-=token:" + accessTocken.getToken());
            System.out.println("-=-=-=-=-=-=-=-=ticket:" + accessTicket.getTicket());
            System.out.println("-=-=-=-=-=-=-=-=signature:" + signature);
            System.out.println("-=-=-=-=-=-=-=-=timestamp:" + cacheAddTime);
            Map<String, Object> map = new HashMap<>();
            map.put("appId", appId);
            map.put("timestamp", cacheAddTime);
            map.put("nonceStr", noncestr);
            map.put("appUrl", appUrl);
            map.put("signature", signature);
            map.put("url", url);
            map.put("urlpath", urlpath);
            return map;
        }
    
        /**
         * 获得Token
         *
         * @return
         */
        public static String getToken(String appId, String secret) {
            Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
            return accessTocken.getToken();
        }
    
        /**
         * 签名
         *
         * @param timestamp
         * @return
         */
        private static String signature(String jsapi_ticket, String timestamp, String noncestr, String url) {
            jsapi_ticket = "jsapi_ticket=" + jsapi_ticket;
            timestamp = "timestamp=" + timestamp;
            noncestr = "noncestr=" + noncestr;
            url = "url=" + url;
            String[] arr = new String[]{jsapi_ticket, noncestr, timestamp, url};
            // 将token、timestamp、nonce,url参数进行字典序排序
            Arrays.sort(arr);
            StringBuilder content = new StringBuilder();
            for (int i = 0; i < arr.length; i++) {
                content.append(arr[i]);
                if (i != arr.length - 1) {
                    content.append("&");
                }
            }
            MessageDigest md = null;
            String tmpStr = null;
    
            try {
                md = MessageDigest.getInstance("SHA-1");
                // 将三个参数字符串拼接成一个字符串进行sha1加密
                byte[] digest = md.digest(content.toString().getBytes());
                tmpStr = byteToStr(digest);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
    
            content = null;
            return tmpStr;
        }
    
        /**
         * 获取access_token
         *
         * @param appid     凭证
         * @param appsecret 密钥
         * @return
         */
        public static Token getToken(String appid, String appsecret, long currentTime) {
            Token tockenTicketCache = getTokenTicket(TOKEN);
            Token Token = null;
    
            if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 缓存存在并且没过期
                System.out.println("==========缓存中token已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
                return tockenTicketCache;
            }
            System.out.println("==========缓存中token不存在或已过期===============");
            String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
            JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
            // 如果请求成功
            if (null != jsonObject) {
                Token = new Token();
                Token.setToken(jsonObject.getString("access_token"));
                Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次
                System.out.println("==========tocket缓存过期时间为:" + Token.getExpiresIn() + "毫秒");
                Token.setAddTime(currentTime);
                updateToken(TOKEN, Token);
            }
            return Token;
        }
    
        /**
         * 获取ticket
         *
         * @param token
         * @return
         */
        private static Token getTicket(String token, long currentTime) {
            Token tockenTicketCache = getTokenTicket(TICKET);
            Token Token = null;
            if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 缓存中有ticket
                System.out.println("==========缓存中ticket已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
                return tockenTicketCache;
            }
            System.out.println("==========缓存中ticket不存在或已过期===============");
            String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);
            JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
            // 如果请求成功
            if (null != jsonObject) {
                Token = new Token();
                Token.setTicket(jsonObject.getString("ticket"));
                Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次
                System.out.println("==========ticket缓存过期时间为:" + Token.getExpiresIn() + "毫秒");
                Token.setAddTime(currentTime);
                updateToken(TICKET, Token);
            }
            return Token;
        }
    
        /**
         * 发起https请求并获取结果
         *
         * @param requestUrl    请求地址
         * @param requestMethod 请求方式(GET、POST)
         * @param outputStr     提交的数据
         * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
         */
        private 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.parseObject(buffer.toString());
                // jsonObject = JSONObject.fromObject(buffer.toString());
            } catch (ConnectException ce) {
                System.out.println("Weixin server connection timed out.");
            } catch (Exception e) {
                System.out.println("https request error:{}" + e.getMessage());
            }
            return jsonObject;
        }
    
        /**
         * 将字节数组转换为十六进制字符串
         *
         * @param byteArray
         * @return
         */
        private static String byteToStr(byte[] byteArray) {
            String strDigest = "";
            for (int i = 0; i < byteArray.length; i++) {
                strDigest += byteToHexStr(byteArray[i]);
            }
            return strDigest;
        }
    
        /**
         * 将字节转换为十六进制字符串
         *
         * @param mByte
         * @return
         */
        private static String byteToHexStr(byte mByte) {
    
            char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
            char[] tempArr = new char[2];
            tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
            tempArr[1] = Digit[mByte & 0X0F];
    
            String s = new String(tempArr);
            return s;
        }
    
        /**
         * 从缓存中读取token或者ticket
         *
         * @return
         */
        private static Token getTokenTicket(String key) {
            if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
                System.out.println("==========从缓存中获取到了" + key + "成功===============");
                return TOKEN_TICKET_CACHE.get(key);
            }
            return null;
        }
    
        /**
         * 更新缓存中token或者ticket
         *
         * @return
         */
        private static void updateToken(String key, Token accessTocken) {
            if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
                TOKEN_TICKET_CACHE.remove(key);
                System.out.println("==========从缓存中删除" + key + "成功===============");
            }
            TOKEN_TICKET_CACHE.put(key, accessTocken);
            cacheAddTime = String.valueOf(accessTocken.getAddTime());// 更新缓存修改的时间
            System.out.println("==========更新缓存中" + key + "成功===============");
        }
    
    }
    

    由于大家都希望能看到分享微信的核心代码,关于微信分享功能代码及微信其他的核心功能代码
    已分享在自己的个人博客网站了 https://dingyinwu.com 在资源共享页面,其中还有其它的一些资源~

    展开全文
  • 现在每天都可以看到很多微信分享的链接上面有网站或者商家的自定义的分享标题,和分享链接的描述及分享出去的图像,例如下面的分享出去的链接:    上面这个是微信的js-SDK页面分享微信好友在聊天列表中显示的...

        现在每天都可以看到很多微信分享的链接上面有网站或者商家的自定义的分享标题,和分享链接的描述及分享出去的图像,例如下面的分享出去的链接:

                     

         上面这个是微信的js-SDK页面分享给微信好友在聊天列表中显示的视觉效果。

          微信JS-SDK Demo :这个是微信网页分享出去的标题。

         微信JS-SDK,帮助第三方为用户提供更优质的移动web服务:这个是被分享的这个页面的分享描述。

         微信图标:这个就是自己网站或者自己自定义的图像。

         上面这个是微信官方网页分享出去的定义描述,那么怎样实现自己网站网页的自定义分享的标题,描述及分享出去的显示图片呢,下面就具体的来探讨一下微信网页第三方分享自定的实现方式。

         关于微信网页分享自定义主要有两方面的工作需要我们来做,一是:分享页面的js分享代码的编写,二是:微信分享网页的链接地址签名。

         首先来看一下网页的连接地址签名,这个功能主要是在服务端来时实现。

         第一步:基础数据的准备,需要如下数据信息:

         APPID:微信公众号的id; APP_SECRECT:公众号号的密钥。签名的网站域名(这个建议配置在配置文件中)。

         第二步:微信签名数据的准备:

        appid,secret,url将这三个参数放入map中, 键值为:appid=微信公众号的id,secret=APP_SECRECT,url=网站的域名+网页的请求地址+请求的参数。

        代码的实现方式如下:

          1. controller层的代码实现: 

          @RequestMapping("cover")
          public String identifyCover(HttpServletRequest request, HttpServletResponse response)
    	    //微信分享授权开始
           String appId = ;//取项目中配置的公众号id
           String secret = ;//取项目中配置的公众号密钥
           //例如我们有一个分享的链接为:http://test.weixinfwenx.cn/project/fenxiang.do?id=1&name=2;
           //那么domainAddr = http://test.weixinfwenx.cn,这个可以动态的配置在项目里,方便测试环境和生产
           //域名的切换
           String domainAddr = "";//项目中配置的网站的域名
           //这个取的是链接上的参数,例如在上面的这个链接中,id=1&name=2就是我们要动态去的参数,可能有人               
           //会想到,这个两个参数直接写在地址中不是挺简单的为啥还要动态去获取这个参数呢;在这里我们引出了一             
           //个微信二次分享的问题,就是别人转发的链接给你,然后你再转发给别人,在你转发给别人后这个链接的签             
           //名就会失败,为啥呢,因为经过再次转发的链接,微信会自动加上一些自己的参数,这样会导致页面上微信             
           //分享的链接和签名的链接不一致。直接导致自定义的标题和链接描述,显示失败,失败原因是微信默认的在             
           //我们的分享链接上加上了&from=singlemessage。
           String str = request.getQueryString();
           Map<String, String> map = new HashMap<String, String>(); 
           map.put("appid", appId); 
           map.put("secret", secret); 
           String url = domainAddr + "/project/fenxiang.do?"+str; map.put("url", url);
            //这个地址是传给页面使用
           request.setAttribute("fenxurl", url);
           //开始微信分享链接签名
           Map<String, String> params = weixinService.weixinjsIntefaceSign(map);
           request.setAttribute("params", params);
           return "自己的页面";
     2.service层的实现代码:

       接口:  

     public interface weixinService{
    	 /**
    	   * @Title: weixinjsIntefaceSign
    	   * @Description: 微信js接口授权
    	   * @param map
    	   * @return
    	   * @return: Map<String,String>
    	   */
      public Map<String,String> weixinjsIntefaceSign(Map<String,String> map);  
    接口实现类:

           public class weixinServiceImpl implements weixinService{
    	  public  Map<String, String> weixinjsIntefaceSign(Map<String, String> map){
    		  //查看缓存数据是否存在
    		  String cacheAccess_token = jedis.get("access_token");
    		  String cacheTicket = jedis.get("ticket");
    		  //取出来为空的话则说明cacheAccess_token缓存过期,重新获取
    		  if(null == cacheAccess_token){
    			  ///////////////////////////////start
    			  //获取cacheAccess_token   
    			  //这段代码实际开发过程中要写成一个方法,我这里为了演示方便写在了一起。
    			  StringBuffer buffer = new StringBuffer();
    			  buffer.append("https://api.weixin.qq.com/cgi-bin/token?");
    			  buffer.append("appid="+map.get("appid"));
    			  buffer.append("&secret="+map.get("secret"));
    			  buffer.append("&grant_type=client_credential");
    			  String resultMsg = SendUtils.sendGet(buffer.toString(), "UTF-8");
    			  ///////////////////// end
    			  
    			  JSONObject json = new JSONObject(resultMsg);
    			  cacheAccess_token = json.getString("access_token");
    			  jedis.set("access_token",cacheAccess_token, "NX", "EX", 3600);//单位是秒
    		  }
    		  //取出来为空的话则说明cacheTicket缓存过期,重新获取
    		  if(null == cacheTicket){
    			  ////////////////////////// start
    			  ////获得jsapi_ticket
    			  StringBuffer buffer = new StringBuffer();
    			  buffer.append("https://api.weixin.qq.com/cgi-bin/ticket/getticket?");
    			  buffer.append("access_token="+access_token);
    			  buffer.append("&type=jsapi");
    			  String ticket = SendUtils.sendGet(buffer.toString(), "UTF-8");
    			  ///////////////////// end
    			  
    			  JSONObject json2 = new JSONObject(ticket);	    
    			  cacheTicket = json2.getString("ticket");
    			  jedis.set("ticket",cacheTicket, "NX", "EX", 3600);//单位是秒	
    		  }
    		  //生成签名
    		  SortedMap<Object,Object> params = new TreeMap<Object,Object>();	       
    		  params.put("timestamp", Long.toString(new Date().getTime()/1000));
    		  params.put("noncestr", this.CreateNoncestr());
    		  params.put("jsapi_ticket",cacheTicket);
    		  params.put("url",map.get("url"));//url地址
    		  StringBuffer sb = new StringBuffer();
    		  Set es = params.entrySet();
    		  Iterator it = es.iterator();
    		  while(it.hasNext()) {
    			  Map.Entry entry = (Map.Entry)it.next();
    			  String k = (String)entry.getKey();
    			  Object v = entry.getValue();
    			  sb.append(k + "=" + v + "&");
    		  }
    		  String  signStr = sb.toString().substring(0, sb.toString().length()-1);
    		  String sign = Sha1.getSha1Sign(signStr);//签名	
    		  Map<String, String> result = new HashMap<String,String>();
    		  result.put("timestamp",(String)params.get("timestamp"));
    		  result.put("noncestr", (String)params.get("noncestr"));
    		  result.put("signature", sign);
    		  result.put("appId",map.get("appid"));
    		  return result;
    		  
    		  return null;
    		  
    	  }
            private  String CreateNoncestr() {
    		String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    		String res = "";
    		for (int i = 0; i < 16; i++) {
    			Random rd = new Random();
    			res += chars.charAt(rd.nextInt(chars.length() - 1));
    		}
    		return res;
    	}
      }

    辅助工具类:

    /**
     * 
     * 加密工具类
     *
     */
    public  class Sha1 {
    	  public static String getSha1Sign(String decript) {  
    		  try {  
    			  MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");  
    			  try {
    				  digest.update(decript.getBytes("UTF-8"));
    			  } catch (UnsupportedEncodingException e) {
    				  // TODO Auto-generated catch block
    				  e.printStackTrace();
    			  }  
    			  byte messageDigest[] = digest.digest();  
    			  // Create Hex String  
    			  StringBuffer hexString = new StringBuffer();  
    			  // 字节数组转换为 十六进制 数  
    			  for (int i = 0; i < messageDigest.length; i++) {  
    				  String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);  
    				  if (shaHex.length() < 2) {  
    					  hexString.append(0);  
    				  }  
    				  hexString.append(shaHex);  
    			  }  
    			  return hexString.toString();  
    			  
    		  } catch (NoSuchAlgorithmException e) {  
    			  e.printStackTrace();  
    		  }  
    		  return "";  
    	  }  
    }
    http请求工具类:

    /** 
     * http请求工具类
     *
     */
     public class SendUtils {
    	  public static String sendGet(String url,String charset){
    			//新建客户端
    			HttpClient httpclient = new HttpClient();
    			GetMethod getMethod = new GetMethod(url);
    			httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, charset);
    			httpclient.executeMethod(getMethod);
    			String responseMsg = getMethod.getResponseBodyAsString();
    			return responseMsg;	
    	  }
      }
     以上是服务器端的微信签名的实现代码,下面介绍一下分享页面中js的编写。

      第一步引入微信的js文件:

       <script src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

     第二步:  

     wx.config({
    				debug: false, 
    				appId: '${params.appId}',
    				timestamp: '${params.timestamp}',
    				nonceStr: '${params.noncestr}', 
    				signature:'${params.signature}',
    				jsApiList: [
    		            'onMenuShareTimeline',
    		            'onMenuShareAppMessage',
    		            'onMenuShareQQ',
    			        'onMenuShareWeibo',
    			        'onMenuShareQZone'  
    				]
    			});
              wx.ready(function(){
    			wx.checkJsApi({
    			    jsApiList: [
    			        'onMenuShareTimeline',
    			        'onMenuShareAppMessage',
    			        'onMenuShareQQ',
    			        'onMenuShareWeibo',
    			        'onMenuShareQZone'    
    			    ]
    			});
    				wx.checkJsApi({
    				    jsApiList: [
    				        'onMenuShareTimeline',
    				        'onMenuShareAppMessage',
    				        'onMenuShareQQ',
    				        'onMenuShareWeibo',
    				        'onMenuShareQZone'    
    				    ]
    				});
    			/*分享到朋友圈*/
    			wx.onMenuShareTimeline({
    			  	title: '计划书', // 分享标题
    			  	desc: '保险让生活更美好!', // 分享描述
    			    link: '${fenxurl}', // 分享链接
    			    imgUrl: '${params.urlg}/PF_IDENTIFY/Cacheable/image/business/plan-cover/product_img.png', // 分享图标
    			    success: function () { 
    			        // 用户确认分享后执行的回调函数
    			    },
    			    cancel: function () { 
    			        // 用户取消分享后执行的回调函数
    			    }
    			});
    			/*分享给朋友*/
    			wx.onMenuShareAppMessage({
    				title: '计划书', // 分享标题
    				desc: '保险让生活更美好!', // 分享描述
    			    link: '${fenxurl}', // 分享链接
    			    imgUrl: '${params.urlg}/PF_IDENTIFY/Cacheable/image/business/plan-cover/product_img.png', // 分享图标
    			    type: 'link', // 分享类型,music、video或link,不填默认为link
    			    dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
    			    success: function () { 
    			    	// 用户确认分享后执行的回调函数
    			    	alert("您已分享");
    			    },
    			    cancel: function () { 
    			    	 // 用户取消分享后执行的回调函数
    			    	alert('您已取消分享');
    			    }
    			});
    			wx.onMenuShareQQ({
    				title: '计划书', // 分享标题
    				desc: '保险让生活更美好!', // 分享描述
    			    link: '${fenxurl}', // 分享链接
    			    imgUrl: '${params.urlg}/PF_IDENTIFY/Cacheable/image/business/plan-cover/product_img.png', // 分享图标
    			    success: function () { 
    			       // 用户确认分享后执行的回调函数
    			    },
    			    cancel: function () { 
    			       // 用户取消分享后执行的回调函数
    			    }
    			});
    			wx.onMenuShareWeibo({
    				title: '计划书', // 分享标题
    				desc: '保险让生活更美好!', // 分享描述
    			    link: '${fenxurl}', // 分享链接
    			    imgUrl: '${params.urlg}/PF_IDENTIFY/Cacheable/image/business/plan-cover/product_img.png', // 分享图标
    			    success: function () { 
    			       // 用户确认分享后执行的回调函数
    			    },
    			    cancel: function () { 
    			        // 用户取消分享后执行的回调函数
    			    }
    			});
    			wx.onMenuShareQZone({
    				title: '计划书', // 分享标题
    				desc: '保险让生活更美好!', // 分享描述
    			    link: '${fenxurl}', // 分享链接
    			    imgUrl: '${params.urlg}/PF_IDENTIFY/Cacheable/image/business/plan-cover/product_img.png', // 分享图标
    			    success: function () { 
    			       // 用户确认分享后执行的回调函数
    			    },
    			    cancel: function () { 
    			        // 用户取消分享后执行的回调函数
    			    }
    			});
    		 });  
    至此整个微信的整个分享开发完成,上面的这些js文件,都必须放在页面上。
    
    
    
    
    
    
    
    
    展开全文
  • 微信公众号开发 从前台到Java后台 调用微信JS接口分享朋友圈,博客中的源代码。数据库请到博客中的GitHub链接自取,建好数据库后需要修改数据库的配置信息。
  • java微信分享自定义内容功能遇到的一个bug  需求:用户通过关注公众号 打开邀请好友页面(前提必须先登录) 点击手机右上角竖形的图标 发送自定义内容 给朋友,qq好友,发送微信朋友圈,QQ空间等  具体的文档可以...

                   java写微信分享自定义内容功能遇到的一个bug

       需求:用户通过关注公众号  打开邀请好友页面(前提必须先登录)  点击手机右上角竖形的图标 发送自定义内容 给朋友,qq好友,发送微信朋友圈,QQ空间等

     具体的文档可以参考微信官方文档

     邀请好友页面:

     

     一定要引入<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>这个js


     js内容:

       

     剩下的完整版会上传   


    一进这个页面调用的后台接口:

              



        获取页面需要用到ticket过程  


              

        把获取到的appId   timestamp nonceStr  singnature 四个参数传递到页面  


       把上面js 里面debug : false  改成debug : true   


       访问页面后 如果有错误信息会弹框提示的  

        如果出现invalid signature 这个错误  :首先去根据你的参数和你拿到jsapi_ticket  用测试工具测试一下跟你获取的signature参数是不是一样的

       微信提供的测试地址 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 

       如果使用测试工具后发现获取的signature 和自己生成的参数一样的话就要看下你的appId和你获取jsapi_ticket  使用的是不是一个appID  

      如果不确定 在js里面建议先把appId写死  确保没问题 

       那么问题来了,如果这些都没问题的话 就要看你的代码获取的url和 你页面当前url是否一致  

       在页面上可以alert(location.href.split('#')[0])得到当前url ,然后后台可以先写死alert出来的这个url   

       注意如果你的地址后面带参数#类似的看下官方文档,只需要获取截止到#以前的数据

       我的地址是http://xxx.baidu.com/img/test       在后台获取的时候就是http://xxx.baidu.com/img/test这个地址  不要再后面加参数或者/

       要了解更多的信息  可以参考微信官方文档  ~~

       

    展开全文
  • 1、登录微信公众平台配置业务域名和JS接口安全域名(不带http://) 2、 服务器配置(如果服务器...微信公众号开发依赖包: &lt;!--添加微信依赖 begin--&gt; &lt;!-- https://mvnrepository.com...

    1、登录微信公众平台配置业务域名和JS接口安全域名(不带http://)

    2、 服务器配置(如果服务器配置开启,则用户发送给公众号的消息和事件都会被微信转发到配置的url中,开发者可自行处理)

     

    服务器地址(URL)具体代码如下:

    微信公众号开发依赖包:

    <!--添加微信依赖 begin-->
        <!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-common -->
        <dependency>
          <groupId>com.github.binarywang</groupId>
          <artifactId>weixin-java-common</artifactId>
          <version>2.7.0</version>
        </dependency>
        <dependency>
          <groupId>com.github.binarywang</groupId>
          <artifactId>weixin-java-mp</artifactId>
          <version>2.8.5.BETA</version>
        </dependency>
    <!--添加微信依赖 end-->
    @Configuration
    public class WeChatAccountConfig {
    
    	@Value("${wechat.appId}")
    	private String appId;
    
    	@Value("${wechat.appSecret}")
    	private String appSecret;
    
    	@Value("${wechat.token}")
    	private String token;
    
    	@Value("${wechat.encodingAESKey}")
    	private String encodingAESKey;
    
    	public String getAppId() {
    		return appId;
    	}
    
    	public String getAppSecret() {
    		return appSecret;
    	}
    
    	public String getToken() {
    		return token;
    	}
    
    	public String getEncodingAESKey() {
    		return encodingAESKey;
    	}
    }
    @Component
    public class WeChatConfig {
    
    	@Autowired
    	private WeChatAccountConfig weChatAccountConfig;
    
    	@Bean
    	public WxMpService wxMpService(){
    		WxMpService wxMpService = new WxMpServiceImpl();
    		wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
    		return wxMpService;
    	}
    
    	public WxMpConfigStorage wxMpConfigStorage(){
    		WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
    		wxMpConfigStorage.setAppId(weChatAccountConfig.getAppId());
    		wxMpConfigStorage.setSecret(weChatAccountConfig.getAppSecret());
    		wxMpConfigStorage.setToken(weChatAccountConfig.getToken());
    		wxMpConfigStorage.setAesKey(weChatAccountConfig.getEncodingAESKey());
    		return wxMpConfigStorage;
    	}
    
    }
    @RestController
    @RequestMapping(value = "/wechat")
    public class WeChatCallBackController {
    
    	@Autowired
    	private WxMpService wxMpService;
    
    
    	/**
    	 * 订阅号(监听关注、取关事件处理)
    	 * @param signature
    	 * @param nonce
    	 * @param timestamp
    	 * @param request
    	 * @return
    	 * @throws Exception
    	 */
    	@RequestMapping(value = "/callback")
    	public String callback(@RequestParam("signature") String signature,
    						 @RequestParam("nonce")String nonce,
    						 @RequestParam("timestamp")String timestamp,
    						 HttpServletRequest request) throws Exception {
    		String echostr = "";
    		System.out.println("signature:" + signature);
    		System.out.println("nonce:" + nonce);
    		System.out.println("timestamp:" + timestamp);
    		// 验证消息签名,说明不是公众平台发送来的消息
    		if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
    			return "非法访问";
    		}
    		// 说明是一个仅仅用来验证的请求,回显echostr
    		echostr = request.getParameter("echostr");
    		if (!StringUtils.isEmpty(echostr)) {
    			return echostr;
    		}
    		String encryptType = StringUtils.isEmpty(request.getParameter("encrypt_type")) ? "raw" : request.getParameter("encrypt_type");
    		if ("raw".equals(encryptType)) {
    			// 明文传输的消息
    			WxMpXmlMessage message = WxMpXmlMessage.fromXml(request.getInputStream());
    			return message.toString();
    		}
    		if ("aes".equals(encryptType)) {
    			// 是aes加密的消息
    			String msgSignature = request.getParameter("msg_signature");
    			WxMpXmlMessage message = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), wxMpService.getWxMpConfigStorage(), timestamp, nonce, msgSignature);
    			return message.toString();
    		}
    		return "不可识别的加密类型";
    	}
    
    
    }

    3、微信分享功能开发

    (1)在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.4.0.js

    (2)通过config接口注入权限验证配置

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名
        jsApiList: [] // 必填,需要使用的JS接口列表
    });

    config配置Demo

    @RestController
    @RequestMapping(value = "/wechat")
    public class WeChatSharingController {
    
    	@Autowired
    	private WxMpService wxMpService;
    
    	@RequestMapping(value = "/share")
    	public Result share(@RequestParam("url") String url) {
    		Result result = new Result();
    		try {
    			WxJsapiSignature signature = wxMpService.createJsapiSignature(url);
    			Result.getSuccessResult(result, "请求成功", signature);
    		} catch (Exception e) {
    			Result.getErrorResult(result, "分享出现错误");
    		}
    		return result;
    	}
    
    }
    $.ajax('/wechat/share', {
                data: {"url": window.location.href},
                dataType: 'json',//服务器返回json格式数据
                type: 'get',//HTTP请求类型
                timeout: 10000,//超时时间设置为10秒;
                contentType: 'application/json',
                success: function (data) {
                    if (data.code == 0) {
                        wx.config({
                            debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                            appId: data.data.appId, // 必填,公众号的唯一标识
                            timestamp: data.data.timestamp, // 必填,生成签名的时间戳
                            nonceStr: data.data.nonceStr, // 必填,生成签名的随机串
                            signature: data.data.signature,// 必填,签名,见附录1
                            jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                        });
                    }
                },
                error: function (xhr, status, error) {
                    //异常处理;
                    console.log(error);
                }
            });

    (3)通过ready接口处理成功验证

    wx.ready(function() {
                wx.hideMenuItems({
                    menuList: ['menuItem:share:qq','menuItem:share:weiboApp','menuItem:share:facebook','menuItem:share:QZone'] // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
                });
                // 获取"分享到朋友圈"按钮点击状态及自定义分享内容接口
                wx.onMenuShareTimeline({
                    title: '#', // 分享标题
                    link: '#',
                    imgUrl: '#' // 分享图标
                });
    
    
                // 获取"分享给朋友"按钮点击状态及自定义分享内容接口
                wx.onMenuShareAppMessage({
                    title: '#', // 分享标题
                    desc: '#', // 分享描述
                    link: window.location.href,
                    imgUrl: '#', // 分享图标
                    type: 'link' // 分享类型,music、video或link,不填默认为link
                });
            })

     

    展开全文
  • 前端时间的业务需求有微信分享,那么我光荣的接下了这个任务,现在跟大家分享下心得,最容易出错的地方: 1.签名 2.分享的时候没有显示分享标题,分享内容,这里是分享链接有误,所以大家要仔细 3.仔细仔细再仔细...
  • 功能我在程自己在学习时候尝试搭建的,可能会有很多问题,在这里只是做一下记录。直接上代码。如有不懂请联系楼主或者加群725395843 这里是技术讨论群。供大家讨论。   此文档做回顾。 先上官方文档:...
  • 微信小程序分享功能知识点微信小程序分享功能知识点概览小程序与普通网页开发的区别小程序运行机制启动前台/后台状态小程序销毁WXS响应事件的动机微信分享需求描述程序流程FAQs同类小程序分享功能调研&...
  • 此篇文章是在做微信分享的时候查阅借鉴的相关的文章所做的总结,刚开始没有接触过,一脸懵逼,不知道从哪里下手,咨询了很多同学朋友,总算是有一点苗头,现在记录下来,方便自己以后查阅,以免忘记。注意点:1、分享...
  • 在偶然间,需要做一个公众账号分享功能,细一想~ 奈何宝宝不会呀,听都没听过肿么破,当时就心累了。  言归正传,由于我所有的开发代码均是在又各位前辈在度娘中... 在开发前,首先必须先要肯定是拥有一个微信公众
  • 刚开始坑公众号开发,然后坑微信支付开发,然后坑小程序开发。我真的走不出来了。。。。关键还没办法。 今天给大家分享一下app的二次分享问题吧。 是不是挺好玩的。这个时候就说了为什么变成这个样子,因为他...
  • 微信开发入门教程 jssdk,通过config接口注入权限验证配置java+jsp微信开发教程,功能:扫描二维码,拍照、本地选图,图片预览,上传图片,下载图片,获取当前网络状态,查看地理位置,获取当前地理位置打开地图,...
  • 最近在做微信服务号开发,简单总结一下,便于自己学习积累和分享给大家: 环境介绍: Spring+ Spring MVC +Mybatis 开发语言: JAVA 微信公众平台的开发中,微信只公布了一个基于Http协议的接口和加解密的...
  • 最近在公司接到需求实现页面在微信浏览器实现自定义分享功能,中间遇到了许多小坑,特地记录下来本人的实现过程主要参考 https://www.cnblogs.com/liuhongfeng/p/5101561.html 这篇文章,大家看的时候互为参考一下 ...
  • 微信分享功能开发 用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路。 一、服务器端程序package com.wiimedia.controller; import java.io.IOE
  • 点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐]先上官方文档:http://mp.weixin.qq.com/wiki/home/index.html做之前建...
  • java微信分享源码

    2020-06-03 23:32:58
    我在网上看到没有java写的,我也下了很多但是都不能用,然后我就自己写了一份让大家看看,是用SERVLET实现的只要改一下appid和APPSECRET就可以用了。特别注意:一定要用微信已经认证后的服务号才能用。要不会一直...
  • 原先的网页需要分享微信,可是转发时,分享的缩略图没有显示,标题和描述都不能自定义现在想让分享显示缩略图。又可以自定义标题和描述,就要用到微信js_sdk。后台基于javaweb,微信分享流程大致如下,详细见...
1 2 3 4 5 ... 20
收藏数 22,041
精华内容 8,816