一指流砂 发布的文章

这个问题真的是一个很坑的问题,在安卓中可以正常扫描,但到苹果机中,就是扫不出来。后来找了好久的资料,终于搞定了。
我是参考的这篇文章解决的问题:https://blog.csdn.net/kung_com/article/details/89497038

其实是一个很简单的需求,调用微信jssdk的扫一扫接口,来识别二维码的内容进行上传。但是安卓可以,苹果就是死活识别不出来。在这记录一下,也特别感谢上面地址的那位兄台,解决了我一个麻烦。

坑:
微信JSSDK文档中,没有对扫一扫接口做任何多余的解决,十分简单,如下:

wx.scanQRCode({
  needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
  scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
  success: function (res) {
    var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
  }
});

上面的代码,调起微信扫一扫功能之后,苹果机中无法识别PDF417格式的二维码,经过查找资料之后,需要对scanType参数做处理,加上"qrCode"和"barCode"就可以了,效果如下:

wx.scanQRCode({
  needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
  scanType: ["qrCode","barCode","qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
  success: function (res) {
    var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
  }
});

微信文档真的好坑好坑!!!

算法概述

  • 加密因子:0xA3
  • 加密算法:将待加密的字符串中的每一个字节,分别与加密因子进行异或,然后将异或后的二进制结果进行高低位交换,然后将交换后的结果转换成2进制字符串。所有的字节转换完成后,将最终的结果base64加密。
  • 解密算法:其实就是加密算法的反向操作。先将加密字符串base64解密,然后字符串的每一个字节(就是上面转的二进制字符串)转换成二进制,再将二进制高低位交换、异或,最后将二进制转换成字符。

具体代码

/**
 * 加密算法
 */
function encrypt($str, $secret)
{
    // 存放结果字符串
    $result = ''; 
    // 加密
    for($i = 0; $i < strlen($str); $i++) {
        // 异或
        $xor = ord($str[$i]) ^ hexdec($secret);
        // 转二进制
        $binary = decbin($xor);
        // 高低位交换
        $reverse = implode('', array_reverse(str_split($binary, 4)));
        // 转换成16进制,如果出现1位的情况,左侧补0
        $encodeData = str_pad(base_convert($reverse, 2, 16), 2, '0', STR_PAD_LEFT);
        // 16进制转二进制字符串
        $result .= pack('H*', $encodeData);
    }
    return base64_encode($result);
}

/**
 * 解密算法
 */
function decrypt($str, $secret)
{
    // 存放结果字符串
    $result = '';
    // 解码base64
    $str = base64_decode($str);
    // 解密
    for($i = 0; $i < strlen($str); $i++) {
        // 二进制字符串转16进制
        $hexadecimal = unpack('H*', $str[$i])[1];
        // 16进制转2进制
        $binary = str_pad(base_convert($hexadecimal, 16, 2), 8, '0', STR_PAD_LEFT);
        // 高低位交换
        $reverse = implode('', array_reverse(str_split($binary, 4)));
        // 异或
        $xor = bindec($reverse) ^ hexdec($secret);
        // 二进制转字符串
        $result .= pack('C', $xor);
    }
    return $result;
}

$result = encrypt('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890~!@#$%^&*()_+-=', 'A3');
$result = decrypt($result, 'A3');

使用这个需求的背景先介绍一下
我是一个PHP程序员,因为平时开发和部署项目的服务器环境,一直都依赖于宝塔面板。但用户我一直用的都是root,经过一次手滑,在root用户下执行了chmod -R www:www / ,结果可想而知,有这一次事故之后,我决定用宝塔的web用户做开发,也就是www用户,所以记录一下将www用户设置为可以登陆用户的过程。

  • 设置用户可以登陆

正常情况下,安装完宝塔之后,如果想用www用户来编辑代码,会这样提示:

# su www
Cannot execute /sbin/nologin: No such file or directory

/sbin/nologin意思就是不允许登陆的shell,现在就需要切换到root用户下编辑 /etc/passwd 文件,找到需要登陆的用户名,如我现在要切换的用户名是www,如下:

www:x:1000:1000::/home/www:/sbin/nologin

/home/www是用户的默认home目录,/sbin/nologin就是用户的登陆shell,将它改为:/bin/bash就可以了。

  • 设置登陆密码

有些情况,www用户需要使用到sudo命令,这时就需要给www用户设置一个密码,切换到root用户,执行下面的命令

# passwd www
Enter new UNIX password:
Retype new UNIX password:

输入两次密码,密码就设置完成了,但切换到www用户后,又会出现下面的提示:

[sudo] password for www: 
www is not in the sudoers file.  This incident will be reported.

解决办法:

先切换到root用户下,给/etc/sudoers文件增加写的权限

chmod u+w /etc/sudoers

然后编辑/etc/sudoers文件

vim /etc/sudoers

找到这行 root ALL=(ALL) ALL,在他下面添加xxx ALL=(ALL) ALL (这里的xxx是你的用户名)
PS:这里说下你可以sudoers添加下面四行中任意一条

youuser            ALL=(ALL)                ALL
%youuser           ALL=(ALL)                ALL
youuser            ALL=(ALL)                NOPASSWD: ALL
%youuser           ALL=(ALL)                NOPASSWD: ALL

第一行:允许用户youuser执行sudo命令(需要输入密码).
第二行:允许用户组youuser里面的用户执行sudo命令(需要输入密码).
第三行:允许用户youuser执行sudo命令,并且在执行的时候不输入密码.
第四行:允许用户组youuser里面的用户执行sudo命令,并且在执行的时候不输入密码.

最后撤销sudoers文件写权限,命令:

chmod u-w /etc/sudoers

一直以来都过度依赖于宝塔面板,很少配置环境了。这次有客户要求必须要用docker来配置服务器环境,于是用docker装了一个ubuntu,在这个ubuntu中安装php和nginx环境。遇到的坑不少,感觉值得记录的,就是这个path_info模式配置了,各种尝试各种不对,最终还是把宝塔的path_info配置复制了过来,生效了,具体配置如下:

location / {
    index index.php index.html index.htm;
    if (!-e $request_filename) {
        rewrite  ^(.*)$  /index.php?s=/$1  last;
        break;
    }   
}

location ~ [^/]\.php(/|$) {
    try_files $uri =404;
        
    # 这是宝塔的配置
    set $real_script_name $fastcgi_script_name;
    if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
        set $real_script_name $1; 
        set $path_info $2; 
    }   
    fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
    fastcgi_param SCRIPT_NAME $real_script_name;
    fastcgi_param PATH_INFO $path_info;                                                                                                                                                    

    include        fastcgi_params;
}

插入排序算法

插入排序,基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。(引自百度百科)
  • 插入排序的中心思想是,从数组的第二个元素开始向前比较,如果前面的元素比当前元素要大,则从前面的那个元素开始,下标整体后移,直到当前元素不大于前面的元素时,终止比较并用当前元素替换到前面后移的位置。

C语言代码demo如下:

#include <stdio.h>
int main()
{
    // 原始数组
    int nums[] = {4, 5, 2, 10, 7, 1, 8, 3, 6, 9}; 

    for (int j = 2; j < 10; j++) {
        int key = nums[j];
        int i = j - 1;
        while (i >= 0 && nums[i] > key) {
            nums[i + 1] = nums[i];
            i = i - 1;
        }
        nums[i + 1] = key;
    }

    // 输出排序后的数组
    for (int i = 0; i < 10; i++) {
        printf("%d ", nums[i]);
    }
    printf("\n");

    return 0;
}