1. 程式人生 > >微信公眾號網頁分享功能開發總結

微信公眾號網頁分享功能開發總結

    最近要做一個微信公眾號頁面分享功能,其中遇到了不少問題,別的先不多說了,直接上程式碼。

Controller層:
/**
	 * 
	 *<pre>
	 *<b> 跳轉二維碼頁面 .</b>
	 *<b>Description:</b> 
	 *    
	 *<b>Author:</b> chendy
	 *<b>Date:</b> 2018/04/25 上午9:46:14
	 *@param session
	 *@return
	 *</pre>
	 */
	@RequestMapping(value="//personerErweima")
	public ModelAndView goErWeiMa(HttpSession session,HttpServletRequest request){
		  ModelAndView modelAndView = new ModelAndView();
		try {
			UserInfoVo user = userInfoService.showUserinfoByCon(retrievalCurrentUserInfo(session).getLogId());
			modelAndView.addObject("user", user);
			modelAndView.setViewName("/wap/userinfo/erweima");//載入頁面的一些資料資訊
			//分享
			String url = "/escq/wap/userinfo/personerErweima.html"; //當前頁面的路徑
			String domainAddr = "http://vm3kgx.natappfree.cc"; //域名
			String fenxurl=domainAddr+"/escq/wap/userinfo/logInfo/jumpJdjerweima.html"; //要分享的路徑(分享出去的連結)

			Map<String, String> params=HttpXmlClient.getShare(request,url);//獲取簽名
			request.setAttribute("params", params);
			request.setAttribute("fenxurl", fenxurl);
			//分享結束  
		} catch (Exception e) {
			modelAndView.setViewName("wap/userinfo/login");
		}
			return modelAndView;
	}
獲取簽名:
public class HttpXmlClient {

	@SuppressWarnings("unchecked")
	public static String getToken(){//獲取access_token
		 String access_token = "";  
		    String grant_type = "client_credential";//獲取access_token填寫client_credential   
		   String AppId="";//第三方使用者唯一憑證  測試號
		   String secret="";//第三方使用者唯一憑證金鑰,即appsecret  測試號 
		    //這個url連結地址和引數皆不能變  
		    String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type="+grant_type+"&appid="+AppId+"&secret="+secret;  
		    try {  
		        URL urlGet = new URL(url);  
		        HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();  
		        http.setRequestMethod("GET"); // 必須是get方式請求  
		        http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");  
		        http.setDoOutput(true);  
		        http.setDoInput(true);  
		        System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 連線超時30秒  
		        System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 讀取超時30秒  
		        http.connect();  
		        InputStream is = http.getInputStream();  
		        int size = is.available();  
		        byte[] jsonBytes = new byte[size];  
		        is.read(jsonBytes);  
		        String message = new String(jsonBytes, "UTF-8");  
		        Map<String, String> map = (Map<String, String>) JSON.parse(message);
//		        JSONObject demoJson = JSONObject.fromObject(message);  
//		        System.out.println("JSON字串:"+demoJson);  
		        access_token = map.get("access_token");  
		        is.close();  
		    } catch (Exception e) {  
		            e.printStackTrace();  
		    }  
		    return access_token;  
	}
	
	@SuppressWarnings("unchecked")
	public static String getTicket(String access_token) {  
	    String ticket = null;  
	    String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token +"&type=jsapi";//這個url連結和引數不能變  
	    try {  
	        URL urlGet = new URL(url);  
	        HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();  
	        http.setRequestMethod("GET"); // 必須是get方式請求  
	        http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");  
	        http.setDoOutput(true);  
	        http.setDoInput(true);  
	        System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 連線超時30秒  
	        System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 讀取超時30秒  
	        http.connect();  
	        InputStream is = http.getInputStream();  
	        int size = is.available();  
	        byte[] jsonBytes = new byte[size];  
	        is.read(jsonBytes);  
	        String message = new String(jsonBytes, "UTF-8");  
	        Map<String, String> map = (Map<String, String>) JSON.parse(message);
//	        JSONObject demoJson = JSONObject.fromObject(message);  
//	        System.out.println("JSON字串:"+demoJson);  
	        ticket = map.get("ticket");  
	        is.close();  
	    } catch (Exception e) {  
	            e.printStackTrace();  
	    }  
	    return ticket;  
	}  
	
	public static String SHA1(String decript) {  
	    try {  
	        MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");  
	        digest.update(decript.getBytes());  
	        byte messageDigest[] = digest.digest();  
	        // Create Hex String  
	        StringBuffer hexString = new StringBuffer();  
	        // 位元組陣列轉換為 十六進位制 數  
	            for (int i = 0; i < messageDigest.length; i++) {  
	                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);  
	                if (shaHex.length() < 2) {  
	                    hexString.append(0);  
	                }  
	                hexString.append(shaHex);  
	            }  
	            return hexString.toString();  
	   
	        } catch (NoSuchAlgorithmException e) {  
	            e.printStackTrace();  
	        }  
	        return "";  
	}  
	public static String CreateNoncestr() {  
	    String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
	    String res = "";  
	    for (int i = 0; i < 16; i++) {  
	        Random rd = new Random();  
	        res += chars.charAt(rd.nextInt(chars.length() - 1));  
	    }  
	    return res;  
	}
	
	public static Map<String,String> getShare(HttpServletRequest request,String url){
		 //微信分享授權開始  
		  String appId ="" ;//取專案中配置的公眾號id 測試號
		  String domainAddr = "http://vm3kgx.natappfree.cc";//專案中配置的網站的域名   測試域名
		  String str = request.getQueryString();  
		  Map<String, String> map = new HashMap<String, String>();   
		  map.put("appid", appId);   
		//  String url="http://vm3kgx.natappfree.cc/escq/wap/userinfo/personerErweima.html";
		  url=domainAddr+url;
		  map.put("url", url);
		  String  jsapi_token=SingletonUtil.getJsapiTicket(SingletonUtil.getAccessToken());
		   //生成簽名  
	      SortedMap<Object,Object> params = new TreeMap<Object,Object>();            
	      params.put("timestamp", Long.toString(new Date().getTime()/1000));  
	      params.put("noncestr", HttpXmlClient.CreateNoncestr());  
	      params.put("jsapi_ticket",jsapi_token);  
	      System.out.println("列印資料:"+jsapi_token+"  url: "+map.get("url"));
	      params.put("url",map.get("url"));//url地址  
	      StringBuffer sb = new StringBuffer();  
	      Set es = params.entrySet();  
	      Iterator it = es.iterator();  
	      while(it.hasNext()) {  
	          Map.Entry entry = (Map.Entry)it.next();  
	          String k = (String)entry.getKey();  
	          Object v = entry.getValue();  
	          sb.append(k + "=" + v + "&");  
	      }  
	      String  signStr = sb.toString().substring(0, sb.toString().length()-1);  
	      String sign = HttpXmlClient.SHA1(signStr);//簽名    
	      Map<String, String> result = new HashMap<String,String>();  
	      result.put("timestamp",(String)params.get("timestamp"));  
	      result.put("noncestr", (String)params.get("noncestr"));  
	      result.put("signature", sign);  
	      result.put("appId",map.get("appid"));  
	      System.out.println("列印資料:"+result);
		  return result;
		
		
	}
}
SingletonUtil:
import java.util.Date;
import java.util.Map;


public class SingletonUtil { //快取授權資訊

	public static String getAccessToken() {
		String result = "";
		SingletonAccessToken singleton = SingletonAccessToken.getInstance();
		Map<String, String> map = singleton.getMap();
		String time = map.get("time");
		String accessToken = map.get("access_token");
		Long nowDate = new Date().getTime();
		if (accessToken != null && time != null && nowDate - Long.parseLong(time) < 7000 * 1000) {
			result = accessToken;
		} else {
			String access_token=HttpXmlClient.getToken();
			map.put("time", nowDate + "");
			map.put("access_token", access_token);
			result = access_token;
			}
		return result;
	}
	
	public static String getJsapiTicket(String accessToken) {
		String result = "";
		SingletonJsapiTicket singleton = SingletonJsapiTicket.getInstance();
		Map<String, String> map = singleton.getMap();
		String time = map.get("time");
		String jsapiTicket = map.get("jsapi_ticket");
		Long nowDate = new Date().getTime();
		if (jsapiTicket != null && time != null && nowDate - Long.parseLong(time) < 7000 * 1000) {
			result = jsapiTicket;
		} else {
			String jsapi_ticket=HttpXmlClient.getTicket(accessToken);  
			map.put("time", nowDate + "");
			map.put("jsapi_ticket", jsapi_ticket);
			result = jsapi_ticket;
		}
		return result;
	}
}

Token單例:
import java.util.HashMap;
import java.util.Map;

/**
 * 
 * <pre>
 * <b> token的單例.</b>
 * <b>Description:</b> 
 *    
 * <b>Author:</b> yanhongyu
 * <b>Date:</b> 2017-6-23上午9:34:38
 * <b>Changelog:</b>
 *   ----------------------------------------------------------------------------
 *   Ver   Date                     Detail
 *   ----------------------------------------------------------------------------
 *   1.0   2017-6-23上午9:34:38         new file.
 * </pre>
 */
public class SingletonAccessToken {
	//快取accessToken 和一個 時間
	private Map<String, String> map = new HashMap<String,String>();

	private SingletonAccessToken() {
	}

	private static SingletonAccessToken single = null;

	public static SingletonAccessToken getInstance() {
		if (single == null) {
			single = new SingletonAccessToken();
		}
		return single;
	}

	public Map<String, String> getMap() {
		return map;
	}

	public void setMap(Map<String, String> map) {
		this.map = map;
	}

	public static SingletonAccessToken getSingle() {
		return single;
	}

	public static void setSingle(SingletonAccessToken single) {
		SingletonAccessToken.single = single;
	}
}

Ticket單例:
import java.util.HashMap;
import java.util.Map;

/**
 * 
 * <pre>
 * <b> ticket的單例.</b>
 * <b>Description:</b> 
 *    
 * <b>Author:</b> yanhongyu
 * <b>Date:</b> 2017-6-23上午9:34:38
 * <b>Changelog:</b>
 *   ----------------------------------------------------------------------------
 *   Ver   Date                     Detail
 *   ----------------------------------------------------------------------------
 *   1.0   2017-6-23上午9:34:38         new file.
 * </pre>
 */
public class SingletonJsapiTicket {
	//快取jsapi_ticket 和一個 時間
	private Map<String, String> map = new HashMap<String,String>();

	private SingletonJsapiTicket() {
	}

	private static SingletonJsapiTicket single = null;

	public static SingletonJsapiTicket getInstance() {
		if (single == null) {
			single = new SingletonJsapiTicket();
		}
		return single;
	}

	public Map<String, String> getMap() {
		return map;
	}

	public void setMap(Map<String, String> map) {
		this.map = map;
	}

	public static SingletonJsapiTicket getSingle() {
		return single;
	}

	public static void setSingle(SingletonJsapiTicket single) {
		SingletonJsapiTicket.single = single;
	}
}

jsp頁面:
  <script src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>  
<%--通過config介面注入許可權驗證配置--%>    
     <script>    
      wx.config({  
            debug: false,   
            appId: '${params.appId}',  
            timestamp: '${params.timestamp}',  
            nonceStr: '${params.noncestr}',   
            signature:'${params.signature}',  
            jsApiList: [  
                'onMenuShareTimeline',  
                'onMenuShareAppMessage',  
                'onMenuShareQQ',  
                'onMenuShareWeibo',  
                'onMenuShareQZone'    
            ]  
        });  
         wx.ready(function(){  
        wx.checkJsApi({  
            jsApiList: [  
                'onMenuShareTimeline',  
                'onMenuShareAppMessage',  
                'onMenuShareQQ',  
                'onMenuShareWeibo',  
                'onMenuShareQZone'      
            ]  
        });  
            wx.checkJsApi({  
                jsApiList: [  
                    'onMenuShareTimeline',  
                    'onMenuShareAppMessage',  
                    'onMenuShareQQ',  
                    'onMenuShareWeibo',  
                    'onMenuShareQZone'      
                ]  
            });  
        /*分享到朋友圈*/  
        wx.onMenuShareTimeline({  
            title: '', // 分享標題  
            desc: '', // 分享描述  
            link: '${fenxurl}', // 分享連結  
            imgUrl: '', // 分享圖示  
            success: function () {   
                // 使用者確認分享後執行的回撥函式  
            },  
            cancel: function () {   
                // 使用者取消分享後執行的回撥函式  
            }  
        });  
        /*分享給朋友*/  
        wx.onMenuShareAppMessage({  
            title: '近', // 分享標題  
            desc: '', // 分享描述  
            link: '${fenxurl}', // 分享連結  
            imgUrl: '', // 分享圖示  
            type: 'link', // 分享型別,music、video或link,不填預設為link  
            dataUrl: '', // 如果type是music或video,則要提供資料鏈接,預設為空  
            success: function () {   
                // 使用者確認分享後執行的回撥函式  
                alert("感謝您的分享");  
            },  
            cancel: function () {   
                 // 使用者取消分享後執行的回撥函式  
                alert('您已取消分享');  
            }  
        });  
        wx.onMenuShareQQ({  
            title: '', // 分享標題  
            desc: '', // 分享描述  
            link: '${fenxurl}', // 分享連結  
            imgUrl: '', // 分享圖示  
            success: function () {   
               // 使用者確認分享後執行的回撥函式  
            },  
            cancel: function () {   
               // 使用者取消分享後執行的回撥函式  
            }  
        });  
        wx.onMenuShareWeibo({  
            title: '', // 分享標題  
            desc: '', // 分享描述  
            link: '${fenxurl}', // 分享連結  
            imgUrl: '', // 分享圖示  
            success: function () {   
               // 使用者確認分享後執行的回撥函式  
            },  
            cancel: function () {   
                // 使用者取消分享後執行的回撥函式  
            }  
        });  
        wx.onMenuShareQZone({  
            title: '', // 分享標題  
            desc: '', // 分享描述  
            link: '${fenxurl}', // 分享連結  
            imgUrl: '', // 分享圖示  
            success: function () {   
               // 使用者確認分享後執行的回撥函式  
            },  
            cancel: function () {   
                // 使用者取消分享後執行的回撥函式  
            }  
        });  
     }); 
    </script>   

完成以上步驟,完成微信公眾號網頁分享功能開發,最後上圖。


注意:

     1、簽名時的url是當前網頁的路徑,一定要一模一樣不然會導致簽名無效。

     2、分享頁面的域名要是安全域名下的路徑

     3、分享路徑和分享圖片路徑一定要正確,如果是404連結會導致分享失敗,查程式碼時會發現都沒問題,然而就不成功。