Installation
composer require cdma-numiscorner/paypal-bundle
Add to config/app.php under providers:
Cdma\PaypalBundle\PaypalServiceProvider::class,
Publish config (optional but recommended):
php artisan vendor:publish --provider="Cdma\PaypalBundle\PaypalServiceProvider" --tag=config
Configuration
Edit .env with PayPal credentials:
PAYPAL_MODE=sandbox # or live
PAYPAL_CLIENT_ID=your_client_id
PAYPAL_SECRET=your_secret
PAYPAL_RETURN_URL=http://your-app.com/paypal/success
PAYPAL_CANCEL_URL=http://your-app.com/paypal/cancel
First Use Case: Create a Payment
use Cdma\PaypalBundle\Facades\Paypal;
$payment = Paypal::createPayment([
'intent' => 'sale',
'payer' => [
'payment_method' => 'paypal',
],
'transactions' => [
[
'amount' => [
'total' => '10.00',
'currency' => 'USD',
],
'description' => 'Test purchase',
],
],
'redirect_urls' => [
'return_url' => route('paypal.success'),
'cancel_url' => route('paypal.cancel'),
],
]);
Redirect user to $payment->getApprovalUrl().
Standard Checkout Flow
// 1. Create payment
$payment = Paypal::createPayment($data);
// 2. Redirect user to PayPal
return redirect()->away($payment->getApprovalUrl());
// 3. Handle return (success/cancel)
public function handlePaypalReturn(Request $request) {
$paymentId = $request->input('paymentId');
$payerId = $request->input('PayerID');
$payment = Paypal::executePayment($paymentId, $payerId);
// Process successful payment
}
Subscription Management
// Create plan
$plan = Paypal::createPlan([
'name' => 'Premium',
'billing_cycles' => [
[
'tenure_type' => 'REGULAR',
'sequence' => 1,
'total_count' => 1,
'pricing_scheme' => [
'fixed_price' => [
'value' => '9.99',
'currency_code' => 'USD',
],
],
],
],
]);
// Create subscription
$subscription = Paypal::createSubscription([
'plan_id' => $plan->getId(),
'start_time' => now()->addDay()->toIso8601String(),
]);
Webhook Handling
public function handlePaypalWebhook(Request $request) {
$event = Paypal::verifyWebhook($request->getContent());
switch ($event->getEventType()) {
case 'PAYMENT.CAPTURE.COMPLETED':
// Handle successful capture
break;
case 'PAYMENT.CANCELED':
// Handle cancellation
break;
}
}
PAYPAL_RETURN_URL/PAYPAL_CANCEL_URL:
Route::get('/paypal/success', [PaymentController::class, 'handleSuccess'])->name('paypal.success');
auth or custom middleware.PAYPAL_DEBUG=true
Webhook Verification
$event = Paypal::verifyWebhook($rawBody, $authHeader);
PAYPAL_WEBHOOK_ID and PAYPAL_WEBHOOK_SECRET in .env.Idempotency
Currency/Country Restrictions
Sandbox vs. Live
Redirect URLs
PAYPAL_RETURN_URL and PAYPAL_CANCEL_URL are HTTPS and accessible from PayPal’s servers.Enable Debug Mode:
PAYPAL_DEBUG=true
Logs will appear in storage/logs/paypal.log.
Common Errors:
INVALID_RESOURCE_ID: Verify paymentId/planId exists.VALIDATION_ERROR: Check request payload structure (e.g., amount.currency must match payer.country_code).AUTHORIZATION_ERROR: Confirm PAYPAL_CLIENT_ID/PAYPAL_SECRET are correct.Customize Responses
Override the default response formatter by binding your own PaypalResponseFormatter:
$this->app->bind('paypal.response.formatter', function() {
return new CustomPaypalResponseFormatter();
});
Add Custom Fields Extend transactions with custom metadata:
'transactions' => [
[
'amount' => [...],
'item_list' => [...],
'custom' => 'order_123', // Your reference
],
];
Batch Processing Use PayPal’s batch APIs for bulk operations (e.g., refunds):
$batch = Paypal::createBatch([
'operations' => [
[
'operation' => 'CREATE',
'resource' => [
'refund' => [
'amount' => ['currency' => 'USD', 'total' => '5.00'],
'invoice_id' => 'INV123',
],
],
],
],
]);
Localization Add language headers for PayPal pages:
Paypal::setLocale('es_ES'); // Spanish
How can I help you explore Laravel packages today?