SSM实现JSSDK
2019-04-15 本文已影响0人
东西汉
最近有对接微信的JSSDK,大概流程如下,先获取全局access_token(注意:这里的access_token不同于网页授权,即获取用户openid的access_token),拿access_token去换jsapi_ticket,然后将jsapi_ticket生成签名signature,下面记录下流程以及附上代码,现贴现用
准备工作
1.设置获取access_token的IP白名单 设置获取access_token的IP白名单2.设置js调用安全域名 设置js调用安全域名
3.nginx配置相关文件访问跳转,已配置好的或者会的可以跳过直接看代码
server {
listen 80;
server_name www.*******.com;
location /MP_verify_sCA2Kb5zEqFxZ6Yu.txt{
root /www/8080/webapps; #文件放置的目录
}
#user nobody;
worker_processes 4;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /root/logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm; proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name www.*******.com;
location /MP_verify_sCA2Kb5zEqFxZ6Yu.txt{
root /www/8080/webapps; #文件放置的目录
}
location / {
root html;
index index.html index.htm;
proxy_pass http: //127.0.0.1:8080/;
client_max_body_size 10m;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
upstream php {
server unix:/tmp/php-cgi.socket;
server 127.0.0.1:9000;
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
开发代码
package com.shadmin.common.util;
import com.alibaba.fastjson.JSONObject;
import java.util.Date;
import java.util.Random;
public class WechatUtil {
public static String app_id = "你的微信公众号AppId"; //微信公众号AppId
public static String app_secrect = "你的微信公众号AppSecrect"; //微信公众号AppSecrect
private static String access_token; //微信获取的AccessToken_
private static long token_expire_time; //微信AccessToken的失效时间
private static String jsapi_ticket; //微信前端调用JSSDK的凭证
private static long jsapi_expire_time; //JSSDK凭证的失效时间
private static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
private static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
/**
* 用第一步拿到的access_token
* https请求方式: GET
* https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
* grant_type 获取access_token填写client_credential
* appid 第三方用户唯一凭证
* secret 第三方用户唯一凭证密钥,即appsecret
* 返回值 {"access_token":"ACCESS_TOKEN","expires_in":7200}
*/
private static void getAccessToken(){
if(new Date().getTime()/1000 > token_expire_time){
//access_token已过期
String requestUrl = access_token_url.replace("APPID", app_id).replace("APPSECRET", app_secrect);
JSONObject jsonObject = HttpUtil.doGet(requestUrl);
access_token = jsonObject.getString("access_token");
if(access_token != null){
token_expire_time = new Date().getTime()/1000 +7000;
}
}
}
/**
* 第二步,用access_token换取jsapi_ticket
* 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):
* https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
* {
* "errcode":0,
* "errmsg":"ok",
* "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
* "expires_in":7200
* }
*/
private static void getJsapiTicket(){
if(new Date().getTime()/1000>jsapi_expire_time){
//先更新基础access_token
getAccessToken();
//jsapi_token已过期
String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", access_token);
JSONObject res = HttpUtil.doGet(requestUrl);
jsapi_ticket = res.getString("ticket");
if (jsapi_ticket != null) {
jsapi_expire_time = new Date().getTime() / 1000;
}
}
}
/**
* 第三步,拿jsapi_ticket完成签名算法
* 步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,
* 使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
* jsapi_ticket=sM4AOVd&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value
* 步骤2. 对string1进行sha1签名,得到signature:
* 0f9de62fce790f9a083d5c99e95740ceb90c27ed
* 注意事项:
* 1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
* 2.签名用的url必须是调用JS接口页面的完整URL,当前网页的URL,不包含#及其后面部分。
* 3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。
*/
public static JSONObject getSignPackage(String page_url){
//先更新jsapi_ticket
getJsapiTicket();
long timestamp = new Date().getTime() / 1000;
JSONObject jsonObject = new JSONObject();
jsonObject.put("appId", app_id); //公众号唯一标识
jsonObject.put("timestamp",timestamp); //生成签名的时间戳
String noncestr = getRandomString(16);
jsonObject.put("nonceStr", noncestr); //生成签名的随机串
String shaStr = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + page_url;
System.out.println(shaStr);
String signature = SHA1.encode(shaStr);
jsonObject.put("signature", signature); //签名
jsonObject.put("jsapi_ticket", jsapi_ticket);
return jsonObject;
}
/**
* 获取随机串
* @return
*/
public static String getRandomString(int length){
//定义一个字符串(A-Z,a-z,0-9)即62位;
String str="zxcvbnmlkjhgfdsaqwertyuiopQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
//由Random生成随机数
Random random=new Random();
StringBuffer sb=new StringBuffer();
//长度为几就循环几次
for(int i=0; i<length; ++i){
//产生0-61的数字
int number=random.nextInt(62);
//将产生的数字通过length次承载到sb中
sb.append(str.charAt(number));
}
//将承载的字符转换成字符串
return sb.toString();
}
}
以下附上发送HTTP的get请求的函数
package com.shadmin.common.util;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
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.util.EntityUtils;
import org.apache.log4j.Logger;
import java.io.IOException;
public class HttpUtil {
private static Logger logger = Logger.getLogger(HttpUtil.class);
//get请求
public static com.alibaba.fastjson.JSONObject doGet(String requestUrl) {
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String responseContent = null;
com.alibaba.fastjson.JSONObject result = null;
try {
//创建Get请求,
HttpGet httpGet = new HttpGet(requestUrl);
//执行Get请求,
response = httpClient.execute(httpGet);
//得到响应体
HttpEntity entity = response.getEntity();
//获取响应内容
responseContent = EntityUtils.toString(entity,"UTF-8");
//转换为map
result = JSON.parseObject(responseContent);
} catch (IOException e) {
logger.error("HttpUtil=====Start");
logger.error(e.getMessage(),e);
logger.error("HttpUtil=====End");
}
return result;
}
}
然后给前端开一个接口,参数传当前页面的url就行
/**
* 获取微信JSSDK的签名
* @param pageUrl 当前网页的URL,不包含#及其后面部分
*/
@RequestMapping("getWechatSignature.htm")
public @ResponseBody JSONObject getWechatSignature(HttpServletRequest request){
String pageUrl = request.getParameter("pageUrl");
JSONObject jsonObject = WechatUtil.getSignPackage(pageUrl);
return jsonObject;
}
前端调用时时相关代码
var url = location.href.split('#')[0]
$.ajax({
url: 'http://localhost:8080/api/getWechatSignature.htm?pageUrl=' + url,
headers: {
'Content-Type': 'application/json;charset=utf8'
},
async: false,
timeout: 20000
}).done(function (info) {
info = JSON.parse(info);
//console.table(info);
//微信初始化权限验证
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: info.appId, // 必填,公众号的唯一标识
timestamp: info.timestamp, // 必填,生成签名的时间戳
nonceStr: info.nonceStr, // 必填,生成签名的随机串
signature: info.signature, // 必填,签名,见附录1
jsApiList: ['openAddress'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
//微信加载完
wx.ready(function () {
$('.addAddress').on('click', function () {
wx.openAddress({
success: function (res) {
// 用户成功拉出地址
},
cancel: function () {
// 用户取消拉出地址
},
error:function (res) {
console.log(res)
}
});
})
});
wx.error(function (res) {
console.log(res)
});
});
以下附上相关路径
微信公众平台首页
微信JS-SDK说明文档
微信 JS 接口签名校验工具