275 lines
7.2 KiB
PHP
275 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Exceptions\User\BalanceNotEnoughException;
|
|
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
|
use GuzzleHttp\Exception\ConnectException;
|
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
|
use Illuminate\Http\Client\PendingRequest;
|
|
use Illuminate\Http\Client\Response;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Str;
|
|
use JetBrains\PhpStorm\ArrayShape;
|
|
|
|
class Module extends Authenticatable
|
|
{
|
|
use Cachable;
|
|
|
|
public $incrementing = false;
|
|
|
|
protected $table = 'modules';
|
|
|
|
protected $keyType = 'string';
|
|
|
|
protected $fillable = [
|
|
'id',
|
|
'name',
|
|
'api_token',
|
|
];
|
|
|
|
protected $hidden = [
|
|
'api_token',
|
|
'wecom_key',
|
|
'balance',
|
|
'url',
|
|
];
|
|
|
|
protected $casts = [
|
|
'id' => 'string',
|
|
'balance' => 'decimal:4',
|
|
];
|
|
|
|
protected static function boot()
|
|
{
|
|
parent::boot();
|
|
static::creating(function (self $model) {
|
|
if (! app()->environment('local')) {
|
|
$model->api_token = Str::random(60);
|
|
}
|
|
|
|
// 如果结尾有 / 则去掉
|
|
$model->url = rtrim($model->url, '/');
|
|
});
|
|
static::updating(function (self $model) {
|
|
// 如果结尾有 / 则去掉
|
|
$model->url = rtrim($model->url, '/');
|
|
});
|
|
}
|
|
|
|
// 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);
|
|
// }
|
|
|
|
// post, get, patch, delete 等请求
|
|
public function remote($func, $requests): array
|
|
{
|
|
$response = $this->http()->post('functions/'.$func, $requests);
|
|
|
|
return $this->getResponse($response);
|
|
}
|
|
|
|
public function http(): PendingRequest
|
|
{
|
|
return Http::module($this->api_token, $this->url.'/remote')->acceptJson()->timeout(5);
|
|
}
|
|
|
|
private function getResponse(Response $response): array
|
|
{
|
|
// $module_token = $response->header('x-module-api-token');
|
|
|
|
$success = true;
|
|
$json = $response->json();
|
|
$status = $response->status();
|
|
|
|
// if status code is not 20x
|
|
if ($status < 200 || $status >= 300) {
|
|
$success = false;
|
|
|
|
// 防止误删除
|
|
// if ($module_token !== $this->api_token) {
|
|
// $this->status = 'maintenance';
|
|
// $this->save();
|
|
//
|
|
// $status = 401;
|
|
// }
|
|
}
|
|
|
|
return [
|
|
'body' => $response->body(),
|
|
'json' => $json,
|
|
'status' => $status,
|
|
'success' => $success,
|
|
];
|
|
}
|
|
|
|
public function request($method, $path, $requests): array
|
|
{
|
|
return $this->baseRequest($method, "functions/$path", $requests);
|
|
}
|
|
|
|
public function baseRequest($method, $path, $requests = []): array
|
|
{
|
|
$user = auth('sanctum')->user();
|
|
|
|
$http = $this->http();
|
|
if ($user) {
|
|
$http = $http->withHeaders([
|
|
'X-User-Id' => $user->id,
|
|
]);
|
|
|
|
// $requests['user_id'] = $user->id;
|
|
// if ($method == 'post') {
|
|
// // add user to requests
|
|
// $requests['user'] = $user;
|
|
// }
|
|
}
|
|
|
|
$response = $http->{$method}($path, $requests);
|
|
|
|
return $this->getResponse($response);
|
|
}
|
|
|
|
public function moduleRequest($method, $path, $requests): array
|
|
{
|
|
$module_id = auth('module')->id();
|
|
|
|
$http = $this->http()->withHeaders([
|
|
'X-Module' => $module_id,
|
|
]);
|
|
|
|
$requests['module_id'] = $module_id;
|
|
|
|
$response = $http->{$method}("exports/$path", $requests);
|
|
|
|
return $this->getResponse($response);
|
|
}
|
|
|
|
public function check(): bool
|
|
{
|
|
// $module_id = null
|
|
// if ($module_id) {
|
|
// $module = Module::find($module_id);
|
|
// } else {
|
|
// $module = $this;
|
|
// }
|
|
|
|
$success = 0;
|
|
|
|
try {
|
|
$response = $this->http()->get('remote');
|
|
|
|
if ($response->status() == 200) {
|
|
$success = 1;
|
|
}
|
|
} catch (ConnectException $e) {
|
|
Log::error($e->getMessage());
|
|
}
|
|
|
|
return $success;
|
|
}
|
|
|
|
#[ArrayShape(['transactions' => 'array'])]
|
|
public function calculate(): array
|
|
{
|
|
$cache_key = 'module_earning_'.$this->id;
|
|
|
|
return Cache::get($cache_key, []);
|
|
}
|
|
|
|
/**
|
|
* 扣除费用
|
|
*
|
|
* @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;
|
|
}
|
|
}
|