Laravel 获取微信小程序二维码并上传至 OSS
本文介绍如何在 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
中携带 authorization
及 x-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/';

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