Lae/app/Models/Module.php

278 lines
7.1 KiB
PHP
Raw Normal View History

2022-08-13 06:04:47 +00:00
<?php
2022-11-06 11:28:22 +00:00
namespace App\Models;
2022-08-13 06:04:47 +00:00
2023-01-17 16:08:30 +00:00
use App\Exceptions\User\BalanceNotEnoughException;
2022-11-06 14:57:01 +00:00
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
2022-11-08 13:01:43 +00:00
use GuzzleHttp\Exception\ConnectException;
2022-11-06 11:28:22 +00:00
use Illuminate\Foundation\Auth\User as Authenticatable;
2022-11-30 07:57:31 +00:00
use Illuminate\Http\Client\PendingRequest;
2022-11-27 06:40:45 +00:00
use Illuminate\Http\Client\Response;
2022-11-19 03:08:16 +00:00
use Illuminate\Support\Facades\Cache;
2022-11-08 13:01:43 +00:00
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
2022-11-19 03:08:16 +00:00
use JetBrains\PhpStorm\ArrayShape;
2022-08-13 06:04:47 +00:00
2022-11-06 11:28:22 +00:00
class Module extends Authenticatable
2022-08-13 06:04:47 +00:00
{
2022-11-06 14:57:01 +00:00
use Cachable;
public $incrementing = false;
2022-08-13 06:04:47 +00:00
protected $table = 'modules';
protected $keyType = 'string';
2022-08-13 06:04:47 +00:00
protected $fillable = [
2022-08-14 13:57:56 +00:00
'id',
2022-08-14 14:00:22 +00:00
'name',
2022-08-14 13:57:56 +00:00
'api_token'
2022-08-13 06:04:47 +00:00
];
2022-08-14 13:57:56 +00:00
2022-09-13 02:04:10 +00:00
protected $hidden = [
'api_token',
2023-01-20 11:11:09 +00:00
'wecom_key',
'balance'
2022-09-13 02:04:10 +00:00
];
2023-01-17 16:08:30 +00:00
protected $casts = [
'id' => 'string',
'balance' => 'decimal:4',
];
protected static function boot()
{
parent::boot();
2023-01-19 08:23:55 +00:00
static::creating(function (self $model) {
if (!app()->environment('local')) {
$model->api_token = Str::random(60);
}
2023-01-19 08:23:55 +00:00
// 如果结尾有 / 则去掉
$model->url = rtrim($model->url, '/');
});
static::updating(function (self $model) {
// 如果结尾有 / 则去掉
$model->url = rtrim($model->url, '/');
});
}
2022-08-19 10:14:23 +00:00
2022-11-20 14:16:04 +00:00
// public function moduleHostFunctions($host_id, $func, $requests): array
// {
// $http = Http::module($this->api_token, $this->url);
// $response = $http->post("hosts/{$host_id}/functions/" . $func, $requests);
//
// return $this->getResponse($response);
// }
2022-08-19 10:31:24 +00:00
// post, get, patch, delete 等请求
2022-11-20 14:16:04 +00:00
public function remote($func, $requests): array
2022-08-19 10:14:23 +00:00
{
2022-11-30 07:57:31 +00:00
$response = $this->http()->post('functions/' . $func, $requests);
2022-08-19 10:14:23 +00:00
2022-11-20 14:16:04 +00:00
return $this->getResponse($response);
2022-08-19 10:14:23 +00:00
}
2022-12-27 16:25:22 +00:00
public function http(): PendingRequest
{
2023-01-19 08:23:55 +00:00
return Http::module($this->api_token, $this->url . '/remote')->acceptJson()->timeout(5);
2022-12-27 16:25:22 +00:00
}
private function getResponse(Response $response): array
{
2023-01-20 07:14:41 +00:00
// $module_token = $response->header('x-module-api-token');
2022-12-27 16:25:22 +00:00
$success = true;
$json = $response->json();
$status = $response->status();
2022-12-27 16:25:22 +00:00
// if status code is not 20x
if ($status < 200 || $status >= 300) {
$success = false;
// 防止误删除
2023-01-20 07:14:41 +00:00
// if ($module_token !== $this->api_token) {
// $this->status = 'maintenance';
// $this->save();
//
// $status = 401;
// }
2022-12-27 16:25:22 +00:00
}
return [
'body' => $response->body(),
'json' => $json,
'status' => $status,
'success' => $success,
];
}
2022-11-20 14:16:04 +00:00
public function request($method, $path, $requests): array
2022-08-29 09:31:08 +00:00
{
2023-01-10 13:42:27 +00:00
return $this->baseRequest($method, "functions/$path", $requests);
2022-11-27 06:40:45 +00:00
}
2022-08-29 09:31:08 +00:00
public function baseRequest($method, $path, $requests = []): array
2022-11-27 06:40:45 +00:00
{
$user = auth('sanctum')->user();
2022-11-23 08:47:34 +00:00
2022-11-27 06:40:45 +00:00
if ($user) {
2022-11-30 07:57:31 +00:00
$this->http()->withHeaders([
2023-01-18 13:56:26 +00:00
'X-User-Id' => $user->id,
2022-11-27 06:40:45 +00:00
]);
$requests['user_id'] = $user->id;
if ($method == 'post') {
// add user to requests
$requests['user'] = $user;
}
}
2022-11-30 07:57:31 +00:00
$response = $this->http()->{$method}($path, $requests);
2022-08-29 09:31:08 +00:00
2022-11-20 14:16:04 +00:00
return $this->getResponse($response);
2022-08-29 09:31:08 +00:00
}
2022-11-20 14:16:04 +00:00
public function moduleRequest($method, $path, $requests): array
{
2022-11-06 14:57:01 +00:00
$module_id = auth('module')->id();
2022-09-19 13:39:12 +00:00
2022-12-19 06:47:06 +00:00
$http = $this->http()->withHeaders([
2022-09-19 13:39:12 +00:00
'X-Module' => $module_id
]);
2022-09-19 13:39:12 +00:00
$requests['module_id'] = $module_id;
2023-01-10 13:42:27 +00:00
$response = $http->{$method}("exports/$path", $requests);
2022-11-20 14:16:04 +00:00
return $this->getResponse($response);
}
2023-01-10 13:42:27 +00:00
public function check(): bool
2022-10-29 05:53:32 +00:00
{
2023-01-10 13:42:27 +00:00
// $module_id = null
// if ($module_id) {
// $module = Module::find($module_id);
// } else {
// $module = $this;
// }
2022-10-29 05:53:32 +00:00
2022-11-20 14:16:04 +00:00
$success = 0;
2022-10-29 05:53:32 +00:00
try {
2022-11-30 07:57:31 +00:00
$response = $this->http()->get('remote');
2022-11-20 14:16:04 +00:00
if ($response->status() == 200) {
$success = 1;
}
2022-10-29 05:53:32 +00:00
} catch (ConnectException $e) {
Log::error($e->getMessage());
}
2022-11-20 14:16:04 +00:00
return $success;
2022-10-29 05:53:32 +00:00
}
2022-11-19 03:08:16 +00:00
#[ArrayShape(['transactions' => "array"])]
public function calculate(): array
{
2022-11-19 04:37:18 +00:00
$cache_key = 'module_earning_' . $this->id;
return Cache::get($cache_key, []);
2022-11-19 03:08:16 +00:00
}
2023-01-17 16:08:30 +00:00
/**
* 扣除费用
*
* @param string|null $amount
* @param string|null $description
* @param bool $fail
* @param array $options
*
* @return string
*/
public function reduce(string|null $amount = "0", string|null $description = "消费", bool $fail = false, array $options = []): string
{
if ($amount === null || $amount === '') {
return $this->balance;
}
Cache::lock('module_balance_' . $this->id, 10)->block(10, function () use ($amount, $fail, $description, $options) {
$this->refresh();
if ($this->balance < $amount) {
if ($fail) {
throw new BalanceNotEnoughException();
}
}
$this->balance = bcsub($this->balance, $amount, 4);
$this->save();
if ($description) {
$data = [
'module_id' => $this->id,
'amount' => $amount,
'description' => $description,
'payment' => 'balance',
'type' => 'payout',
];
if ($options) {
$data = array_merge($data, $options);
}
(new Transaction)->create($data);
}
});
return $this->balance;
}
/**
* 增加余额
*
* @param string|null $amount
* @param string $payment
* @param string|null $description
* @param array $options
*
* @return string
*/
public function charge(string|null $amount = "0", string $payment = 'console', string|null $description = '充值', array $options = []): string
{
if ($amount === null || $amount === '') {
return $this->balance;
}
Cache::lock('module_balance_' . $this->id, 10)->block(10, function () use ($amount, $description, $payment, $options) {
$this->refresh();
$this->balance = bcadd($this->balance, $amount, 4);
$this->save();
if ($description) {
$data = [
'module_id' => $this->id,
'amount' => $amount,
'payment' => $payment,
'description' => $description,
'type' => 'income',
];
if ($options) {
$data = array_merge($data, $options);
}
(new Transaction)->create($data);
}
});
return $this->balance;
}
2022-08-13 06:04:47 +00:00
}