bocapro / boca-payments
Payment helper for Stripe, PayPal, Plaid, MercadoPago, Authorize.Net, JustiFi and Global Payments
v1.0.0
2026-06-08 12:30 UTC
Requires
- php: ^8.2
- ext-curl: *
- ext-json: *
- authorizenet/authorizenet: ^2.0
- globalpayments/php-sdk: ^14.0
- illuminate/support: ^11.0|^12.0|^13.0
- mercadopago/dx-php: ^3.0
- paypal/paypal-server-sdk: ^2.0
- saloonphp/saloon: ^4.0
- smpita/typeas: ^4.2
- stripe/stripe-php: ^16.0
- tomorrow-ideas/plaid-sdk-php: *
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
- phpstan/phpstan: ^2.0
README
A unified payment gateway package for Laravel. One package, one interface, seven gateways.
Stripe, PayPal, Plaid, MercadoPago, Authorize.Net, JustiFi, and Global Payments.
Supported Gateways
Installation
composer require bocapro/boca-payments
Publish Config
php artisan vendor:publish --tag="boca-payments-config"
Setup
Add your credentials to .env. You only need to fill in the gateways you use.
BOCA_PAYMENTS_DEFAULT=stripe STRIPE_SECRET_KEY=sk_test_... STRIPE_PUBLISHABLE_KEY=pk_test_... STRIPE_WEBHOOK_SECRET=whsec_... PAYPAL_CLIENT_ID=... PAYPAL_CLIENT_SECRET=... PAYPAL_MODE=sandbox PLAID_CLIENT_ID=... PLAID_SECRET=... PLAID_ENVIRONMENT=sandbox MERCADOPAGO_ACCESS_TOKEN=... AUTHORIZE_NET_LOGIN_ID=... AUTHORIZE_NET_TRANSACTION_KEY=... AUTHORIZE_NET_MODE=sandbox JUSTIFI_CLIENT_ID=... JUSTIFI_CLIENT_SECRET=... GLOBAL_PAYMENT_MERCHANT_ID=... GLOBAL_PAYMENT_ACCOUNT_ID=... GLOBAL_PAYMENT_SHARED_SECRET=... GLOBAL_PAYMENT_APP_KEY=... GLOBAL_PAYMENT_MODE=sandbox
How to Use
1. Pay
use BetterFutures\BocaPayments\Facades\BocaPayments; use BetterFutures\BocaPayments\Data\Customer; use BetterFutures\BocaPayments\Enums\Currency; use BetterFutures\BocaPayments\Enums\Gateway; $response = BocaPayments::setAmount(99.99) ->setCurrency(Currency::USD) ->setCustomer(new Customer(email: 'john@example.com', firstName: 'John', lastName: 'Doe')) ->setDescription('Order #1234') ->setReturnUrl('https://myapp.com/payment/success') ->setCancelUrl('https://myapp.com/payment/cancel') ->pay();
This uses the default gateway from your config. To use a different gateway:
$response = BocaPayments::gateway(Gateway::PayPal) ->setAmount(50.00) ->setCurrency(Currency::USD) ->setCustomer(new Customer(email: 'john@example.com')) ->pay();
Pay Response:
$response->status; // PaymentStatus::Completed, Pending, Failed, RequiresAction, etc. $response->paymentId; // "pi_3abc123" - store this in your orders table $response->redirectUrl; // "https://..." - for gateways that redirect (PayPal, MercadoPago) $response->html; // rendered html for gateways that need it $response->message; // "succeeded" $response->raw; // full raw gateway response $response->isSuccessful(); // true if completed $response->requiresRedirect(); // true if needs redirect $response->requiresAction(); // true if needs 3D Secure, etc.
Handle the response in your controller:
if ($response->requiresRedirect()) { return redirect($response->redirectUrl); } // payment completed return view('payment.success', ['payment_id' => $response->paymentId]);
2. Verify
After the user is redirected back or you receive a webhook, verify the payment:
$response = BocaPayments::verify($paymentId); if ($response->isSuccessful()) { // mark order as paid }
3. Refund
// full refund $refund = BocaPayments::refund(paymentId: $paymentId); // partial refund $refund = BocaPayments::refund(paymentId: $paymentId, amount: 25.00, reason: 'Customer request'); if ($refund->isSuccessful()) { // refund processed }
Switch Gateway Dynamically
Pass a gateway string from user input, a database column, or a form select:
use Smpita\TypeAs\TypeAs; $response = BocaPayments::gateway(Gateway::from($request->input('gateway'))) ->setAmount(TypeAs::float($request->input('amount'))) ->setCurrency(Currency::USD) ->setCustomer(new Customer(email: TypeAs::string($request->input('email')))) ->pay(); // valid strings: stripe, paypal, plaid, mercadopago, authorize_net, justifi, global_payment
Full Controller Example
use BetterFutures\BocaPayments\Facades\BocaPayments; use BetterFutures\BocaPayments\Data\Customer; use BetterFutures\BocaPayments\Enums\Currency; use BetterFutures\BocaPayments\Enums\Gateway; use Smpita\TypeAs\TypeAs; class PaymentController extends Controller { public function pay(Request $request) { $response = BocaPayments::gateway(Gateway::from($request->input('gateway', 'stripe'))) ->setAmount(TypeAs::float($request->input('amount'))) ->setCurrency(Currency::USD) ->setCustomer(new Customer( email: TypeAs::string($request->input('email')), firstName: TypeAs::nullableString($request->input('first_name')), lastName: TypeAs::nullableString($request->input('last_name')), )) ->setReturnUrl(route('payment.verify')) ->pay(); if ($response->requiresRedirect()) { return redirect($response->redirectUrl); } return redirect()->route('orders.show', $response->paymentId); } public function verify(Request $request) { $response = BocaPayments::verify($request->input('payment_id')); if ($response->isSuccessful()) { // update order status return redirect()->route('orders.success'); } return redirect()->route('orders.failed'); } public function refund(string $paymentId) { $refund = BocaPayments::refund(paymentId: $paymentId); if ($refund->isSuccessful()) { return back()->with('success', 'Refund processed'); } return back()->with('error', 'Refund failed'); } }
Test Cards and Sandbox Credentials
Testing
vendor/bin/pest
Formatting
vendor/bin/pint
License
MIT