直接上干货
1. 首先你需要有一个可以访问的外网IP(需要和域名绑定(这个绑定就是域名解析。)) 直接Java代码
package org.jeecg.modules.wx.controller;
import com.alibaba.fastjson.JSONObject;
import io.micrometer.core.instrument.util.StringUtils;
import io.swagger.annotations.Api;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.wx.util.HttpClientUtils;
import org.jeecg.modules.wx.util.SignUtil;
import org.jeecg.modules.zz.bstCompanyAccount.entity.BstCompanyAccount;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.util.*;
@Api(tags = "微信相关接口")
@RestController
@RequestMapping("/wx")
public class GetWx {
public static String appid = "wx12****1";
public static String appsecret = "445d***1349d1";
@PostMapping("/Get_access_token")
public Result<?> Get_access_token(String code) throws IOException {
// 第二步:通过code换取网页授权access_token
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
JSONObject jsonObject = HttpClientUtils.doGet(url);
String access_Token = jsonObject.getString("access_token");
System.out.println(access_Token + "--------" + code);
return Result.OK(access_Token);
}
@PostMapping("/getticket")
public Result<?> getticket(String code) throws IOException {
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
JSONObject jsonObject = HttpClientUtils.doGet(url);
String ACCESS_TOKEN = jsonObject.getString("access_token");
String url2 = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + ACCESS_TOKEN + "&type=jsapi";
JSONObject jsonObject2 = HttpClientUtils.doGet(url2);
return Result.OK(jsonObject2);
}
//其实上面两个接口可以同时并到 下面这个接口中
/**
* 对string1进行sha1签名,得到signature:
*
*
* @return
* @throws IOException
*/
@PostMapping("/getSha1")
public Result<?> getSha1(String ticket, String url) throws Exception {
//获取access_token
// String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
// JSONObject jsonObject = HttpClientUtils.doGet(accessTokenUrl);
// String ACCESS_TOKEN = jsonObject.getString("access_token");
// //获取Ticket
// String getTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + ACCESS_TOKEN + "&type=jsapi";
// JSONObject jsonObject2 = HttpClientUtils.doGet(getTicketUrl);
// String ticket = (String) jsonObject2.get("ticket");
Map<String,String> paraMap = new HashMap<String,String>();
paraMap.put("jsapi_ticket",ticket);
paraMap.put("noncestr", create_nonce_str(16));
paraMap.put("timestamp", create_timestamp());
paraMap.put("url",url);
String string1 = getSign(paraMap);
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
paraMap.put("signature",byteToHex(crypt.digest()));
System.out.println(paraMap.toString());
return Result.ok(paraMap);
}
public static String getSign(Map<String, String> params) {
Map<String, String> sortMap = new TreeMap<String, String>();
sortMap.putAll(params);
// 以k1=v1&k2=v2...方式拼接参数
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, String> s : sortMap.entrySet()) {
String k = s.getKey();
String v = s.getValue();
if (StringUtils.isBlank(v)) {// 过滤空值
continue;
}
builder.append(k).append("=").append(v).append("&");
}
if (!sortMap.isEmpty()) {
builder.deleteCharAt(builder.length() - 1);
}
return builder.toString();
}
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(int length) {
String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random=new Random();
StringBuffer sb=new StringBuffer();
for(int i=0;i<length;i++){
int number=random.nextInt(62);
sb.append(str.charAt(number));
}
return sb.toString();
}
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
工具类
package org.jeecg.modules.wx.util;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jeecgframework.poi.util.MyX509TrustManager;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.URL;
public class HttpClientUtils {
public static String httpsRequest(String requestUrl,String requestMethod,String outputStr){
StringBuffer buffer=null;
try{
//创建SSLContext
SSLContext sslContext= SSLContext.getInstance("SSL");
TrustManager[] tm={new MyX509TrustManager()};
//初始化
sslContext.init(null, tm, new java.security.SecureRandom());;
//获取SSLSocketFactory对象
SSLSocketFactory ssf=sslContext.getSocketFactory();
URL url=new URL(requestUrl);
HttpsURLConnection conn=(HttpsURLConnection)url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestMethod(requestMethod);
//设置当前实例使用的SSLSoctetFactory
conn.setSSLSocketFactory(ssf);
conn.connect();
//往服务器端写内容
if(null!=outputStr){
OutputStream os=conn.getOutputStream();
os.write(outputStr.getBytes("utf-8"));
os.close();
}
//读取服务器端返回的内容
InputStream is=conn.getInputStream();
InputStreamReader isr=new InputStreamReader(is,"utf-8");
BufferedReader br=new BufferedReader(isr);
buffer=new StringBuffer();
String line=null;
while((line=br.readLine())!=null){
buffer.append(line);
}
}catch(Exception e){
e.printStackTrace();
}
return buffer.toString();
}
/**
* 发起一个GET请求, 返回数据是以JSON格式返回
* @param url
* @return
* @throws IOException
*/
public static JSONObject doGet(String url) throws IOException {
JSONObject jsonObject = null;
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity, "UTF-8");
jsonObject = JSONObject.parseObject(result);
}
httpGet.releaseConnection();
return jsonObject;
}
}
2. 需要配置你 业务域名 JS接口安全域名 网页授权域名 IP白名单(千万要注意域名这里www.xxx.com 和 xxxx.com 是不一样的,本人就是在这里踩坑了)
3. 前端js 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>分享</h1>
<button class="btn">分享</button>
<script src="./jweixin-1.6.0.js"></script>
<script src="./jquery-3.2.1.js"></script>
<script>
const URL = "https://***.com/jeecg-boot/"
const APPID = "wx***e81";
const APPSECRET = "445****1";
//获取 GetAccessToken
function GetAccessToken() {
return $.ajax({
url: URL + "/wx/Get_access_token",
type: "post",
success(res) {
}
})
}
//获取 getTicket
function getTicket(ACCESS_TOKEN) {
return $.ajax({
url: URL + "/wx/getticket?ACCESS_TOKEN=" + ACCESS_TOKEN,
type: "post",
success(res) {
}
})
}
function getSha1(ticket) {
let urlParams = decodeURIComponent(location.href.split('#'));
console.error(location.href.split('#'))
return $.ajax({
url: URL + `/wx/getSha1?url=${urlParams}&ticket=${ticket}`,
method: "post",
async: false,
success(res) {
console.log(res)
let data = res.result
}
})
}
async function init() {
let ACCESS_TOKEN = await GetAccessToken()
console.log("GetAccessToken", ACCESS_TOKEN.result)
let ticket = await getTicket(ACCESS_TOKEN.result)
console.log("ticket", ticket.result.ticket)
// ACCESS_TOKEN.result.ticket
let signature = await getSha1(ticket.result.ticket)
console.log("signature", signature.result)
let data = signature.result
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: "wx1239d9ad87f2ae81", // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.noncestr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline', 'onMenuShareQQ']
})
wx.ready(function(){
wx.onMenuShareTimeline({
title: '这是标题', // 分享标题
link: 'https://***.com/home/newList/newInfo?id=1476123610963910657', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: 'https://***.com:9000/jeecg-boot/temp/5_1629256461497.png', // 分享图标
success: function () {
// 设置成功
}
})
})
}
init()
</script>
</body>
</html>