ThirdPartyService.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. <?php
  2. namespace App\Module\ThirdParty\Models;
  3. use UCore\ModelCore;
  4. use App\Module\ThirdParty\Enums\SERVICE_TYPE;
  5. use App\Module\ThirdParty\Enums\AUTH_TYPE;
  6. use App\Module\ThirdParty\Enums\SERVICE_STATUS;
  7. use Illuminate\Database\Eloquent\Relations\HasMany;
  8. /**
  9. * 第三方服务模型
  10. *
  11. * field start
  12. * @property int $id 主键ID
  13. * @property string $name 服务名称
  14. * @property string $code 服务代码(唯一标识)
  15. * @property string $type 服务类型
  16. * @property string $provider 服务提供商
  17. * @property string $description 服务描述
  18. * @property string $base_url 基础URL
  19. * @property string $version API版本
  20. * @property string $auth_type 认证类型
  21. * @property string $status 服务状态
  22. * @property int $priority 优先级(数字越小优先级越高)
  23. * @property int $timeout 超时时间(秒)
  24. * @property int $retry_times 重试次数
  25. * @property int $retry_delay 重试延迟(毫秒)
  26. * @property array $config 服务配置信息
  27. * @property array $headers 默认请求头
  28. * @property array $params 默认参数
  29. * @property string $webhook_url Webhook回调地址
  30. * @property string $webhook_secret Webhook密钥
  31. * @property string $health_check_url 健康检查URL
  32. * @property int $health_check_interval 健康检查间隔(秒)
  33. * @property \Carbon\Carbon $last_health_check 最后健康检查时间
  34. * @property string $health_status 健康状态
  35. * @property \Carbon\Carbon $created_at 创建时间
  36. * @property \Carbon\Carbon $updated_at 更新时间
  37. * field end
  38. */
  39. class ThirdPartyService extends ModelCore
  40. {
  41. /**
  42. * 数据表名
  43. *
  44. * @var string
  45. */
  46. protected $table = 'thirdparty_services';
  47. /**
  48. * 属性类型转换
  49. *
  50. * @var array
  51. */
  52. protected $casts = [
  53. 'config' => 'array',
  54. 'headers' => 'array',
  55. 'params' => 'array',
  56. 'priority' => 'integer',
  57. 'timeout' => 'integer',
  58. 'retry_times' => 'integer',
  59. 'retry_delay' => 'integer',
  60. 'health_check_interval' => 'integer',
  61. 'last_health_check' => 'datetime',
  62. 'created_at' => 'datetime',
  63. 'updated_at' => 'datetime',
  64. ];
  65. /**
  66. * 获取配置信息(用于表单回显)
  67. *
  68. * @param mixed $value
  69. * @return array
  70. */
  71. public function getConfigAttribute($value): array
  72. {
  73. if (is_string($value)) {
  74. $decoded = json_decode($value, true);
  75. return is_array($decoded) ? $decoded : [];
  76. }
  77. return is_array($value) ? $value : [];
  78. }
  79. /**
  80. * 获取请求头信息(用于表单回显)
  81. *
  82. * @param mixed $value
  83. * @return array
  84. */
  85. public function getHeadersAttribute($value): array
  86. {
  87. if (is_string($value)) {
  88. $decoded = json_decode($value, true);
  89. return is_array($decoded) ? $decoded : [];
  90. }
  91. return is_array($value) ? $value : [];
  92. }
  93. /**
  94. * 获取参数信息(用于表单回显)
  95. *
  96. * @param mixed $value
  97. * @return array
  98. */
  99. public function getParamsAttribute($value): array
  100. {
  101. if (is_string($value)) {
  102. $decoded = json_decode($value, true);
  103. return is_array($decoded) ? $decoded : [];
  104. }
  105. return is_array($value) ? $value : [];
  106. }
  107. /**
  108. * 获取服务类型枚举
  109. *
  110. * @return SERVICE_TYPE
  111. */
  112. public function getServiceTypeEnum(): SERVICE_TYPE
  113. {
  114. return SERVICE_TYPE::from($this->type);
  115. }
  116. /**
  117. * 获取认证类型枚举
  118. *
  119. * @return AUTH_TYPE
  120. */
  121. public function getAuthTypeEnum(): AUTH_TYPE
  122. {
  123. return AUTH_TYPE::from($this->auth_type);
  124. }
  125. /**
  126. * 获取服务状态枚举
  127. *
  128. * @return SERVICE_STATUS
  129. */
  130. public function getServiceStatusEnum(): SERVICE_STATUS
  131. {
  132. return SERVICE_STATUS::from($this->status);
  133. }
  134. /**
  135. * 获取服务类型标签
  136. *
  137. * @return string
  138. */
  139. public function getTypeLabel(): string
  140. {
  141. return $this->getServiceTypeEnum()->getLabel();
  142. }
  143. /**
  144. * 获取认证类型标签
  145. *
  146. * @return string
  147. */
  148. public function getAuthTypeLabel(): string
  149. {
  150. return $this->getAuthTypeEnum()->getLabel();
  151. }
  152. /**
  153. * 获取状态标签
  154. *
  155. * @return string
  156. */
  157. public function getStatusLabel(): string
  158. {
  159. return $this->getServiceStatusEnum()->getLabel();
  160. }
  161. /**
  162. * 检查服务是否可用
  163. *
  164. * @return bool
  165. */
  166. public function isAvailable(): bool
  167. {
  168. return $this->getServiceStatusEnum()->isAvailable();
  169. }
  170. /**
  171. * 检查服务是否可以调用API
  172. *
  173. * @return bool
  174. */
  175. public function canCallApi(): bool
  176. {
  177. return $this->getServiceStatusEnum()->canCallApi();
  178. }
  179. /**
  180. * 检查服务是否需要关注
  181. *
  182. * @return bool
  183. */
  184. public function needsAttention(): bool
  185. {
  186. return $this->getServiceStatusEnum()->needsAttention();
  187. }
  188. /**
  189. * 获取完整的API URL
  190. *
  191. * @param string $endpoint
  192. * @return string
  193. */
  194. public function getApiUrl(string $endpoint = ''): string
  195. {
  196. $baseUrl = rtrim($this->base_url, '/');
  197. $endpoint = ltrim($endpoint, '/');
  198. if (empty($endpoint)) {
  199. return $baseUrl;
  200. }
  201. return $baseUrl . '/' . $endpoint;
  202. }
  203. /**
  204. * 获取默认请求头
  205. *
  206. * @return array
  207. */
  208. public function getDefaultHeaders(): array
  209. {
  210. $headers = $this->headers ?? [];
  211. // 添加认证相关的默认头
  212. $authType = $this->getAuthTypeEnum();
  213. if ($authType->getHeaderName()) {
  214. $headers['Content-Type'] = 'application/json';
  215. $headers['Accept'] = 'application/json';
  216. }
  217. return $headers;
  218. }
  219. /**
  220. * 获取默认参数
  221. *
  222. * @return array
  223. */
  224. public function getDefaultParams(): array
  225. {
  226. return $this->params ?? [];
  227. }
  228. /**
  229. * 关联认证凭证
  230. *
  231. * @return HasMany
  232. */
  233. public function credentials(): HasMany
  234. {
  235. return $this->hasMany(ThirdPartyCredential::class, 'service_id');
  236. }
  237. /**
  238. * 关联调用日志
  239. *
  240. * @return HasMany
  241. */
  242. public function logs(): HasMany
  243. {
  244. return $this->hasMany(ThirdPartyLog::class, 'service_id');
  245. }
  246. /**
  247. * 关联配额管理
  248. *
  249. * @return HasMany
  250. */
  251. public function quotas(): HasMany
  252. {
  253. return $this->hasMany(ThirdPartyQuota::class, 'service_id');
  254. }
  255. /**
  256. * 关联监控记录
  257. *
  258. * @return HasMany
  259. */
  260. public function monitors(): HasMany
  261. {
  262. return $this->hasMany(ThirdPartyMonitor::class, 'service_id');
  263. }
  264. /**
  265. * 获取激活的凭证
  266. *
  267. * @param string $environment
  268. * @return ThirdPartyCredential|null
  269. */
  270. public function getActiveCredential(string $environment = 'production'): ?ThirdPartyCredential
  271. {
  272. return $this->credentials()
  273. ->where('is_active', true)
  274. ->where('environment', $environment)
  275. ->where(function ($query) {
  276. $query->whereNull('expires_at')
  277. ->orWhere('expires_at', '>', now());
  278. })
  279. ->first();
  280. }
  281. /**
  282. * 更新健康状态
  283. *
  284. * @param string $status
  285. * @return bool
  286. */
  287. public function updateHealthStatus(string $status): bool
  288. {
  289. return $this->update([
  290. 'health_status' => $status,
  291. 'last_health_check' => now(),
  292. ]);
  293. }
  294. /**
  295. * 检查是否需要健康检查
  296. *
  297. * @return bool
  298. */
  299. public function needsHealthCheck(): bool
  300. {
  301. if (!$this->health_check_url) {
  302. return false;
  303. }
  304. if (!$this->last_health_check) {
  305. return true;
  306. }
  307. $nextCheck = $this->last_health_check->addSeconds($this->health_check_interval);
  308. return now()->gte($nextCheck);
  309. }
  310. /**
  311. * 生成唯一的服务代码
  312. *
  313. * @param string $name
  314. * @param string $provider
  315. * @return string
  316. */
  317. public static function generateCode(string $name, string $provider): string
  318. {
  319. $code = strtolower($provider . '_' . str_replace(' ', '_', $name));
  320. $code = preg_replace('/[^a-z0-9_]/', '', $code);
  321. // 确保代码唯一
  322. $counter = 1;
  323. $originalCode = $code;
  324. while (static::where('code', $code)->exists()) {
  325. $code = $originalCode . '_' . $counter;
  326. $counter++;
  327. }
  328. return $code;
  329. }
  330. }