jwj 发布的文章

在实际的项目开发过程中,总会遇到多套程序使用一个公众号的情况。而共用一个公众号,首先会遇到的应该是access_token问题了,两个程序互相的去获取access_token,导致被“挤下线”。
这次我遇到的情况比较简单,两套程序都是自己负责开发的,所以比较好处理,只需要修改代码,让它们共用access_token即可。

什么是access_token?

access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。

为什么会被“挤下线”呢?

access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效

怎么解决被“挤下线”呢?

建议公众号开发者使用中控服务器统一获取和刷新access_token,其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则容易造成冲突,导致access_token覆盖而影响业务

详细想法

微信那边建议的是,使用中控服务器统一获取和刷新access_token,但要去搞一套中控程序,那就太麻烦了,还是用现有的实在点。
这里想到的是用redis来储存access_token,然后A程序从redis获取access_token
如果access_token不存在或已过期,则A程序就从微信服务器获取access_token,然后更新到redis里去。
这样,B程序去resis获取到的access_token就是最新的了,不用再去微信哪里获取,导致A程序获取到的access_token失效。
当然A跟B的顺序不是固定的,谁先发现access_token过期,就谁去更新。然后,如果刚好并发,也有极有可能会出问题(出问题再说)。

ThinkPHP配置

因为要用TP的缓存,所以要在缓存配置里增加redis配置,这样才能用redis来储存缓存内容。
首先,按照手册配置缓存配置,增加Redis的配置。

<?php
use think\facade\Env;

// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------

return [
    // 默认缓存驱动
    'default' => Env::get('cache.driver', 'file'),

    // 缓存连接方式配置
    'stores'  => [
        'file' => [
            // 驱动方式
            'type'       => 'File',
            // 缓存保存目录
            'path'       => '',
            // 缓存前缀
            'prefix'     => '',
            // 缓存有效期 0表示永久缓存
            'expire'     => 0,
            // 缓存标签前缀
            'tag_prefix' => 'tag:',
            // 序列化机制 例如 ['serialize', 'unserialize']
            'serialize'  => [],
        ],
        /*** 下面这些是新加的 ***/
        // Redis缓存驱动
        'redis'   =>  [
            // 驱动方式
            'type'   => 'redis',
            // 服务器地址
            'host'       => '127.0.0.1',
        ],
        /*** 上面这些是新加的 ***/
    ],
];

EasyWeChat使用示例

虽然详细想法里写了很多,但其中很多工作都EasyWeChatThinkPHP完成了,所以代码很简单。
下面是简单的使用示例:

// 初始化EasyWeChat,app_id和secret经过脱敏,不要zhao'chao
$wechat = \EasyWeChat\Factory::officialAccount([
    'app_id'    => 'wx4202f388888',
    'secret'    => 'b06e645090bb1bd0aefc6588888',
]);

// 就这么简单的一句,就可以使用Redis储存AccessToken了
$wechat->access_token->setCache(\think\facade\Cache::store('redis'));

// 发模板消息
$wechat->template_message->send([
    'touser'      => 'dsadasdasdas',
    'template_id' => 'vN_nAl6UiLbCnCT_-lwPoGgaMZUXvY0G72Rr3C-5k6o',
    'url'         => 'https://blog.ll00.cn',
    'data'        => [
        // 头部
        'first'    => '您有新的待审批通行证,请尽快处理!',
        // 申请内容
        'keyword1' => '钞票',
        // 预约时间
        'keyword2' => '2020年6月6日',
        // 申请人
        'keyword3' => '西虹市首富',
        // 申请时间
        'keyword4' => '2020年5月20日 13时14分',
        // 底部
        'remark'   => '王多鱼爱夏竹冠名代码',
    ],
]);

layui的数据表格用起来的确很方便,开发时能节省很多时间。但是,在投入使用后,导出的表格却是能收到很多反馈,说内容不对。不对的地方主要体现在身份证号码之类的比较长数值,用Excel软件打开后,15位以后的数值会丢失,导致身份证号码不完整。Layui最近一两年的更新力度越来越小了,经常跳票,也不知道能活多久,只能先自己动手吧~

首先,我们用文本查看工具查看导出的内容,可以确定,导出的身份证号码是完整,但用Excel软件打开之后,就出问题了。为此,我百度了下Excel的处理机制,得知,Excel显示数字时,如果数字大于12位,它会自动转化为科学计数法,如果数字大于15位,它不仅用于科学技术法表示,还会只保留高15位,其他位都变0。

如果要解决这个问题,目前只想到一个解决方法,让Excel处理这个数据的时候,不识别它为数值。这要怎么做呢?

首先,我们先前往github下载未压缩过的代码,搜索table.exportFile = function
这个方法的原始代码如下

//表格导出
table.exportFile = function(id, data, type){
    var that = this;

    data = data || table.clearCacheKey(table.cache[id]);
    type = type || 'csv';

    var config = thisTable.config[id] || {}
        ,textType = ({
        csv: 'text/csv'
        ,xls: 'application/vnd.ms-excel'
    })[type]
        ,alink = document.createElement("a");

    if(device.ie) return hint.error('IE_NOT_SUPPORT_EXPORTS');

    alink.href = 'data:'+ textType +';charset=utf-8,\ufeff'+ encodeURIComponent(function(){
        var dataTitle = [], dataMain = [], dataTotal = [];

        //表头和表体
        layui.each(data, function(i1, item1){
            var vals = [];
            if(typeof id === 'object'){ //如果 id 参数直接为表头数据
                layui.each(id, function(i, item){
                    i1 == 0 && dataTitle.push(item || '');
                });
                layui.each(table.clearCacheKey(item1), function(i2, item2){
                    vals.push('"'+ (item2 || '') +'"');
                });
            } else {
                table.eachCols(id, function(i3, item3){
                    if(item3.field && item3.type == 'normal' && !item3.hide){
                        var content = item1[item3.field];
                        if(content === undefined || content === null) content = '';

                        i1 == 0 && dataTitle.push(item3.title || '');
                        vals.push('"'+ parseTempData(item3, content, item1, 'text') + '"');
                    }
                });
            }
            dataMain.push(vals.join(','));
        });

        //表合计
        layui.each(that.dataTotal, function(key, value){
            dataTotal.push(value);
        });

        return dataTitle.join(',') + '\r\n' + dataMain.join('\r\n') + '\r\n' + dataTotal.join(',');
    }());

    alink.download = (config.title || 'table_'+ (config.index || '')) + '.' + type;
    document.body.appendChild(alink);
    alink.click();
    document.body.removeChild(alink);
};

然后将里面的

vals.push('"'+ parseTempData(item3, content, item1, 'text') + '"');

替换成

content = parseTempData(item3, content, item1, 'text').replace(/(^\s*)|(\s*$)/g, "");
if (/^\d+$/.test(content) && content.length > 15 && type == 'xls') {
    vals.push('="'+ content + '"');
} else {
    vals.push('"'+ content + '"');
}

显示问题解决了,但不适合用于数据运算,但办公室的Excel大神们应该有办法吧。反正我能让他正常显示就行了,其它我不管,哈哈。

哦,对了,差点忘了标题。上面只是解决了数值大于15位会丢失尾数的问题,并没有解决科学计数法的问题。如果想不显示科学计数法,将里面的代码替换下即可。其实推荐使用上面的代码就可以了,科学计数法问题可以设置单元格格式来解决。

vals.push('"'+ parseTempData(item3, content, item1, 'text') + '"');

替换成

content = parseTempData(item3, content, item1, 'text').replace(/(^\s*)|(\s*$)/g, "");
if (/^\d+$/.test(content) && content.length > 12 && type == 'xls') {
    vals.push('="'+ content + '"');
} else {
    vals.push('"'+ content + '"');
}

每次要在电脑上启动v2ray还是挺不方便的,直接在路由器运行,这样局域网的设备都能直接使用,方便很多。

更新opkg源

opkg update
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/targets/ralink/mt7621/packages/Packages.gz
Updated list of available packages in /var/opkg-lists/19.02_core
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/base/Packages.gz
Updated list of available packages in /var/opkg-lists/19.02_base
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/newifi/Packages.gz
Updated list of available packages in /var/opkg-lists/19.02_newifi
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/pear/Packages.gz
Updated list of available packages in /var/opkg-lists/19.02_pear
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/packages/Packages.gz
Updated list of available packages in /var/opkg-lists/19.02_packages
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/luci/Packages.gz
Updated list of available packages in /var/opkg-lists/19.02_luci
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/lafite/Packages.gz
Updated list of available packages in /var/opkg-lists/19.02_lafite
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/mtkdrv/Packages.gz
Updated list of available packages in /var/opkg-lists/19.02_mtkdrv

安装unzip

opkg install unzip
Installing unzip (6.0-2) to root...
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/packages/unzip_6.0-2_mipsel_1004kc_dsp.ipk
Configuring unzip.

安装ssl ca证书

opkg install wget ca-certificates openssl-util ca-bundle
Package wget (1.18-2) installed in root is up to date.
Installing ca-certificates (20160104) to root...
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/base/ca-certificates_20160104_all.ipk
Installing openssl-util (1.0.2o-1) to root...
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/base/openssl-util_1.0.2o-1_mipsel_1004kc_dsp.ipk
Installing ca-bundle (20160104) to root...
Downloading http://downloads.pangubox.com:6380/pandorabox/19.02/packages/mipsel_1004kc_dsp/base/ca-bundle_20160104_all.ipk
Configuring openssl-util.
Configuring ca-certificates.
Configuring ca-bundle.

下载v2ray

wget https://github.com/v2ray/v2ray-core/releases/download/v4.23.1/v2ray-linux-mipsle.zip

解压v2ray

unzip v2ray-linux-mipsle.zip
Archive:  v2ray-linux-mipsle.zip
  inflating: config.json
   creating: doc/
  inflating: doc/readme.md
  inflating: geoip.dat
  inflating: geosite.dat
   creating: systemd/
  inflating: systemd/v2ray.service
   creating: systemv/
  inflating: systemv/v2ray
  inflating: v2ctl
 extracting: v2ctl.sig
  inflating: v2ctl_softfloat
 extracting: v2ctl_softfloat.sig
  inflating: v2ray
 extracting: v2ray.sig
  inflating: v2ray_softfloat
 extracting: v2ray_softfloat.sig
  inflating: vpoint_socks_vmess.json
  inflating: vpoint_vmess_freedom.json

配置v2ray

省略,跟linux或windows端一样配置

运行v2ray

./v2ray
V2Ray 4.23.1 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.13 linux/mipsle)
A unified platform for anti-censorship.
2020/04/11 13:35:08 Using default config:  /mnt/sda1/v2ray/config.json
2020/04/11 13:35:11 [Info] v2ray.com/core/common/platform/ctlcmd: <v2ctl message>
v2ctl> Read config:  /mnt/sda1/v2ray/config.json
2020/04/11 13:35:12 [Warning] v2ray.com/core: V2Ray 4.23.1 started

写入启动项

系统 - 启动项 - 本地启动脚本

# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

/mnt/sda1/v2ray/v2ray >/dev/null 2>&1 &

exit 0

下载:https://downloads.mysql.com/archives/community/
解压到:C:\Program Files目录
创建my.ini配置文件

[mysql]
port = 3306
default-character-set=utf8

[mysqld]
default_authentication_plugin=mysql_native_password
port = 3306
basedir="C:/Program Files/mysql-5.7.28-winx64"
datadir="C:/Program Files/mysql-5.7.28-winx64/data"
log-error="C:/Program Files/mysql-5.7.28-winx64/logs/mysql.log"
character-set-server=utf8
default-storage-engine=INNODB

C:/Program Files/mysql-5.7.28-winx64加入环境变量
初始化mysql

mysqld --initialize-insecure --user=root

初始化后,默认用户为root,密码为空
安装服务

mysqld --install

执行返回

Service successfully installed.

启动服务

今天重新安装了下Wampserver3.2.0,安装好之后,发下MySQL8.0数据库的服务一直启动不了,查看事件查看器应用程序日志没有错误信息,查看MySQL日志也没有错误信息,这就很蛋疼了!

既然通过刚刚那些地方都找不到错误信息,只能在控制台尝试运行下mysql了。在控制台打开mysqlbin目录,然后输入

./mysqld

返回以下错误

2020-03-08T12:13:19.585857Z 0 [System] [MY-010116] [Server] C:\wamp64\bin\mysql\mysql8.0.18\bin\mysqld.exe (mysqld 8.0.18) starting as process 3132
2020-03-08T12:13:19.813867Z 0 [Warning] [MY-010091] [Server] Can't create test file C:\wamp64\bin\mysql\mysql8.0.18\data\mysqld_tmp_file_case_insensitive_test.lower-test
2020-03-08T12:13:19.814672Z 0 [Warning] [MY-010091] [Server] Can't create test file C:\wamp64\bin\mysql\mysql8.0.18\data\mysqld_tmp_file_case_insensitive_test.lower-test
2020-03-08T12:13:19.815318Z 0 [ERROR] [MY-013276] [Server] Failed to set datadir to 'C:\wamp64\bin\mysql\mysql8.0.18\data\' (OS errno: 2 - No such file or directory)
2020-03-08T12:13:19.988677Z 0 [ERROR] [MY-010119] [Server] Aborting
2020-03-08T12:13:19.997084Z 0 [System] [MY-010910] [Server] C:\wamp64\bin\mysql\mysql8.0.18\bin\mysqld.exe: Shutdown complete (mysqld 8.0.18)  MySQL Community Server - GPL.

通过错误信息,可以知道,因为文件无法创建,导致MySQL启动失败。再检查下MySQLdata目录,发现这个目录不存在。
然后回想下安装过程,安装的时候,因为没有提前安装好运行库,所以安装过程中,提示了几次缺少xxx.dll。我想应该是这个原因,导致MySQL初始化失败了。
那就手动初始化下吧~还是打开控制台,在控制台打开mysqlbin目录,然后输入以下命令

mysqld --initialize-insecure --user=root

执行完之后,再尝试启动MySQL的服务,正常运行~