微信开发:使用微信jssdk接口调用语音,图片,分享等功能,获取config接口注入权限验证

微信公众号开发,在公众号界面调用微信JS SDK接口,实现媒体(图片、语言、视频)上传,分析等功能之前,需要获取Config接口注入权限验证。

微信Config接口注入权限验证,需要如下参数:

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

那么如何获得Config接口注入权限验证的相关参数:其中appId,timestamp,nonceStr是自己后台随机生成的,但是 signatrue签名生成需要jsapi_ticket,并按照指定顺序将拼接好的参数字符串进行加密,生成签名,下面首先了解如何生成jsapi_ticket:

jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。

 因为Access_token,Jsapi_ticket是有次数限制的,所以需要将数据生成并保持在缓存中,或者数据库中,过期之后,重新拉取。

下面给出Demo示例,仅供参考:

package com.inspur.tax.api.login.controller;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.SignUtils;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.alibaba.fastjson.JSONObject;
import com.inspur.tax.api.login.entity.LoginUser;
import com.inspur.tax.api.login.service.ILoginUserService;
import com.inspur.tax.api.sms.cache.CacheManagerImpl;
import com.inspur.tax.api.util.WeixinUtil;
import com.inspur.tax.api.common.Const;
import com.inspur.tax.utils.DateUtils;
import com.inspur.tax.utils.FastJsonUtils;
import com.inspur.tax.utils.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/WX/JsapiTicket")
public class WxJsapiTicketController {

    private final WxMpService wxService;
    @Autowired
    private ILoginUserService loginUserService;

    static CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();
    @RequestMapping("/wxConfig/{appid}")
    public Map<String,Object> index(@PathVariable String appid,@RequestParam String urlx) {
    	Map<String,Object> wxConfig = new HashMap<String,Object>();
        try {
        	/**
        	 * 生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,
        	 * jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,
        	 * 频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
				
			        参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):
			   https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
			
			      用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):
			  https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
        	 * */
        	
        	//access_token 和jsapi_token 都是需要本地缓存的
        	
        	//通过appid获得secret
        	String secret = Const.SERVICE_WxConfig.get(appid);
        	
        	//判断是否在缓存中
        	String token2 = "";
        	boolean flagTimeOut  = false;
        	boolean flagExist = false;
        	flagExist = cacheManagerImpl.isContains(appid+"AC");
        	if(flagExist) {
        		//判断是否过期
        		flagTimeOut = cacheManagerImpl.isTimeOut(appid+"AC");
        		if(flagTimeOut) {
        			cacheManagerImpl.clearByKey(appid+"AC");
        		}
        	}
        	
        	if(!flagTimeOut && flagExist) {
        		token2 = cacheManagerImpl.getCacheByKey(appid+"AC").getDatas().toString();
            	
        	}else {
        		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appid + "&secret=" + secret;
            	JSONObject json = WeixinUtil.httpRequest(url, "GET", null);
            	token2=json.getString("access_token");
            	
            	cacheManagerImpl.putCache(appid+"AC", token2, 6500*1000);
        	}
        	
        	
        	String jsapi_token = "";
        	flagExist = cacheManagerImpl.isContains(appid+"JT");
        	if(flagExist) {
        		//判断是否过期
        		flagTimeOut = cacheManagerImpl.isTimeOut(appid+"JT");
        		if(flagTimeOut) {
        			cacheManagerImpl.clearByKey(appid+"JT");
        		}
        	}
        	
        	if(!flagTimeOut && flagExist) {
        		jsapi_token = cacheManagerImpl.getCacheByKey(appid+"JT").getDatas().toString();
            	
        	}else {

            	String jsapiUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ token2 + "&type=jsapi";
            	JSONObject jsapiJson = WeixinUtil.httpRequest(jsapiUrl, "GET", null);
            	if (jsapiJson != null) {
            		jsapi_token = jsapiJson.getString("ticket");
            	}
            	cacheManagerImpl.putCache(appid+"JT", jsapi_token, 6500*1000);
        	}
        	
        	
        	wxConfig = WeixinUtil.getWxConfig(urlx, jsapi_token,appid);
        } catch (Exception e) {
           log.error("JsapiTicket,异常日志",e);
        }
        return wxConfig;
    }


}
package com.inspur.tax.api.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.alibaba.fastjson.JSONObject;

public class WeixinUtil {

/**

* 方法名:httpRequest</br>

* 详述:发送http请求</br>

* 开发人员:souvc </br>

* 创建时间:2016-1-5 </br>

* @param requestUrl

* @param requestMethod

* @param outputStr

* @return 说明返回值含义

* @throws 说明发生此异常的条件

*/
public static JSONObject httpRequest(String requestUrl,String requestMethod, String outputStr) {
	JSONObject jsonObject = null;
	StringBuffer buffer = new StringBuffer();
	try {
	
	URL url = new URL(requestUrl);
	HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
	
	httpUrlConn.setDoOutput(true);
	httpUrlConn.setDoInput(true);
	httpUrlConn.setUseCaches(false);
	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());
	} catch (ConnectException ce) {
		ce.printStackTrace();
	} catch (Exception e) {
		e.printStackTrace();
	}
	return jsonObject;
}


/**

* 方法名:getWxConfig</br>

* 详述:获取微信的配置信息 </br>

* 开发人员:souvc </br>

* 创建时间:2016-1-5 </br>

* @param request

* @return 说明返回值含义

* @throws 说明发生此异常的条件

*/
public static Map<String, Object> getWxConfig(String urlx,String jsapi,String appid) {
	Map<String, Object> ret = new HashMap<String, Object>();
	
	//HttpSession session=request.getSession();
	String appId = appid; // 必填,公众号的唯一标识
	
	String secret = "";
	
	String requestUrl = urlx;
	
	String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填,生成签名的时间戳
	
	String nonceStr = UUID.randomUUID().toString(); // 必填,生成签名的随机串
	
	
	String signature = "";
	// 注意这里参数名必须全部小写,且必须有序
	
	System.out.println("jsapi_ticket:"+jsapi);
	
	String sign = "jsapi_ticket=" + jsapi + "&noncestr=" + nonceStr+ "&timestamp=" + timestamp + "&url=" + requestUrl;
	try {
	MessageDigest crypt = MessageDigest.getInstance("SHA-1");
	crypt.reset();
	crypt.update(sign.getBytes("UTF-8"));
	signature = byteToHex(crypt.digest());
	} catch (NoSuchAlgorithmException e) {
	e.printStackTrace();
	} catch (UnsupportedEncodingException e) {
	e.printStackTrace();
	}
	ret.put("appId", appId);
	ret.put("timestamp", timestamp);
	ret.put("nonceStr", nonceStr);
	ret.put("signature", signature);
	return ret;
}


/**

* 方法名:byteToHex</br>

* 详述:字符串加密辅助方法 </br>

* 开发人员:souvc </br>

* 创建时间:2016-1-5 </br>

* @param hash

* @return 说明返回值含义

* @throws 说明发生此异常的条件

*/
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;

	}
}

通过上面Demo,我们可以获取微信Config接口注入权限验证所需要的参数;然后就可以按照以下操作,调用微信JSSDK接口

JSSDK使用步骤

 

步骤一:绑定域名

先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。

备注:登录后可在“开发者中心”查看对应的接口权限。

步骤二:引入JS文件

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

如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)。

备注:支持使用 AMD/CMD 标准模块加载方法加载

 

步骤三:通过config接口注入权限验证配置

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。

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

步骤四:通过ready接口处理成功验证

wx.ready(function(){
  // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});

步骤五:通过error接口处理失败验证

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

其他方法请参考官方文档:

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html

 

参考文档:

https://www.cnblogs.com/haw2106/p/10345081.html

关注公众号的都知道:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章