关于springboot:SpringBoot接入微信JSSDK看这篇妥妥的

48次阅读

共计 16129 个字符,预计需要花费 41 分钟才能阅读完成。

先给猴急的客官上干货代码

GitHub

接入微信 JSSDK GitHub 地址

Gitee

接入微信 JSSDK GitHub 地址

前言

事件的起因是因为疫情重大,领导要求做一个专题页,可能尽可能帮忙所须要的人。
于是乎本狗与共事挑灯奋战,加班加点赶工进去。
部署上线实现,用微信内置浏览器分享后,现实状态应该是这样的,如下图⬇️

然而,后果却不是现实的这样,默默地留下了没有技术的泪水,如下图⬇️

居然没有关键字和展现图片,在本菜狗的不懈努力下,终于抵赖技术不行,去求教了大佬,得出如下论断。

  • 1. 微信内置浏览器分享若须要自定义展现形容及右侧封面图,必须接入 微信 JSSDK, 并且肯定须要有配合本站的 微信公众号(appId 和 appSecret)才可自定义分享,切记小程序(appId 和 appSecret)的不能够
  • 2. 非微信分享,如 QQ 浏览器,UC 浏览器等各大厂商,会依据本身定义获取 HTML 页面中的 TDK(title,description,keyword),举例 UC 浏览器分享⬇️

    所以,对接微信 JSSDK, 势在必行!


    Tip

    史上最具体的 接入微信 JSSDK 菜鸟教程,本文全面的记录了接入微信 JSSDK 的步骤,具体的代码及遇到的坑,并且展现公布最终成果, 并将代码公布 GitHub。随篇幅较长,但史上最全。大佬勿喷,新手入门,亲测可用!!!

本文试用人群

  • 须要接入微信 JSSDK 却 看不懂文档 的同学
  • 看懂文档然而 实操不知如何下手 的同学
  • 下了手然而出错不晓得 如何调试批改 的同学
  • 胜利接入过然而想 重温具体流程 的同学

本文指标

  • 实战进行 H5 网站 微信自定义分享
  • 实战进行 H5 网站 调取相册选取图片

放松心态,缓缓来看


注释

官网文档

任何平台接入,官网文档是标杆,虽有些关键点一笔带过,咱们也要通读有个印象,点击微信官网文档打开文档,如下⬇️

总览
  • 1.x 是接入关键步骤,需认真品读,与接入无关
  • 2.x – 12.x 具体接口接入,须要对接时具体参考
  • 13.x 须要留神下,api_ticket 微信长期票据,与接入无关
  • 16-22 均是附录,可查阅谬误列表对应含意,及接口菜单列表等形容


    实操步骤

    应用 IDEA 工具,新建 SpringBoot 我的项目,我的项目名为 springboot-wexin,目录构造如下

    AjaxJson.java – 自定义接口返回前台数据格式的封装类

    /**
     * Copyright &copy; 2005-2020 <a href="http://www.jhmis.com/">jhmis</a> All rights reserved.
     */
    package net.javadog.springbootwexin.common;
    
    import com.fasterxml.jackson.annotation.JsonIgnore;
    
    import java.util.LinkedHashMap;
    import java.util.List;
    
    
    /**
     * $.ajax 后须要承受的 JSON
     *
     */
    public class AjaxJson {
    
      private boolean success = true;// 是否胜利
      private String errorCode = "-1";// 错误代码
      private String msg = "操作胜利";// 提示信息
      private Long count;             // 返回表格记录数量
      private List<?> data;           // 返回表格数据
      private LinkedHashMap<String, Object> body = new LinkedHashMap<String, Object>();// 封装 json 的 map
    
      public static AjaxJson ok(){AjaxJson j = new AjaxJson();
          return j;
      }
    
      public static AjaxJson ok(String msg){AjaxJson j = new AjaxJson();
          j.setMsg(msg);
          return j;
      }
    
      public static AjaxJson ok(String msg, Object object){AjaxJson j = new AjaxJson();
          j.setMsg(msg);
          j.setResult(object);
          return j;
      }
    
      public static AjaxJson ok(Object object){AjaxJson j = new AjaxJson();
          j.setResult(object);
          return j;
      }
    
      public static AjaxJson fail(String errorMsg){AjaxJson j = new AjaxJson();
          j.setSuccess(false);
          j.setErrorCode("999");// 默认错误码
          j.setMsg(errorMsg);
          return j;
      }
    
      public static AjaxJson fail(String errorCode,String errorMsg){AjaxJson j = new AjaxJson();
          j.setSuccess(false);
          j.setErrorCode(errorCode);
          j.setMsg(errorMsg);
          return j;
      }
      // 返回不分页的 layui 表数据
      public static AjaxJson layuiTable(List<?> list){AjaxJson j = new AjaxJson();
          j.setSuccess(true);
          j.setCount(Long.valueOf(list.size()));
          j.setData(list);
          return j;
      }
      public LinkedHashMap<String, Object> getBody() {return body;}
    
      public void setBody(LinkedHashMap<String, Object> body) {this.body = body;}
    
      public void put(String key, Object value){// 向 json 中增加属性,在 js 中拜访,请调用 data.map.key
          body.put(key, value);
      }
      
      public void remove(String key){body.remove(key);
      }
    
      /**
       * 间接设置 result 内容
       * @param result
       */
      public void setResult(Object result){body.put("result", result);
      }
      @JsonIgnore// 返回对象时疏忽此属性
      public Object getResult(){return body.get("result");
      }
    
      public String getMsg() {return msg;}
    
      public void setMsg(String msg) {// 向 json 中增加属性,在 js 中拜访,请调用 data.msg
          this.msg = msg;
      }
    
    
      public boolean isSuccess() {return success;}
    
      public void setSuccess(boolean success) {this.success = success;}
      
    
      public void setErrorCode(String errorCode) {this.errorCode = errorCode;}
    
      public String getErrorCode() {return errorCode;}
    
      public Long getCount() {return count;}
    
      public void setCount(Long count) {this.count = count;}
    
      public List<?> getData() {return data;}
    
      public void setData(List<?> data) {this.data = data;}
    }

    WxInitController.java – 微信初始化接入 Controller 控制器

    package net.javadog.springbootwexin.controller;
    import net.javadog.springbootwexin.common.AjaxJson;
    import net.javadog.springbootwexin.service.WxService;
    import net.javadog.springbootwexin.utils.WxUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import java.util.Map;
    
    /**
     * 一个低端大方没品位的程序狗 JavaDog
     * blog.javadog.net
     *
     * @BelongsProject: springboot-wexin
     * @BelongsPackage: net.javadog.springbootwexin.controller
     * @Author: hdx
     * @CreateTime: 2020-02-14 14:52
     * @Description: 微信初始化接入 Controller 控制器
     */
    @RestController
    @RequestMapping("/weixin")
    public class WxInitController {protected Logger logger = LoggerFactory.getLogger(getClass());
    
      @Autowired
      private WxService wxService;
    
      /**
      *@Author: hdx
      *@CreateTime: 20:39 2020/2/14
      *@param:  shareUrl 分享 url 地址
      *@Description: 初始化微信 JSSDK Config 信息
       1. 先通过 appId 和 appSecret 参数申请指定微信地址 获取 AccessToken
       2. 在通过第一步中的 AccessToken 作为参数申请微信地址 获取 jsapi_ticket 长期票据(此处不思考调用频率,使用者依据状况放入缓存或定时工作)
       3. 通过第二步的 JssdkGetticket 和 timestamp,nonceStr,url 作为参数申请微信地址,获取签名 signature
       4. 将第三步取得的 signature 和 jsapi_ticket,nonceStr,timestamp,url 返回给前端,作为 Config 初始化验证的信息
      */
      @RequestMapping("/initWXJSSDKConfigInfo")
      public AjaxJson initWXJSConfig (@RequestParam(required = false) String url) throws Exception{logger.info("url=" + url);
          String json = "";
          try {Map map = wxService.initJSSDKConfig(url);
              json = WxUtil.mapToJson(map);
          }catch (Exception e){AjaxJson.fail(e.getMessage());
          }
          return AjaxJson.ok(json);
      }
    
    }

    WxService.java – 初始化 JSSDKConfig

    package net.javadog.springbootwexin.service;
    
    import lombok.Getter;
    import net.javadog.springbootwexin.utils.WxUtil;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    /**
     * 一个低端大方没品位的程序狗 JavaDog
     * blog.javadog.net
     *
     * @BelongsProject: springboot-wexin
     * @BelongsPackage: net.javadog.springbootwexin.service
     * @Author: hdx
     * @CreateTime: 2020-02-14 20:43
     * @Description: 微信相干 service
     */
    @Service
    public class WxService {
      @Getter
      private static String AppId;
      @Value("${wx.appId}")
      public void setAppId(String appId) {AppId = appId;}
      /**
      *@Author: hdx
      *@CreateTime: 20:46 2020/2/14
      *@param:  shareUrl 分享的 url
      *@Description: 初始化 JSSDKConfig
      */
      public Map initJSSDKConfig(String url) throws Exception {
          // 获取 AccessToken
          String accessToken = WxUtil.getJSSDKAccessToken();
          // 获取 JssdkGetticket
          String jsapiTicket = WxUtil.getJssdkGetticket(accessToken);
          String timestamp = Long.toString(System.currentTimeMillis() / 1000);
          String nonceStr = UUID.randomUUID().toString();
          String signature = WxUtil.buildJSSDKSignature(jsapiTicket,timestamp,nonceStr,url);
          Map<String,String> map = new HashMap<String,String>();
          map.put("url", url);
          map.put("jsapi_ticket", jsapiTicket);
          map.put("nonceStr", nonceStr);
          map.put("timestamp", timestamp);
          map.put("signature", signature);
          map.put("appid", AppId);
          return map;
      }
    }

    WxUtil.java – 微信工具类

    package net.javadog.springbootwexin.utils;
    
    import com.google.gson.Gson;
    import com.google.gson.reflect.TypeToken;
    import lombok.Getter;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Component;
    import org.springframework.web.client.RestTemplate;
    import java.security.MessageDigest;
    import java.util.Map;
    
    /**
     * 一个低端大方没品位的程序狗 JavaDog
     * blog.javadog.net
     *
     * @BelongsProject: springboot-wexin
     * @BelongsPackage: net.javadog.springbootwexin.utils
     * @Author: hdx
     * @CreateTime: 2020-02-14 21:19
     * @Description: 微信工具类
     */
    @Component
    public class WxUtil {
      @Getter
      protected static String AppId;
      @Getter
      protected static String AppSecret;
      @Getter
      protected static String JssdkAccesstokenUrl;
      @Getter
      protected static String JssdkGetticketUrl;
    
      @Value("${wx.appId}")
      public void setAppId(String appId) {AppId = appId;}
    
      @Value("${wx.appSecret}")
      public void setAppSecret(String appSecret) {AppSecret = appSecret;}
    
      @Value("${wx.jssdk_accesstoken_url}")
      public void setJssdkAccesstokenUrl(String jssdkAccesstokenUrl) {JssdkAccesstokenUrl = jssdkAccesstokenUrl;}
    
      @Value("${wx.jssdk_getticket_url}")
      public void setJssdkGetticketUrl(String jssdkGetticketUrl) {JssdkGetticketUrl = jssdkGetticketUrl;}
    
      /**
      *@Author: hdx
      *@CreateTime: 21:31 2020/2/14
      *@param:  * @param null
      *@Description:
      
      */
      public static String getJSSDKAccessToken() {
          String token = null;
          String url = JssdkAccesstokenUrl.replaceAll("APPID",
                  AppId).replaceAll("APPSECRET",
                  AppSecret);
          String json = postRequestForWeiXinService(url);
          Map map = jsonToMap(json);
          if (map != null) {token = (String) map.get("access_token");
          }
          return token;
      }
    
      /**
      *@Author: hdx
      *@CreateTime: 21:40 2020/2/14
      *@param:  * @param null
      *@Description: 依据 accessToken 获取 JssdkGetticket
    
      */
      public static String getJssdkGetticket(String accessToken) {String url = JssdkGetticketUrl.replaceAll("ACCESS_TOKEN", accessToken);
          String json = postRequestForWeiXinService(url);
          Map map = jsonToMap(json);
          String jsapi_ticket = null;
          if (map != null) {jsapi_ticket = (String) map.get("ticket");
          }
          return jsapi_ticket;
      }
    
      /**
      *@Author: hdx
      *@CreateTime: 21:41 2020/2/14
      *@param:ticket 依据 accessToken 生成的 JssdkGetticket
      *@param:timestamp 领取签名工夫戳,留神微信 jssdk 中的所有应用 timestamp 字段均为小写。但最新版的领取后盾生成签名应用的 timeStamp 字段名需大写其中的 S 字符
      *@param:nonceStr 随机字符串
      *@param:url 以后网页的 URL
      *@Description: 构建分享链接的签名
    
      */
      public static String buildJSSDKSignature(String ticket,String timestamp,String nonceStr ,String url) throws Exception {
          String orderedString = "jsapi_ticket=" + ticket
                  + "&noncestr=" + nonceStr + "&timestamp=" + timestamp
                  + "&url=" + url;
    
          return sha1(orderedString);
      }
    
      /**
       * sha1 加密 JSSDK 微信配置参数获取签名。*
       * @return
       */
      public static String sha1(String orderedString) throws Exception {
          String ciphertext = null;
          MessageDigest md = MessageDigest.getInstance("SHA-1");
          byte[] digest = md.digest(orderedString.getBytes());
          ciphertext = byteToStr(digest);
          return ciphertext.toLowerCase();}
      /**
       * 将字节数组转换为十六进制字符串
       *
       * @param byteArray
       * @return
       */
      private static String byteToStr(byte[] byteArray) {
          String strDigest = "";
          for (int i = 0; i < byteArray.length; i++) {strDigest += byteToHexStr(byteArray[i]);
          }
          return strDigest;
      }
      /**
       * 将字节转换为十六进制字符串
       *
       * @param mByte
       * @return
       */
      private static String byteToHexStr(byte mByte) {char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
          char[] tempArr = new char[2];
          tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
          tempArr[1] = Digit[mByte & 0X0F];
    
          String s = new String(tempArr);
          return s;
      }
      /**
      *@Author: hdx
      *@CreateTime: 21:49 2020/2/14
      *@param:  map
      *@Description:  mapToJson
    
      */
      public static String mapToJson(Map map){Gson gson = new Gson();
          String json = gson.toJson(map);
          return json;
      }
    
      /**
      *@Author: hdx
      *@CreateTime: 21:37 2020/2/14
      *@param:  json
      *@Description: jsonToMap
    
      */
      private static Map jsonToMap(String json) {Gson gons = new Gson();
          Map map = gons.fromJson(json, new TypeToken<Map>(){}.getType());
          return map;
      }
    
      /**
      *@Author: hdx
      *@CreateTime: 21:36 2020/2/14
      *@param:  * @param null
      *@Description: 调取微信接口
    
      */
      private static String postRequestForWeiXinService(String getAccessTokenUrl) {RestTemplate restTemplate = new RestTemplate();
          ResponseEntity<String> postForEntity = restTemplate.postForEntity(getAccessTokenUrl, null, String.class);
          String json = postForEntity.getBody();
          return json;
      }
    
    }

    SpringbootWexinApplication.java – SpringBoot 启动类

    package net.javadog.springbootwexin;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class SpringbootWexinApplication {public static void main(String[] args) {SpringApplication.run(SpringbootWexinApplication.class, args);
      }
    
    }

    config/application.yml – 根底配置文件

    spring:
    profiles:
      #激活配置文件
      active: prod
    #配置动态资源门路
    resources:
      static-locations: classpath:/static/
    
    #日志相干
    logging:
    #配置文件日志门路
    config: classpath:logback-spring.xml
    
    #微信相干配置
    wx:
    #appId(到时候换成本人公众号的)appId: wx4ad618620f8c3528
    #appSecret(到时候换成本人公众号的)appSecret: b772c7863b29e270aa86e40f9b9e6215
    #参考以下文档获取 access_token(有效期 7200 秒,开发者必须在本人的服务全局缓存 access_token)jssdk_accesstoken_url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
    #用第一步拿到的 access_token 采纳 http GET 形式申请取得 jsapi_ticket(有效期 7200 秒,开发者必须在本人的服务全局缓存 jsapi_ticket)jssdk_getticket_url: https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

    application-dev.yml - 开发配置文件(可选)

    # 开发环境配置
    spring:
    profiles: dev
    
    #端口设置
    server:
    port: 8000

application-prod.yml - 生产配置文件(因 JS 接口平安域名限度,则采取正式生产配置)

# 生产环境配置
spring:
  profiles: prod

#端口设置
server:
  port: 8002

application-test.yml - 测试配置文件(可选)

# 生产环境配置
spring:
  profiles: prod

#端口设置
server:
  port: 8002

demo.html – 测试 h5 页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title> 测试 jssdk</title>
    <!-- 引入微信 JS 文件 -->
    <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" type="text/javascript"></script>
    <!-- 引入 jquery-->
    <script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
<script>
    // 获取以后页面地址
    var url = (window.location.href).split('#')[0];
    // 调取后盾接口获取权限验证配置
    $.ajax({
        type : "get",
        /*!!!切记到时候改成本人的 */
        url : "http://wxjssdk.javadog.net/weixin/initWXJSSDKConfigInfo?url="+url,// 替换网址,xxx 依据本人 jssdk 文件地位批改
        success : function(data){console.log("返回值为 =" + data);
            var msg = "";
            if(data.success){msg = JSON.parse(data.msg);
            }
            // 通过 config 接口注入权限验证配置
            wx.config({
                debug: true, // 开启调试模式, 调用的所有 api 的返回值会在客户端 alert 进去,若要查看传入的参数,能够在 pc 端关上,参数信息会通过 log 打出,仅在 pc 端时才会打印
                appId: msg.appid,
                timestamp: msg.timestamp,
                nonceStr: msg.nonceStr,
                signature: msg.signature,
                /*!!!切记到时候按需本人抉择,参考文档填写 */
                jsApiList: [
                    "onMenuShareAppMessage",// 分享给好友
                    "chooseImage"
                ]
            });
        },
        error:function(data){alert(JSON.stringify(data));
        }
    });

    // 通过 ready 接口解决胜利验证
    wx.ready(function (){
        wx.checkJsApi({jsApiList: ['chooseImage','onMenuShareAppMessage'],
            success: function (res) {JSON.stringify(res)}
        });
        var shareData = {
            title: '题目',
            desc: '简介',// 这里请特地留神是要去除 html
            link: url,
            imgUrl: 'http://b2b.haier.com/shop/userfiles/sys/1/files/201912/af656b3a-8c2c-424d-937b-a8035deb78f5.jpg'
        };
        wx.onMenuShareAppMessage(shareData);


    });
    // 从相册选取图片
    function wxchooseImage(){
        wx.chooseImage({
            count: 1, // 默认 9
            sizeType: ['original', 'compressed'], // 能够指定是原图还是压缩图,默认二者都有
            sourceType: ['album', 'camera'], // 能够指定起源是相册还是相机,默认二者都有
            success: function (res) {var localIds = res.localIds; // 返回选定照片的本地 ID 列表,localId 能够作为 img 标签的 src 属性显示图片}
        });
    }
</script>
</head>
<body>
<button onclick="wxchooseImage();"> 点我选取相册 </button>
</body>
</html>

🔥nginx 配置,此处不是我的项目中的代码!!!
nginx.config – nginx 服务器配置

 server
    {
        listen   80;                           #监听端口设为 80。server_name  wxjssdk.javadog.net;      #请绑定本人的前缀域名。location / {
        proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8002/;
      }
    }

MP_verify_B0vMQLCguxRzP1Rc.txt – JS 接口平安域名验证文件(到时候替换成本人公众号上的),必须在域名根门路下能够拜访

# 肯定把本人公众号上的 txt 验证文件放上!!!
B0vMQLCguxRzP1Rc

步骤详解

打开文档 JSSDK 应用步骤段落,如下⬇️

1. 绑定域名

先登录微信公众平台进入“公众号设置”的“性能设置”里填写“JS 接口平安域名”。如下⬇️

点击设置如下⬇️

关键点
  • 1. 只能是三个域名或门路,中文,ip,带端口等门路均不可
  • 2. 域名必须是 ICP 备案过的,有些同学 应用内网穿透花生壳之类的无奈设置 JS 平安域名
  • 3. 必须将 txt 文件搁置平安域名所对应的目录,如 wxjssdk.javadog.net/xxx.txt。可由 nginx 配置,只有能拜访即可,如果拜访不到则无奈设置 JS 平安域名
2. 引入 JS 文件

理论援用在咱们的我的项目 Demo.html 页面中第 9 行,如

3. 通过 config 接口注入权限验证配置

关键点

必须在 后盾凋谢一个对外获取 config 接口注入权限的接口

对应咱们代码中 **WxInitController.java 中的 initWXJSSDKConfigInfo()** 办法,会返回文档中所需的必填项 **appId,timestamp,nonceStr,signature** 验证参数
![在这里插入图片形容](https://img-blog.csdnimg.cn/20200224092342176.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JhaWR1XzI1OTg2MDU5,size_16,color_FFFFFF,t_70)
实现步骤
 1. 先通过 appId 和 appSecret 参数申请指定微信地址 获取 AccessToken
 2. 在通过第一步中的 AccessToken 作为参数申请微信地址 获取 jsapi_ticket 长期票据(此处不思考调用频率,使用者依据状况放入缓存或定时工作)
 3. 通过第二步的 JssdkGetticket 和 timestamp,nonceStr,url 作为参数申请微信地址,获取签名 signature
 4. 将第三步取得的 signature 和 jsapi_ticket,nonceStr,timestamp,url 返回给前端,作为 Config 初始化验证的信息

  • 1. 先通过 appId 和 appSecret 参数申请指定微信地址 获取 AccessToken
    对应咱们代码中 WxUtil.java 第 61 行getJSSDKAccessToken() 办法

    通过 本人公众号的 appId 和 appSecret调用 微信服务器 access_token 接口地址获取 token, 地址如下
    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_cre…
    将其中 APPID 和 APPSECRET替换成本人公众号的 appId 和 appSecret,调取后返回 Json 字符串后果,获取 access_token

  • 2. 通过第一步中的 AccessToken 作为参数申请微信地址 获取 jsapi_ticket 长期票据
    对应咱们代码中 WxUtil.java 第 81 行getJssdkGetticket() 办法

    通过上一步取得的 access_token 调用 微信服务器 jsapi_ticket 接口地址获取 jsapi_ticket, 地址如下
    https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_tok…
    将其中 ACCESS_TOKEN替换成上一步获取的 access_token,调取后返回 Json 字符串后果,获取 jsapi_ticket

  • 3. 通过第二步的 JssdkGetticket 和 timestamp,nonceStr,url 作为参数申请微信地址,获取签名 signature
    对应咱们代码中 WxUtil.java 第 102 行 buildJSSDKSignature()办法

    通过上一步取得的 jsapi_ticket,加上 timestamp(领取签名工夫戳),nonceStr(随机字符串),url(以后网页的 URL), 依照字段名的 ASCII 码从小到大排序(字典序)后通过 sha1 进行签名,生成最终签名数据。
    对应咱们代码中 WxUtil.java 第 115 行 sha1()办法

  • 4. 前端胜利接到返回值

对应咱们代码中 demo.html 第 16 行 $.ajax 办法

接口返回值为

JSON.parse(msg)转化一下 JSON 对象,对应咱们代码中的 Demo.html 中 24 行,转化后数据做 wx.config 接口注入权限验证,对应咱们代码 demo.html 第 37 行

4. 通过 ready 接口解决胜利验证

关键点

所以如果须要在页面加载时就调用相干接口,则须把相干接口放在 ready 函数中调用来确保正确执行
在咱们代码在 demo.html 第 46 行,自定义分享接口,须要在页面初始化加载时就放入 ready 才可失效

反之不须要初始化加载的即可通过用户事件触发执行即可
在咱们代码在 demo.html 第 63 行,用户点击按钮触发 - 拍照或从手机相册当选图接口

公布

我采纳的 IDEA 插件 Alibaba Cloud Toolkit 工具一键部署本地利用到 ECS 服务器,可百度或等我下篇文章详解一下这个插件的用法。

Target ECS:指标服务器,我买的是阿里的服务器,则间接能够搜寻到。
Target Directory: 目标目录,须要把打成的 jar 包上传至哪个门路下 如:/usr/local/hdx/web/
Command: 上传后执行的操作命令 如:nohup java -jar /usr/local/hdx/web/springboot-wexin.jar

公布胜利后会在终端呈现胜利提示信息

而后功败垂成,拜访一下试试 http://wxjssdk.javadog.net/demo.html
如果调试举荐应用 微信开发者工具,也就是

切记 配置 nginx 服务器平安端口拜访权限!!!否则会 404 哦!!!

测试

  • 1. 先来测试下拍照或从手机相册当选图接口

    调试失常

  • 2. 再来测试微信内置分享

    调试报错,这是个小坑。本狗在这调试了良久,起因出在集体的 订阅号是没有自定义分享权限 的!!

小坑总结

  1. 订阅号和服务号所波及权限不同,需具体查看微信开发文档,查问公众号权限
  2. IP 白名单未设置, 会报 40164

    IP 白名单须要在公众号 平安核心设置

  3. invalid signature 签名异样
    倡议应用微信 JSSDK 签名验证工具验证是否有误

我是 JavaDog,谢谢博友急躁看完, 抽空来我狗窝🐕瞅瞅呗 blog.javadog.net

正文完
 0