header-bg.jpg
Laravel 获取微信小程序二维码并上传至 OSS
发表于 2021-05-11 03:06
|
分类于 PHP
|
评论次数 0
|
阅读次数 1056

本文介绍如何在 Laravel 中通过发送 HTTP 请求,访问微信的二维码接口,拿到二维码图片数据,并将图片数据上传至 OSS,最后将图片链接返回至客户端。

获取二维码

获取 Access Token

点击此链接查看:微信二维码接口官方文档

访问此接口必须携带 access_token,所以第一步需要获取 access_token,如下所示:

public function getAccessToken(): string
{
    $accessTokenKey = 'access_token';
    $accessToken = Rds::get($accessTokenKey);
    if ($accessToken) return $accessToken;

    $result = self::get(
        url: self::APP_ACCESS_TOKEN_API,
        queryParams: [
            'secret' => self::APP_SECRET,
            'appid' => self::APP_ID,
            'grant_type' => 'client_credential'
        ],
    );
    $result = json_decode($result, true);
    if (empty($result['access_token']) || empty($result['expires_in'])) return '';

    $expireTime = $result['expires_in'] - 10;
    Rds::setex($accessTokenKey, max($expireTime, 1), $result['access_token']);
    return $result['access_token'];
}

上面的代码是很好理解的,首先查询缓存中的 access_token 是否存在,如果存在则直接从缓存取出,不必通过 API 获取。

通过 GET 请求拿到 access_token,并缓存至 Redis,下次再访问本接口,则可以命中缓存。

获取二维码图片的二进制数据

拿到 access_token,通过 POST 请求微信官方接口,拿到图片的二进制数据,如下所示:

public function getQrCodeImage(string $accessToken, string $scene, string $page): array|string
{
    if (!$this->isGdLoaded()) return 'GD 扩展库未开启,无法检测图片格式';

    $result = self::post(
        url: self::QR_CODE_API . "?access_token=$accessToken",
        data: [
//                'access_token' => $accessToken,
            'scene' => $scene,
            'page' => $page,
        ],
    );

    $isImage = false;
    try {
        $isImage = imagecreatefromstring($result);
    } catch (Exception) {
    }
    if ($isImage) return $result;

    $result = json_decode($result, true);
    if (!empty($result['errmsg'])) return $result;
    return ['errmsg' => '二维码图片生成失败,请重新尝试!'];
}

上传图片至 OSS

生成 Authorization

阿里云 OSS 文档中指出,访问 OSS 的接口必须在 header 中携带 authorizationx-oss-date 两个字段。通过以下代码,可以生成所需的 authorization

private function makeAuthorization(
    string $objectKey,
    string $mimeType,
    string $requestDate,
    string $bucket,
    string $method = 'PUT',
): string
{

    $data = "$method\n"
        . "\n"
        . "$mimeType\n"
        . "$requestDate\n"
        . "x-oss-date:$requestDate\n"
        . "/$bucket/$objectKey";

    $signature = base64_encode(hash_hmac('sha1', $data, self::ACCESS_KEY_SECRET, true));
    $accessKeyId = self::ACCESS_KEY_ID;
    return "OSS $accessKeyId:$signature";
}

通过 PUT 接口发送图片数据至 OSS 服务端

通过以下代码生成 GMT 格式的 x-oss-date 所需的值,并使用 Laravel 自带的 HTTP 门面类发送 PUT 请求,如下所示:

public function putImage(string $objectKey, string $image): string
{
    $mimeType = 'image/jpeg';
    $requestDate = gmdate('D, d M Y H:i:s \G\M\T');

    $authorization = self::makeAuthorization(
        objectKey: $objectKey,
        mimeType: $mimeType,
        requestDate: $requestDate,
        bucket: self::IMAGE_BUCKET,
    );

    $response = Http::withBody(content: $image, contentType: $mimeType)
        ->withHeaders([
            'authorization' => $authorization,
            'x-oss-date' => $requestDate
        ])
        ->withOptions(['verify' => false])
        ->put(self::IMAGE_HOST . $objectKey);

    return $response->successful() ? self::IMAGE_CDN_URL . $objectKey : '';
}

以上的代码中,图片上传成功则返回 CDN 地址,失败则返回空字符串。

所需要的常量

以上方法中所需要访问的常量:

const APP_ID = 'wx*****';
const APP_SECRET = '70c*****';
const APP_ACCESS_TOKEN_API = 'https://api.weixin.qq.com/cgi-bin/token';
const QR_CODE_API = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit';

const ACCESS_KEY_ID = 'LTAI4*****';//Access Key ID
const ACCESS_KEY_SECRET = 'zjDzI*****';//Access Key Secret
const IMAGE_CDN_URL = 'https://img.lcgod.com/';
const IMAGE_BUCKET = 'blog-img';
const VIDEO_BUCKET = 'blog-video';
const IMAGE_HOST = 'https://lcgod-img.oss-cn-beijing.aliyuncs.com/';

发布评论
还没有评论,快来抢沙发吧!