微信開發:使用微信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

關注公衆號的都知道:

 

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