Files
miniapi/app/service/MiniProgramWechatService.php
gaofeng 81ade70944 提交
2026-06-17 09:23:18 +08:00

128 lines
4.1 KiB
PHP

<?php
declare (strict_types=1);
namespace app\service;
use api\Httpcurl;
use think\facade\Cache;
use think\facade\Log;
class MiniProgramWechatService
{
private string $miniAppCode;
private array $miniApp;
public function __construct(string $miniAppCode, array $miniApp)
{
$this->miniAppCode = $miniAppCode;
$this->miniApp = $miniApp;
}
public function openidByLoginCode(string $loginCode, bool $required = false): string
{
$config = $this->wechatConfig();
if ($loginCode === '' || $config['appid'] === '' || $config['secret'] === '') {
return '';
}
$response = Httpcurl::request('https://api.weixin.qq.com/sns/jscode2session', 'get', [
'appid' => $config['appid'],
'secret' => $config['secret'],
'js_code' => $loginCode,
'grant_type' => 'authorization_code',
], [], 8);
$result = $this->decodeWechatResponse($response, 'miniapi wx code2session');
if (!empty($result['openid'])) {
return (string)$result['openid'];
}
if ($required) {
Log::warning('miniapi wx openid missing: ' . json_encode($result, JSON_UNESCAPED_UNICODE));
}
return '';
}
public function mobileByPhoneCode(string $phoneCode): string
{
$accessToken = $this->wechatAccessToken();
if ($phoneCode === '' || $accessToken === '') {
return '';
}
$response = Httpcurl::request(
'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=' . urlencode($accessToken),
'post',
json_encode(['code' => $phoneCode], JSON_UNESCAPED_UNICODE),
['Content-Type: application/json'],
8
);
$result = $this->decodeWechatResponse($response, 'miniapi wx get phone number');
$phoneInfo = $result['phone_info'] ?? [];
return (string)($phoneInfo['purePhoneNumber'] ?? $phoneInfo['phoneNumber'] ?? '');
}
private function wechatAccessToken(): string
{
$config = $this->wechatConfig();
if ($config['appid'] === '' || $config['secret'] === '') {
Log::warning('miniapi wx config missing: ' . $this->miniAppCode);
return '';
}
$cacheKey = 'miniapp_access_token_' . $this->miniAppCode;
$cached = Cache::get($cacheKey);
if (!empty($cached)) {
return (string)$cached;
}
$response = Httpcurl::request('https://api.weixin.qq.com/cgi-bin/token', 'get', [
'grant_type' => 'client_credential',
'appid' => $config['appid'],
'secret' => $config['secret'],
], [], 8);
$result = $this->decodeWechatResponse($response, 'miniapi wx access token');
if (empty($result['access_token'])) {
return '';
}
$ttl = max(60, intval($result['expires_in'] ?? 7200) - 300);
Cache::set($cacheKey, $result['access_token'], $ttl);
return (string)$result['access_token'];
}
private function wechatConfig(): array
{
return [
'appid' => trim((string)($this->miniApp['wechat_appid'] ?? '')),
'secret' => trim((string)($this->miniApp['wechat_secret'] ?? '')),
];
}
private function decodeWechatResponse($response, string $scene): array
{
$result = $this->decodeResponse($response, $scene);
if (isset($result['errcode']) && intval($result['errcode']) !== 0) {
Log::warning($scene . ' failed: ' . json_encode($result, JSON_UNESCAPED_UNICODE));
return [];
}
return $result;
}
private function decodeResponse($response, string $scene): array
{
if (!is_array($response) || !isset($response[0]) || !empty($response[3])) {
Log::error($scene . ' request failed: ' . json_encode($response, JSON_UNESCAPED_UNICODE));
return [];
}
$result = json_decode($response[0], true);
if (!is_array($result)) {
Log::error($scene . ' response decode failed: ' . $response[0]);
return [];
}
return $result;
}
}