最近公司项目要求自定义微信分享样式,我就接手了这个微信JSSDK的接口调用。
首先你要有一个公众号。
然后需要在公众号的设置-公众号设置-功能设置
设置我们的安全域名。
我们把文件下载下来,然后放到我们填写的域名,注意:一定要放在你要调用微信的接口的路径下一,只能是域名后跟一个目录,
我们要调用的页面必须是在这个目录下的子目录或者这个目录下。还有如果你用的是SpringMVC的话请对这个域名下的静态资源进行处理。因为微信要去判断你填写的这个域名下是否有这个文件。
这一步完成之后我们进入 开发-基础配置-服务器配置
首先我们需要对我们服务器的IP地址加入白名单。
去启用的我们的服务器信息,这个服务器必须是你要调用微信的JSSDK的项目服务器。
首先说下这个URL,这个URL必须要能接受微信发送的请求
微信服务器会给你发送一个请求,这个请求有几个参数
分别是:signature timestamp nonce echostr
拿到这四个参数之后,需要将 你在页面中写Token,nonce,timestamp 放入到一个String数组里面,然后进行sort排序,
排序完成之后将这三个字符串进行拼接,然后使用SHA-1算法进行加密,将加密后的结果与echostr进行比较,相同返回微信发给你的echostr
具体代码:
@RequestMapping(value="getToken",method=RequestMethod.GET)
public @ResponseBody String getToken(String signature,String timestamp,String nonce,String echostr) throws NoSuchAlgorithmException{
String[] array ={wxToken,nonce,timestamp};
Arrays.sort(array);
String newArray="";
for (int i = 0; i < array.length; i++) {
newArray+=array[i];
}
//SHA-1加密
MessageDigest instance = MessageDigest.getInstance("SHA-1");
instance.update(newArray.getBytes());
byte[] digest = instance.digest();
StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
if(hexstr.equals(signature)){
return echostr;//相同返回微信发给我们的echostr
}
return "erro";
}
此时就可以完成认证了。
然后是页面:
var wxObjet;
href=encodeURIComponent(window.location.href)//这个参数是用来获取当前页面的url
$.ajax({
url:用来提供配置权限信息的一个Controller/href,
type:"get",
dataType:"json",
async: false,
success:function(data){
wxObjet=data;
}
})
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: wxObjet.aapid, // 必填,公众号的唯一标识
timestamp: wxObjet.timestamp, // 必填,生成签名的时间戳
nonceStr: wxObjet.noncestr, // 必填,生成签名的随机串
signature: wxObjet.Signature,// 必填,签名
jsApiList: ["onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ"] // 必填,需要使用的JS接口列表
});
然后看后台代码:
@RequestMapping("getJsapi")
public @ResponseBody Map getJsapi(String url//就是你发送请求的页面){
Map map=new HashMap();
try {
//微信JSSDK Acces_token和jsapi的全局缓存
//因为微信的Token和jsapi30分钟内有效,每天只能获取2000次,所以我们要加上缓存。
String token ="";
String jsapi_ticket ="";
Map mes = (Map)redisTemplate.opsForValue().get("mes");
Map redis=mes;
if(mes==null){
redis=new HashMap();
token=CommonUtil.getToken(appid, appsecret);//写一个工具类,用来给微信发送请求,请求所需参数:appid,和AppSecret,下面有代码
jsapi_ticket= CommonUtil.getJsapi_ticket(token);//拿到微信给我们的token之后我们去获取jsapi_ticket.下,下面有代码
//放入ticket
redis.put("ticket",jsapi_ticket);
redis.put("ticketDate",new Date().getTime());
//放入token
redis.put("token",token);
redis.put("tokenDate",new Date().getTime());
redisTemplate.opsForValue().set("mes", redis);
}else{
long tokenDate=(long)mes.get("tokenDate");
if(new Date().getTime()-tokenDate>=1200000){
token=CommonUtil.getToken(appid, appsecret);
//放入token
System.out.println(token);
redis.put("token",token);
redis.put("tokenDate",new Date().getTime());
}else{
token=(String) mes.get("token");
}
long ticketDate=(long)mes.get("ticketDate");
if(new Date().getTime()-ticketDate>=1200000){
jsapi_ticket= CommonUtil.getJsapi_ticket(token);
//放入ticket
redis.put("ticket",jsapi_ticket);
redis.put("ticketDate",new Date().getTime());
}else{
jsapi_ticket = (String)mes.get("ticket");
}
redisTemplate.opsForValue().set("mes", redis);
}
//生成一个随机字符,我这里直接用时间戳来代替了
long time = new Date().getTime();
String noncestr = String.valueOf(time);
//时间绰
long time2 = new Date().getTime();
String timestamp=String.valueOf(time2/1000);//微信接收的时间戳是10位的所以咱们要除以1000
//去使用SHA-1获取安全签名 ,下面有代码
String jsSDKSignature = CommonUtil.getJsSDKSignature(jsapi_ticket, noncestr, timestamp, url);
map.put("Signature",jsSDKSignature);//将所有验证权限所需要数据放入一个map,这个是安全签名
map.put("noncestr",noncestr);//这个是随机字符
map.put("aapid",appid);//这个是咱们的APPID
map.put("timestamp", timestamp);//这个是时间戳
return map;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map;
}
工具类代码
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
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.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSON;
/**
* 拿到微信的Access_Tocken
*
* @author liuyk
*
*/
public class CommonUtil {
public static String getToken(String appid, String appSecret) throws ClientProtocolException, IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建参数队列
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("grant_type", "access_token"));
params.add(new BasicNameValuePair("appid", appid));
/* secret */
params.add(new BasicNameValuePair("appid", AppSecret));
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret="
+ appSecret;
// 创建httpget.
HttpGet httpget = new HttpGet(url);
// 发送请求
CloseableHttpResponse response = httpclient.execute(httpget);
// 得到响应提
HttpEntity entity = response.getEntity();
String param = EntityUtils.toString(entity);
System.out.println(param);
// 将JSON转换为Map
Map parseParam = (Map) JSON.parse(param);
Object object = parseParam.get("access_token");
return object.toString();
}
public static String getJsSDKSignature(String jsapi_ticket, String noncestr, String timestamp, String url) {
//这几个参数名按照字典顺序进行拼接
String string = "jsapi_ticket=" + jsapi_ticket;
string += "&noncestr=" + noncestr;
string += "&tamp=" + timestamp;
string += "&url=" + url;
StringBuffer hexstr = new StringBuffer();
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
// 对接后的字符串进行sha1加密
md.update(string.getBytes());
byte[] digest = md.digest();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return hexstr.toString();
}
public static String getJsapi_ticket(String access_token) {
String ticket = "";
String requestUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token
+ "&type=jsapi";
CloseableHttpClient httpclient = HttpClients.createDefault();
// 先从线程中取值,如果取不到,说明没有使用线程,再利用这个方法获取
// 因为发送信息等操作,都是调用的这个方法,所以在这里进行处理一下吧
HttpGet httpget = new HttpGet(requestUrl);
// 发送请求
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpget);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 得到响应提
HttpEntity entity = response.getEntity();
String param = null;
try {
param = EntityUtils.toString(entity);
} catch (ParseException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(param);
// 将JSON转换为Map
Map parseParam = (Map) JSON.parse(param);
Object object = parseParam.get("ticket");
return object.toString();
}
}
//前端的权限认证之后我们把要用的微信接口放入ready回调里面
wx.ready(function(){
/* 分享到朋友圈 */
wx.onMenuShareTimeline({
title: '', // 分享标题
link: '', // 分享链接,这个链接必须是你配置的jssdk的安全域名,如果不是在那个域名或者路径下会没有效果
imgUrl: '', // 同上
});
/*分享给朋友 */
wx.onMenuShareAppMessage({
title: '', // 分享标题
desc: '', // 分享描述
link: '', // 分享链接,该链接域名必须与当前企业的可信域名一致
imgUrl: '', // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
alert("分享成功");
},
cancel: function () {
// 用户取消分享后执行的回调函数
alert("已取消分享");
}
});
以上就是整个流程,如果有什么问题可以来问我,很欢迎帮忙解决。