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>
This commit is contained in:
134
app/controller/api/v1/InternalController.php
Normal file
134
app/controller/api/v1/InternalController.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user