微信开发jssdk分享_静态页面开发jssdk微信分享 - CSDN
  • 微信jssdk分享开发经验

    千次阅读 2015-01-16 11:55:23
    最近微信开发出来了一套jssdk,坑死一片人啊。 不过最后总算我也完成了分享功能的开发,在这里做个记录吧。 ...

    最近微信新开发出来了一套jssdk,坑死一片人啊。

    不过最后总算我也完成了分享功能的开发,在这里做个记录吧。

    http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html?ADUIN=1099048193&ADSESSION=1421112583&ADTAG=CLIENT.QQ.5371_.0&ADPUBNO=26422

    这是微信官方文档

     

    这是最新的有关分享朋友圈的规定

    https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&key=1419941033&version=14&lang=zh_CN

     

    https://github.com/zxlie/WeixinApi/blob/master/WeixinApi.js

    这是某个hack通过暴力劫持的方式实现的分享,测试有效(以后是否会当做插件封掉还不清楚)

    使用方法很简单,引入这个js然后按照文档写的方法直接调用即可,和以前网上的方法相似。

     

     

     

    最新官方开放的JSSDK接口需要 认证的服务号,在工信部备案的域名(可以是个人名义的),域名可以不是80端口,二级域名也可以。

    (域名填写位置:公众号设置>功能设置>JS接口安全域名)

    (PS:测试号没有这个地方,所以这个功能的开发无法使用测试号。)

     

     

    分享流程可以简单理解为。

     

    第一步,引入js文件http://res.wx.qq.com/open/js/jweixin-1.0.0.js(注意,不可以下载到本地后调用,否则所有功能无效)

    第二步,通过config接口注入权限验证配置。

                      其中主要的问题在signature中,具体函数可以参考附件中的java类中的

    public Map<String, String> sign(String jsapi_ticket, Stringurl) 方法。

    其中jsapi_ticket的流程和获取公众号的access_token基本一样,也是7200有效

    url就是你的页面url

    第三步,调用wx.ready,然后执行相应的方法,比如分享朋友圈就是wx.onMenuShareTimeline

     

     

     

    我开发过程中遇见的问题

    1,  wx.config报错,未定义。原因:res.wx.qq.com被公司的网络过滤

    2,  报错config:fail,wx.config中的参数错误

    3,  报错config:invail url domain,域名没有在公众号设置中填写,或不一致。

     



    ps:如果在分享的链接上挂上当前人的openID,使用outh授权链接分享出去的话,我们就能知道是谁分享出去的,然后有谁通过分享的途径进入这个页面的。

            对于一些活动,或者无聊的想分析用户关系的话这个方法还是可以考虑



    详细流程请阅读微信的官方文档,附录里面也有代码和实例


    展开全文
  • 微信JSSDK分享功能详解

    万次阅读 热门讨论 2017-04-19 16:23:09
    微信6.0之后JSSDK的调用,微信分享功能的实现,傻瓜教程

    本文以微信分享到朋友圈,分享给微信好友为例为参考,进行调用测试,想添加其他的功能,自行查看开发人员文档即可


    工欲善其事,必先利其器,好好利用下边的帮助工具,都是腾讯给开发人员的工具

    1.微信开发者说明文档:点击查看

    2.微信WEB开发者工具:

    Windows 64位版本:下载地址

    Windows 32位版本:下载地址

    Mac版本:下载地址

    3.微信JSSDK分享sample:点击下载

    4.在线DEMO:http://203.195.235.76/jssdk/



    微信版本6.0以后,原有的WeixinJSBridge.on('menu:share:timeline', function (argv) {}不再可在以使用,那如何在使用微信的其他功能呢?官方给出了JSSDK的使用,帮助我们解决~



    前言:


    虽然微信提供了JSSDK,但是这不意味着你可以用自定义的按钮来直接打开微信的分享界面,这套JSSDK只是把微信分享接口的内容定义好了,实际还是需要用户点击右上角的菜单按钮进行主动的分享,用户点开分享界面之后,出现的内容就会是你定义的分享标题、图片和链接



    • 2.实测图解

    • 2.1 测试页面:

    2.2分享到朋友圈:









    2.3分享到朋友圈:

    (这个是触发success的效果,配图描述写错了,抱歉)
    (这个是触发cancel的效果)



    2.3调试界面:







    后台代码(jssdk.php见后边):

    	//获取apptoken
    	require_once "jssdk.php";
    	$jssdk = new JSSDK($appid,$appsecret);//这里填写自己的appid 和secret
    	$signPackage = $jssdk->GetSignPackage();
    	$this->assign("signPackage",$signPackage);

    JS配置代码

    <script type="text/javascript" src='http://res.wx.qq.com/open/js/jweixin-1.0.0.js'></script>
      <script type="text/javascript">
      wx.config({
        debug: false,
        appId: '{$signPackage["appId"]}',
        timestamp: '{$signPackage["timestamp"]}',
        nonceStr: '{$signPackage["nonceStr"]}',
        signature: '{$signPackage["signature"]}',
        jsApiList: [
          // 所有要调用的 API 都要加到这个列表中
            'checkJsApi',
            'onMenuShareTimeline',
            'onMenuShareAppMessage',
            'onMenuShareQQ',
            'onMenuShareWeibo',
            'onMenuShareQZone'
        ]
      });
      </script>
      <script type="text/javascript" src='http://203.195.235.76/jssdk/js/zepto.min.js'></script>


    JS分享代码:

    <script type="text/javascript">
            //完成wx.config,执行这里
             wx.ready(function () {
                 //分享到朋友圈
                 wx.onMenuShareTimeline({
                     title: '1111111', // 分享标题
                     link:window.location.href,
                     imgUrl: "{pigcms:$res['pic']}", // 分享图标
                     success: function () {
    		    // 分享成功执行此回调函数
                        alert('success');
                     },
                     cancel: function () {
                        alert('cancel');
                     }
                 });
    
                 //分享给朋友
                 wx.onMenuShareAppMessage({
                     title: '22222', // 分享标题
                     desc: '22222',
                     link:window.location.href,
                     imgUrl: "{pigcms:$res['pic']}", // 分享图标
                     trigger: function (res) {
                         // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
                     },
                     success: function (res) {
    		     // 分享成功执行此回调函数
                         alert('已分享');
                     },
                     cancel: function (res) {
                         alert('已取消');
                     },
                     fail: function (res) {
                         alert(JSON.stringify(res));
                     }
                 });
             });
    
    </script>




    JSSDK类

    jssdk.php

    <?php
    class JSSDK {
      private $appId;
      private $appSecret;
    
      public function __construct($appId, $appSecret) {
        $this->appId = $appId;
        $this->appSecret = $appSecret;
      }
    
      public function getSignPackage() {
        $jsapiTicket = $this->getJsApiTicket();
    
        // 注意 URL 一定要动态获取,不能 hardcode.
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    
        $timestamp = time();
        $nonceStr = $this->createNonceStr();
    
        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
    
        $signature = sha1($string);
    
        $signPackage = array(
          "appId"     => $this->appId,
          "nonceStr"  => $nonceStr,
          "timestamp" => $timestamp,
          "url"       => $url,
          "signature" => $signature,
          "rawString" => $string
        );
        return $signPackage; 
      }
    
      private function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
          $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
      }
    
      private function getJsApiTicket() {
        
          $accessToken = $this->getAccessToken();
         
          // 如果是企业号用以下 URL 获取 ticket
          // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
          $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
          $res = json_decode($this->httpGet($url));
         
          $ticket = $res->ticket;
          
        return $ticket;
      }
    
      private function getAccessToken() {
        // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
        // 如果是企业号用以下URL获取access_token
        // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
          $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
          $res = json_decode($this->httpGet($url));
          $access_token = $res->access_token;
         
        return $access_token;
      }
    
      private function httpGet($url) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_URL, $url);
    
        $res = curl_exec($curl);
        curl_close($curl);
    
        return $res;
      }
    }
    



    展开全文
  • 微信JSSDK分享DEMO

    2020-07-21 09:56:52
    PHP开发微信JSSDK分享demo(内有实例)提供大家参考学习
  • 前提:调用微信jssdk分享功能,通过微信开发者工具调试,调用正常,无任何报错信息。 问题:调用成功,且开发者工具正常显示,但是通过真机调试,分享出去后,自定义内容失效,为微信自动获取的默认内容!截止发稿...

    前提:调用微信jssdk分享功能,通过微信开发者工具调试,调用正常,无任何报错信息。

    问题:调用成功,且开发者工具正常显示,但是通过真机调试,分享出去后,自定义内容失效,为微信自动获取的默认内容!截止发稿日:IOS端一切正常(可能IOS端规则还没有变),Android端分享操作正常,自定义内容失效。

    原因:微信重新调整分享规则:分享地址必须与公众号JS接口安全域名一致。

       例如:自定义url:    http://xxx.xxxx.com/xxx/xxx.html       此自定义路径的根地址是  xxx.xxxx.com    。那么公众号JS接口安全域名 xxx.xxxx.com      。这样就可以正常自定义分享了。

       例如:自定义url:    http://xxx.xxxx.com/xxx/xxx.html       此自定义路径的根地址是  xxx.xxxx.com/xxx   。那么公众号JS接口安全域名 xxx.xxxx.com/xxx     。这样就可以正常自定义分享了。 

       备注:如上例子,JS接口安全域名地址必须和自定义路径配置的根路径相同。

    以上结论均为本人自测所得,如和他人有出入,请谅解。

    其他:如上所述均没问题,但是图片无法显示,请参考此篇文章。http://www.cnblogs.com/ygjoe/p/6688539.html

    转载于:https://www.cnblogs.com/ygjoe/p/7070771.html

    展开全文
  • 微信JSSDK实现微信自定义分享微信扫一扫 前言: 由于微信使用的越来越多,也让大多数平台或者APP与微信建立了比较深的合作关系,我们公司自主研发的产品也是比较依赖于微信,最近也写了几篇关于微信的博客,本文...

    前言:
    由于微信使用的越来越多,也让大多数平台或者APP与微信建立了比较深的合作关系,我们公司自主研发的产品也是比较依赖于微信,最近也写了几篇关于微信的博客,本文针对在微信浏览器中使用微信自身的控件进行调用,主要介绍微信自定义分享功能,当然微信暴露出来的接口并不能让你直接调起他们的分享控件,只能自定义分享内容,然后手动触发微信右上角的...进行间接的分享,另外就是微信的扫一扫功能,扫一扫分为两种,一种是直接返回扫码内容,另一种就是让微信自主处理,跳转处理后的结果页面。
    由于我的博客都比较注重代码,今天呢依旧是一样的,当然也会介绍操作步骤

    第一、登录公众平台设置满足条件

    1、设置-公众号设置-功能设置-JS安全域名(JSSDK接口访问域名)

    注:MP_verify_SksIbfInd6JMk57k.txt该文件必须下载保存到服务器域名所在的根路径,如果不知道是否放置正确,可以根据访问地址进行判断。例如:域名为t.link.cn,那么可以通过t.link.cn/MP_verify_SksIbfInd6JMk57k.txt进行直接访问,如果存在返回结果,那么配置成功,如果没有返回结果或者找不到路径,则表示放置的位置不正确

    在这里插入图片描述
    2、设置-公众号设置-功能设置-网页授权域名(必须与JS安全域名一致)
    在这里插入图片描述
    3、开发-基础配置-IP白名单(设置接口可访问的IP地址)
    在这里插入图片描述
    3、创建WxCommon.java(公共配置文件)

    package com.casom.base.wechat.common;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.Serializable;
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Formatter;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.core.io.ClassPathResource;
    
    import com.casom.base.wechat.entity.wx.AccessToken;
    import com.casom.base.wechat.entity.wx.JsapiTicket;
    
    /**
     * 微信公共配置
     *
     */
    public class WxCommon implements Serializable {
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	/**
    	 * 微信公众号唯一标识
    	 */
    	public static final String APP_ID = "";
    	/**
    	 * 微信公众密码
    	 */
    	public static final String APP_SECRET = "";
    	/**
    	 * 获取access_token的地址
    	 */
    	public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APP_ID&secret=APP_SECRET";
    	/**
    	 * 获取微信临时票据的地址
    	 */
    	public static final String JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
    	/**
    	 * access_token文件名
    	 */
    	public static final String ACCESS_TOKEN_FILE_NAME = "access_token.txt";
    	/**
    	 * jsapi-ticket文件名
    	 */
    	public static final String JSAPI_TICKET_FILE_NAME = "jsapi_ticket.txt";
    	/**
    	 * 保存access_token
    	 */
    	public static final String ACCESS_TOKEN_FILE_PATH = "/js-sdk/" + ACCESS_TOKEN_FILE_NAME;
    	/**
    	 * 保存jsapi-ticket
    	 */
    	public static final String JSAPI_TICKET_FILE_PATH = "/js-sdk/" + JSAPI_TICKET_FILE_NAME;
    
    	/**
    	 * 获取resources目录下的源文件
    	 * 
    	 * @param path
    	 * @return
    	 */
    	public static ClassPathResource getResource(String... paths) {
    		return new ClassPathResource(paths.length == 0 ? ACCESS_TOKEN_FILE_PATH : paths[0]);
    	}
    
    	/**
    	 * Linux系统
    	 */
    	public static final class Linux {
    		/**
    		 * access_token 存储地址
    		 */
    		public static final String SAVE_FILE_PATH_ACCESS_TOKEN = "/usr/local/src/temp/wechat";
    		/**
    		 * jsapi_ticket 存储地址
    		 */
    		public static final String SAVE_FILE_PATH_JSAPI_TICKET = "/usr/local/src/temp/wechat";
    	}
    
    	/**
    	 * Windows系统
    	 */
    	public static final class Windows {
    		/**
    		 * access_token 存储地址
    		 */
    		public static final String SAVE_FILE_PATH_ACCESS_TOKEN = "F:\\temp\\wechat";
    		/**
    		 * jsapi_ticket 存储地址
    		 */
    		public static final String SAVE_FILE_PATH_JSAPI_TICKET = "F:\\temp\\wechat";
    	}
    
    	/**
    	 * 得到保存的地址
    	 * 
    	 * @return
    	 */
    	public static File initFile(String... fileNames) {
    		String filePath = "";
    		if (System.getProperty("os.name").toLowerCase().contains("linux")) {
    			if (fileNames.length == 0 || ACCESS_TOKEN_FILE_NAME.equals(fileNames[0])) {
    				filePath = Linux.SAVE_FILE_PATH_ACCESS_TOKEN;
    			} else {
    				filePath = Linux.SAVE_FILE_PATH_JSAPI_TICKET;
    			}
    		} else {
    			if (fileNames.length == 0 || ACCESS_TOKEN_FILE_NAME.equals(fileNames[0])) {
    				filePath = Windows.SAVE_FILE_PATH_ACCESS_TOKEN;
    			} else {
    				filePath = Windows.SAVE_FILE_PATH_JSAPI_TICKET;
    			}
    		}
    		File file = new File(filePath);
    		if (!file.exists()) {
    			file.mkdirs();
    		}
    		File writeFile = new File(filePath, fileNames.length == 0 || ACCESS_TOKEN_FILE_NAME.equals(fileNames[0])
    				? ACCESS_TOKEN_FILE_NAME : JSAPI_TICKET_FILE_NAME);
    		if (!writeFile.exists()) {
    			try {
    				writeFile.createNewFile();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		return writeFile;
    
    	}
    	
    	/**
    	 * 15分钟的秒数
    	 * @return
    	 */
    	public static Integer getTimestamp(int t) {
    		return t * 60;
    	}
    }
    

    第二、获取access_token

    1、由于access_token有效期只有2个小时,因此需要进行本地保存,或者存放在缓存数据库中,到期之后再进行刷新(本文将会把access_token保存到文件中)
    2、获取access_token的请求地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APP_ID&secret=APP_SECRET
    3、创建AccessToken.java

    package com.casom.base.wechat.entity.wx;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.Serializable;
    
    import org.apache.commons.lang3.StringUtils;
    
    import com.alibaba.fastjson.JSONObject;
    import com.casom.base.util.RestTemplateUtil;
    import com.casom.base.wechat.common.WxCommon;
    
    /**
     * 获取微信AccessToken
     * 此access_token与微信网页授权的access_token不一致
     * @author rf
     *
     */
    public class AccessToken implements Serializable {
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	private String access_token;
    	private Integer expires_in;
    	private Integer errcode;
    	private String errmsg;
    	private Long timestamp;
    	
    	/**
    	 * @return the access_token
    	 */
    	public String getAccess_token() {
    		return access_token;
    	}
    	/**
    	 * @param access_token the access_token to set
    	 */
    	public void setAccess_token(String access_token) {
    		this.access_token = access_token;
    	}
    	/**
    	 * @return the expires_in
    	 */
    	public Integer getExpires_in() {
    		return expires_in;
    	}
    	/**
    	 * @param expires_in the expires_in to set
    	 */
    	public void setExpires_in(Integer expires_in) {
    		this.expires_in = expires_in;
    	}
    	/**
    	 * @return the errcode
    	 */
    	public Integer getErrcode() {
    		return errcode;
    	}
    	/**
    	 * @param errcode the errcode to set
    	 */
    	public void setErrcode(Integer errcode) {
    		this.errcode = errcode;
    	}
    	/**
    	 * @return the errmsg
    	 */
    	public String getErrmsg() {
    		return errmsg;
    	}
    	/**
    	 * @param errmsg the errmsg to set
    	 */
    	public void setErrmsg(String errmsg) {
    		this.errmsg = errmsg;
    	}
    	/**
    	 * @return the timestamp
    	 */
    	public Long getTimestamp() {
    		return timestamp;
    	}
    	/**
    	 * @param timestamp the timestamp to set
    	 */
    	public void setTimestamp(Long timestamp) {
    		this.timestamp = timestamp;
    	}
    	/**
    	 * 获取access_token
    	 * @return
    	 */
    	private static AccessToken execute() throws Exception{
    		String access_token_url = WxCommon.ACCESS_TOKEN_URL.replace("APP_ID", WxCommon.APP_ID).replace("APP_SECRET",WxCommon.APP_SECRET);
    
    		AccessToken token = null;
    		String rs = RestTemplateUtil.get(access_token_url);
    		if (rs == null || "404".equals(rs)) {} else {
    			token = JSONObject.parseObject(rs, AccessToken.class);
    			if (token != null) {
    				// 当前时间 - 15分钟
    				token.setTimestamp(WxCommon.getTimestamp() - WxCommon.getTimestamp(15));
    			}
    		}
    
    		return token;
    	}
    	/**
    	 * 保存access_token到文件,并返回
    	 * @param timestamp
    	 * @param file
    	 * @return
    	 */
    	private static AccessToken writeAccessToken(File file){
    		AccessToken r_access_token = null;
    		try {
    			r_access_token = execute();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		if(r_access_token == null) return null;
    		FileOutputStream out = null;
    		try{
    			out = new FileOutputStream(file, false);// 不允许追加
    			out.write(JSONObject.toJSONString(r_access_token).getBytes());
    		}
    		catch(IOException e){
    			e.printStackTrace();
    		}
    		finally{
    			try {
    				if(out != null) out.close();
    			} catch (IOException e2) {
    				e2.printStackTrace();
    			}
    		}
    		return r_access_token;
    	}
    	/**
    	 * 从文件中读取access_token
    	 * @param timestamp
    	 * @param file
    	 * @return
    	 */
    	private static AccessToken readyAccessToken(File file){
    		FileInputStream input = null;
    		try {
    			input = new FileInputStream(file);
    			byte[] b = new byte[2048];
    			int len = input.read(b);
    			if(len == -1){
    				return writeAccessToken(file);
    			}
    			String str_access_token = new String(b, 0, len);// 读取到的文件内容
    			if(str_access_token == null || "".equals(str_access_token)){
    				return writeAccessToken(file);
    			}
    			AccessToken r_access_token = JSONObject.parseObject(str_access_token, AccessToken.class);
    			if(r_access_token == null 
    					|| StringUtils.isBlank(r_access_token.getAccess_token())
    					|| r_access_token.getExpires_in() == null
    					|| r_access_token.getTimestamp() == null){
    				r_access_token =  writeAccessToken(file);
    			}
    			else{
    				// 如果已经超时,则重新写入文件
    				if (r_access_token.getTimestamp() + r_access_token.getExpires_in() < WxCommon.getTimestamp()) {
    					r_access_token = writeAccessToken(file);
    				}
    			}
    			return r_access_token;
    		}
    		catch (Exception e) {
    			e.printStackTrace();
    		}
    		finally{
    			try {
    				if(input != null) input.close();
    			} catch (IOException e2) {
    				e2.printStackTrace();
    			}
    		}
    		return null;
    	}
    	/**
    	 * 获取accessToken
    	 * @param timestamp
    	 * @return
    	 * @throws Exception
    	 */
    	public static AccessToken getAccessToken() throws Exception {
    		return readyAccessToken(WxCommon.initFile());
    	}
    }
    
    

    第三、根据access_token获取jsapi_ticket

    1、由于jsapi_ticket有效期只有2个小时,因此需要进行本地保存,或者存放在缓存数据库中,到期之后再进行刷新 (本文的jsapi_ticket将会保存到文件中)
    2、获取jsapi_ticket的请求地址:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
    3、创建JsapiTicket.java

    package com.casom.base.wechat.entity.wx;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.Serializable;
    
    import org.apache.commons.lang3.StringUtils;
    
    import com.alibaba.fastjson.JSONObject;
    import com.casom.base.util.RestTemplateUtil;
    import com.casom.base.wechat.common.WxCommon;
    
    /**
     * 获取微信JsapiTicket
     * 
     * @author rf
     *
     */
    public class JsapiTicket implements Serializable {
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	private String ticket;
    	private Integer expires_in;
    	private Integer errcode;
    	private String errmsg;
    	private Long timestamp;
    
    	/**
    	 * @return the ticket
    	 */
    	public String getTicket() {
    		return ticket;
    	}
    
    	/**
    	 * @param ticket the ticket to set
    	 */
    	public void setTicket(String ticket) {
    		this.ticket = ticket;
    	}
    
    	/**
    	 * @return the expires_in
    	 */
    	public Integer getExpires_in() {
    		return expires_in;
    	}
    
    	/**
    	 * @param expires_in the expires_in to set
    	 */
    	public void setExpires_in(Integer expires_in) {
    		this.expires_in = expires_in;
    	}
    
    	/**
    	 * @return the errcode
    	 */
    	public Integer getErrcode() {
    		return errcode;
    	}
    
    	/**
    	 * @param errcode the errcode to set
    	 */
    	public void setErrcode(Integer errcode) {
    		this.errcode = errcode;
    	}
    
    	/**
    	 * @return the errmsg
    	 */
    	public String getErrmsg() {
    		return errmsg;
    	}
    
    	/**
    	 * @param errmsg the errmsg to set
    	 */
    	public void setErrmsg(String errmsg) {
    		this.errmsg = errmsg;
    	}
    
    	/**
    	 * @return the timestamp
    	 */
    	public Long getTimestamp() {
    		return timestamp;
    	}
    
    	/**
    	 * @param timestamp the timestamp to set
    	 */
    	public void setTimestamp(Long timestamp) {
    		this.timestamp = timestamp;
    	}
    
    	/**
    	 * 获取jsapi_ticket
    	 * 
    	 * @return
    	 */
    	public static JsapiTicket execute(String access_token) throws Exception {
    		if(StringUtils.isBlank(access_token)) return null;
    		JsapiTicket ticket = null;
    
    		String jsapi_ticket_url = WxCommon.JSAPI_TICKET_URL.replace("ACCESS_TOKEN", access_token);
    
    		String rs = RestTemplateUtil.get(jsapi_ticket_url);
    		if (rs == null || "404".equals(rs)) {
    		} else {
    			ticket = JSONObject.parseObject(rs, JsapiTicket.class);
    			if(ticket != null){
    				ticket.setTimestamp(WxCommon.getTimestamp() - WxCommon.getTimestamp(15));
    			}
    		}
    		return ticket;
    	}
    
    	/**
    	 * 保存jsapi_ticket到文件,并返回
    	 * @param timestamp
    	 * @param file
    	 * @return
    	 */
    	public static JsapiTicket writeJsapiTicket(String access_token, File file){
    		JsapiTicket r_jsapi_ticket = null;
    		try {
    			r_jsapi_ticket = execute(access_token);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		if(r_jsapi_ticket == null) return null;
    		FileOutputStream out = null;
    		try{
    			out = new FileOutputStream(file, false);// 不允许追加
    			out.write(JSONObject.toJSONString(r_jsapi_ticket).getBytes());
    		}
    		catch(IOException e){
    			e.printStackTrace();
    		}
    		finally{
    			try {
    				if(out != null) out.close();
    			} catch (IOException e2) {
    				e2.printStackTrace();
    			}
    		}
    		return r_jsapi_ticket;
    	}
    	/**
    	 * 从文件中读取jsapi_ticket
    	 * @param timestamp
    	 * @param file
    	 * @return
    	 */
    	public static JsapiTicket readyJsapiTicket(String access_token,File file){
    		FileInputStream input = null;
    		try {
    			input = new FileInputStream(file);
    			byte[] b = new byte[2048];
    			int len = input.read(b);
    			if(len == -1){
    				return writeJsapiTicket(access_token, file);
    			}
    			String str_jsapi_ticket = new String(b, 0, len);// 读取到的文件内容
    			if(str_jsapi_ticket == null || "".equals(str_jsapi_ticket)){
    				return writeJsapiTicket(access_token, file);
    			}
    			JsapiTicket r_jsapi_ticket = JSONObject.parseObject(str_jsapi_ticket, JsapiTicket.class);
    			if(r_jsapi_ticket == null 
    					|| StringUtils.isBlank(r_jsapi_ticket.getTicket())
    					|| r_jsapi_ticket.getExpires_in() == null
    					|| r_jsapi_ticket.getTimestamp() == null ){
    				r_jsapi_ticket =  writeJsapiTicket(access_token, file);
    			}
    			else{
    				// 如果已经超时,则重新写入文件
    				if (r_jsapi_ticket.getTimestamp() + r_jsapi_ticket.getExpires_in() < WxCommon.getTimestamp()) {
    					r_jsapi_ticket = writeJsapiTicket(access_token, file);
    				}
    			}
    			return r_jsapi_ticket;
    		}
    		catch (Exception e) {
    			e.printStackTrace();
    		}
    		finally{
    			try {
    				if(input != null) input.close();
    			} catch (IOException e2) {
    				e2.printStackTrace();
    			}
    		}
    		return null;
    	}
    	/**
    	 * 获取jsapi_ticket
    	 * @param timestamp
    	 * @return
    	 * @throws Exception
    	 */
    	public static JsapiTicket getJsapiTicket(String access_token) throws Exception {
    		return readyJsapiTicket(access_token, WxCommon.initFile(WxCommon.JSAPI_TICKET_FILE_NAME));
    	}
    }
    
    

    第四,生成签名并返回参数,在公共配置文件WxCommon.java添加下列代码

    	/**
    	 * 获取时间戳(秒)
    	 */
    	public static Long getTimestamp() {
    		return new Date().getTime() / 1000;
    	}
    
    	/**
    	 * 获取当前时间 yyyyMMddHHmmss
    	 */
    	public static String getCurrTime() {
    		Date now = new Date();
    		SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
    		String s = outFormat.format(now);
    		return s;
    	}
    
    	/**
    	 * 生成随机字符串
    	 */
    	public static String getNonceStr() {
    		String currTime = getCurrTime();
    		String strTime = currTime.substring(8, currTime.length());
    		String strRandom = buildRandom(4) + "";
    		return strTime + strRandom;
    	}
    
    	/**
    	 * 取出一个指定长度大小的随机正整数.
    	 * 
    	 * @param length
    	 *            int设定所取出随机数的长度。length小于11
    	 * @return int 返回生成的随机数。
    	 */
    	public static int buildRandom(int length) {
    		int num = 1;
    		double random = Math.random();
    		if (random < 0.1) {
    			random = random + 0.1;
    		}
    		for (int i = 0; i < length; i++) {
    			num = num * 10;
    		}
    		return (int) ((random * num));
    	}
    
    	/**
    	 * 精制转化
    	 * 
    	 * @param hash
    	 * @return
    	 */
    	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;
    	}
    
    	/**
    	 * 生成签名
    	 * @param jsapi_ticket
    	 * @param url
    	 * 1、如果需要在当前页面的链接上加参数,或者需要把当前页面直接转发
    	 * 注:前端必须通过encodeURIComponent进行转码,后端接收的URL通过URLDecode.decode进行解码
    	 * 否则将会提示"签名错误",导致无法正常使用jssdk的功能,为了避免这个情况的发生,需要对链接进行转码
    	 * 2、如果当前页面没有参数,并且不需要将当前页面进行立即转发,则无需转码
    	 * @param timestamp
    	 * @return
    	 */
    	public static Map<String, Object> sign(String jsapi_ticket, String url) {
    		Map<String, Object> ret = new HashMap<String, Object>();
    		String string1;
    		String signature = "";
    		String nonce_str = getNonceStr();
    		Long timestamp = getTimestamp();
    		// 注意这里参数名必须全部小写,且必须有序
    		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;
    	}
    
    	/**
    	 * 返回jssdk初始化参数
    	 * 
    	 * @param url
    	 * @return
    	 */
    	public static Map<String, Object> initSssdkConfig(String url) throws Exception {
    		AccessToken accessToken = AccessToken.getAccessToken();
    		if (accessToken == null)
    			return null;
    
    		JsapiTicket jsapiTicket = JsapiTicket.getJsapiTicket(accessToken.getAccess_token());
    		if (jsapiTicket == null)
    			return null;
    
    		Map<String, Object> rmap = sign(jsapiTicket.getTicket(), URLDecoder.decode(url));
    		rmap.put("appid", APP_ID);
    		return rmap;
    	}
    

    第五、暴露接口,在自己的Controller里加入下列代码

    	/**
    	 * 初始化jssdk配置参数
    	 * @return
    	 */
    	@PostMapping("/jssdk/config")
    	public APIResult wx_jssdk_config(String url) {
    		try {
    			Map<String, Object> jssdkConfig = WxCommon.initSssdkConfig(url);
    			if (jssdkConfig == null) {
    				return APIResult.fail("初始化失败");
    			}
    			return APIResult.success("初始化成功", jssdkConfig);
    		} catch (Exception e) {
    			e.printStackTrace();
    			return APIResult.exception(e.getMessage());
    		}
    	}
    

    第六,前端配置

    1、页面必须引入http://res2.wx.qq.com/open/js/jweixin-1.4.0.js否则无法使用微信的js
    2、初始化微信配置config

    注:
    1、需要定义允许使用的js接口["scanQRCode","updateAppMessageShareData"]
    2、需要使用微信控件,就需要先注册配置,否则将无法使用微信分享和微信扫码等功能
    3、如果在location.href.split("#")[0]存在参数,或者在使用自定义微信转发的时候,会将location.href.split("#")[0]直接转发出去,则必须要将location.href.split("#")[0] 进行encodeURIComponent转码,然后在java中通过URLDecode.decode进行解码,否则将会提示 "签名错误"
    注:为避免出现签名错误,建议加上转码和解码的操作

    common.sync("/jssdk/config",{
    	url : encodeURIComponent(location.href.split('#')[0])
    },function(rs){
    	if(rs.code == "0" && rs.data != null){
    		wx.config({
    		    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    		    appId:rs.data.appid, // 必填,公众号的唯一标识
    		    timestamp:rs.data.timestamp, // 必填,生成签名的时间戳
    		    nonceStr:rs.data.nonceStr, // 必填,生成签名的随机串
    		    signature:rs.data.signature,// 必填,签名
    		    jsApiList:["scanQRCode","updateAppMessageShareData"]  // 必填,需要使用的JS接口列表
    		});
    	}
    });
    

    3、注册微信自定义分享

    wx.ready(function(){
    	wx.updateAppMessageShareData({ 
            title: title, // 分享标题
            desc: desc, // 分享描述
            link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: imgUrl, // 分享图标
            success: function () {}
        });
    });
    

    4、微信扫一扫

    注:微信扫码分成两种
    1、直接扫码返回结果,然后由开发人员自己处理获取的扫码信息
    2、微信自主处理扫码结果,扫码完成后将会直接跳转页面(比如某个商品的条形码或者二维码)
    3、区分方式:needResult=1表示直接返回结果,needResult=0表示由微信自主处理扫码结果,默认needResult=0

    wx.scanQRCode({
    	needResult: needResult, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
    	scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
    	success: function (res) {
    		var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
    	}
    });
    

    5、错误信息提示

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

    6、前端JS完整代码(包括操作按钮隐藏和显示)

    var jssdk = {
    	/**
    	 * jssdk配置
    	 */
    	config : {
    		/**
    		 * 需要注册的接口
    		 */
    		jsApiList : ["hideAllNonBaseMenuItem","showMenuItems","scanQRCode","updateAppMessageShareData"],
    		/**
    		 * 初始化配置
    		 */
    		init : function(){
    			common.sync("/user-api/api/wechat/jssdk/config",{
    				url : encodeURIComponent(location.href.split('#')[0])
    			},function(rs){
    				if(rs.code == "0" && rs.data != null){
    					//初始化jssdk配置
    					wx.config({
    					    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    					    appId:rs.data.appid, // 必填,公众号的唯一标识
    					    timestamp:rs.data.timestamp, // 必填,生成签名的时间戳
    					    nonceStr:rs.data.nonceStr, // 必填,生成签名的随机串
    					    signature:rs.data.signature,// 必填,签名
    					    jsApiList:jssdk.config.jsApiList  // 必填,需要使用的JS接口列表
    					});
    				}
    			});
    		}
    	},
    	/**
    	 * 初始化所有接口
    	 */
    	ready : function(){
    		//初始化配置
    		jssdk.config.init();
    		//初始化接口
    		wx.ready(function(){
    			//隐藏非基础类按钮
    			jssdk.menu.hide();
    			//显示需要的按钮
    			jssdk.menu.show();
    			//初始化分享(默认分享当前页面)
    			jssdk.share($("title").html(),$("title").html(),location.href.split("#")[0],"https://img.alicdn.com/imgextra/i4/3294772646/O1CN0110v0je1VPuWTQQXvO_!!3294772646.jpg")
    		});
    	},
    	/**
    	 * 操作按钮
    	 */
    	menu : {
    		/**
    		 * 显示的操作按钮
    		 */
    		list : ["menuItem:share:appMessage","menuItem:share:timeline"],
    		/**
    		 * 隐藏所有非基础类按钮
    		 */
    		hide : function(){
    			wx.hideAllNonBaseMenuItem(); 
    		},
    		/**
    		 * 只显示分享到朋友和朋友圈的按钮
    		 */
    		show : function(){
    			wx.showMenuItems({
    				menuList: jssdk.menu.list// 要显示的菜单项,所有menu项见附录3
    			});
    		}
    	},
    	/**
    	 * 初始化自定义分享(注:该分享不会调起微信的分享插件,需要手动点击右上角的"..."进行分享)
    	 */
    	share : function(title,desc,link,imgUrl){
    		wx.updateAppMessageShareData({ 
    	        title: title, // 分享标题
    	        desc: desc, // 分享描述
    	        link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
    	        imgUrl: imgUrl, // 分享图标
    	        success: function () {}
    	    });
    	},
    	/**
    	 * 扫一扫(调用该方法的时候将会打开摄像头进行扫描)
    	 */
    	scan : function(needResult,callback){
    		wx.scanQRCode({
    			needResult: needResult, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
    			scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
    			success: function (res) {
    				//var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
    				callback(res);
    			}
    		});
    	}
    }
    /**
     * 初始化jssdk配置
     */
    jssdk.ready();
    /**
     * 输出错误信息
     */
    wx.error(function(res){
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    	common._comfirm(JSON.stringify(res));
    });
    

    本文简单介绍到这里,如果有不明白的可以在评论中留言

    展开全文
  • 微信开发入门教程 jssdk,通过config接口注入权限验证配置java+jsp微信开发教程,功能:扫描二维码,拍照、本地选图,图片预览,上传图片,下载图片,获取当前网络状态,查看地理位置,获取当前地理位置打开地图,...
  • 这个是使用微信原本的Deom修改 但是一定要注意几个注意事项,代码很简单,却让我一周mmp 在微信开发者工具调试,有时候你代码正确但是会报错 一定要真机调试 appid和secret一定要正确 一定要在在微信公众号后台设置...
  • 要想自定义分享的link、title、desc、imgUrl(分享卡片缩略图)就得集成JSSDK做自定义分享。准备阶段第一步要先配置安全域名:开发阶段可以将测试服和正式服的域名都配进去。没配置的话点击设置---公众号设置---功能...
  • 通过使用微信jssdk,网页开发者可以借助微信高效的使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更加优质的网页体验。 JSSDK使用...
  • 微信JSSDK说明文档

    千次阅读 2019-05-24 11:15:00
    微信JSSDK说明文档 转 微信JSSDK说明文档 2015年12月02日 09:41:34 panpanhm91 阅读数:10073 ...
  • 微信jssdk本地测试

    2017-09-23 23:53:45
    摘要因项目中需要使用微信语音相关接口功能,所以需要引入微信jssdk,但是这个东西的测试不是本地运行那么简单,需要借助微信web开发工具来进行,本文记录了我个人今日完成测试的这个过程,本文的重点不是开发教程,...
  • 微信分享JSSDK接入

    2019-07-11 11:30:42
    结果如下,自定义分享链接,分享图片等等... 开始对接 1.JS安全域名 配置路径在: 登录公众号号平台后,-----------进入公众号设置-------功能设置------,如下 JS安全域名强烈建议如下配置: cylothes.cn 2...
  • PHP或者HTML开发微信网页JSSDK

    千次阅读 2018-08-13 16:46:04
    最近公司开发了几款用于宣传的微信页面,里面主要用到了JSSDK,以及如何用它进行分享到朋友圈和好友的时候,实现小图标和文字描述。 首先需要一个认证了的服务号,在公众号设置-&gt;功能设置-&gt;JS接口...
  • 微信jssdk h5分享

    千次阅读 2018-11-07 11:54:17
    使用微信jssdk进行h5分享 一、首先,要严格按照微信文档步骤执行前面几个步骤,不然后面你会发现很多莫名其妙的坑。这里主要是4个步骤: JSSDK使用步骤 步骤一:绑定域名 先登录微信公众平台进入“公众号设置”...
  • 那一抹淡淡的忧伤—–微信开发基础 2. 用纯js是不可能用纯js了,这辈子都不用纯js了 —– 微信JSSDK开发以及问题解答 3. 要你命3000 —— 微信支付开发系列问题解决导语 微信JS-SDK是微信公众平台面向网页...
  • 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。 此文档面向...
  • 微信JSSDK引入微信开发

    千次阅读 2016-07-15 11:08:47
    微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券...
  • 简单记录下 微信js sdk 微信H5分享定义内置微信分享内容开发 其实很简单 ,先来第一步打开微信文档查看说明传送门:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 小伙伴也可以直接...
1 2 3 4 5 ... 20
收藏数 1,832
精华内容 732
关键字:

微信开发jssdk分享