微信JSSDK实现微信自定义分享,微信扫一扫

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

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

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

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

微信JSSDK实现微信自定义分享,微信扫一扫_第1张图片
2、设置-公众号设置-功能设置-网页授权域名(必须与JS安全域名一致)
微信JSSDK实现微信自定义分享,微信扫一扫_第2张图片
3、开发-基础配置-IP白名单(设置接口可访问的IP地址)
微信JSSDK实现微信自定义分享,微信扫一扫_第3张图片
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 sign(String jsapi_ticket, String url) {
		Map ret = new HashMap();
		String string1;
		String signature = "";
		String nonce_str = getNonceStr();
		Long timestamp = getTimestamp();
		// 注意这里参数名必须全部小写,且必须有序
		string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + 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 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 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 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));
});

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

你可能感兴趣的:(微信开发,JAVA,JSSDK)