|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
|
|
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
|
|
|
use App\Models\WechatUser;
|
|
|
|
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
|
|
|
|
|
|
|
|
class H5WechatController extends Controller
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 公众号网页授权 code 换用户信息,并签发 Sanctum 令牌(WechatUser)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function oauth(Request $request): JsonResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
$data = $request->validate([
|
|
|
|
|
|
'code' => ['required', 'string'],
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$appId = (string) config('wechat.app_id');
|
|
|
|
|
|
$secret = (string) config('wechat.app_secret');
|
|
|
|
|
|
if ($appId === '' || $secret === '') {
|
|
|
|
|
|
return response()->json(['message' => '服务端未配置微信公众号 AppId/AppSecret'], 503);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$tokenRes = Http::timeout(15)
|
|
|
|
|
|
->get('https://api.weixin.qq.com/sns/oauth2/access_token', [
|
|
|
|
|
|
'appid' => $appId,
|
|
|
|
|
|
'secret' => $secret,
|
|
|
|
|
|
'code' => $data['code'],
|
|
|
|
|
|
'grant_type' => 'authorization_code',
|
|
|
|
|
|
])
|
|
|
|
|
|
->json();
|
|
|
|
|
|
|
|
|
|
|
|
if (! empty($tokenRes['errcode'])) {
|
|
|
|
|
|
throw ValidationException::withMessages([
|
|
|
|
|
|
'code' => [$tokenRes['errmsg'] ?? '微信 code 无效或已使用'],
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$accessToken = (string) ($tokenRes['access_token'] ?? '');
|
|
|
|
|
|
$openid = (string) ($tokenRes['openid'] ?? '');
|
|
|
|
|
|
if ($accessToken === '' || $openid === '') {
|
|
|
|
|
|
return response()->json(['message' => '微信未返回 access_token'], 422);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$unionid = $tokenRes['unionid'] ?? null;
|
|
|
|
|
|
|
|
|
|
|
|
$info = Http::timeout(15)
|
|
|
|
|
|
->get('https://api.weixin.qq.com/sns/userinfo', [
|
|
|
|
|
|
'access_token' => $accessToken,
|
|
|
|
|
|
'openid' => $openid,
|
|
|
|
|
|
'lang' => 'zh_CN',
|
|
|
|
|
|
])
|
|
|
|
|
|
->json();
|
|
|
|
|
|
|
|
|
|
|
|
if (! empty($info['errcode'])) {
|
|
|
|
|
|
$info = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ($unionid === null && ! empty($info['unionid'])) {
|
|
|
|
|
|
$unionid = $info['unionid'];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$wu = WechatUser::query()->updateOrCreate(
|
|
|
|
|
|
['openid' => $openid],
|
|
|
|
|
|
[
|
|
|
|
|
|
'unionid' => $unionid,
|
|
|
|
|
|
'nickname' => $info['nickname'] ?? null,
|
|
|
|
|
|
'avatar_url' => $info['headimgurl'] ?? null,
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
$plain = $wu->createToken('wechat-h5')->plainTextToken;
|
|
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
|
'token' => $plain,
|
|
|
|
|
|
'user' => [
|
|
|
|
|
|
'id' => $wu->id,
|
|
|
|
|
|
'nickname' => $wu->nickname,
|
|
|
|
|
|
'avatar_url' => $wu->avatar_url,
|
|
|
|
|
|
],
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|