结果如下,自定义分享链接,分享图片等等...
开始对接
1.JS安全域名
配置路径在:
登录公众号号平台后,-----------进入公众号设置-------功能设置------,如下
JS安全域名强烈建议如下配置:
cylothes.cn
2获取和设置APP_ID,和APP_SECRET
获取:
微信公众号----基本配置----公众号开发信息---下
AppId是唯一的
APPSecret是每次都可以重新设置,丢了可以重设,不用担心
IP白名单,需要设置你线上的,在此可以提醒你一下, ip白名单,可以设置多个,空格隔开,通过内网穿透将您的本地id可以让微信访问,增加你调试的快捷性.
设置:
public class WeChatJsConfig {
public final static String APP_ID = "你的APPID";
public final static String APP_SECRET = "你的秘钥";
public final static String GET_ACCESSTOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
public final static String GET_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
// public static ConcurrentHashMap<String, Object> INTERFACE_URL_PROPERTIES = new ConcurrentHashMap<>();
}
因为accessToken和Ticket 每天只能调用2000次,这里我们选择一个缓存方式即可我这里只做个例子自行参考
------------------------------------------定时更新Token和Ticket-----建议存redis中---------------------------------------------
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @ClassName: 微信jsSDK 定时刷新
* @Descripton:
* @Author: sansy
* @Date: 2019/7/4 15:30
* @Version: 2.0
*/
@Component
@EnableScheduling
public class WeChatTask {
//@Scheduled(cron = "0 0/2 * * * ?")//两分钟
/**
* 每隔两小时执行一次
*/
@Scheduled(cron = "0 0 */2 * * ?")
public void getTokenGetTicket() throws Exception {
System.out.println("WeChatTask-执行一次");
// //通过AppId和Secret获取 Access_token
// Map<String, String> params = new HashMap<String, String>();
// params.put("grant_type", "client_credential");
// params.put("appid", WeChatJsConfig.APP_ID);
// params.put("secret", WeChatJsConfig.APP_SECRET);
//
// //获取accessToken
// String accessTokenStr = HttpClientUtil.sendGet(WeChatJsConfig.GET_ACCESSTOKEN_URL, params);
// HashMap accessTokenMap = JSON.parseObject(accessTokenStr, HashMap.class);
//
// String accessToken = accessTokenMap.get("access_token").toString();
//
// //将结果存入
// WeChatJsConfig.INTERFACE_URL_PROPERTIES.put("accessTokenMap", accessTokenMap);
// System.out.println("1 " + WeChatJsConfig.INTERFACE_URL_PROPERTIES.hashCode());
// WeChatJsConfig.INTERFACE_URL_PROPERTIES.put("accessToken", accessToken);
// System.out.println("2 " + WeChatJsConfig.INTERFACE_URL_PROPERTIES.hashCode());
//
// //1,清空参数集合
// params.clear();
// //传入参数
// params.put("type", "jsapi");
// params.put("access_token", accessToken);
//
// String jsApiTicketMapStr = HttpClientUtil.sendGet(WeChatJsConfig.GET_TICKET_URL, params);
//
// HashMap jsApiTicketMap = JSON.parseObject(jsApiTicketMapStr, HashMap.class);
// String jsApiTicket = jsApiTicketMap.get("ticket").toString();
//
// WeChatJsConfig.INTERFACE_URL_PROPERTIES.put("jsApiTicketMap", jsApiTicketMap);
// WeChatJsConfig.INTERFACE_URL_PROPERTIES.put("jsApiTicket", jsApiTicket);
// }
// @Scheduled(cron = "0 0/1 * * * ?")
// public void testOne() {
// System.out.println("===========================每分钟执行一次===========================");
// }
//
// @Scheduled(fixedRate = 30000)
// public void testTwo() {
// System.out.println("===========================每30秒执行一次===========================");
}
}
-------------------------------------------------------------定时更新Token和Ticket-------------------------------------------------------------
给前端一个接口传入URL
controller层-----------------------------------------
@PostMapping("/jsSdk")
public DzResult jSSDKConfig(@RequestParam(value = "url") String url) {
try {
Map<String, String> configMap = customService.sign(url);
return new DzResult().success(configMap);
} catch (Exception e) {
return new DzResult().error(1001, "调用失败");
}
}
----------------------------------------------------------
service层
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() {
return UUID.randomUUID().toString();
}
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
@Override
public Map<String, String> sign(String url) {
System.out.println("进入调用SDK----------------");
//如果不存在,重新加载,覆盖
boolean accToken = redisTemplate.hasKey("acctoken");
System.out.println("是否有这个key " + accToken);
Map<String, String> params = new HashMap<String, String>();
if (!accToken) {
System.out.println("进入获取access");
params.put("grant_type", "client_credential");
params.put("appid", WeChatJsConfig.APP_ID);
params.put("secret", WeChatJsConfig.APP_SECRET);
System.out.println("appid: " + WeChatJsConfig.APP_ID);
//获取accessToken
String accessTokenStr = HttpClientUtil.sendGet(WeChatJsConfig.GET_ACCESSTOKEN_URL, params);
HashMap accessTokenMap = JSON.parseObject(accessTokenStr, HashMap.class);
String accessToken = accessTokenMap.get("access_token").toString();
System.out.println("------------------------------------------------------");
System.out.println("accessTokenMap: " + accessTokenMap);
System.out.println("access_token: " + accessToken);
System.out.println("------------------------------------------------------");
//将结果存入
redisTemplate.boundValueOps("acctoken").set(accessToken);
//设置有效期为110分钟
redisTemplate.boundValueOps("acctoken").expire(110, TimeUnit.MINUTES);
//1,清空参数集合
params.clear();
}
String accesstoken = redisTemplate.boundValueOps("acctoken").get().toString();
Boolean aBoolean = redisTemplate.hasKey("ticket");
if (!aBoolean) {
//传入参数
params.put("type", "jsapi");
params.put("access_token", accesstoken);
String jsApiTicketMapStr = HttpClientUtil.sendGet(WeChatJsConfig.GET_TICKET_URL, params);
HashMap jsApiTicketMap = JSON.parseObject(jsApiTicketMapStr, HashMap.class);
String jsApiTicket = jsApiTicketMap.get("ticket").toString();
//将结果存入
redisTemplate.boundValueOps("ticket").set(jsApiTicket);
//设置有效期为110分钟
redisTemplate.boundValueOps("ticket").expire(110, TimeUnit.MINUTES);
}
String jsTicket = redisTemplate.boundValueOps("ticket").get().toString();
System.out.println("拿到的url为: " + url);
System.out.println("拿到的App_id为: " + WeChatJsConfig.APP_ID);
System.out.println("拿到的App_SECRET为: " + WeChatJsConfig.APP_SECRET);
System.out.println("拿到的AccessToken为: " + accesstoken);
System.out.println("拿到的ticket为: " + jsTicket);
Map<String, String> ret = new HashMap<String, String>();
String nonceStr = create_nonce_str();
String timestamp = create_timestamp();
String string1;
String signature = "";
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsTicket +
"&noncestr=" + nonceStr +
"×tamp=" + timestamp +
"&url=" + url;
System.out.println("有序的拼接参数为: " + string1);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ret.put("url", url);
ret.put("jsapi_ticket", jsTicket);
ret.put("nonceStr", nonceStr);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
return ret;
}
关于Springboot静态访问JS安全文件 非templates 模板模式
看了一个写的比较好的可以参考下,我没照着他的做,
参考文档:https://blog.csdn.net/wangyang00700/article/details/78256943