题目

本帖针对微信JSSDK网页开发中碰到的坑,讲述填坑进程。

官网: developers.weixin.qq.com/doc/offiacc…

流程

过程一:获取大众号的access_token准备工作

目的:正如一切揭露渠道,都需求注册并获取appID和appSecret,以便你开发的“app”能够拜访该大众号的资源(大众号不一定是你一切,能够是的客户的,只需供给appID和appSecret即可)

办法:获取大众号的appID和appSecret,并设置你的服务器的ip地址(假如本地开发,则用本机IP:百度搜索ip即可)

微信JS-SDK公众平台网页开发大坑硬填

过程二:设置你的网页的domain

目的:白名单你的域名,这样你的网页比方http(s)://domain.com/page.index 就能够调用JS-SDK来获取微信渠道/app露出给你的功用,比方摄影,录音,付出等原生的H5没有的功用,能够把JSSDK看成是一个桥接器。

为什么要这样?你可能有这样的疑问。的确,相似的开发渠道有时分设置很麻烦,简单让人摸不着头脑。为了快速理清思路,我一般会这么想:假如我是渠道方,我会怎么做?所以,假如你是微信方,你会不会想:尽管我有接口让开发者动态供给url并给他返回签名,见签名文档,但是这个url我没有做任何约束,会不会有安全隐患,就算没有安全隐患也要管控吧?所以,要供给白名单功用。

微信JS-SDK公众平台网页开发大坑硬填

办法:如图,输入根域名和www次域名(不一定要输入,这个不一定,没有测验)

条件:

  1. 域名需求icp
  2. 用txt文件验证域名一切权

我的操作,办法1

  1. 在linux部署nginx(腾讯服务器,由于好像icp存案完成后也需求指向一个服务器)
  2. 设置nginx(大约如下)

server {
    root /var/www/domain.com;
    index index.html  index.htm;
   server_name  www.domain.com domain.com;
    location / {
        try_files $uri $uri/ /index.html?/$request_uri;
    }
}
  1. 部署certbot增加https

  2. 把txt文件放入 /var/www/domain.com

  3. 大众号验证成功

别的一个办法2(没有测验):

  1. 免费获取阿里云或许腾讯云的证书(免费的不是通配符,比方能够是www.domain.com)

  2. 注册腾讯云COS或许阿里的OSS,把文件夹绑定到域名上面(经过CDN)

  3. 把txt文件放到OSS或许COS上面

  4. 大众号认证

定论:

  1. 大众号txt认证,好像认证不需求https协议,http即可(除非你用的是办法2,由于CDN需求https)

  2. 白名单后,测验网页域名好像不需求https(测验http能够)

  3. 白名单根域名后(domain.com)后,测验网页好像能够是其他次域名,比方ngrok.domain.com

第2,3定论,请持续看。

过程三:服务器获取signature

目的:服务器(过程一,白名单的IP)从微信拿到签名

import cache from 'memory-cache';
import sha1 from 'sha1';
import config from '../config';
import { axiosGet } from './util';
export default function (url: string) {
    return new Promise((resolve, reject) => {
        const noncestr = config.wechat.noncestr;
        const timestamp = Math.floor(Date.now() / 1000); //精确到秒
        if (cache.get('ticket')) {
            console.log('get wechat ticket from memory cache...success');
            const jsapi_ticket = cache.get('ticket');
            return resolve({
                openTagList: "wx-open-launch-weapp",
                appId: config.wechat.appid,
                nonceStr: noncestr,
                timestamp: timestamp,
                url: url,
                jsapi_ticket: jsapi_ticket,
                signature: sha1('jsapi_ticket=' + jsapi_ticket + '&noncestr=' + noncestr + '&timestamp=' + timestamp + '&url=' + url)
            });
        }
        console.log('ticket expired, refetching token and ticket...');
        axiosGet(config.wechat.accessTokenUrl, {
            grant_type: config.wechat.grant_type,
            appid: config.wechat.appid,
            secret: config.wechat.secret
        }).then(res => {
            const accessToken = res.data.access_token;
            axiosGet(config.wechat.ticketUrl, {
                access_token: accessToken,
                type: 'jsapi',
            }).then(res => {
                const ticket = res.data.ticket;
                cache.put('ticket', ticket, config.wechat.cache_duration);
                resolve({
                    appId: config.wechat.appid,
                    openTagList: "wx-open-launch-weapp",
                    nonceStr: noncestr,
                    timestamp: timestamp,
                    url: url,
                    jsapi_ticket: ticket,
                    signature: sha1('jsapi_ticket=' + ticket + '&noncestr=' + noncestr + '&timestamp=' + timestamp + '&url=' + url)
                });
            }).catch(err => {
                reject(err);
            });
        });
    });
}
//util
export const axiosGet = async <T>(baseUrl: string, params: T) : Promise <any> => {
  try { 
    return await axios.get(baseUrl, {
        params
    });
  }catch (e) {
    console.log(e);
  }
};

定论:

  1. 先获取access_token (微信设置两小时过期,见官网)

  2. 然后换取js_ticket (微信设置两小时过期,见官网)

  3. 自己设置缓存,防止重复请求微信形成拒绝

过程四:本地开发网页H5并调取JSSDK

目的:开发前端

办法: 用微信开发者东西IDE开发(用浏览器调用JSSDK没有反应,由于不是微信模仿环境)

微信JS-SDK公众平台网页开发大坑硬填

问题来啦:假如你用本地开发localhost在IDE中会无法拜访接口,过错如下:

  • localhost,在微信开发者东西中调试时报以下过错:
  • xxxx:fail, the permission value is offline verifying

糟糕的英语的意思是:网页为离线网页,即没有在服务器上。

过程五:填补大坑

目的:把认证的域名domain.com映射到本地localhost,解决如上问题。问题的本源是,好像IDE在夹在JSSDK的时分,会把当时的url传递到微信后端,并核对是否是认证的域名,假如不是则报错。

办法:首先讲,这个开发十分不友爱。

  1. 开发不可能把网页放到真实服务器上开发,几乎是自杀式开发

  2. 微信为啥不能白名单localhost,给程序员供给一个友爱的开发环境

  3. 微信为啥不能供给一个沙箱测验appID来放开localhost约束

既然,没有这样的环境,只能想办法自己解决。

基本思路:把认证的域名映射到本地localhost,然后在IDE输入域名,欺骗微信IDE,即:domain.com -> localhost

办法1(macos):

  1. 编辑hosts文件 $ sudo nano /etc/hosts

  2. 映射domain到localhost

localhost www.domain.com

  1. 测验

ping www.domain.com

  1. 用www.domain.com开发,成果发现失利。 由于代码放在localhost 3000端口上。默认的localhost在80端口。

  2. 需求把代码加载到80端口,比方用reactjs的话是

sudo PORT=80 react-scripts start

留意:80端口小于1024,所以需求sudo权限

怎么把domain映射到恣意的localhost的端口呢?

办法1:

  1. 购买ngrok的服务ngrok.com,大约是25美金pro版

  2. 把domain域名绑定到ngrok, 设置CNAME进行绑定比方:ngrok.domain.com(不影响你现有的www.domain.com拜访互联网,CNAME设置也只是影响ngrok次域名)

  3. 下载ngrok,并运行

$ ./ngrok http --hostname=ngrok.domain.com 3000

  1. 成功

⚠️留意:ngrok的设置办法和config文件如下

⚠️留意:在wechat的IDE上面假如你输入 ngrok.domain.com的话,拜访本地服务器可能会有跨域过错,所以要用https

nano .ngrok2/ngrok.yml

微信JS-SDK公众平台网页开发大坑硬填

参数ngrok.com/docs/ngrok-…

办法2:(没有测验)

  1. 本地建立nginx服务器

  2. 把domain映射到loalhost

  3. 然后经过nginx的vhosts敞开不同的端口