Java微信分享接口開(kāi)發(fā)詳解
本文實(shí)例為大家分享了Java微信分享接口開(kāi)發(fā)的具體代碼,供大家參考,具體內(nèi)容如下
Java微信分享,步驟是
1、根據(jù)當(dāng)前的url,獲取signature,nonceStr,timestamp 和appId。
2、通過(guò)signature,nonceStr,timestamp 和appId來(lái)配置微信 wx.config。
3、通過(guò)wx.ready實(shí)現(xiàn)微信分享功能。
1、html端
引入微信JS-SDK.
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
//分享核心js代碼
$(document).ready(function () {
//通過(guò)ajax,在頁(yè)面加載的時(shí)候獲取微信分享接口signature,nonceStr,timestamp 和appId
$.ajax({
type: "post",
url: "/weixin/share",
dataType: "json",
data:"url="+window.location.href,
success: function (data) {
wx.config({
debug: false,
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline', 'hideAllNonBaseMenuItem', 'showMenuItems']
// 功能列表,我們要使用JS-SDK的什么功能
});
wx.ready(function () {
// 獲取“分享給朋友”按鈕點(diǎn)擊狀態(tài)及自定義分享內(nèi)容接口
wx.onMenuShareAppMessage({
title: "分享自定義標(biāo)題", // 分享標(biāo)題
desc: "分享自定義描述", // 分享描述
link: "http://localhost/weixin/share?openId=1",//分享點(diǎn)擊之后的鏈接
imgUrl:'/images/photo/1.jpg', // 分享圖標(biāo)
type: 'link', // 分享類型,music、video或link,不填默認(rèn)為link
success: function () {
//成功之后的回調(diào)
}
});
wx.hideAllNonBaseMenuItem();
wx.showMenuItems({
menuList: ['menuItem:share:appMessage', 'menuItem:share:timeline'] // 要隱藏的菜單項(xiàng),只能隱藏“傳播類”和“保護(hù)類”按鈕,所有menu項(xiàng)見(jiàn)附錄3
});
wx.onMenuShareTimeline({
title: "分享自定義標(biāo)題", // 分享標(biāo)題
desc: "分享自定義描述", // 分享描述
link: "http://localhost/weixin/share?openId=1",//分享點(diǎn)擊之后的鏈接
imgUrl:'/images/photo/1.jpg', // 分享圖標(biāo)
type: 'link', // 分享類型,music、video或link,不填默認(rèn)為link
success: function () {
//成功之后的回調(diào)
}
cancel: function () {
// 用戶取消分享后執(zhí)行的回調(diào)函數(shù)
}
});
});
wx.error(function (res) {
//打印錯(cuò)誤消息。及把 debug:false,設(shè)置為debug:ture就可以直接在網(wǎng)頁(yè)上看到彈出的錯(cuò)誤提示
});
}
})
});
2、Java代碼,獲取 signature,nonceStr,timestamp 和appId
@RequestMapping(value = "/share", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> share(HttpServletRequest request) {
String urlTemp = "http://" + request.getServerName() + request.getContextPath();
String urlpath = "http://" + request.getServerName();
String appUrl = request.getParameter("url");
if (request.getParameter("code") != null) {
appUrl += "&code=" + request.getParameter("code");
}
if (request.getParameter("state") != null) {
appUrl += "&state=" + request.getParameter("state");
}
return WxConfigUtil.getSignature(appUrl, ContentValues.APPID, ContentValues.SECRET, urlTemp, urlpath);
}
工具類我就把整個(gè)貼上來(lái)了,其中有些方法是沒(méi)有用到的。
getSignature()整個(gè)方法是微信分享中的核心方法,用來(lái)獲取signature,nonceStr,timestamp 和appId這幾個(gè)核心參數(shù)。
package com.blog.common.util;
import com.alibaba.fastjson.JSONObject;
import com.blog.common.model.Token;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 公眾平臺(tái)通用接口工具類
*
* @author james
* @date 2015-02-27
*/
public class WxConfigUtil {
// 獲取access_token的接口地址(GET) 限2000(次/天)
public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
// 獲取jsapi_ticket的接口地址(GET) 限2000(次/天)
public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
// 緩存添加的時(shí)間
public static String cacheAddTime = null;
// token,ticket緩存
public static Map<String, Token> TOKEN_TICKET_CACHE = new HashMap<String, Token>();
// token對(duì)應(yīng)的key
private static final String TOKEN = "token";
// ticket對(duì)應(yīng)的key
private static final String TICKET = "ticket";
/**
* 外部獲取簽名入口類
*
* @param appUrl 應(yīng)用的url
* @return
*/
public static Map<String, Object> getSignature(String appUrl, String appId, String secret, String url, String urlpath) {
// 生成簽名的隨機(jī)串
String noncestr = RandomUtil.getStringRandom(4);
if (appUrl == null || "".equals(appUrl)) {
return null;
}
String signature = null;
Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
Token accessTicket = getTicket(accessTocken.getToken(), System.currentTimeMillis() / 1000);
signature = signature(accessTicket.getTicket(), cacheAddTime, noncestr, appUrl);
System.out.println("-=-=-=-=-=-=-=-=appUrl:" + appUrl);
System.out.println("-=-=-=-=-=-=-=-=token:" + accessTocken.getToken());
System.out.println("-=-=-=-=-=-=-=-=ticket:" + accessTicket.getTicket());
System.out.println("-=-=-=-=-=-=-=-=signature:" + signature);
System.out.println("-=-=-=-=-=-=-=-=timestamp:" + cacheAddTime);
Map<String, Object> map = new HashMap<>();
map.put("appId", appId);
map.put("timestamp", cacheAddTime);
map.put("nonceStr", noncestr);
map.put("appUrl", appUrl);
map.put("signature", signature);
map.put("url", url);
map.put("urlpath", urlpath);
return map;
}
/**
* 獲得Token
*
* @return
*/
public static String getToken(String appId, String secret) {
Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
return accessTocken.getToken();
}
/**
* 簽名
*
* @param timestamp
* @return
*/
private static String signature(String jsapi_ticket, String timestamp, String noncestr, String url) {
jsapi_ticket = "jsapi_ticket=" + jsapi_ticket;
timestamp = "timestamp=" + timestamp;
noncestr = "noncestr=" + noncestr;
url = "url=" + url;
String[] arr = new String[]{jsapi_ticket, noncestr, timestamp, url};
// 將token、timestamp、nonce,url參數(shù)進(jìn)行字典序排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
if (i != arr.length - 1) {
content.append("&");
}
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 將三個(gè)參數(shù)字符串拼接成一個(gè)字符串進(jìn)行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
content = null;
return tmpStr;
}
/**
* 獲取access_token
*
* @param appid 憑證
* @param appsecret 密鑰
* @return
*/
public static Token getToken(String appid, String appsecret, long currentTime) {
Token tockenTicketCache = getTokenTicket(TOKEN);
Token Token = null;
if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 緩存存在并且沒(méi)過(guò)期
System.out.println("==========緩存中token已獲取時(shí)長(zhǎng)為:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
return tockenTicketCache;
}
System.out.println("==========緩存中token不存在或已過(guò)期===============");
String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果請(qǐng)求成功
if (null != jsonObject) {
Token = new Token();
Token.setToken(jsonObject.getString("access_token"));
Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常過(guò)期時(shí)間是7200秒,此處設(shè)置3600秒讀取一次
System.out.println("==========tocket緩存過(guò)期時(shí)間為:" + Token.getExpiresIn() + "毫秒");
Token.setAddTime(currentTime);
updateToken(TOKEN, Token);
}
return Token;
}
/**
* 獲取ticket
*
* @param token
* @return
*/
private static Token getTicket(String token, long currentTime) {
Token tockenTicketCache = getTokenTicket(TICKET);
Token Token = null;
if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresIn())) {// 緩存中有ticket
System.out.println("==========緩存中ticket已獲取時(shí)長(zhǎng)為:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
return tockenTicketCache;
}
System.out.println("==========緩存中ticket不存在或已過(guò)期===============");
String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果請(qǐng)求成功
if (null != jsonObject) {
Token = new Token();
Token.setTicket(jsonObject.getString("ticket"));
Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);// 正常過(guò)期時(shí)間是7200秒,此處設(shè)置3600秒讀取一次
System.out.println("==========ticket緩存過(guò)期時(shí)間為:" + Token.getExpiresIn() + "毫秒");
Token.setAddTime(currentTime);
updateToken(TICKET, Token);
}
return Token;
}
/**
* 發(fā)起https請(qǐng)求并獲取結(jié)果
*
* @param requestUrl 請(qǐng)求地址
* @param requestMethod 請(qǐng)求方式(GET、POST)
* @param outputStr 提交的數(shù)據(jù)
* @return JSONObject(通過(guò)JSONObject.get(key)的方式獲取json對(duì)象的屬性值)
*/
private static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 創(chuàng)建SSLContext對(duì)象,并使用我們指定的信任管理器初始化
TrustManager[] tm = {new MyX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 從上述SSLContext對(duì)象中得到SSLSocketFactory對(duì)象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 設(shè)置請(qǐng)求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 當(dāng)有數(shù)據(jù)需要提交時(shí)
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意編碼格式,防止中文亂碼
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 將返回的輸入流轉(zhuǎn)換成字符串
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());
// jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
System.out.println("Weixin server connection timed out.");
} catch (Exception e) {
System.out.println("https request error:{}" + e.getMessage());
}
return jsonObject;
}
/**
* 將字節(jié)數(shù)組轉(zhuǎn)換為十六進(jìn)制字符串
*
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 將字節(jié)轉(zhuǎn)換為十六進(jìn)制字符串
*
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
/**
* 從緩存中讀取token或者ticket
*
* @return
*/
private static Token getTokenTicket(String key) {
if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
System.out.println("==========從緩存中獲取到了" + key + "成功===============");
return TOKEN_TICKET_CACHE.get(key);
}
return null;
}
/**
* 更新緩存中token或者ticket
*
* @return
*/
private static void updateToken(String key, Token accessTocken) {
if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
TOKEN_TICKET_CACHE.remove(key);
System.out.println("==========從緩存中刪除" + key + "成功===============");
}
TOKEN_TICKET_CACHE.put(key, accessTocken);
cacheAddTime = String.valueOf(accessTocken.getAddTime());// 更新緩存修改的時(shí)間
System.out.println("==========更新緩存中" + key + "成功===============");
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java動(dòng)態(tài)驗(yàn)證碼單線設(shè)計(jì)的兩種方法
這篇文章主要介紹了Java動(dòng)態(tài)驗(yàn)證碼單線設(shè)計(jì)的兩種方法,需要的朋友可以參考下2018-07-07
Spring Security認(rèn)證提供程序示例詳解
這篇文章主要給大家介紹了關(guān)于Spring Security認(rèn)證提供程序的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Security具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
SpringBoot+websocket實(shí)現(xiàn)消息對(duì)話功能
WebSocket是一種在Web應(yīng)用程序中實(shí)現(xiàn)實(shí)時(shí)雙向通信的技術(shù),它可以用于在線游戲、在線聊天、推送通知、實(shí)時(shí)監(jiān)控等,并且比傳統(tǒng)的輪詢技術(shù)更加高效和可靠,本文就給大家介紹基于SpringBoot+websocket實(shí)現(xiàn)消息對(duì)話功能,感興趣的小伙伴可以自己動(dòng)手試一試2023-09-09
Java Swing SpringLayout彈性布局的實(shí)現(xiàn)代碼
這篇文章主要介紹了Java Swing SpringLayout彈性布局的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12

