Files
douba_shop/app/controller/api/v1/InternalController.php
Karlcarlo fc353899a9 chore: 入库生产基线(2026-10-26 与 shop.douba.top 一致)
- 11 个已跟踪文件的在途改动此前只存在于工作区,生产已在运行
- 补入两个从未入库的文件:InternalController.php(app_03/box_app 内部接口)、
  config/internal.php(内部通信 key,值从 .env 读取,不含硬编码密钥)
- 逐文件 md5 比对过生产,内容一致

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-26 17:08:55 +08:00

135 lines
5.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace app\controller\api\v1;
use app\Request;
use app\services\user\UserServices;
use app\services\wechat\RoutineServices;
use app\services\wechat\WechatUserServices;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
use think\Response;
/**
* 内部服务接口(不经过用户认证)
* 用于 H5 / app_03 后端通过 openid 自动补齐用户信息
*/
class InternalController
{
/**
* 验证内部 API Key
* @param Request $request
* @return bool true=通过,false=拒绝
*/
private function checkInternalKey(Request $request): bool
{
$apiKey = $request->header('X-Internal-Key');
// 注意:在 Swoole 沙箱里 env()/getenv() 经常读不到 .env
// 用 config() 兜底,确保两种部署(PHP-FPM / Swoole)都生效
$configKey = (string)(config('internal.api_key') ?: env('INTERNAL_API_KEY', ''));
return $apiKey && $configKey && $apiKey === $configKey;
}
/**
* 根据 openid 获取用户信息
* @param Request $request
* @param WechatUserServices $wechatUserServices
* @return Response
*/
public function userInfo(Request $request, WechatUserServices $wechatUserServices): Response
{
if (!$this->checkInternalKey($request)) {
return Response::create(['code' => 403, 'msg' => 'Forbidden'], 'json');
}
$openid = $request->param('openid', '');
if (!$openid) {
return Response::create(['code' => 400, 'msg' => 'openid is required'], 'json');
}
try {
$wechatUser = $wechatUserServices->getWechatUserInfo(['openid' => $openid]);
} catch (DataNotFoundException | ModelNotFoundException | DbException $e) {
return Response::create(['code' => 500, 'msg' => '查询失败'], 'json');
}
if (!$wechatUser) {
return Response::create(['code' => 404, 'msg' => 'user not found'], 'json');
}
$uid = (int)$wechatUser['uid'];
$userServices = app()->make(UserServices::class);
try {
$user = $userServices->getUserInfo($uid);
} catch (DataNotFoundException | ModelNotFoundException | DbException $e) {
$user = null;
}
return Response::create([
'code' => 200,
'data' => [
'uid' => $uid,
'nickname' => $user['nickname'] ?? $wechatUser['nickname'] ?? '',
'phone' => $user['phone'] ?? $wechatUser['phone'] ?? '',
'avatar' => $user['avatar'] ?? $wechatUser['headimgurl'] ?? '',
],
], 'json');
}
/**
* 通过微信 code 换 openid(绕过 store_user_mobile 限制)
*
* 设计目的:H5/app_03 在新用户场景下(CRMEB 强制绑手机号=true),
* 原 silenceAuth 返回 {auth_login:1, key:...},前端拿不到 openid 会被
* 引导到授权页。本端点只调微信 code2session 拿 openid/unionid,不查
* store_user_mobile、不建用户、不发 token,前端拿到 openid 后走自己的
* openid-login 即可自助登录。
*
* @param Request $request
* @param RoutineServices $routineServices
* @return Response
*/
public function getOpenidByCode(Request $request, RoutineServices $routineServices): Response
{
if (!$this->checkInternalKey($request)) {
return Response::create(['code' => 403, 'msg' => 'Forbidden'], 'json');
}
$code = $request->param('code', '');
if (!$code) {
return Response::create(['code' => 400, 'msg' => 'code is required'], 'json');
}
try {
$wechatInfo = $routineServices->getUserInfoByCode((string)$code);
} catch (ValidateException $e) {
return Response::create(['code' => 400, 'msg' => $e->getMessage()], 'json');
} catch (\Throwable $e) {
return Response::create(['code' => 500, 'msg' => 'code2session 失败: ' . $e->getMessage()], 'json');
}
$openid = $wechatInfo['openid'] ?? '';
if (!$openid) {
return Response::create(['code' => 500, 'msg' => 'openid 缺失'], 'json');
}
return Response::create([
'code' => 200,
'data' => [
'openid' => $openid,
'unionid' => $wechatInfo['unionid'] ?? '',
],
], 'json');
}
}