微信 JSSDK 教程以及在Vue中实战教程

Hi,很高兴认识你~

世界很大,巧妙的是我们在这里相遇。

欢迎关注天宇文创意乐派,一个职场人的聚集地。

一.官方教程

官方文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html

官方文档——常见的错误及解决方法:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html     ——>  见页面底端的 附录5-常见错误及解决方法

官方问题反馈:https://developers.weixin.qq.com/community/develop/doc/0000e2f5d0cdc02c0a391aedd58c00

官方校验签名工具:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

官方demo:https://www.weixinsxy.com/jssdk/

二.常见问题以及需要注意的地方

1. invalid signature签名错误。建议按如下顺序检查:
    1. 确认签名算法正确,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。
    2. 确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。
    3. 确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。
    4. 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
    5. 确保一定缓存access_token和jsapi_ticket。
    6. 确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取,而且需要encodeURIComponent,后端接收url时且必须用例如:Java URLDecoder.decode解码),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。

2.invalid domain?
    配置的url与公众号JS接口安全域名不匹配

三.绑定JS接口安全域名

图片图片

域名格式:如果你的项目域名是http://test.domain.com,那么JS接口安全域名为test.domain.com。切记!

四.引入JSSDK

第一种引入方式:

npm install jweixin-module --save

第二种引入方式:

在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js
如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>

代码实现:

前端

import wx from 'weixin-js-sdk';

async _goWxchat(){
  let url = encodeURIComponent(location.href.split('#')[0]);
  let data={
  url
  }
  alert(url)
  const res = await reqConfigSignature(data);
  if (res.code === RESULT_SUCCESS_CODE) {
    //拿到后端给的这些数据
    let appId = res.data.appId;  
    let timestamp = res.data.timestamp;
    let nonceStr = res.data.nonceStr;
    let signature = res.data.signature;
    wx.config({
      debug: true,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
      appId,         // 必填,公众号的唯一标识,填自己的!(开发者账号)
      timestamp, // 必填,生成签名的时间戳,刚才接口拿到的数据
      nonceStr,   // 必填,生成签名的随机串
      signature, // 必填,签名,见附录1
      jsApiList: [
        'onMenuShareTimeline',
        'onMenuShareAppMessage'
      ]
    })
    wx.ready(function () {
      //分享到朋友圈
      wx.onMenuShareTimeline({
        title: '小婊子',   // 分享时的标题
        link: url + '?redirectUrl=http://auth.motopa.cn/logo.png',     // 分享时的链接  如果项目域名与JS接口安全域名不一致 可以采用此方式
        imgUrl: '',    // 分享时的图标
        success: function () {
          console.log("分享成功");
        },
        cancel: function () {
          console.log("取消分享");
        }
      });


      //分享给朋友
      wx.onMenuShareAppMessage({
        title: tit,
        desc: '这件商品终于优惠了,每件只需元',
        link: url + '?redirectUrl=http://auth.motopa.cn/logo.png',
        imgUrl: '',
        type: '',
        dataUrl: '',
        success: function () {
          console.log("分享成功");
        },
        cancel: function () {
          console.log("取消分享");
        }
      });
    })

    wx.error(function(res){
    })
  }
},

后端

package com.auth.sdk.controller;


import com.alibaba.fastjson.JSONObject;
import com.auth.sdk.common.ResultData;
import com.auth.sdk.db.redisson.dao.base.StringRedisBaseDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Random;


@RestController
@RequestMapping("/wx")
@Slf4j
public class WxShareController {


    private static final String appId = "wxea6631d168a33e95";


    private static final String appSecret= "3eae75d6a79a9af781391c9c1460026f";


    private static final long expireTime = 120l;


    @Autowired
    RestTemplate restTemplate;

    //redis 可以替换成自己环境的redis
    @Autowired
    StringRedisBaseDao stringRedisBaseDao;


    /**
     * 获取最终签名的restful方法
     * @param reqJson
     * @return
     */
    @PostMapping("/WeixinAction_getWXConfigSignature")
    public ResultData getWXConfigSignature(@RequestBody JSONObject reqJson) {
        String url = URLDecoder.decode(reqJson.getString("url"));
        log.info("原始URL: " + url);
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String nonceStr = getRandomStr(8);
        log.info("随机串:"+nonceStr+", 获取签名URL: " + url);
        JSONObject respJson = new JSONObject();
        String[] signArr = new String[]{"url=" + url, "jsapi_ticket=" + getWXJsapiTicket(), "noncestr=" + nonceStr, "timestamp=" + timestamp};
        Arrays.sort(signArr);
        String signStr = StringUtils.join(signArr, "&");
        String resSign = DigestUtils.sha1Hex(signStr);
        log.info("返回的签名:" + resSign);
        respJson.put("appId", appId);
        respJson.put("timestamp", timestamp);
        respJson.put("nonceStr", nonceStr);
        respJson.put("signature", resSign);
        log.info(respJson.toJSONString());
        return ResultData.success(respJson);
    }


    /**
     * 获取jsapi_ticket方法
     * @return
     */
    private String getWXJsapiTicket() {
        String ticket = stringRedisBaseDao.getItem(appId);
        if (StringUtils.isBlank(ticket)) {
            String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + getWXaccessToken() + "&type=jsapi";
            String resp = restTemplate.getForObject(url, String.class);
            JSONObject resJson = JSONObject.parseObject(resp);
            log.info("获取到ticket:" + resJson.getString("ticket"));
            stringRedisBaseDao.addItem(appId, resJson.getString("ticket"), expireTime);
            return resJson.getString("ticket");
        }
        return ticket;
    }


    /**
     * 获取access_token
     * @return
     */
    private String getWXaccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;
        String resp = restTemplate.getForObject(url, String.class);
        JSONObject resJson = JSONObject.parseObject(resp);
        log.info("获取到access_token:" + resp);
        return resJson.getString("access_token");
    }


    /**
     * 随机字符串
     * @param length
     * @return
     */
    public static String getRandomStr(int length) {
        String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        int randomNum;
        char randomChar;
        Random random = new Random();
        // StringBuffer类型的可以append增加字符
        StringBuffer str = new StringBuffer();

        for (int i = 0; i < length; i++) {
            // 可生成[0,n)之间的整数,获得随机位置
            randomNum = random.nextInt(base.length());
            // 获得随机位置对应的字符
            randomChar = base.charAt(randomNum);
            // 组成一个随机字符串
            str.append(randomChar);
        }
        return str.toString();
    }
}

微信分享步骤测试 建议在wechat开发工具中测试

配置 switchhost  将本机指向JS接口安全域名

图片

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值