first commit
This commit is contained in:
49
app/api/controller/AuthController.php
Normal file
49
app/api/controller/AuthController.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\common\model\User;
|
||||
use app\common\service\AuthService;
|
||||
|
||||
class AuthController
|
||||
{
|
||||
public function login(Request $request)
|
||||
{
|
||||
$mobile = trim((string)$request->post('mobile', ''));
|
||||
$code = trim((string)$request->post('code', ''));
|
||||
if ($mobile === '' || $code === '') {
|
||||
return jsonResponse(null, '参数错误', 400);
|
||||
}
|
||||
if (!preg_match('/^\d{11}$/', $mobile)) {
|
||||
return jsonResponse(null, '手机号格式错误', 400);
|
||||
}
|
||||
|
||||
$user = User::firstOrCreate(
|
||||
['mobile' => $mobile],
|
||||
['nickname' => '用户' . substr($mobile, -4), 'status' => 1]
|
||||
);
|
||||
if (intval($user->status) !== 1) {
|
||||
return jsonResponse(null, '账号已禁用', 403);
|
||||
}
|
||||
|
||||
$token = AuthService::issueUserToken($user);
|
||||
return jsonResponse([
|
||||
'token' => $token,
|
||||
'user' => $user
|
||||
], '登录成功');
|
||||
}
|
||||
|
||||
public function me(Request $request)
|
||||
{
|
||||
return jsonResponse([
|
||||
'user' => $request->user
|
||||
]);
|
||||
}
|
||||
|
||||
public function logout(Request $request)
|
||||
{
|
||||
AuthService::revokeUserToken($request->token ?? null);
|
||||
return jsonResponse(null, '已退出登录');
|
||||
}
|
||||
}
|
||||
|
||||
132
app/api/controller/OrderController.php
Normal file
132
app/api/controller/OrderController.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\common\service\OrderFlowService;
|
||||
use app\common\service\PaymentService;
|
||||
use app\common\model\Order;
|
||||
|
||||
class OrderController
|
||||
{
|
||||
public function create(Request $request)
|
||||
{
|
||||
$params = $request->post();
|
||||
$userId = $request->user->id;
|
||||
|
||||
try {
|
||||
$order = OrderFlowService::createOrder($params, $userId);
|
||||
|
||||
return jsonResponse([
|
||||
'order_id' => $order->id,
|
||||
'order_no' => $order->order_no,
|
||||
'pay_amount' => $order->total_price
|
||||
], '下单成功');
|
||||
} catch (\Exception $e) {
|
||||
return jsonResponse(null, '下单失败: ' . $e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
|
||||
public function list(Request $request)
|
||||
{
|
||||
$status = $request->get('status', 'all');
|
||||
$userId = $request->user->id;
|
||||
|
||||
$query = Order::where('user_id', $userId);
|
||||
if ($status !== 'all') {
|
||||
$query->where('status', $status);
|
||||
}
|
||||
|
||||
$orders = $query->orderBy('id', 'desc')->get();
|
||||
|
||||
return jsonResponse(['items' => $orders, 'total' => $orders->count()]);
|
||||
}
|
||||
|
||||
public function detail(Request $request, $id)
|
||||
{
|
||||
$userId = $request->user->id;
|
||||
$order = Order::with(['logs'])->where('id', $id)->where('user_id', $userId)->first();
|
||||
|
||||
if (!$order) {
|
||||
return jsonResponse(null, '订单不存在', 404);
|
||||
}
|
||||
|
||||
$timeline = [];
|
||||
$isFirst = true;
|
||||
foreach ($order->logs as $log) {
|
||||
$timeline[] = [
|
||||
'title' => $log->title,
|
||||
'time' => $log->created_at->format('Y-m-d H:i:s'),
|
||||
'desc' => $log->description,
|
||||
'is_current' => $isFirst,
|
||||
'is_done' => true
|
||||
];
|
||||
$isFirst = false;
|
||||
}
|
||||
|
||||
return jsonResponse([
|
||||
'id' => $order->id,
|
||||
'order_no' => $order->order_no,
|
||||
'category' => $order->category,
|
||||
'service_type' => $order->service_type,
|
||||
'status' => $order->status,
|
||||
'is_fast' => (bool)$order->is_fast,
|
||||
'express_company' => $order->express_company,
|
||||
'express_no' => $order->express_no,
|
||||
'timeline' => $timeline
|
||||
]);
|
||||
}
|
||||
|
||||
public function pay(Request $request)
|
||||
{
|
||||
$orderId = (int)$request->post('order_id');
|
||||
$userId = $request->user->id;
|
||||
$payType = trim((string)$request->post('pay_type', 'jsapi'));
|
||||
$appId = trim((string)$request->post('app_id', ''));
|
||||
|
||||
$order = Order::where('id', $orderId)->where('user_id', $userId)->first();
|
||||
if (!$order) {
|
||||
return jsonResponse(null, '订单不存在', 404);
|
||||
}
|
||||
|
||||
try {
|
||||
if ($payType === 'native') {
|
||||
$pay = PaymentService::createWechatNativePay($order);
|
||||
return jsonResponse($pay, '支付发起成功');
|
||||
}
|
||||
|
||||
if ($appId === '') {
|
||||
return jsonResponse(null, '缺少 app_id,无法发起 JSAPI 支付', 400);
|
||||
}
|
||||
|
||||
$openid = trim((string)$request->post('openid', ''));
|
||||
$pay = PaymentService::createWechatJsapiPay($order, $appId, $openid);
|
||||
return jsonResponse($pay, '支付发起成功');
|
||||
} catch (\Throwable $e) {
|
||||
return jsonResponse(null, $e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
|
||||
public function ship(Request $request)
|
||||
{
|
||||
$orderId = (int)$request->post('order_id');
|
||||
$expressCompany = trim($request->post('express_company', ''));
|
||||
$expressNo = trim($request->post('express_no', ''));
|
||||
|
||||
if (!$expressCompany || !$expressNo) {
|
||||
return jsonResponse(null, '物流信息不完整', 400);
|
||||
}
|
||||
|
||||
$userId = $request->user->id;
|
||||
$order = Order::where('id', $orderId)->where('user_id', $userId)->first();
|
||||
if (!$order) {
|
||||
return jsonResponse(null, '订单不存在', 404);
|
||||
}
|
||||
|
||||
try {
|
||||
OrderFlowService::userShip($order, $expressCompany, $expressNo);
|
||||
return jsonResponse(null, '发货信息已提交');
|
||||
} catch (\Exception $e) {
|
||||
return jsonResponse(null, $e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
103
app/api/controller/PayController.php
Normal file
103
app/api/controller/PayController.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\common\model\Order;
|
||||
use app\common\model\PaymentTransaction;
|
||||
use app\common\model\WechatMerchant;
|
||||
use app\common\service\OrderFlowService;
|
||||
use app\common\service\WechatPayV3Client;
|
||||
use Illuminate\Database\Capsule\Manager as DB;
|
||||
|
||||
class PayController
|
||||
{
|
||||
public function wechatNotify(Request $request)
|
||||
{
|
||||
$body = (string)$request->rawBody();
|
||||
|
||||
$timestamp = (string)$request->header('Wechatpay-Timestamp', '');
|
||||
$nonce = (string)$request->header('Wechatpay-Nonce', '');
|
||||
$signature = (string)$request->header('Wechatpay-Signature', '');
|
||||
if ($timestamp === '' || $nonce === '' || $signature === '') {
|
||||
return json(['code' => 'FAIL', 'message' => 'missing headers'], 400);
|
||||
}
|
||||
|
||||
$merchants = WechatMerchant::where('status', 1)->get();
|
||||
if ($merchants->count() === 0) {
|
||||
return json(['code' => 'FAIL', 'message' => 'no merchant'], 500);
|
||||
}
|
||||
|
||||
$client = new WechatPayV3Client($merchants->first());
|
||||
$ok = $client->verifyPlatformSignature($timestamp, $nonce, $body, $signature);
|
||||
if (!$ok) {
|
||||
return json(['code' => 'FAIL', 'message' => 'invalid signature'], 400);
|
||||
}
|
||||
|
||||
$payload = json_decode($body, true) ?: [];
|
||||
$resource = $payload['resource'] ?? null;
|
||||
if (!is_array($resource)) {
|
||||
return json(['code' => 'FAIL', 'message' => 'invalid body'], 400);
|
||||
}
|
||||
|
||||
$decrypt = null;
|
||||
$matchedMerchant = null;
|
||||
foreach ($merchants as $m) {
|
||||
$apiV3Key = (string)($m->api_v3_key ?? '');
|
||||
if ($apiV3Key === '') continue;
|
||||
try {
|
||||
$decrypt = $client->decryptNotifyResource($resource, $apiV3Key);
|
||||
$matchedMerchant = $m;
|
||||
break;
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
}
|
||||
if (!$decrypt || !$matchedMerchant) {
|
||||
return json(['code' => 'FAIL', 'message' => 'decrypt failed'], 400);
|
||||
}
|
||||
|
||||
$outTradeNo = (string)($decrypt['out_trade_no'] ?? '');
|
||||
$tradeState = (string)($decrypt['trade_state'] ?? '');
|
||||
if ($outTradeNo === '') {
|
||||
return json(['code' => 'FAIL', 'message' => 'missing out_trade_no'], 400);
|
||||
}
|
||||
|
||||
$tx = PaymentTransaction::where('out_trade_no', $outTradeNo)->first();
|
||||
if (!$tx) {
|
||||
return json(['code' => 'SUCCESS', 'message' => 'OK']);
|
||||
}
|
||||
|
||||
if ($tradeState !== 'SUCCESS') {
|
||||
return json(['code' => 'SUCCESS', 'message' => 'OK']);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$tx->status = 'paid';
|
||||
$tx->paid_at = date('Y-m-d H:i:s');
|
||||
$tx->raw_json = $decrypt;
|
||||
$tx->save();
|
||||
|
||||
$order = Order::find($tx->order_id);
|
||||
if ($order) {
|
||||
$order->pay_channel = 'wechat';
|
||||
$order->pay_status = 'paid';
|
||||
$order->pay_merchant_id = (int)$matchedMerchant->id;
|
||||
$order->pay_out_trade_no = $outTradeNo;
|
||||
if (!$order->pay_time) {
|
||||
$order->pay_time = date('Y-m-d H:i:s');
|
||||
}
|
||||
$order->save();
|
||||
|
||||
OrderFlowService::payOrder($order);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
return json(['code' => 'FAIL', 'message' => 'server error'], 500);
|
||||
}
|
||||
|
||||
return json(['code' => 'SUCCESS', 'message' => 'OK']);
|
||||
}
|
||||
}
|
||||
|
||||
70
app/api/controller/ReportController.php
Normal file
70
app/api/controller/ReportController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\common\model\Report;
|
||||
use app\common\model\Order;
|
||||
|
||||
class ReportController
|
||||
{
|
||||
// 获取C端自己的报告
|
||||
public function detail(Request $request)
|
||||
{
|
||||
$orderId = (int)$request->get('order_id');
|
||||
$userId = $request->user->id;
|
||||
|
||||
$order = Order::where('id', $orderId)->where('user_id', $userId)->first();
|
||||
if (!$order) {
|
||||
return jsonResponse(null, '订单不存在', 404);
|
||||
}
|
||||
|
||||
$report = Report::with(['inspector'])->where('order_id', $orderId)->first();
|
||||
if (!$report) {
|
||||
return jsonResponse(null, '报告尚未出具', 404);
|
||||
}
|
||||
|
||||
return jsonResponse([
|
||||
'report_no' => $report->report_no,
|
||||
'conclusion' => $report->conclusion,
|
||||
'level' => $report->level,
|
||||
'flaws' => $report->flaws_json,
|
||||
'images' => $report->images_json,
|
||||
'verify_code' => $report->verify_code,
|
||||
'created_at' => $report->created_at->format('Y-m-d H:i:s'),
|
||||
'inspector' => [
|
||||
'name' => $report->inspector->nickname ?? $report->inspector->username,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
// 公开验证防伪码 (无需登录)
|
||||
public function verify(Request $request)
|
||||
{
|
||||
$code = trim($request->get('code', ''));
|
||||
if (!$code) {
|
||||
return jsonResponse(null, '防伪码不能为空', 400);
|
||||
}
|
||||
|
||||
$report = Report::with(['order', 'inspector'])->where('verify_code', $code)->first();
|
||||
if (!$report) {
|
||||
return jsonResponse(null, '无效的防伪码或报告不存在', 404);
|
||||
}
|
||||
|
||||
return jsonResponse([
|
||||
'report_no' => $report->report_no,
|
||||
'conclusion' => $report->conclusion,
|
||||
'level' => $report->level,
|
||||
'flaws' => $report->flaws_json,
|
||||
'images' => $report->images_json,
|
||||
'created_at' => $report->created_at->format('Y-m-d H:i:s'),
|
||||
'order' => [
|
||||
'category' => $report->order->category,
|
||||
'brand' => $report->order->brand,
|
||||
'model' => $report->order->model,
|
||||
],
|
||||
'inspector' => [
|
||||
'name' => $report->inspector->nickname ?? $report->inspector->username,
|
||||
]
|
||||
], '验证成功,该报告真实有效');
|
||||
}
|
||||
}
|
||||
37
app/api/controller/UploadController.php
Normal file
37
app/api/controller/UploadController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use Webman\Http\UploadFile;
|
||||
|
||||
class UploadController
|
||||
{
|
||||
public function image(Request $request)
|
||||
{
|
||||
$file = $request->file('file');
|
||||
if (!$file || !$file->isValid()) {
|
||||
return jsonResponse(null, '未找到文件或文件无效', 400);
|
||||
}
|
||||
|
||||
$ext = strtolower($file->getUploadExtension());
|
||||
if (!in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
|
||||
return jsonResponse(null, '仅支持图片文件', 400);
|
||||
}
|
||||
|
||||
$dir = public_path() . '/upload/images/' . date('Ymd');
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0777, true);
|
||||
}
|
||||
|
||||
$filename = uniqid() . bin2hex(random_bytes(4)) . '.' . $ext;
|
||||
$path = $dir . '/' . $filename;
|
||||
$file->move($path);
|
||||
|
||||
$url = '/upload/images/' . date('Ymd') . '/' . $filename;
|
||||
|
||||
return jsonResponse([
|
||||
'url' => $url,
|
||||
'name' => $file->getUploadName(),
|
||||
], '上传成功');
|
||||
}
|
||||
}
|
||||
49
app/api/controller/UserController.php
Normal file
49
app/api/controller/UserController.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\common\model\Order;
|
||||
use app\common\model\Report;
|
||||
use app\common\model\User;
|
||||
|
||||
class UserController
|
||||
{
|
||||
public function stat(Request $request)
|
||||
{
|
||||
$userId = $request->user->id;
|
||||
|
||||
$totalOrders = Order::where('user_id', $userId)->count();
|
||||
$totalReports = Report::whereHas('order', function ($query) use ($userId) {
|
||||
$query->where('user_id', $userId);
|
||||
})->count();
|
||||
|
||||
return jsonResponse([
|
||||
'total_orders' => $totalOrders,
|
||||
'total_reports' => $totalReports
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateInfo(Request $request)
|
||||
{
|
||||
$userId = $request->user->id;
|
||||
$user = User::find($userId);
|
||||
|
||||
if (!$user) {
|
||||
return jsonResponse(null, '用户异常', 404);
|
||||
}
|
||||
|
||||
$nickname = trim($request->post('nickname', ''));
|
||||
$avatar = trim($request->post('avatar', ''));
|
||||
|
||||
if ($nickname) {
|
||||
$user->nickname = $nickname;
|
||||
}
|
||||
if ($avatar) {
|
||||
$user->avatar = $avatar;
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
return jsonResponse($user, '更新成功');
|
||||
}
|
||||
}
|
||||
205
app/api/controller/WechatAuthController.php
Normal file
205
app/api/controller/WechatAuthController.php
Normal file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use app\common\model\User;
|
||||
use app\common\model\WechatApp;
|
||||
use app\common\model\UserWechatIdentity;
|
||||
use app\common\service\AuthService;
|
||||
|
||||
class WechatAuthController
|
||||
{
|
||||
public function appList(Request $request)
|
||||
{
|
||||
$type = trim((string)$request->get('type', ''));
|
||||
$query = WechatApp::query()->where('status', 1);
|
||||
if ($type !== '') {
|
||||
$query->where('type', $type);
|
||||
}
|
||||
$list = $query->select(['id', 'name', 'type', 'app_id'])->orderByDesc('id')->get();
|
||||
return jsonResponse($list);
|
||||
}
|
||||
|
||||
public function miniLogin(Request $request)
|
||||
{
|
||||
$appId = trim((string)$request->post('app_id', ''));
|
||||
$code = trim((string)$request->post('code', ''));
|
||||
if ($appId === '' || $code === '') {
|
||||
return jsonResponse(null, '参数错误', 400);
|
||||
}
|
||||
|
||||
try {
|
||||
$app = $this->getApp($appId, 'mini');
|
||||
} catch (\Throwable $e) {
|
||||
return jsonResponse(null, $e->getMessage(), 400);
|
||||
}
|
||||
$secret = (string)($app->app_secret ?? '');
|
||||
if ($secret === '') {
|
||||
return jsonResponse(null, '未配置 app_secret', 400);
|
||||
}
|
||||
|
||||
$url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . urlencode($appId) .
|
||||
'&secret=' . urlencode($secret) .
|
||||
'&js_code=' . urlencode($code) .
|
||||
'&grant_type=authorization_code';
|
||||
$res = $this->httpGetJson($url);
|
||||
$openid = isset($res['openid']) ? trim((string)$res['openid']) : '';
|
||||
$unionid = isset($res['unionid']) ? trim((string)$res['unionid']) : '';
|
||||
if ($openid === '') {
|
||||
$msg = $res['errmsg'] ?? '获取 openid 失败';
|
||||
return jsonResponse(null, (string)$msg, 400);
|
||||
}
|
||||
|
||||
$user = $this->resolveUserByWechatIdentity($appId, $openid, $unionid, 'mini');
|
||||
if (intval($user->status) !== 1) {
|
||||
return jsonResponse(null, '账号已禁用', 403);
|
||||
}
|
||||
|
||||
$this->upsertIdentity($user->id, $appId, $openid, $unionid, 'mini');
|
||||
$user->openid = $openid;
|
||||
$user->save();
|
||||
|
||||
$token = AuthService::issueUserToken($user);
|
||||
return jsonResponse([
|
||||
'token' => $token,
|
||||
'user' => $user,
|
||||
'openid' => $openid,
|
||||
'app_id' => $appId,
|
||||
], '登录成功');
|
||||
}
|
||||
|
||||
public function h5Login(Request $request)
|
||||
{
|
||||
$appId = trim((string)$request->post('app_id', ''));
|
||||
$code = trim((string)$request->post('code', ''));
|
||||
if ($appId === '' || $code === '') {
|
||||
return jsonResponse(null, '参数错误', 400);
|
||||
}
|
||||
|
||||
try {
|
||||
$app = $this->getApp($appId, 'h5');
|
||||
} catch (\Throwable $e) {
|
||||
return jsonResponse(null, $e->getMessage(), 400);
|
||||
}
|
||||
$secret = (string)($app->app_secret ?? '');
|
||||
if ($secret === '') {
|
||||
return jsonResponse(null, '未配置 app_secret', 400);
|
||||
}
|
||||
|
||||
$url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . urlencode($appId) .
|
||||
'&secret=' . urlencode($secret) .
|
||||
'&code=' . urlencode($code) .
|
||||
'&grant_type=authorization_code';
|
||||
$res = $this->httpGetJson($url);
|
||||
$openid = isset($res['openid']) ? trim((string)$res['openid']) : '';
|
||||
$unionid = isset($res['unionid']) ? trim((string)$res['unionid']) : '';
|
||||
if ($openid === '') {
|
||||
$msg = $res['errmsg'] ?? '获取 openid 失败';
|
||||
return jsonResponse(null, (string)$msg, 400);
|
||||
}
|
||||
|
||||
$user = $this->resolveUserByWechatIdentity($appId, $openid, $unionid, 'h5');
|
||||
if (intval($user->status) !== 1) {
|
||||
return jsonResponse(null, '账号已禁用', 403);
|
||||
}
|
||||
|
||||
$this->upsertIdentity($user->id, $appId, $openid, $unionid, 'h5');
|
||||
$user->openid = $openid;
|
||||
$user->save();
|
||||
|
||||
$token = AuthService::issueUserToken($user);
|
||||
return jsonResponse([
|
||||
'token' => $token,
|
||||
'user' => $user,
|
||||
'openid' => $openid,
|
||||
'app_id' => $appId,
|
||||
], '登录成功');
|
||||
}
|
||||
|
||||
public function h5AuthorizeUrl(Request $request)
|
||||
{
|
||||
$appId = trim((string)$request->get('app_id', ''));
|
||||
$redirectUri = trim((string)$request->get('redirect_uri', ''));
|
||||
$scope = trim((string)$request->get('scope', 'snsapi_base'));
|
||||
$state = trim((string)$request->get('state', ''));
|
||||
|
||||
if ($appId === '' || $redirectUri === '') {
|
||||
return jsonResponse(null, '参数错误', 400);
|
||||
}
|
||||
if (!in_array($scope, ['snsapi_base', 'snsapi_userinfo'], true)) {
|
||||
return jsonResponse(null, 'scope 不合法', 400);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->getApp($appId, 'h5');
|
||||
} catch (\Throwable $e) {
|
||||
return jsonResponse(null, $e->getMessage(), 400);
|
||||
}
|
||||
|
||||
$url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . urlencode($appId) .
|
||||
'&redirect_uri=' . urlencode($redirectUri) .
|
||||
'&response_type=code&scope=' . urlencode($scope) .
|
||||
'&state=' . urlencode($state) .
|
||||
'#wechat_redirect';
|
||||
|
||||
return jsonResponse(['url' => $url]);
|
||||
}
|
||||
|
||||
private function getApp(string $appId, string $type): WechatApp
|
||||
{
|
||||
$row = WechatApp::where('app_id', $appId)->where('status', 1)->first();
|
||||
if (!$row) {
|
||||
throw new \RuntimeException('AppID 未配置或已停用');
|
||||
}
|
||||
if ((string)$row->type !== $type) {
|
||||
throw new \RuntimeException('AppID 类型不匹配');
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
private function httpGetJson(string $url): array
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
$body = curl_exec($ch);
|
||||
if ($body === false) {
|
||||
$err = curl_error($ch);
|
||||
curl_close($ch);
|
||||
throw new \RuntimeException('微信接口请求失败: ' . $err);
|
||||
}
|
||||
curl_close($ch);
|
||||
return json_decode($body, true) ?: [];
|
||||
}
|
||||
|
||||
private function resolveUserByWechatIdentity(string $appId, string $openid, string $unionid, string $scene): User
|
||||
{
|
||||
if ($unionid !== '') {
|
||||
$identity = UserWechatIdentity::where('unionid', $unionid)->first();
|
||||
if ($identity) {
|
||||
$user = User::find($identity->user_id);
|
||||
if ($user) return $user;
|
||||
}
|
||||
}
|
||||
|
||||
$identity = UserWechatIdentity::where('app_id', $appId)->where('openid', $openid)->first();
|
||||
if ($identity) {
|
||||
$user = User::find($identity->user_id);
|
||||
if ($user) return $user;
|
||||
}
|
||||
|
||||
return User::create([
|
||||
'openid' => $openid,
|
||||
'nickname' => $scene === 'mini' ? '小程序用户' : '微信用户',
|
||||
'status' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
private function upsertIdentity(int $userId, string $appId, string $openid, string $unionid, string $scene): void
|
||||
{
|
||||
UserWechatIdentity::updateOrCreate(
|
||||
['user_id' => $userId, 'app_id' => $appId],
|
||||
['openid' => $openid, 'unionid' => $unionid ?: null, 'scene' => $scene]
|
||||
);
|
||||
}
|
||||
}
|
||||
35
app/api/middleware/AuthMiddleware.php
Normal file
35
app/api/middleware/AuthMiddleware.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace app\api\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use app\common\service\AuthService;
|
||||
|
||||
class AuthMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$token = $this->getBearerToken($request);
|
||||
$user = AuthService::getUserByToken($token);
|
||||
if (!$user) {
|
||||
return jsonResponse(null, '未登录', 401);
|
||||
}
|
||||
$request->user = $user;
|
||||
$request->token = $token;
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
protected function getBearerToken(Request $request): ?string
|
||||
{
|
||||
$authorization = $request->header('authorization');
|
||||
if (!$authorization) {
|
||||
return null;
|
||||
}
|
||||
if (stripos($authorization, 'Bearer ') === 0) {
|
||||
return trim(substr($authorization, 7));
|
||||
}
|
||||
return trim($authorization);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user