网页分享到微信中如何显示标题图,如果自定义标题图,描述
官网接口地址;https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
HttpClientUtil.java
package com.weixin.share; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class HttpClientUtil { private static class SingletonHolder{ private final static HttpClientUtil INSTANCE=new HttpClientUtil(); } private HttpClientUtil(){} public static HttpClientUtil getInstance(){ return SingletonHolder.INSTANCE; } public String get(String url){ CharsetHandler handler = new CharsetHandler("UTF-8"); CloseableHttpClient client = null; try { HttpGet httpget = new HttpGet(new URI(url)); HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); client= httpClientBuilder.build(); client = (CloseableHttpClient) wrapClient(client); return client.execute(httpget, handler); } catch (Exception e) { //e.printStackTrace(); return ""; }finally { try { if(client!=null){ client.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static String post(String url, String params,String contentType) { //创建HttpClientBuilder HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //HttpClient CloseableHttpClient client = httpClientBuilder.build(); client = (CloseableHttpClient) wrapClient(client); HttpPost post = new HttpPost(url); CloseableHttpResponse res = null; try { StringEntity s = new StringEntity(params,"UTF-8"); if(StringUtils.isBlank(contentType)){ s.setContentType("application/json"); } s.setContentType(contentType); s.setContentEncoding("utf-8"); post.setEntity(s); res = client.execute(post); HttpEntity entity = res.getEntity(); return EntityUtils.toString(entity, "utf-8"); } catch (Exception e) { e.printStackTrace(); } finally { try { res.close(); client.close(); } catch (IOException e) { e.printStackTrace(); } } return ""; } public static String post(String urlStr,String xmlInfo) { String line1 = ""; try { URL url = new URL(urlStr); URLConnection con = url.openConnection(); con.setDoOutput(true); //con.setRequestProperty("Pragma:", "no-cache"); con.setRequestProperty("Cache-Control", "no-cache"); con.setRequestProperty("Content-Type", "text/xml"); OutputStreamWriter out = new OutputStreamWriter(con .getOutputStream()); out.write(new String(xmlInfo.getBytes("utf-8"))); out.flush(); out.close(); BufferedReader br = new BufferedReader(new InputStreamReader(con .getInputStream())); String line = ""; for (line = br.readLine(); line != null; line = br.readLine()) { line1+=line; } return new String(line1.getBytes(),"utf-8"); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private class CharsetHandler implements ResponseHandler<String> { private String charset; public CharsetHandler(String charset) { this.charset = charset; } public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException { StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() >= 300) { throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); } HttpEntity entity = response.getEntity(); if (entity != null) { if (!StringUtils.isBlank(charset)) { return EntityUtils.toString(entity, charset); } else { return EntityUtils.toString(entity); } } else { return null; } } } private static HttpClient wrapClient(HttpClient base) { try { SSLContext ctx = SSLContext.getInstance("TLSv1"); X509TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; ctx.init(null, new TrustManager[] { tm }, null); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); return httpclient; } catch (Exception ex) { return null; } } }
RandomStr.java
package com.weixin.share; import java.util.Random; public class RandomStr { private static char ch[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1' };//最后又重复两个0和1,因为需要凑足数组长度为64 private static Random random = new Random(); //生成指定长度的随机字符串 public static String createRandomString(int length) { if (length > 0) { int index = 0; char[] temp = new char[length]; int num = random.nextInt(); for (int i = 0; i < length % 5; i++) { temp[index++] = ch[num & 63];//取后面六位,记得对应的二进制是以补码形式存在的。 num >>= 6;//63的二进制为:111111 // 为什么要右移6位?因为数组里面一共有64个有效字符。为什么要除5取余?因为一个int型要用4个字节表示,也就是32位。 } for (int i = 0; i < length / 5; i++) { num = random.nextInt(); for (int j = 0; j < 5; j++) { temp[index++] = ch[num & 63]; num >>= 6; } } return new String(temp, 0, length); } else if (length == 0) { return ""; } else { throw new IllegalArgumentException(); } } public static void main(String[] args) { System.out.println(createRandomString(16)); } }
Sha1.java
package com.weixin.share; import java.security.MessageDigest; public class Sha1 { private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; private static String getFormattedText(byte[] bytes) { int len = bytes.length; StringBuilder buf = new StringBuilder(len * 2); // 把密文转换成十六进制的字符串形式 for (int j = 0; j < len; j++) { buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); buf.append(HEX_DIGITS[bytes[j] & 0x0f]); } return buf.toString(); } public static String encode(String str) { if (str == null) { return null; } try { MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); messageDigest.update(str.getBytes()); return getFormattedText(messageDigest.digest()); } catch (Exception e) { throw new RuntimeException(e); } } }
控制器类
package com.weixin.share; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.json.JSONException; import org.json.JSONObject; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.net.URI; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; public class Test { private String appid="公众号的APP_ID"; private String secret="公众号的APP_SECRET"; /** * 请求方法 方法只写了主要方法,需要根据自己的要求 完善代码 * @param model * @return */ @RequestMapping(value = "/to_detail") public String test( ModelMap model){ long timestamp = System.currentTimeMillis() / 1000; String noncestr = RandomStr.createRandomString(16); String ticket =getJsapiTicket(); String url = "跳转页面所显示URL地址(就是当前请求的完整地址),如果含有参数 也需要把参数加上去 "; String str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url; System.out.println("签名str:" + str); String signature = Sha1.encode(str); model.addAttribute("appid", appid); model.addAttribute("timestamp", timestamp); model.addAttribute("noncestr", noncestr); model.addAttribute("signature", signature); return "跳转到指定页面(这里我用的share.html)"; } public String getJsapiTicket() { String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code"; tokenUrl = tokenUrl + "&appid=" + appid + "&secret=" + secret; JSONObject tokenJson=new JSONObject(); tokenJson=getUrlResponse(tokenUrl); System.out.println("tokenJson:"+tokenJson.toString()); String token=""; try { token=tokenJson.getString("access_token"); } catch (JSONException e) { e.printStackTrace(); System.out.println("报错了"); return null; } String jsapiTicketUrl="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; JSONObject jsapiTickeJson=new JSONObject(); System.out.println("getJsapiTicket:获取token:"+token); if(StringUtils.isNotBlank(token)){ jsapiTicketUrl = jsapiTicketUrl.replace("ACCESS_TOKEN",token); jsapiTickeJson=getUrlResponse(jsapiTicketUrl); System.out.println("tokenJson:"+jsapiTickeJson.toString()); try { return (String) jsapiTickeJson.get("ticket"); } catch (JSONException e) { e.printStackTrace(); return null; } }else{ return null; } } private JSONObject getUrlResponse(String url){ CharsetHandler handler = new CharsetHandler("UTF-8"); try { HttpGet httpget = new HttpGet(new URI(url)); HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //HttpClient CloseableHttpClient client = httpClientBuilder.build(); client = (CloseableHttpClient) wrapClient(client); return new JSONObject(client.execute(httpget, handler)); } catch (Exception e) { e.printStackTrace(); return null; } } private static HttpClient wrapClient(HttpClient base) { try { SSLContext ctx = SSLContext.getInstance("TLSv1"); X509TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; ctx.init(null, new TrustManager[] { tm }, null); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); return httpclient; } catch (Exception ex) { return null; } } private class CharsetHandler implements ResponseHandler<String> { private String charset; public CharsetHandler(String charset) { this.charset = charset; } public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException { StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() >= 300) { throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); } HttpEntity entity = response.getEntity(); if (entity != null) { if (!StringUtils.isBlank(charset)) { return EntityUtils.toString(entity, charset); } else { return EntityUtils.toString(entity); } } else { return null; } } } }
页面主要代码、这里展示的是分享到朋友圈代码,其他分享可以具体看官方接口代码
share.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1.0,width=device-width,user-scalable=no" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="format-detection" content="telephone=no, email=no" /> <title>分享到朋友圈</title> <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script> <script> var latitudes = "null"; var longitudes = "null"; $(function () { wx.config({ debug: false, appId: '${appid!}', timestamp: '${timestamp!}', nonceStr: '${noncestr!}', signature: '${signature!}', jsApiList: [ 'checkJsApi', 'getLocation' ] }); wx.ready(function () { //需在用户可能点击分享按钮前就先调用 wx.updateTimelineShareData({ title: '', // 分享标题 link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: '', // 分享图标 success: function () { // 设置成功 } }) }); wx.error(function (res) { //alert(res.errMsg); }); }); </script> </head> <body> </body> </html>