微信jssdk_微信jssdk开发教程 - CSDN
精华内容
参与话题
  • 微信jssdk使用心得与源码分析

    千次阅读 2016-11-15 16:04:56
    所以微信官方就出了一个浏览器,内置在微信中,阉割了一下原生js的支持,并且封装好了sdk,提供的sdk功能还是比较强大,可以直接调用相机,相册,录音这些功能。但是要使用的话需要微信公众号的凭据,需要在微信...

    1.前言

    javascript的功能固然很强大,但是对移动平台的支持不是很好。所以微信官方就出了一个浏览器,内置在微信中,阉割了一下原生js的支持,并且封装好了sdk,提供的sdk功能还是比较强大,可以直接调用相机,相册,录音这些功能。但是要使用的话需要微信公众号的凭据,需要在微信服务器和开发者服务器进行双向绑定。

    1-1.本例子demo下载

    点我下载

    2.使用步骤

    2-1.微信服务器绑定开发者服务器

    2-1-1.在公众号设置->功能设置,中配置域名信息

    这里写图片描述

    2-1-2.在接口权限,中配置权限

    这里写图片描述

    2-2. 在开发者服务器中绑定微信服务器

    2-2-1.配置appid和appsecret

    这里写图片描述

    2-2-2.引入官方的js库,并把验证后的信息放在wx对象的配置中

    这里写图片描述

    2-2-3.配置好wx对象后,然后在wx.ready()方法内进行事件绑定

    这里写图片描述

    3.Q&A

    3-1.微信服务器是如何绑定开发者服务器的?

    微信服务器绑定开发服务器是通过域名的方式进行绑定,域名可以配置多个,在验证的时候微信服务器会生成一个MP_verify开头,内容随机的txt文件,开发者需要把这个文件放在域名所在的服务器上,微信服务器通过验证后才能绑定成功.

    3-2.开发者服务器是如何绑定微信服务器的?

    在开发者的服务器上,需要先通过程序生成签名,然后把签名放wx对象的配置中,通过验证才可以调用微信的jssdk,验证过程比较复杂,先是服务器端生成各种获取签名需要的数据,然后通过官方的接口生成签名,最后把生成的签名和生成签名需要的一部分数据加入从官方引入的js文件的配置中。由于程序需取一个随机字符串,所以每次生成的签名都不一致。
    这里写图片描述

    展开全文
  • 微信分享JSSDK接入

    2019-07-11 11:30:42
    结果如下,自定义分享链接,分享图片等等... 开始对接 1.JS安全域名 配置路径在: ... 登录公众号号平台后,-----------进入公众号设置-------功能设置------,如下 ... 微信公众号----基本配置--...

    结果如下,自定义分享链接,分享图片等等...

    开始对接

    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 +
                "&timestamp=" + 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

    展开全文
  • 微信公众号—JSSDK测试环境调用

    万次阅读 2018-05-20 14:01:16
    这两天要调用微信原生的JS,获取地理位置和扫描二维码,在本地测试。网上的博客特别多,但是很乱有的说了上面没了下面,有的只说了上面。我弄了很久现在记录下来,防止忘记。第一步:本地需要有一个WEB服务在运行,...

    这两天要调用微信原生的JS,获取地理位置和扫描二维码,在本地测试。网上的博客特别多,但是很乱有的说了上面没了下面,有的只说了上面。我弄了很久现在记录下来,防止忘记。

    第一步:本地需要有一个WEB服务在运行,并且是80端口。如果是搞微信工作号开发的,就是你本地web服务,现在的访问地址是127.0.0.1


    第二步:将本地环境设置为外网能够访问,俗称“内网网穿透”。这一步是为了微信能够访问到本地的服务器,完成Token验证。

    访问:https://natapp.cn

    注册一个账号,然后在“我的隧道”中购买第二个:


    免费的那个实测不行,一个月9块钱。购买好了之后在“我的隧道”中配置自己的域名,因为微信拒绝三级以上的域名直接访问,所以先随便注册一个三级的域名,再修改成二级,还要花三块钱(一年)升权限,本地地址默认,端口用80:


    域名配置好了之后,下载netapp的客户端:


    就是一个exe,解压到本机。放在一个固定的位置,最好是全英文。接着下载配置文件:


    把配置文件放到natapp.exe同级目录下:


    修改配置文件:将刚刚配好的域名中的“token”复制


    写到config.ini中,其他的不变:


    然后就可以启动natapp.exe了。成功之后:


    这个我们的整个服务就可以被外网访问了:


    据说是全球,没测过,全国是可以的。

    第三步:按照微信的官网介绍,完成自己这个域名在公众号的注册。在微信公众号主页,进入设置->公众号设置->功能设置->js安全域名,将刚才我们的域名设置进去。


    这一串的要求就是说,要保证本地的web服务能够识别访问这个路径并且获得一串字符串




    点击提交。

    第三步:让自己的web服务能够识别响应微信的Token验证,就是自己写一个接口,官网有例子。



      

    把做好了网页连接发给手机,测试环境下,手机就可以正常的调用“微信扫码”或者获取位置了。



    展开全文
  • 微信jssdk接入指南

    2019-07-05 05:29:08
    好久没有写点东西了,最近手里做了一个小小的H5项目,其中用到了微信jssdk。 一提到微信开发,大家肯定很容易想到微信那复杂的文档,我也遇到了同样的问题。 接入jssdk的过程是比较曲折的,所以在这里写一篇文章记录...

    好久没有写点东西了,最近手里做了一个小小的H5项目,其中用到了微信jssdk。

    一提到微信开发,大家肯定很容易想到微信那复杂的文档,我也遇到了同样的问题。

    接入jssdk的过程是比较曲折的,所以在这里写一篇文章记录一下接入过程,也希望能够给大家提供一点帮助。

    一、微信官方文档阅读

    首先,我们要接入微信jssdk,那么第一步就是要阅读微信开发文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432

    打开这个网页,在左边的菜单栏,依次点击:微信网页开发 - 微信JS-SDK说明文档

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1JhYml0TW91bnRhaW4=,size_16,color_FFFFFF,t_70

    打开之后,我们就可以看到微信JS-SDK接入说明了。

    概述,我就不多说了,我们直接来看使用步骤。

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1JhYml0TW91bnRhaW4=,size_16,color_FFFFFF,t_70

    二、微信JSSDK使用步骤

    微信JSSDK使用步骤有以下五步:

    步骤一:绑定域名

    这里需要我们先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。也就是这样:

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1JhYml0TW91bnRhaW4=,size_16,color_FFFFFF,t_70

    点击设置之后,弹出这样一个输入框:

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1JhYml0TW91bnRhaW4=,size_16,color_FFFFFF,t_70

    这里,大家可能就会有疑问了?需要备案的域名,这我怎么办呢?别急,这里我交大家用内网穿透的方式,来搭建本地开发环境。

    内网穿透传送门:https://blog.csdn.net/RabitMountain/article/details/85298819

    好了,大家实现了内网穿透,那么这个txt文件我们放到哪里呢?tomcat的默认访问路径是ROOT,大家直接丢进去就好,但要注意把原来的东西删掉,要不然会因为示例中可能使用的springmvc造成请求转发,进而无法访问到这个txt文件。

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1JhYml0TW91bnRhaW4=,size_16,color_FFFFFF,t_70

    步骤二:引入js文件

    这个我也就不多说了,直接在你的网页里引入js文件就行

    <script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>

    步骤三:通过config接口注入权限验证配置

    这个是前端html页面中需要我们处理的,就是通过wx.config()注入欸之信息,要不然就会无法调用其他接口。

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名
        jsApiList: [] // 必填,需要使用的JS接口列表
    });
    

    这些东西,除了jsApiList,我们都需要从后端获取,那我们就向后台发起一个请求,然后后台封装一下返回给前端是不是就好了,很简单吧。

    appId简单,直接从微信后台拿来用就行。

    timestamp,后台直接生成就行,但要注意要以秒为单位。

    nonceStr,java后台随便使用个uuid就可以了。

    signature,这个有点东西啊,但也别急,微信有文档,我们慢慢看。

    JS-SDK使用权限签名算法

    在生成签名之前我们必须先了解一下jsapi_ticket。

    jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket。

    步骤如下:

    1. 获取access_token

    我们据先获取access_token:思路很简单,就是我们用代码向微信服务器发一个请求,来换取它返回的access_token就行了。在写代码直接,我们还要添加ip白名单。这是因为微信规定,通过开发者ID及密码调用获取access_token接口时,需要设置访问来源IP为白名单。

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1JhYml0TW91bnRhaW4=,size_16,color_FFFFFF,t_70

    添加了这个之后,我们来看一下代码:

    WechatUtil.java

    import com.alibaba.fastjson.JSONObject;
    
    import java.security.MessageDigest;
    import java.util.Formatter;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    public class WechatUtil {
    
        private static String appId = "xxxxxxxxxx";
        private static String appSecret = "xxxxxxxxxxxxxxxxxxxx";
    
        public static JSONObject getAccessToken() {
            String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appId=APPID&secret=APPSECRET";
            String requestUrl = accessTokenUrl.replace("APPID", appId).replace("APPSECRET", appSecret);
            return WebUtil.doGet(requestUrl);
        }
    
        // 后面还有部分代码
    }
    

    WebUtil.java

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    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 java.io.IOException;
    
    /**
     * Web相关工具类
     */
    public class WebUtil {
    
        /**
         * 发起http get请求
         */
        public static JSONObject doGet(String requestUrl) {
            CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = null;
            String responseContent = null;
            JSONObject result = null;
    
            try {
                HttpGet httpGet = new HttpGet(requestUrl);
                response = httpClient.execute(httpGet);
                HttpEntity entity = response.getEntity();
                responseContent = EntityUtils.toString(entity, "UTF-8");
                result = JSON.parseObject(responseContent);
            } catch (IOException e) {
                System.out.println("HTTP请求异常:" + e.getMessage());
            }
    
            return result;
        }
    }

    2. 用access_token换取jsapi_ticket

    用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

    成功返回如下JSON:

    {
        "errcode":0,
        "errmsg":"ok",
        "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
        "expires_in":7200
    }

    这个就要我用access_token再向微信服务器发起请求,然后获得ticket就行了。但是,这个上面说了,调用次数有限,需要我们缓存,这里我们直接采用单例来缓存。

    TokenSingleton.java

    import com.alibaba.fastjson.JSONObject;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 使用单例模式access_token全局缓存
     */
    public class TokenSingleton {
    
        private Map<String, String> map = new HashMap<>(); // 缓存accessToken的Map, map中包含一个accessToken和缓存的时间戳
    
        private TokenSingleton() {
        }
    
        private static TokenSingleton single = null;
    
        public static TokenSingleton getInstance() {
            if (single == null) {
                single = new TokenSingleton();
            }
            return single;
        }
    
        public Map<String, String> getMap() {
            String time = map.get("time");
            String accessToken = map.get("access_token");
            long nowDate = new Date().getTime() / 1000;
    
            if (accessToken != null && time != null && nowDate - Long.parseLong(time) < 5000 * 1000) {
                System.out.println("access_token存在,尚未超时,返回单例!");
            } else {
                System.out.println("access_token超时或者不存在,重新获取!");
                JSONObject jsonObject = WechatUtil.getAccessToken();
                String newAccessToken = jsonObject.getString("access_token");
                System.out.println("new access_token = " + newAccessToken);
                String jsApiTicket = getJsApiTicket(newAccessToken);
                map.put("time", nowDate + "");
                map.put("access_token", newAccessToken);
                map.put("jsapi_ticket", jsApiTicket);
            }
    
            return map;
        }
    
        public String getJsApiTicket(String accessToken) {
            String apiTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
            String requestUrl = apiTicketUrl.replace("ACCESS_TOKEN", accessToken);
            System.out.println("getJsApiTicket.requestUrl ====> " + requestUrl);
    
            JSONObject result = WebUtil.doGet(requestUrl);
            System.out.println("getHsApiTicket.response ====> " + result);
    
            String jsApiTicket = null;
            if (null != result) {
                jsApiTicket = result.getString("ticket");
            }
            return jsApiTicket;
        }
    }
    

    3. 签名

    获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。微信上给出的签名算法如下:

    参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

    即signature=sha1(string1)。 示例:

    noncestr=Wm3WZYTPz0wzccnW
    jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
    timestamp=1414587457
    url=http://mp.weixin.qq.com?params=value
    1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
    jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value
    1. 对string1进行sha1签名,得到signature:0f9de62fce790f9a083d5c99e95740ceb90c27ed

    注意事项

    • 签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
    • 签名用的url必须是调用JS接口页面的完整URL。
    • 出于安全考虑,开发者必须在服务器端实现签名的逻辑。

    总结来看,就是按顺序组装参数,用SHA-1加密一下就行了。当然,这里为了前后端交互,我们直接把所有需要的参数封装起来,到时候通过controller直接返回给前端。代码如下:

    import com.alibaba.fastjson.JSONObject;
    
    import java.security.MessageDigest;
    import java.util.Formatter;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    public class WechatUtil {
    
        // 接上面的access_token获取代码
    
        public static Map<String, String> generateWxTicket(String jsApiTicket, String url) {
            Map<String, String> ret = new HashMap<>();
            String nonceStr = createNonceStr();
            String timestamp = createTimestamp();
            String string1;
            String signature = "";
    
            string1 = "jsapi_ticket=" + jsApiTicket +
                    "&noncestr=" + nonceStr +
                    "&timestamp=" + timestamp +
                    "&url=" + url;
    
            System.out.println("string1 ====> " + string1);
    
            try {
                MessageDigest crypt = MessageDigest.getInstance("SHA-1");
                crypt.reset();
                crypt.update(string1.getBytes("UTF-8"));
                signature = byteToHex(crypt.digest());
                System.out.println("signature ====> " + signature);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            ret.put("url", url);
            ret.put("jsapi_ticket", jsApiTicket);
            ret.put("nonceStr", nonceStr);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
            ret.put("appid", appId);
    
            return ret;
        }
    
        /**
         * 字节数组转换为十六进制字符串
         *
         * @param hash 字节数组
         * @return 十六进制字符串
         */
        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;
        }
    
        /**
         * 生成随机字符串
         *
         * @return 随机字符串
         */
        private static String createNonceStr() {
            return UUID.randomUUID().toString();
        }
    
        /**
         * 生成时间戳
         *
         * @return 时间戳
         */
        private static String createTimestamp() {
            return Long.toString(System.currentTimeMillis() / 1000);
        }
    }
    

    后台控制器

    接下来我们用springmvc组装一个控制器,来接受前端的请求。

    WechatController.java

    import com.hbwomen.util.TokenSingleton;
    import com.hbwomen.util.WechatUtil;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.util.HashMap;
    import java.util.Map;
    
    @RestController
    @RequestMapping("/wechat")
    public class WechatController {
    
        @PostMapping("/config")
        @ResponseBody
        public Map<String, String> config(HttpServletRequest request) throws UnsupportedEncodingException {
            String signUrl = request.getParameter("signUrl");
            Map<String, String> ret = new HashMap<>();
            TokenSingleton tokenSingleton = TokenSingleton.getInstance();
            Map<String, String> map = tokenSingleton.getMap();
    
            String jsapi_ticket = map.get("jsapi_ticket");
            // String newUrl = URLDecoder.decode(signUrl, "UTF-8");
            ret = WechatUtil.generateWxTicket(jsapi_ticket, signUrl);
            return ret;
        }
    }
    

    完整前端代码

    这里我们在补上前端的代码,就可以进行config了。

    $(function () {
            var signUrl = window.location.href.split('#')[0];
            $.ajax({
                url: "/wechat/config",
                method: "post",
                data: {
                    signUrl: signUrl
                },
                success: function (data) {
                    console.log("wx.config() ---> 接收后台返回的参数");
                    wx.config({
                        debug: true,
                        appId: data.appid,
                        timestamp: data.timestamp,
                        nonceStr: data.nonceStr,
                        signature: data.signature,
                        jsApiList: ['onMenuShareAppMessage']
                    })
                }
            });
        });

    步骤四:通过ready接口处理成功验证

    wx.ready(function(){
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
    });

    步骤五:通过error接口处理失败验证

    wx.error(function(res){
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    });

    三、总结

    好了,基本接入的过程,也就上面那些了。

    微信开发这块,配置确实是个比较烦的事情,我也是花了好多天才成功配置起来,不是这有问题就是那有问题。

    我也想通过这篇文章,来详细系统的总结一下怎么接入jssdk,一方面方便自己以后查看,另一方面也希望能够帮助到大家,少走弯路,毕竟网上的博文太多太多,东看看,西看看,就会比较混乱。

    最后,新的一年,祝大家新年快乐,冲冲冲!!!


    老样子,欢迎大家!!!

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1JhYml0TW91bnRhaW4=,size_16,color_FFFFFF,t_70

    转载于:https://www.cnblogs.com/xiaofeng-blog/p/10216988.html

    展开全文
  • 微信JSSDK分享功能详解

    万次阅读 热门讨论 2017-04-19 16:23:09
    微信6.0之后JSSDK的调用,微信分享功能的实现,傻瓜教程
  • 微信JSSDK实现微信自定义分享,微信扫一扫 前言: 由于微信使用的越来越多,也让大多数平台或者APP与微信建立了比较深的合作关系,我们公司自主研发的产品也是比较依赖于微信,最近也写了几篇关于微信的博客,本文...
  • 总结微信jssdk使用

    千次阅读 2019-04-11 11:55:20
    总结微信jssdk使用 在实际项目中调用微信jssdk,这篇博客主要做一个总结记录    首先是关于微信jssdk调用步骤 1.在公众号内部的“公众号设置”的“功能设置”里填写“JS接口安全域名”。    备注:登录后可在...
  • 微信JSSDK

    2018-07-17 11:02:19
    首先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。要记得哦。 先看后端操作,基于thinkphp5, /* 微信JS-SDK配置 */ public function share(){ $ticket = getJsapiTicket...
  • 微信jssdk基本使用

    万次阅读 2017-12-11 20:36:58
    对于如何使用jssdk并没有,太大难度,对于不熟悉的人来说,最大的坑在它配置的过程中。  使用jssdk需要注意以下几点:  1.需要在微信公众平台设置js接口安全域名。需要注意的是此处你需要设置的是域名,使用ip是...
  • 第一次用微信调用时,总是出现这个提示框,只要点击确定,原有的 animate就出现了问题。,如何用js监控这个提示框的出现
  • ![图片说明](https://img-ask.csdn.net/upload/201602/15/1455521560_936050.png) 有人遇到过报 timeout 这个问题吗,实在找不到原因。求大神!!
  • 微信jssdk调用地图(openLocation)小坑

    万次阅读 2017-09-11 22:57:32
    今天发现微信jssdk里调用微信地图的一个小坑,记录一下。具体调用如下:wx.openLocation(function(){ longitude: longitude, latitude: latitude, name: name, address: address });乍看之下调用没有什么问题,...
  • 如题。。用这个接口给我返回的是...我知道可以上传到微信服务器获取mediaId,我的服务器可以用这个mediaId从微信服务器那边取图片。。。我想请问有没有办法从我前台直接取得图片数据,直接提交给我自己的服务器呢?
  • HTML5微信jssdk录音播放语音的方法

    万次阅读 2017-01-13 14:22:08
    HTML5微信jssdk录音播放语音的方法 需要注意的2个问题 1 就是一定要判断1秒内 录音都不算 ps:太短不能录音 2 录音超过1分钟 会发现正在录音突然消失 所以要写wx.onVoiceRecordEnd 这个是是1分钟会自动出发 然后写...
  • 又搜索到网上有很多调用微信jssdk的方法。 开始我还以为直接调用微信jssdk,就可以弹出一个二维码呢。 后来发现太天真了,写了很多代码,点击之后啥反应都没有。 想问一问微信jssdk里的接口,比如说是分享接口。 1....
  • VUE项目引入微信jssdk

    万次阅读 2017-04-26 03:10:11
    我们的一个vue + webpack的 SPA... 通过搜索发现npm有微信jssdk的依赖包: weixin-js-sdk, 于是 导入依赖包 npm i -S weixin-js-sdk 页面中 import wx from 'weixin-js-sdk'export default { created(){ wx.config
  • ios 调用微信JSSDK 签名失败解决方法

    万次阅读 热门讨论 2017-07-21 11:20:12
    用SPA做微信h5,调用微信jssdk的页面,安卓微信上木有问题,ios微信报当前url未注册经过调试,是ios微信版本问题导致页面跳转url未变化,导致验签失败所以我们大致的思想就是:在ios微信环境中(判断浏览器环境请参考...
  • 微信JSSDK引入微信开发

    千次阅读 2016-07-15 11:08:47
    微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。...以上了说白了,微信JSSDK其实就是微信爸爸开放了一些微信的API功能让你用,这些API功能以JSSDK的形式呈现,有摄像头,相册,
  • 微信填坑之jssdk中的图片下载api

    千次阅读 2018-01-20 10:34:09
    在jsddk中有下载图片接口,通过接口我们可以拿到一个图片的base64码,但是这个在Android和ios中是不同。 在Android中,这串base64码是不带前缀的的也就是没有data:img/jpg等信息,而在ios中会包含这个信息。...
  • 微信公众平台开发之公众号JSSDK开发是子恒老师《微信公众平台开发》视频教程的第9部。详细讲解了用php开发微信公众号,对微信公众平台中的JSSDK开发。内容包含用JSSDK获取网络状态,地理位置,分享到朋友圈,QQ,...
1 2 3 4 5 ... 20
收藏数 6,174
精华内容 2,469
关键字:

微信jssdk