一键导入
laravel-services
Service layer for external API integration using manager pattern and Saloon. Use when integrating external APIs or third-party services.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Service layer for external API integration using manager pattern and Saloon. Use when integrating external APIs or third-party services.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Form request validation and comprehensive validation testing. Use when creating or modifying form requests, validation rules, or validation tests.
Feature module pattern organizing domain logic into queries, mutations, and actions. Use when implementing data fetching with filters, API mutations with loading states, business logic with UI feedback, or organizing domain-specific code.
File-based routing with page patterns for lists, details, and navigation. Use when creating pages, defining page meta (permissions, layouts), implementing list/detail patterns, or setting up breadcrumbs and headers.
Foundational architecture for Nuxt 4 + Vue 3 + Nuxt UI applications. Use when starting new projects, understanding project structure, or making architectural decisions about directory organization, technology choices, and pattern selection.
Vue component patterns with Composition API and script setup. Use when creating components, understanding script setup order convention, organizing component directories, or implementing component patterns like slideovers, modals, and tables.
Creating custom Vue composables with proper patterns. Use when building reusable stateful logic, shared state management, or encapsulating feature-specific behavior.
| name | laravel-services |
| description | Service layer for external API integration using manager pattern and Saloon. Use when integrating external APIs or third-party services. |
External services use Laravel's Manager pattern with multiple drivers.
Related guides:
Use service layer when:
Services/
└── Payment/
├── PaymentManager.php # Manager (extends Laravel Manager)
├── Connectors/
│ └── StripeConnector.php # Saloon HTTP connector
├── Contracts/
│ └── PaymentDriver.php # Driver interface
├── Drivers/
│ ├── StripeDriver.php # Stripe implementation
│ ├── PayPalDriver.php # PayPal implementation
│ └── NullDriver.php # For testing
├── Exceptions/
│ └── PaymentException.php
├── Facades/
│ └── Payment.php # Facade
└── Requests/
└── Stripe/
├── CreatePaymentIntentRequest.php
└── RefundPaymentRequest.php
<?php
declare(strict_types=1);
namespace App\Services\Payment;
use App\Services\Payment\Drivers\NullDriver;
use App\Services\Payment\Drivers\StripeDriver;
use Illuminate\Support\Manager;
class PaymentManager extends Manager
{
public function getDefaultDriver(): string
{
return $this->config->get('payment.default');
}
public function createStripeDriver(): StripeDriver
{
return new StripeDriver(
apiKey: $this->config->get('payment.drivers.stripe.api_key'),
webhookSecret: $this->config->get('payment.drivers.stripe.webhook_secret'),
);
}
public function createNullDriver(): NullDriver
{
return new NullDriver;
}
}
<?php
declare(strict_types=1);
namespace App\Services\Payment\Contracts;
use App\Data\PaymentIntentData;
interface PaymentDriver
{
public function createPaymentIntent(int $amount, string $currency): PaymentIntentData;
public function refundPayment(string $paymentIntentId, ?int $amount = null): bool;
public function retrievePaymentIntent(string $paymentIntentId): PaymentIntentData;
}
<?php
declare(strict_types=1);
namespace App\Services\Payment\Drivers;
use App\Data\PaymentIntentData;
use App\Services\Payment\Connectors\StripeConnector;
use App\Services\Payment\Contracts\PaymentDriver;
use App\Services\Payment\Exceptions\PaymentException;
use App\Services\Payment\Requests\Stripe\CreatePaymentIntentRequest;
use Saloon\Http\Response;
class StripeDriver implements PaymentDriver
{
private static ?StripeConnector $connector = null;
public function __construct(
private readonly string $apiKey,
private readonly string $webhookSecret,
) {}
public function createPaymentIntent(int $amount, string $currency): PaymentIntentData
{
$response = $this->sendRequest(
new CreatePaymentIntentRequest($amount, $currency)
);
return PaymentIntentData::from($response->json());
}
public function refundPayment(string $paymentIntentId, ?int $amount = null): bool
{
// Implementation...
}
private function sendRequest(Request $request): Response
{
$response = $this->getConnector()->send($request);
if ($response->failed()) {
throw PaymentException::failedRequest($response);
}
return $response;
}
private function getConnector(): StripeConnector
{
if (static::$connector === null) {
static::$connector = new StripeConnector($this->apiKey);
}
return static::$connector;
}
}
<?php
declare(strict_types=1);
namespace App\Services\Payment\Connectors;
use Saloon\Http\Connector;
class StripeConnector extends Connector
{
public function __construct(private readonly string $apiKey) {}
public function resolveBaseUrl(): string
{
return 'https://api.stripe.com';
}
protected function defaultHeaders(): array
{
return [
'Authorization' => "Bearer {$this->apiKey}",
'Content-Type' => 'application/json',
];
}
}
<?php
declare(strict_types=1);
namespace App\Services\Payment\Requests\Stripe;
use Saloon\Contracts\Body\HasBody;
use Saloon\Enums\Method;
use Saloon\Http\Request;
use Saloon\Traits\Body\HasJsonBody;
class CreatePaymentIntentRequest extends Request implements HasBody
{
use HasJsonBody;
protected Method $method = Method::POST;
public function __construct(
private readonly int $amount,
private readonly string $currency,
) {}
public function resolveEndpoint(): string
{
return '/v1/payment_intents';
}
protected function defaultBody(): array
{
return [
'amount' => $this->amount,
'currency' => $this->currency,
];
}
}
<?php
declare(strict_types=1);
namespace App\Services\Payment\Facades;
use App\Data\PaymentIntentData;
use Illuminate\Support\Facades\Facade;
/**
* @method static PaymentIntentData createPaymentIntent(int $amount, string $currency)
* @method static bool refundPayment(string $paymentIntentId, ?int $amount = null)
* @method static PaymentIntentData retrievePaymentIntent(string $paymentIntentId)
*
* @see \App\Services\Payment\PaymentManager
*/
class Payment extends Facade
{
protected static function getFacadeAccessor(): string
{
return \App\Services\Payment\PaymentManager::class;
}
}
use App\Services\Payment\Facades\Payment;
// Use default driver
$paymentIntent = Payment::createPaymentIntent(
amount: 10000, // $100.00 in cents
currency: 'usd'
);
// Refund payment
Payment::refundPayment($paymentIntent->id);
// Use specific driver
Payment::driver('stripe')->createPaymentIntent(10000, 'usd');
Payment::driver('paypal')->createPaymentIntent(10000, 'usd');
// Use in actions
class ProcessPaymentAction
{
public function __invoke(Order $order, PaymentData $data): Payment
{
$paymentIntent = Payment::createPaymentIntent(
amount: $order->total,
currency: 'usd'
);
// ...
}
}
<?php
declare(strict_types=1);
namespace App\Services\Payment\Drivers;
use App\Data\PaymentIntentData;
use App\Services\Payment\Contracts\PaymentDriver;
class NullDriver implements PaymentDriver
{
public function createPaymentIntent(int $amount, string $currency): PaymentIntentData
{
return PaymentIntentData::from([
'id' => 'pi_test_' . uniqid(),
'amount' => $amount,
'currency' => $currency,
'status' => 'succeeded',
]);
}
public function refundPayment(string $paymentIntentId, ?int $amount = null): bool
{
return true;
}
public function retrievePaymentIntent(string $paymentIntentId): PaymentIntentData
{
return PaymentIntentData::from([
'id' => $paymentIntentId,
'status' => 'succeeded',
]);
}
}