贴几个不错的链接:
http://www.cnblogs.com/backtozero/p/7064247.html
有一个问题一直无法解决,就是在本地测试的时候,除非前后端代码在一起,不然通过内网映射以后,前端代码无法使用。
在微信开发的过程中遇到了分享时自定义标题和图片的需求,通过微信分享的链接会出现无法指定标题和说明以及图片。
下面贴出代码:
package com.ruhr.ow.module.vote.util;
import com.alibaba.fastjson.JSONObject;
import com.ruhr.core.data.mysql.multiple.logging.LogUtils;
import com.ruhr.core.utils.StringUtils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* 获取微信帮助类.
*
* @author yi wei
* @date create in 2019/1/17 19:32 *
**/
@RestController
public class WeChatUtil {
private Logger log = LogUtils.getLogger(WeChatUtil.class);
private static final String APPID = "wx3b8fa9fddd320ab6";
private static final String APP_SECRET = "9213714edeebde5a22e37db96dda9f82";
private String accessToken;
private String jsApiTicket;
private Long getTiketTime = 0L;
private Long getTokenTime = 0L;
private Long tokenExpireTime = 0L;
private Long ticketExpireTime = 0L;
/**
* 获取微信参数.
**/
@RequestMapping("/wechatParam")
@ResponseBody
public Map<String, String> getWechatParam(String url) {
//当前时间
long now = System.currentTimeMillis();
log.info("currentTime====>" + now + "ms");
//判断accessToken是否已经存在或者token是否过期
if (StringUtils.isBlank(accessToken) || (now - getTokenTime > tokenExpireTime * 1000)) {
JSONObject tokenInfo = getAccessToken();
if (tokenInfo != null) {
log.info("tokenInfo====>" + tokenInfo.toJSONString());
accessToken = tokenInfo.getString("access_token");
tokenExpireTime = tokenInfo.getLongValue("expires_in");
//获取token的时间
getTokenTime = System.currentTimeMillis();
log.info("accessToken====>" + accessToken);
log.info("tokenExpireTime====>" + tokenExpireTime + "s");
log.info("getTokenTime====>" + getTokenTime + "ms");
} else {
log.info("====>tokenInfo is null~");
log.info("====>failure of getting tokenInfo,please do some check~");
}
}
//判断jsApiTicket是否已经存在或者是否过期
if (StringUtils.isBlank(jsApiTicket) || (now - getTiketTime > ticketExpireTime * 1000)) {
JSONObject ticketInfo = getJsApiTicket();
if (ticketInfo != null) {
log.info("ticketInfo====>" + ticketInfo.toJSONString());
jsApiTicket = ticketInfo.getString("ticket");
ticketExpireTime = ticketInfo.getLongValue("expires_in");
getTiketTime = System.currentTimeMillis();
log.info("jsApiTicket====>" + jsApiTicket);
log.info("ticketExpireTime====>" + ticketExpireTime + "s");
log.info("getTiketTime====>" + getTiketTime + "ms");
} else {
log.info("====>ticketInfo is null~");
log.info("====>failure of getting tokenInfo,please do some check~");
}
}
//生成微信权限验证的参数
Map<String, String> wechatParam = makeWXTicket(jsApiTicket, url);
return wechatParam;
}
private JSONObject getAccessToken() {
String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
String requestUrl = accessTokenUrl.replace("APPID", APPID).replace("APPSECRET", APP_SECRET);
log.info("getAccessToken.requestUrl====>" + requestUrl);
return httpsRequest(requestUrl, "GET", null);
}
private JSONObject getJsApiTicket() {
String apiTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
String requestUrl = apiTicketUrl.replace("ACCESS_TOKEN", accessToken);
log.info("getJsApiTicket.requestUrl====>" + requestUrl);
return httpsRequest(requestUrl, "GET", null);
}
//生成微信权限验证的参数
public Map<String, String> makeWXTicket(String jsApiTicket, String url) {
Map<String, String> ret = new HashMap<String, String>();
String nonceStr = createNonceStr();
String timestamp = createTimestamp();
String string1;
String signature = "";
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsApiTicket +
"&noncestr=" + nonceStr +
"×tamp=" + timestamp +
"&url=" + url;
log.info("String1=====>" + string1);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
log.info("signature=====>" + signature);
} catch (NoSuchAlgorithmException e) {
log.error("WeChatController.makeWXTicket=====Start");
log.error(e.getMessage(), e);
log.error("WeChatController.makeWXTicket=====End");
} catch (UnsupportedEncodingException e) {
log.error("WeChatController.makeWXTicket=====Start");
log.error(e.getMessage(), e);
log.error("WeChatController.makeWXTicket=====End");
}
ret.put("url", url);
ret.put("jsapi_ticket", jsApiTicket);
ret.put("nonceStr", nonceStr);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
ret.put("appid", APPID);
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;
}
/**
* 发送https请求.
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
*/
private JSONObject httpsRequest(String requestUrl, String requestMethod,
String outputStr) {
JSONObject jsonObject = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = {new MyX509TrustManagerUtil()};
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
conn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
} catch (ConnectException ce) {
log.error("连接超时:{}", ce);
} catch (Exception e) {
log.error("https请求异常:{}", e);
}
return jsonObject;
}
//生成随机字符串
private static String createNonceStr() {
return UUID.randomUUID().toString();
}
//生成时间戳
private static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
package com.ruhr.ow.module.vote.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* @Author:yiwei@ruhrtec.cn
* @Date: create in 2017/10/18 17:12
* 信任管理器:用于获取acces_token的帮助类(不能删除)
**/
public class MyX509TrustManagerUtil implements X509TrustManager{
// 检查客户端证书
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 检查服务器端证书
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 返回受信任的X509证书数组
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}