1. 程式人生 > >Java呼叫微信JSSDK那些坑

Java呼叫微信JSSDK那些坑

最近公司專案要求自定義微信分享樣式,我就接手了這個微信JSSDK的介面呼叫。

首先你要有一個公眾號。

然後需要在公眾號的設定-公眾號設定-功能設定

設定我們的安全域名。


我們把檔案下載下來,然後放到我們填寫的域名,注意:一定要放在你要呼叫微信的介面的路徑下一,只能是域名後跟一個目錄,

我們要呼叫的頁面必須是在這個目錄下的子目錄或者這個目錄下。還有如果你用的是SpringMVC的話請對這個域名下的靜態資源進行處理。因為微信要去判斷你填寫的這個域名下是否有這個檔案。

這一步完成之後我們進入 開發-基礎配置-伺服器配置

首先我們需要對我們伺服器的IP地址加入白名單。


去啟用的我們的伺服器資訊,這個伺服器必須是你要呼叫微信的JSSDK的專案伺服器。


首先說下這個URL,這個URL必須要能接受微信傳送的請求

微信伺服器會給你傳送一個請求,這個請求有幾個引數

分別是:signature timestamp nonce echostr

拿到這四個引數之後,需要將 你在頁面中寫Token,nonce,timestamp 放入到一個String數組裡面,然後進行sort排序,

排序完成之後將這三個字串進行拼接,然後使用SHA-1演算法進行加密,將加密後的結果與echostr進行比較,相同返回微信發給你的echostr

具體程式碼:

@RequestMapping(value="getToken",method=RequestMethod.GET)
public @ResponseBody String getToken(String signature,String timestamp,String nonce,String echostr) throws NoSuchAlgorithmException{
String[] array ={wxToken,nonce,timestamp};
Arrays.sort(array);
String newArray="";
for (int i = 0; i < array.length; i++) {
	newArray+=array[i];
}
//SHA-1加密
MessageDigest instance = MessageDigest.getInstance("SHA-1");
instance.update(newArray.getBytes());
byte[] digest = instance.digest();
StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
    shaHex = Integer.toHexString(digest[i] & 0xFF);
    if (shaHex.length() < 2) {
	hexstr.append(0);
    }
    hexstr.append(shaHex);
}
if(hexstr.equals(signature)){
	return echostr;//相同返回微信發給我們的echostr
}
return "erro";
}

此時就可以完成認證了。

然後是頁面:

var wxObjet;
	href=encodeURIComponent(window.location.href)//這個引數是用來獲取當前頁面的url
	$.ajax({
		url:用來提供配置許可權資訊的一個Controller/href,
		type:"get",
		dataType:"json",
		async: false,
		success:function(data){
			wxObjet=data;
		}
	})
	
wx.config({
    debug: false, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
    appId: wxObjet.aapid, // 必填,公眾號的唯一標識
    timestamp: wxObjet.timestamp, // 必填,生成簽名的時間戳
    nonceStr: wxObjet.noncestr, // 必填,生成簽名的隨機串
    signature: wxObjet.Signature,// 必填,簽名
    jsApiList: ["onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ"] // 必填,需要使用的JS介面列表
    
});

然後看後臺程式碼:

@RequestMapping("getJsapi")
public @ResponseBody Map getJsapi(String url//就是你傳送請求的頁面){
		Map map=new HashMap();
		try {
			//微信JSSDK Acces_token和jsapi的全域性快取
			//因為微信的Token和jsapi30分鐘內有效,每天只能獲取2000次,所以我們要加上快取。
			String token ="";
			String jsapi_ticket ="";
			Map mes = (Map)redisTemplate.opsForValue().get("mes");
			Map redis=mes;
			if(mes==null){
				redis=new HashMap();
				token=CommonUtil.getToken(appid, appsecret);//寫一個工具類,用來給微信傳送請求,請求所需引數:appid,和AppSecret,下面有程式碼
				jsapi_ticket= CommonUtil.getJsapi_ticket(token);//拿到微信給我們的token之後我們去獲取jsapi_ticket.下,下面有程式碼
				//放入ticket
				redis.put("ticket",jsapi_ticket);
				redis.put("ticketDate",new Date().getTime());
				//放入token
				redis.put("token",token);
				redis.put("tokenDate",new Date().getTime());
				redisTemplate.opsForValue().set("mes", redis);
			}else{
				long  tokenDate=(long)mes.get("tokenDate");
				if(new Date().getTime()-tokenDate>=1200000){
					token=CommonUtil.getToken(appid, appsecret);
					//放入token
					System.out.println(token);
					redis.put("token",token);
					redis.put("tokenDate",new Date().getTime());
				}else{
					token=(String) mes.get("token");
					
				}
				long  ticketDate=(long)mes.get("ticketDate");
				if(new Date().getTime()-ticketDate>=1200000){
					jsapi_ticket= CommonUtil.getJsapi_ticket(token);
					//放入ticket
					redis.put("ticket",jsapi_ticket);
					redis.put("ticketDate",new Date().getTime());
				}else{
					jsapi_ticket = (String)mes.get("ticket");
				}
				redisTemplate.opsForValue().set("mes", redis);
			}
			
			
			
			
			//生成一個隨機字元,我這裡直接用時間戳來代替了
			long time = new Date().getTime();
			String noncestr = String.valueOf(time);
			//時間綽
			long time2 = new Date().getTime();
			String timestamp=String.valueOf(time2/1000);//微信接收的時間戳是10位的所以咱們要除以1000
			//去使用SHA-1獲取安全簽名 ,下面有程式碼
			String jsSDKSignature = CommonUtil.getJsSDKSignature(jsapi_ticket, noncestr, timestamp, url);
			map.put("Signature",jsSDKSignature);//將所有驗證許可權所需要資料放入一個map,這個是安全簽名
			map.put("noncestr",noncestr);//這個是隨機字元
			map.put("aapid",appid);//這個是咱們的APPID
			map.put("timestamp", timestamp);//這個是時間戳
			return map;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return map;
	}

工具類程式碼


import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSON;

/**
 * 拿到微信的Access_Tocken
 * 
 * @author liuyk
 *
 */
public class CommonUtil {
	public static String getToken(String appid, String appSecret) throws ClientProtocolException, IOException {
		CloseableHttpClient httpclient = HttpClients.createDefault();
		// 建立引數佇列
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("grant_type", "access_token"));
		params.add(new BasicNameValuePair("appid", appid));
		/* secret */
		params.add(new BasicNameValuePair("appid", AppSecret));
		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret="
				+ appSecret;
		// 建立httpget.
		HttpGet httpget = new HttpGet(url);
		// 傳送請求
		CloseableHttpResponse response = httpclient.execute(httpget);
		// 得到響應提
		HttpEntity entity = response.getEntity();

		String param = EntityUtils.toString(entity);
		System.out.println(param);
		// 將JSON轉換為Map
		Map parseParam = (Map) JSON.parse(param);
		Object object = parseParam.get("access_token");
		return object.toString();
	}

	public static String getJsSDKSignature(String jsapi_ticket, String noncestr, String timestamp, String url) {
            //這幾個引數名按照字典順序進行拼接
		String string = "jsapi_ticket=" + jsapi_ticket;
		string += "&noncestr=" + noncestr;
		string += "&tamp=" + timestamp;
		string += "&url=" + url;
                
		StringBuffer hexstr = new StringBuffer();
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			// 對接後的字串進行sha1加密
			md.update(string.getBytes());
			byte[] digest = md.digest();
			String shaHex = "";
			for (int i = 0; i < digest.length; i++) {
				shaHex = Integer.toHexString(digest[i] & 0xFF);
				if (shaHex.length() < 2) {
					hexstr.append(0);
				}
				hexstr.append(shaHex);
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return hexstr.toString();
	}

	public static String getJsapi_ticket(String access_token) {
		String ticket = "";
		String requestUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token
				+ "&type=jsapi";
		CloseableHttpClient httpclient = HttpClients.createDefault();
		// 先從執行緒中取值,如果取不到,說明沒有使用執行緒,再利用這個方法獲取
		// 因為傳送資訊等操作,都是呼叫的這個方法,所以在這裡進行處理一下吧
		HttpGet httpget = new HttpGet(requestUrl);
		// 傳送請求
		CloseableHttpResponse response = null;
		try {
			response = httpclient.execute(httpget);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 得到響應提
		HttpEntity entity = response.getEntity();

		String param = null;
		try {
			param = EntityUtils.toString(entity);
		} catch (ParseException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(param);
		// 將JSON轉換為Map
		Map parseParam = (Map) JSON.parse(param);
		Object object = parseParam.get("ticket");
		return object.toString();
	}

}
//前端的許可權認證之後我們把要用的微信介面放入ready回撥裡面
wx.ready(function(){
	/* 分享到朋友圈 */
	wx.onMenuShareTimeline({
    title: '', // 分享標題
    link: '', // 分享連結,這個連結必須是你配置的jssdk的安全域名,如果不是在那個域名或者路徑下會沒有效果
    imgUrl: '', // 同上

    });
  /*分享給朋友  */
	wx.onMenuShareAppMessage({
    title: '', // 分享標題
    desc: '', // 分享描述
    link: '', // 分享連結,該連結域名必須與當前企業的可信域名一致
    imgUrl: '', // 分享圖示
    type: '', // 分享型別,music、video或link,不填預設為link
    dataUrl: '', // 如果type是music或video,則要提供資料鏈接,預設為空
    success: function () {
        alert("分享成功");
    },
    cancel: function () {
        // 使用者取消分享後執行的回撥函式
        alert("已取消分享");
    }
});

以上就是整個流程,如果有什麼問題可以來問我,很歡迎幫忙解決。


相關推薦

Java呼叫JSSDK那些

最近公司專案要求自定義微信分享樣式,我就接手了這個微信JSSDK的介面呼叫。首先你要有一個公眾號。然後需要在公眾號的設定-公眾號設定-功能設定設定我們的安全域名。我們把檔案下載下來,然後放到我們填寫的域名,注意:一定要放在你要呼叫微信的介面的路徑下一,只能是域名後跟一個目錄,

呼叫JSSDK實現分享功能

最近遇到一個專案是基於微擎框架做一個分享功能的,微擎本身是自帶分享功能的,只是這次想要實現自定義分享內容,故進行了以下程式碼處理 * $_W[‘account’][‘jssdkconfig’]是微擎封裝好的jssdk簽名包的內容 * php頁面程式碼 <?php if

呼叫JSSDK介面,實現自定義分享功能

1,你需有一個公眾號,沒有不用談自定義分享內容了; 2,公眾號上把你的域名增加到“JS介面安全域名”: 3,我這功能是基於thinkphp3.1實現的,按下圖上網下包放在對應該目錄下: 4,修改核心公共檔案:functions.php 加入程式碼: /*

Java呼叫掃碼支付介面(模式二)

前些天幫朋友實現了一個微信掃碼的介面,在之前也是不會搞這個東西,抱著試試的心態就開始看各種文件和blogs,大多數人都在吐槽微信給的java呼叫微信介面文件太含糊,而且網上的查到的資料也不詳細,只有大概的開發流程沒有太多細節上的講解,最後還是花了一些錢買了一套視

java呼叫支付

微信開發文件地址:https://mp.weixin.qq.com/wiki/home/ 從呼叫處開始 我的流程: 1.點選“支付”按鈕,去後臺 —-> 2.後臺生成支付所需資料返回頁面 —-> 3.頁面點選“確認支付”呼叫微信支付js

呼叫JSSDK

1定義一個微信jssdk 類 <?php class JSSDK { private $appId; private $appSecret; public function __construct($appId, $appSecret) { $t

java呼叫分享

這篇文章主要是介紹如何使用java開發微信分享功能,因為工作,已經開發完成,可使用。下面有聯絡方式,可交流 如果想要自定義微信的分享功能,首先在自己的頁面內首先使用AJAX。下面我具體舉例。 首先是在頁面內寫入請求後臺的AJAX /** *

JAVA呼叫掃一掃

java微信開發官方文件地址:https://mp.weixin.qq.com/wiki/home/ 開發微信付款和掃一掃,必須有內網穿透,最好有伺服器 微信開發掃一掃開發過程: // WeixinUtil.getAccess_token此工具類,將放在下面一點。 這裡是

Java呼叫客服訊息介面

package com.yhxc.utils.wechat; import net.sf.json.JSONObject; import java.io.*; import java.net.HttpURLConnection; import java.net.URL;

ios 呼叫JSSDK 簽名失敗解決方法

用SPA做微信h5,呼叫微信jssdk的頁面,安卓微信上木有問題,ios微信報當前url未註冊 經過除錯,是ios微信版本問題導致頁面跳轉url未變化,導致驗籤失敗 所以我們大致的思想就是:在ios微信環境中(判斷瀏覽器環境請參考我的另一篇文章–js判斷瀏覽

JSSDK開發,呼叫掃一掃 JAVA & jsp前端 & js實現

// 微信JSSDK的AccessToken請求URL地址 ublic final static String weixin_jssdk_acceToken_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type

JSSDK分享--挖坑填之小結

file com 附錄 success 成功 文檔 -i 是把 n)   最近參與微信服務號小項目的開發,關於微信分享,我是只知其功能,並沒深入了解其中的彎彎道道。雖然項目中不是我負責微信分享這一塊(因為我也不太會),但是團隊在這個功能上,那可是說多了都是淚,耗費了超級多的

Java-Web網頁支付開發流程以及各種

微信網頁支付流程概覽 生成Oauth2.0授權連結獲得code 使用code獲得使用者資訊(OpenId) 向微信統一下單介面提交訂單獲得PrepayID 在JS頁面中向用戶發起支付請求 使用者輸入支付密碼完成支付 使用weixin-

Java專案呼叫支付到指定銀行卡

public static EnterpriceToCustomer WXPayToBC(String encBankAcctNo, String encBankAcctName, String bank_code, String desc, String amount) throws Ex

JAVA實現呼叫js-sdk掃一掃

喜歡的朋友可以關注下。 已經很久沒有給大家分享一片技術文章了,今天抽了點時間來,給大家說一說如何呼叫微信提供的掃一掃介面。 前提: 需要申請一個公眾號:申請公眾號需要的資料我就不說了,去申請微信會提示需要哪些。 準備appid(公眾號的id) AppSecret (

JSSDK呼叫原生的功能上傳圖片儲存到自己的伺服器中

第一件事首先是微信的選擇圖片功能,就是微信發朋友圈選擇圖片的時候那個介面 //呼叫微信拍照功能 wx.chooseImage({ count: 1,

記錄 呼叫圖片上傳 前端上傳 後端Java下載儲存(多圖上傳)

測試頁面 <template>     <div id="test">         <button @click="wxchoose">微信上傳測試</butt

php curl返回false填記-curl呼叫建立自定義選單返回false

首先宣告一點,這個錯誤可能在你的開發生涯中不會遇到,除非你直接複製了微信公眾平臺的api地址。不過這應該算是php中curl擴充套件的一個bug,為什麼是bug呢?讓我們仔細來看。 下邊是示例程式碼,程式碼的功能是呼叫微信公眾平臺的建立自定義選單介面來建立自定義選單。 建

公眾號開發 自定義分享 從前臺到Java後臺 呼叫JS介面分享朋友圈

20180811寫在前面的話 有很多人遇到問題之後問我,結果大多數是因為配置問題,所以請詳細閱讀前面的配置步驟。 20181016注意事項 文中原始碼下載地址 上面這個地址是我當時做的整個專案的原始碼,包含了一些業務在裡面,用的是SSM框架,現在寫了一

Java公眾平臺開發(十五)--JSSDK的使用

轉自:http://www.cuiyongzhi.com/post/63.html 在前面的文章中有介紹到我們在微信web開發過程中常常用到的 【微信JSSDK中Config配置】 ,但是我們在真正的使用中我們不僅僅只是為了配置Config而已,而是要在我們的專案中真正去使用微信JS-S