laravel-abacatepay maintained by cavalheri
Laravel AbacatePay
Laravel-native wrapper for the official AbacatePay PHP SDK.
Requirements
- PHP 8.3 or higher
- Laravel 13.x
- Composer
Installation
composer require cavalheri/laravel-abacatepay
This package requires the official SDK:
composer require abacatepay/php-sdk
Publish The Configuration
php artisan vendor:publish --tag=abacatepay-config
The published file will be available at config/abacatepay.php.
Environment Variables
ABACATEPAY_API_KEY=
ABACATEPAY_WEBHOOK_SECRET=
ABACATEPAY_DEV_MODE=false
Usage With The Facade
use Cavalheri\LaravelAbacatePay\Facades\AbacatePay;
$billing = AbacatePay::billing()->create([
'frequency' => 'ONE_TIME',
'methods' => ['PIX'],
'products' => [
[
'external_id' => 'PRO-PLAN',
'name' => 'Pro plan',
'quantity' => 1,
'price' => 1000,
],
],
'metadata' => [
'return_url' => route('dashboard'),
'completion_url' => route('billing.success'),
],
]);
Usage With Dependency Injection
use Cavalheri\LaravelAbacatePay\AbacatePayManager;
public function __invoke(AbacatePayManager $abacatePay)
{
return $abacatePay->billing()->create([
'frequency' => 'ONE_TIME',
'methods' => ['PIX'],
'products' => [
[
'external_id' => 'PRO-PLAN',
'name' => 'Pro plan',
'quantity' => 1,
'price' => 1000,
],
],
'metadata' => [
'return_url' => route('dashboard'),
'completion_url' => route('billing.success'),
],
]);
}
Creating A PIX Billing
$billing = AbacatePay::billing()->create([
'frequency' => 'ONE_TIME',
'methods' => ['PIX'],
'products' => [
[
'external_id' => 'ORDER-123',
'name' => 'Order #123',
'description' => 'Example order',
'quantity' => 1,
'price' => 4990,
],
],
'metadata' => [
'return_url' => route('checkout.index'),
'completion_url' => route('checkout.success'),
],
'customer_id' => 'cust_abcdefghij',
]);
return redirect()->away($billing->url);
You may also send customer data directly:
$billing = AbacatePay::billing()->create([
'frequency' => 'ONE_TIME',
'methods' => ['PIX'],
'products' => [
[
'external_id' => 'ORDER-123',
'name' => 'Order #123',
'quantity' => 1,
'price' => 4990,
],
],
'metadata' => [
'return_url' => route('checkout.index'),
'completion_url' => route('checkout.success'),
],
'customer' => [
'name' => 'Abacate Lover',
'email' => 'lover@example.com',
'cellphone' => '11999999999',
'tax_id' => '12345678901',
],
]);
Customers
$customer = AbacatePay::customers()->firstOrCreate([
'email' => 'lover@example.com',
'name' => 'Abacate Lover',
'tax_id' => '12345678901',
]);
You can also use the full v2 customer resource methods:
$customer = AbacatePay::customers()->create([...]);
$customers = AbacatePay::customers()->list(['limit' => 50]);
$customer = AbacatePay::customers()->get('cust_abcdefghij');
$deleted = AbacatePay::customers()->delete('cust_abcdefghij');
Coupons
$coupon = AbacatePay::coupons()->percentage('WELCOME10', 10, [
'max_redeems' => -1,
]);
Fixed amount coupons use cents:
$coupon = AbacatePay::coupons()->fixed('PROMO20', 2000);
You can also use the full v2 coupon resource methods:
$coupon = AbacatePay::coupons()->create([...]);
$coupons = AbacatePay::coupons()->list(['status' => 'ACTIVE']);
$coupon = AbacatePay::coupons()->get('WELCOME10');
$coupon = AbacatePay::coupons()->toggle('WELCOME10');
$deleted = AbacatePay::coupons()->delete('WELCOME10');
Products
Create a one-time product:
$product = AbacatePay::products()->oneTime('PRO-PLAN', 'Pro plan', 10000);
Create a subscription product:
$product = AbacatePay::products()->subscription('PRO-MONTHLY', 'Pro monthly', 10000, 'MONTHLY');
You can also use the full v2 product resource methods:
$product = AbacatePay::products()->create([
'external_id' => 'PRO-PLAN',
'name' => 'Pro plan',
'price' => 10000,
'description' => 'Professional plan',
]);
$products = AbacatePay::products()->list(['status' => 'ACTIVE']);
$product = AbacatePay::products()->get('prod_abc123xyz');
$product = AbacatePay::products()->get(['external_id' => 'PRO-PLAN']);
$deleted = AbacatePay::products()->delete('prod_abc123xyz');
Checkouts
Create a hosted checkout for a product:
$checkout = AbacatePay::checkouts()->forProduct('prod_abc123xyz');
return redirect()->away($checkout->url);
Create a PIX-only checkout:
$checkout = AbacatePay::checkouts()->pix('prod_abc123xyz', 1, [
'customer_id' => 'cust_abcdefghij',
]);
Create a card checkout with installments:
$checkout = AbacatePay::checkouts()->card('prod_abc123xyz', 1, [
'max_installments' => 12,
]);
You can also use the full v2 checkout resource methods:
$checkout = AbacatePay::checkouts()->create([
'items' => [
['id' => 'prod_abc123xyz', 'quantity' => 1],
],
'methods' => ['PIX', 'CARD'],
'return_url' => route('checkout.index'),
'completion_url' => route('checkout.success'),
]);
$checkouts = AbacatePay::checkouts()->list(['status' => 'PENDING']);
$checkout = AbacatePay::checkouts()->get('bill_abc123xyz');
$refund = AbacatePay::checkouts()->refund('bill_abc123xyz', 'Customer canceled the order.');
Payment Links
Create a reusable payment link for a product:
$paymentLink = AbacatePay::paymentLinks()->forProduct('prod_abc123xyz');
return redirect()->away($paymentLink->url);
Create a PIX-only payment link:
$paymentLink = AbacatePay::paymentLinks()->pix('prod_abc123xyz');
You can also use the full v2 payment link resource methods:
$paymentLink = AbacatePay::paymentLinks()->create([
'items' => [
['id' => 'prod_abc123xyz', 'quantity' => 1],
],
'methods' => ['PIX', 'CARD'],
'return_url' => route('checkout.index'),
'completion_url' => route('checkout.success'),
]);
$paymentLinks = AbacatePay::paymentLinks()->list(['status' => 'PENDING']);
$paymentLink = AbacatePay::paymentLinks()->get('bill_link123xyz');
$refund = AbacatePay::paymentLinks()->refund('bill_link789xyz', 'Duplicated charge.');
Transparent Checkouts
Create a PIX QR Code without redirecting the customer:
$charge = AbacatePay::transparentCheckouts()->pix(10000, [
'description' => 'Order #123',
'metadata' => ['order_id' => 'ORDER-123'],
]);
echo $charge->brCode;
Create a boleto with alternative PIX:
$charge = AbacatePay::transparentCheckouts()->boleto(25000, [
'name' => 'Abacate Lover',
'tax_id' => '12345678901',
]);
You can also use the full v2 transparent checkout methods:
$charge = AbacatePay::transparentCheckouts()->create([
'method' => 'PIX',
'data' => [
'amount' => 10000,
'expires_in' => 3600,
],
]);
$status = AbacatePay::transparentCheckouts()->check('pix_char_abc123xyz');
$charge = AbacatePay::transparentCheckouts()->simulatePayment('pix_char_abc123xyz');
$charges = AbacatePay::transparentCheckouts()->list(['status' => 'PENDING']);
$refund = AbacatePay::transparentCheckouts()->refund('pix_char_abc123xyz', 'Customer paid twice.');
Payouts
Create a payout in one line:
$payout = AbacatePay::payouts()->withdraw(10000, 'withdraw-123');
You can also use the full v2 payout resource methods:
$payout = AbacatePay::payouts()->create([
'amount' => 10000,
'external_id' => 'withdraw-123',
'description' => 'Weekly withdrawal',
]);
$payout = AbacatePay::payouts()->get('withdraw-123');
$payouts = AbacatePay::payouts()->list(['status' => 'PENDING']);
PIX Transfers
Send PIX to a key in one line:
$pix = AbacatePay::pixTransfers()->toPhone(10000, 'pix-123', '11987654321');
Use the helper that matches the key type:
AbacatePay::pixTransfers()->toEmail(10000, 'pix-124', 'supplier@example.com');
AbacatePay::pixTransfers()->toCpf(10000, 'pix-125', '12345678901');
AbacatePay::pixTransfers()->toCnpj(10000, 'pix-126', '12345678000199');
AbacatePay::pixTransfers()->toRandomKey(10000, 'pix-127', 'random-key');
AbacatePay::pixTransfers()->toBrCode(10000, 'pix-128', '000201...');
You can also use the full v2 PIX transfer methods:
$pix = AbacatePay::pixTransfers()->send([
'amount' => 10000,
'external_id' => 'pix-123',
'description' => 'Supplier payment',
'pix' => [
'key' => '11987654321',
'type' => 'PHONE',
],
]);
$pix = AbacatePay::pixTransfers()->get('txn_pix_abc123');
$pix = AbacatePay::pixTransfers()->getByExternalId('pix-123');
$pixTransfers = AbacatePay::pixTransfers()->list(['status' => 'PENDING']);
Subscriptions
Create a subscription checkout in one line:
$checkout = AbacatePay::subscriptions()->card('prod_monthly_abc123');
You can also use the full v2 subscription checkout payload:
$checkout = AbacatePay::subscriptions()->create([
'items' => [
['id' => 'prod_monthly_abc123', 'quantity' => 1],
],
'methods' => ['CARD'],
'customer_id' => 'cust_abc123xyz',
'external_id' => 'sub-123',
'metadata' => ['plan' => 'monthly'],
]);
$subscriptions = AbacatePay::subscriptions()->list(['status' => 'PAID']);
Manage active subscriptions:
$subscription = AbacatePay::subscriptions()->cancel('subs_abc123xyz');
$update = AbacatePay::subscriptions()->changePlan('subs_abc123xyz', 'prod_plano_pro', 1);
$usage = AbacatePay::subscriptions()->addUsage('subs_abc123xyz', 'prod_api_calls', 50);
$usage = AbacatePay::subscriptions()->subtractUsage('subs_abc123xyz', 'prod_api_calls', 10);
Store
Get your store details and balance in one line:
$store = AbacatePay::store()->get();
$availableBalance = $store->balance->available;
Public MRR
Get public merchant metrics in one line:
$mrr = AbacatePay::publicMrr()->mrr();
You can also use the full v2 public MRR methods:
$merchant = AbacatePay::publicMrr()->merchantInfo();
$mrr = AbacatePay::publicMrr()->mrr();
$revenue = AbacatePay::publicMrr()->revenue('2024-01-01', '2024-01-31');
$revenue = AbacatePay::publicMrr()->revenueForPeriod([
'start_date' => '2024-01-01',
'end_date' => '2024-01-31',
]);
Webhooks
Create a webhook with a fluent, Laravel-friendly flow:
$webhook = AbacatePay::webhooks()
->checkoutEvents()
->at('https://example.com/webhooks/abacatepay')
->named('Checkout payments')
->create();
Use official event presets, or subscribe to one exact event:
use Cavalheri\LaravelAbacatePay\Webhooks\WebhookEvent;
AbacatePay::webhooks()->subscriptionEvents()->at($url)->named('Subscriptions')->create();
AbacatePay::webhooks()->payoutEvents()->at($url)->named('Payouts')->create();
AbacatePay::webhooks()->listenTo(WebhookEvent::CHECKOUT_COMPLETED)->at($url)->named('Paid checkouts')->create();
You can still use the raw v2 resource methods when you need full control:
$webhook = AbacatePay::webhooks()->create([
'name' => 'Webhook de Pagamentos',
'endpoint' => 'https://example.com/webhooks/abacatepay',
'secret' => env('ABACATEPAY_WEBHOOK_SECRET'),
'events' => [
WebhookEvent::CHECKOUT_COMPLETED,
WebhookEvent::SUBSCRIPTION_RENEWED,
],
]);
$webhooks = AbacatePay::webhooks()->list(['search' => 'pagamentos']);
$webhook = AbacatePay::webhooks()->get('webh_abc123xyz');
$deleted = AbacatePay::webhooks()->delete('webh_abc123xyz');
Validate incoming webhook requests with the URL secret and HMAC signature:
$isValid = AbacatePay::webhooks()->verify(
rawBody: $request->getContent(),
signature: $request->header('X-Webhook-Signature'),
secret: $request->query('webhookSecret'),
);
Running Tests
composer test
Or run Pest directly:
vendor/bin/pest
Creating This Package From Scratch
mkdir laravel-abacatepay
cd laravel-abacatepay
composer init --name=cavalheri/laravel-abacatepay --type=library
composer require php:^8.3 illuminate/support:^13.0 abacatepay/php-sdk
composer require --dev orchestra/testbench:^11.0 pestphp/pest:^4.0 pestphp/pest-plugin-laravel:^4.0
mkdir -p config src/Clients src/Exceptions src/Facades tests/Feature
After creating the package files, refresh Composer autoloading:
composer dump-autoload
Publishing To Packagist
- Push the repository to GitHub.
- Create a release tag, for example
v0.1.0. - Sign in to Packagist.
- Submit the repository URL.
- Enable GitHub synchronization so Packagist updates on each new tag.
- Install the package in a Laravel 13 application and run a smoke test before announcing it.
Contributing
Pull requests are welcome. Please include tests for new behavior and keep changes focused.
License
The MIT License (MIT). Please see LICENSE for more information.