微信公衆號分享的坑

記一次微信公衆號分享sdk

這裏我的腳本是用jquery寫的,不帶框架源碼

首先創建jsp引入JavaScript微信分享js

<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

引入jquery

<script type="text/javascript" src="../script/jquery.js"></script>

這裏是使用的是http請求,以下貢獻http請求工具類

package com.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

/**
 * http get post
 * @author 爲中華之崛起而編程
 *
 */
@SuppressWarnings("all")
public class HttpUtil {

	/**
	 * 執行HTTP GET請求,返回請求響應的內容
	 * @param url
	 *            請求的URL地址
	 * @return 
	 * 			     返回請求響應的內內容
	 * @throws IOException
	 * @throws ClientProtocolException
	 */
	public static String doGet(String url) throws IOException {
		StringBuffer sb = new StringBuffer();
		HttpClient httpClient = new HttpClient();
		httpClient.getHttpConnectionManager().getParams()
				.setConnectionTimeout(2000);
		GetMethod getMethod = new GetMethod(url);
		try {
			getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,
					2000);
			httpClient.executeMethod(getMethod);
			if (getMethod.getStatusCode() == HttpStatus.SC_OK) {
				BufferedReader in = new BufferedReader(new InputStreamReader(
						getMethod.getResponseBodyAsStream()));
				String ln;
				while ((ln = in.readLine()) != null) {
					sb.append(ln);
				}
				try {
					in.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			getMethod.releaseConnection();
		}
		return null;
	}

	/**
	 * 執行HTTP POST請求,返回請求響應的內容
	 * 
	 * @param url
	 *            請求的URL地址
	 * @param params
	 *            請求的查詢的參數可以爲null
	 * @return 	      返回請求響應的內容
	 * @throws IOException
	 */
	public static String doPost(String url, Map<String, String> map)
			throws IOException {
		StringBuffer sb = new StringBuffer();
		HttpClient httpClient = new HttpClient();
		httpClient.getHttpConnectionManager().getParams()
				.setConnectionTimeout(2000);
		PostMethod postMethod = new PostMethod(url);
		postMethod.setRequestHeader("Content-Type",
				"application/x-www-form-urlencoded");

		int i = 0;
		NameValuePair[] data = new NameValuePair[map.size()];
		for (Map.Entry<String, String> entry : map.entrySet()) {
			data[i++] = new NameValuePair(entry.getKey(), entry.getValue());
		}
		postMethod.setRequestBody(data);

		try {
			postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,
					2000);
			postMethod.getParams().setParameter(
					HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
			httpClient.executeMethod(postMethod);
			if (postMethod.getStatusCode() == HttpStatus.SC_OK) {
				BufferedReader in = new BufferedReader(new InputStreamReader(
						postMethod.getResponseBodyAsStream(), "UTF-8"));
				String ln;
				while ((ln = in.readLine()) != null) {
					sb.append(ln);
				}
				try {
					in.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			postMethod.releaseConnection();
		}
		return null;
	}

	/**
	 * 執行HTTP POST請求,返回請求響應的內容
	 * 
	 * @param url
	 *            請求的URL地址
	 * @param params
	 *            請求的查詢參數可以爲null
	 * @return 返回請求響應的內容
	 * @throws IOException
	 */
	public static String doPost(String url, String body) throws IOException {
		StringBuffer sb = new StringBuffer();
		HttpClient httpClient = new HttpClient();
		httpClient.getHttpConnectionManager().getParams()
				.setConnectionTimeout(2000);
		PostMethod postMethod = new PostMethod(url);
		postMethod.setRequestHeader("Content-Type",
				"application/x-www-form-urlencoded");
		postMethod.setRequestBody(body);

		try {
			postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,
					2000);
			postMethod.getParams().setParameter(
					HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
			httpClient.executeMethod(postMethod);
			if (postMethod.getStatusCode() == HttpStatus.SC_OK) {
				BufferedReader in = new BufferedReader(new InputStreamReader(
						postMethod.getResponseBodyAsStream(), "UTF-8"));
				String ln;
				while ((ln = in.readLine()) != null) {
					sb.append(ln);
				}
				try {
					in.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			postMethod.releaseConnection();
		}
		return null;
	}

}

創建一個servlet,在servlet初始化時獲取access_token

1.獲取access_token地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=

2.獲取ticket地址:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=&type=jsapi

創建servlet初始化

public class InitServlet extends HttpServlet{
    //這裏創建一個線程2小時調用一次循環調用,預防access_token過期
    private static ScheduledExecutorService POOL = Executors.newScheduledThreadPool(1);
    //創建一個map存ticket
    public static Map<String,String> map = new HashMap<String,String>();
    
    public void init() throws ServletException {
        
        POOL.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				try {
					String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=&secret=d51ff270c9d161fd6065a0c5891ca802";
					String json = HttpUtil.doGet(url);
					Map mapss = JSON.parseObject(json, Map.class);
					String access_token = (String)mapss.get("access_token");
					url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
					json = HttpUtil.doGet(url);
					Map mapOne = JSON.parseObject(json, Map.class);
					System.out.println(JSON.toJSONString(mapOne));
					String jsapi_ticket = (String)mapOne.get("ticket");
					map.put("ticket", jsapi_ticket);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}, 0, 2 * 60 * 59 * 1000, TimeUnit.MILLISECONDS);
    }
}

web.xml調用servlet初始化

  <servlet>  
   <servlet-name>InitServlet</servlet-name>  
   <servlet-class>com.servlet.InitServlet</servlet-class>  
   <load-on-startup>1</load-on-startup>  
  </servlet> 

下面創建jsp獲取全域名,第一次就是在全域名這裏栽跟頭,因爲沒有動態獲取所以sdk驗籤一直失敗,一定要確保url參數跟你訪問的頁面的url保持一致

<%	
    //訪問頁的url
	String strBackUrl = "http://" + request.getServerName() + ":"+ request.getServerPort() + request.getContextPath()  + request.getServletPath(); 
    //參數 
	if(request.getQueryString() != null){
		strBackUrl = strBackUrl + "?" + (request.getQueryString());
	}
    //獲取項目啓動時初始化好的ticket
    String ticket = InitServlet.map.get("ticket");
    //調用簽名算法,存入返回參數
	Map<String,String> map = Sha1.sign(ticket, strBackUrl);
%>

加入微信簽名算法Sha1

package com.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

public class Sha1 {
	public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意這裏參數名必須全部小寫,且必須有序
        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;
    }

    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;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
	
	public static String getRandomString(int length){
	    //產生隨機數
	    Random random=new Random();
	    StringBuffer sb=new StringBuffer();
	    //循環length次
	    for(int i=0; i<length; i++){
	      //產生0-2個隨機數,既與a-z,A-Z,0-9三種可能
	      int number=random.nextInt(3);
	      long result=0;
	      switch(number){
	      //如果number產生的是數字0;
	      case 0:
	        //產生A-Z的ASCII碼
	        result=Math.round(Math.random()*25+65);
	        //將ASCII碼轉換成字符
	        sb.append(String.valueOf((char)result));
	        break;
	        case 1:
	          //產生a-z的ASCII碼
	        result=Math.round(Math.random()*25+97);
	          sb.append(String.valueOf((char)result));
	        break;
	        case 2:
	          //產生0-9的數字
	                   sb.append(String.valueOf
	                          (new Random().nextInt(10)));
	        break; 
	      }
	    }
	    return sb.toString();
	  }
}

執行腳本

<script type="text/javascript">
$(function() {
	wx.config({
        debug: true, // 開啓調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時纔會打印。
            appId: '', // 必填,企業號的唯一標識,此處填寫企業號corpid
        timestamp: '<%=map.get("timestamp")%>', // 必填,生成簽名的時間戳
         nonceStr: '<%=map.get("nonceStr")%>', // 必填,生成簽名的隨機串
        signature: '<%=map.get("signature")%>',// 必填,簽名,見附錄1
        jsApiList: [
            'onMenuShareAppMessage',
            'scanQRCode'
        ] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2
    });
	wx.ready(function () {   //需在用戶可能點擊分享按鈕前就先調用
	    
	    var url = '自定義跳轉url';
		wx.onMenuShareAppMessage({
			title: '', // 分享標題
		    desc: '', // 分享描述
		    link: url, // 分享鏈接,該鏈接域名或路徑必須與當前頁面對應的公衆號JS安全域名一致
		    imgUrl: '', // 分享圖標
			success: function () {
			// 用戶點擊了分享後執行的回調函數
			}
		});
	});
	wx.error(function(res){
	    // config信息驗證失敗會執行error函數,如簽名過期導致驗證失敗,具體錯誤信息可以打開config的debug模式查看,也可以在返回的res參數中查看,對於SPA可以在這裏更新簽名。
	});
	
});

</script>

打開調試模式,返回config:ok就算是成功了,這裏拿分享舉例

還有一個就是,想多個頁面都使用同一個自定義分享,把分享的sdk單獨出來,要使用的頁面去引用此頁面就可以了

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