Guzzle 使用文档

安装

composer require guzzlehttp/guzzle:7.0.1

发起 Get 请求

use GuzzleHttp\Client as guzzleClient;

$guzzleClient = new guzzleClient([
    'timeout' => 2.0
]);

// 同步请求方式
$response = $guzzleClient->get('http://api.org/get', ['headers' => ['User-Agent' => 'Guzzle'], 'http_errors' => false]);
$code = $response->getStatusCode();
$body = $response->getBody();
$content = $body->getContents();
// 异步请求方式
$promise = $guzzleClient->getAsync('http://api.org/get');
$promise->then(
    function (ResponseInterface $res) {
        echo $res->getStatusCode() . "\n";
    },
    function (RequestException $e) {
        echo $e->getMessage() . "\n";
        echo $e->getRequest()->getMethod();
    }
);

发起 Post 请求

use GuzzleHttp\Client as guzzleClient;

$guzzleClient = new guzzleClient([
    'timeout' => 2.0
]);

// 原始类型
$response = $guzzleClient->post('http://api.org/post', [
    'body' => 'raw data'
]);

// json 类型 application/json
$response = $guzzleClient->post('http://api.org/post', [
    'json' => ['name' => 'admin']
]);

// 表单类型 application/x-www-form-urlencoded
$response = $guzzleClient->post('http://api.org/post', [
    'form_params' => [
        'username' => 'abc',
        'password' => '123'
    ]
]);

// 上传文件 multipart/form-data
$response = $guzzleClient->post('http://api.org/post', [
    'multipart' => [
        [
            'name'     => 'user',
            'contents' => 'admin'
        ],
        [
            'name'     => 'file',
            'contents' => fopen('/path/to/file', 'r')
        ],
    ]
]);

EasySwoole环境和框架安装

安装 PHP 环境

# PHP 7.3.19
# Swoole 4.5.2
# Composer 1.10.10

配置阿里云镜像源

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

安装 EasySwoole

composer require easyswoole/easyswoole=3.3.7
php vendor/easyswoole/easyswoole/bin/easyswoole install
composer dump-autoload

安装 RPC 组件

composer require easyswoole/rpc=4.0.10

启动 EasySwoole

php easyswoole start

PHP实现Base16编码算法

我们经常使用的 Base64 编码用来对字符串或者字节数组进行编码转换,以方便存储。可是Base64 编码的结果可能会带有特殊字符,应用场景有限。

而 Base16 编码生成的结果是用[0-9A-F]十六个字符表示,可以用来生成字符索引和文件名等,应用范围比 Base64 要大的多。

缺点的话 Base16 编码的结果字符串比 Base64 编码的结果字符串要长, Base64 大概是1.3倍长,而 Base16 是原长度的两倍。

Base16 编码的原理是先获取字符串每个字节的二进制值,高位用0补充到8位。然后每4比特分割成一组,每组的二进制值转换成十进制,然后再对应到[0-9A-F],对应的结果就是编码的值。

PHP 官方并没有 Base16 的编码实现,使用下面的函数就可以实现Base16的编码和解码。

function base16_encode($string)
{
    $encode = '';
    $chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
    for ($i = 0; $i < strlen($string); $i++) {
        $encode .= $chars[(ord($string[$i]) & 0b11110000) >> 4] . $chars[ord($string[$i]) & 0b00001111];
    }
    return $encode;
}

function base16_decode($encode)
{
    $result = '';
    for ($i = 0; $i < strlen($encode) / 2; $i++) {
        $result .= chr(intval(substr($encode, $i * 2, 2), 16));
    }
    return $result;
}

生成TOTP临时密码

生成二次验证的临时密码,兼容谷歌验证器

function base32Decode($in)
{
    $l = strlen($in);
    $n = $bs = 0;
    for ($i = 0; $i < $l; $i++) {
        $n <<= 5;
        $n += stripos('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $in[$i]);
        $bs = ($bs + 5) % 8;
        $out .= $bs < 5 ? chr(($n & (255 << $bs)) >> $bs) : null;
    }
    return $out;
}

function getOTP($secret)
{
    $seed = base32Decode($secret);
    $time = str_pad(pack('N', intval(0 + time() / 30)), 8, "\x00", STR_PAD_LEFT);
    $hash = hash_hmac('sha1', $time, $seed, false);
    $otp = (hexdec(substr($hash, hexdec($hash[39]) * 2, 8)) & 0x7fffffff) % pow(10, 6);
    return sprintf("%'06u", $otp);
}

echo getOTP('secret_key');

列出腾讯云存储的文件

使用腾讯云 COS API 查看存储里的所有文件(最多1000个)

define('SecretId', 'SecretId');
define('SecretKey', 'SecretKey');

function listBucketFiles($region, $bucket)
{

    $host = $bucket . '.cos.' . $region . '.myqcloud.com';
    $path = '/';
    $url = 'https://' . $host . $path;
    $header = array(
        'Authorization: ' . requestSign($host, 'GET', $path),
        'Date: ' . gmdate('D, d M Y H:i:s T'),
    );

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    $response = curl_exec($curl);
    curl_close($curl);

    $files = [];
    $list = simplexml_load_string($response);
    foreach ($list->Contents as $v) {
        $files[] = (String) $v->Key;
    }

    return $files;
}

function requestSign($host, $method, $path)
{
    $signTime = (string) (time() - 60) . ';' . (string) (time() + 1200);
    $httpString = sprintf("%s\n%s\n\nhost=%s\n", strtolower($method), $path, $host);
    $stringToSign = sprintf("sha1\n%s\n%s\n", $signTime, sha1($httpString));
    $signKey = hash_hmac('sha1', $signTime, SecretKey);
    $signature = hash_hmac('sha1', $stringToSign, $signKey);
    return sprintf('q-sign-algorithm=sha1&q-ak=%s&q-sign-time=%s&q-key-time=%s&q-header-list=host&q-url-param-list=&q-signature=%s', SecretId, $signTime, $signTime, $signature);
}

使用阿里云API管理域名解析


define('AccessKeyId', 'AccessKeyId');
define('AccessKeySecret', 'AccessKeySecret');

date_default_timezone_set('UTC');

/**
 *  获取请求签名
 */
function getSign($add)
{
    $nonce = time() . rand(11111, 99999);
    $time = date('Y-m-d') . 'T' . date('H:i:s') . 'Z';
    $data = array(
        'AccessKeyId' => AccessKeyId,
        'Format' => 'json',
        'SignatureMethod' => 'HMAC-SHA1',
        'SignatureNonce' => $nonce,
        'SignatureVersion' => '1.0',
        'Timestamp' => $time,
        'Version' => '2015-01-09',
    );
    $data = array_merge($data, $add);
    ksort($data);
    $format = http_build_query($data);
    $signUrl = 'GET&%2F&' . urlencode($format);
    $sign = urlencode(base64_encode(hash_hmac('sha1', $signUrl, AccessKeySecret . '&', true)));
    return array('url' => $format, 'sign' => $sign);
}

/**
 *  获取域名列表
 */
function getDomains()
{
    $sign = getSign(['Action' => 'DescribeDomains']);
    $url = 'https://alidns.aliyuncs.com/?' . $sign['url'] . '&Signature=' . $sign['sign'];
    $data = json_decode(httpRequest($url));
    if (isset($data->Domains)) {
        return $data;
    } else {
        return false;
    }
}

/**
 *  获取域名解析记录
 */
function getDomainRecords($domain)
{
    $sign = getSign(['Action' => 'DescribeDomainRecords', 'DomainName' => $domain]);
    $url = 'https://alidns.aliyuncs.com/?' . $sign['url'] . '&Signature=' . $sign['sign'];
    $data = json_decode(httpRequest($url));
    if (isset($data->DomainRecords)) {
        return $data;
    } else {
        return false;
    }
}

/**
 *  获取子域名解析记录
 */
function getSubDomainRecords($domain)
{
    $sign = getSign(['Action' => 'DescribeSubDomainRecords', 'SubDomain' => $domain]);
    $url = 'https://alidns.aliyuncs.com/?' . $sign['url'] . '&Signature=' . $sign['sign'];
    $dns = json_decode(httpRequest($url));
    if (isset($dns->DomainRecords)) {
        return $dns;
    } else {
        return false;
    }
}

/**
 *  更新域名解析
 */
function updateSubDomainRecords($id, $name, $ip)
{
    $data = array(
        'Action' => 'UpdateDomainRecord',
        'RecordId' => $id,
        'RR' => $name,
        'Type' => 'A',
        'Value' => $ip,
    );
    $sign = getSign($data);
    $url = 'https://alidns.aliyuncs.com/?' . $sign['url'] . '&Signature=' . $sign['sign'];
    return httpRequest($url);
}

/**
 *  发起 HTTP 请求
 */
function httpRequest($url)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    $data = curl_exec($curl);
    $error = curl_error($curl);
    curl_close($curl);
    if ($error) {
        return $error;
    } else {
        return $data;
    }
}

使用Google API获取谷歌相册的内容

首先要申请一个谷歌 Oauth2 应用的 ID 和密钥,然后用浏览器访问下面的地址获取授权码 code

https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http://localhost&response_type=code&client_id={ClientID}&scope=https://www.googleapis.com/auth/photoslibrary+https://www.googleapis.com/auth/drive&access_type=offline

获取到 code 以后,请求谷歌服务器换取 refresh_token

define('Client_ID', 'client_id');
define('Client_Secrec', 'client_secrec');

function getRefreshToken($code) {
    $params = ['grant_type' => 'authorization_code', 'code' => $code, 'client_id' => Client_ID, 'client_secret' => Client_Secrec, 'redirect_uri' => 'http://localhost'];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://www.googleapis.com/oauth2/v4/token');
    curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
    $data = curl_exec($curl);
    curl_close($curl);
    return $data;
}

用 refresh_token 获取 access_token

function getAccessToken($refresh_token) {
    $params = ['grant_type' => 'refresh_token', 'client_id' => 'client_id', 'client_secret' => 'client_secre', 'refresh_token' => $refresh_token];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://www.googleapis.com/oauth2/v4/token');
    curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
    $data = curl_exec($curl);
    curl_close($curl);
    return $data;
}

获取Google Oauth2 JWT签名

首先获取服务账号密钥文件 google-gce.json

use Google\Auth\OAuth2;

require 'vendor/autoload.php';

function getGoogleJWT($scopes, $jsonKey) {
    $jsonKey = json_decode(file_get_contents($jsonKey), true);
    $config = [
        'audience' => 'https://oauth2.googleapis.com/token',
        'issuer' => $jsonKey['client_email'],
        'scope' => $scopes,
        'signingAlgorithm' => 'RS256',
        'signingKey' => $jsonKey['private_key'],
        'sub' => NULL,
        'tokenCredentialUri' => 'https://oauth2.googleapis.com/token'
    ];
    $auth = new OAuth2($config);
    return $auth->toJWT();
}

$scopes = ['https://www.googleapis.com/auth/drive.readonly'];

echo getGoogleJWT($scopes, 'google-gce.json');

然后用 JWT 签名就可以获取 Access Token 密钥,有效期为一小时

function getAccessToken($jwt) {
    $params = ['grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://oauth2.googleapis.com/token');
    curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
    $data = curl_exec($curl);
    curl_close($curl);
    return $data;
}

$jwt = 'JWT';

echo getAccessToken($jwt);

PHP独立使用Illuminate Database数据库组件

1 安装

composer require illuminate/database
composer require illuminate/events
composer require illuminate/container

2 使用

use Illuminate\Database\Capsule\Manager as DB;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;

require 'vendor/autoload.php';

$capsule = new DB;

$capsule->addConnection([
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'test',
    'username'  => 'root',
    'password'  => '123456',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]);

$capsule->setEventDispatcher(new Dispatcher(new Container));
$capsule->setAsGlobal();
$capsule->bootEloquent();

$data = DB::table('user')->select('*')->get();

var_dump($data);

WordPress 禁用 REST

添加以下代码到插件文件里,可以实现:

  1. 已登录用户可以正常使用 wp-json API
  2. 未登录用户禁止使用 wp-json API
/*
 *  disable rest api
 */
function disable_rest_api($access)
{
    if (is_user_logged_in()) {
        return $access;
    } else {
        return new WP_Error('rest_disabled', __('The REST API on this site has been disabled.'), ['status' => rest_authorization_required_code()]);
    }
}

add_filter('rest_authentication_errors', 'disable_rest_api');