Installation
composer require clubmaster/quickpay
Add the bundle to config/bundles.php:
Clubmaster\QuickpayBundle\ClubmasterQuickpayBundle::class => ['all' => true],
Configuration Publish the default config:
php bin/console config:dump-reference ClubmasterQuickpayBundle
Update config/packages/clubmaster_quickpay.yaml with your Quickpay credentials:
clubmaster_quickpay:
api_key: "your_api_key_here"
secret_key: "your_secret_key_here"
test_mode: true # Set to false for production
First Use Case: Creating a Payment
Inject the QuickpayGateway service into your controller/service:
use Clubmaster\QuickpayBundle\Gateway\QuickpayGateway;
public function __construct(private QuickpayGateway $quickpay) {}
public function createPayment(Request $request) {
$payment = $this->quickpay->createPayment(
1000, // Amount in smallest currency unit (e.g., 1000 DKK = 10 DKK)
'DKK', // Currency
'order_123', // Order ID
'Customer Name', // Customer name
'customer@example.com', // Customer email
'https://your-site.com/payment/callback' // Callback URL
);
return new JsonResponse($payment->getPaymentUrl());
}
/quickpay/callback).QuickpayWebhookHandler service to validate and process events:
use Clubmaster\QuickpayBundle\Event\WebhookEvent;
use Clubmaster\QuickpayBundle\Gateway\QuickpayWebhookHandler;
public function handleWebhook(Request $request, QuickpayWebhookHandler $handler) {
$event = $handler->handle($request);
if ($event->isValid()) {
// Process payment event (e.g., capture, refund, cancellation)
$this->processPaymentEvent($event);
}
return new Response('OK');
}
$capture = $this->quickpay->capturePayment(
'payment_id_from_quickpay',
1000 // Amount to capture (optional; defaults to authorized amount)
);
$refund = $this->quickpay->refundPayment(
'payment_id_from_quickpay',
500 // Amount to refund
);
$subscription = $this->quickpay->createSubscription(
'customer_id',
1000, // Price per period
'month', // Billing period
'product_name'
);
Service Container Binding:
Bind the QuickpayGateway to Laravel’s container in a service provider:
$this->app->bind(QuickpayGateway::class, function ($app) {
return new QuickpayGateway(
$app['config']['clubmaster_quickpay.api_key'],
$app['config']['clubmaster_quickpay.secret_key'],
$app['config']['clubmaster_quickpay.test_mode']
);
});
Event Dispatching:
Extend the bundle to dispatch Laravel events (e.g., PaymentCaptured) for decoupled handling:
// In your webhook handler
event(new PaymentCaptured($event->getPayment()));
test_mode: true in config to test without real transactions.QuickpayGateway in PHPUnit:
$mockGateway = $this->createMock(QuickpayGateway::class);
$mockGateway->method('createPayment')->willReturn(new Payment('test_url'));
$this->app->instance(QuickpayGateway::class, $mockGateway);
Webhook Validation:
QuickpayWebhookHandler. Skipping this risks processing fake events.if (!$event->isValid()) {
throw new \RuntimeException('Invalid Quickpay webhook signature');
}
Currency and Amount Units:
Idempotency:
Rate Limits:
Deprecated Methods:
Enable Logging:
Add logging to the QuickpayGateway constructor:
public function __construct(string $apiKey, string $secretKey, bool $testMode) {
$this->logger = new \Monolog\Logger('quickpay');
$this->logger->pushHandler(new \Monolog\Handler\StreamHandler('var/log/quickpay.log'));
}
Test Mode Quirks:
Error Handling:
QuickpayException:
try {
$payment = $this->quickpay->createPayment(...);
} catch (QuickpayException $e) {
$this->logger->error('Quickpay error: ' . $e->getMessage());
throw new \RuntimeException('Payment failed. Please try again.');
}
Custom Payment Models:
class PaymentMapper {
public function mapToDomain(array $quickpayData): Payment {
return new Payment(
$quickpayData['id'],
$quickpayData['amount'],
// ...
);
}
}
Additional Gateway Features:
QuickpayGateway.Laravel Notifications:
use Illuminate\Notifications\Notification;
class PaymentNotification extends Notification {
public function toMail($notifiable) {
return (new MailMessage)
->line('Payment captured: ' . $this->payment->id);
}
}
How can I help you explore Laravel packages today?