美文网首页
SSM实现JSSDK

SSM实现JSSDK

作者: 东西汉 | 来源:发表于2019-04-15 11:34 被阅读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&timestamp=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 + "&timestamp=" + 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 接口签名校验工具

    相关文章

      网友评论

          本文标题:SSM实现JSSDK

          本文链接:https://www.haomeiwen.com/subject/nhoywqtx.html