perafan / cashier-openpay
Laravel Cashier provides an expressive, fluent interface to Openpay's subscription billing services.
Requires
- ext-json: *
- illuminate/support: ~6|~7|~8
- openpay/sdk: dev-master
Requires (Dev)
- mockery/mockery: ^1.1
- orchestra/testbench: ~3|~4
- phpunit/phpunit: ^8.0
- sempro/phpunit-pretty-print: ^1.0
This package is auto-updated.
Last update: 2024-10-29 06:00:02 UTC
README
Installation
Require the Cashier package for Openpay with Composer:
composer require perafan/cashier-openpay
Run to publish migrations, WebHookController and config file.
php artisan vendor:publish --tag="cashier-openpay-migrations" php artisan vendor:publish --tag="cashier-openpay-configs" php artisan vendor:publish --tag="cashier-openpay-webhook-controller"
The Cashier service provider registers its own database migration directory, so remember to migrate your database after installing the package. The Cashier migrations will add several columns to your users table as well as create a new subscriptions table to hold all of your customer's subscriptions:
php artisan migrate
Configuration
Billable Model
Add the Billable
trait to your model definition.
Billable
trait provides methods to allow yo to perform common billing tasks (creating subscriptions, add payment method information, creating charges ,etc.)
use Perafan\CashierOpenpay\Billable; class User extends Authenticatable { use Billable; }
Cashier assumes your Billable model will be the App\Models\User class that ships with Laravel. If you wish to change this you can specify a different model in your
.env` file:
OPENPAY_MODEL=App\Models\User
API Keys
Next, you should configure your Openpay keys in your .env file. You can retrieve your Openpay API keys from the Openpay control panel.
OPENPAY_PUBLIC_KEY=-your-openpay-public-key- OPENPAY_PRIVATE_KEY=-your-openpay-private-key- OPENPAY_ID=-your-openpay-id-
Environment
By convenience and security, the sandbox mode is activated by default in the client library. This allows you to test your own code when implementing Openpay, before charging any credit card in production environment.
OPENPAY_PRODUCTION_MODE=false
Logging
Cashier allows you to specify the log channel to be used when logging all Openpay related exceptions.
OPENPAY_LOG_ERRORS=true
Show openpay errors (Optional)`
If you want to catch all the openpay exceptions add in your app/Exceptions/Handler.php
<?php namespace App\Exceptions; use Perafan\CashierOpenpay\OpenpayExceptionsHandler; ... class Handler extends ExceptionHandler { use OpenpayExceptionsHandler; ... public function render($request, Throwable $exception) { if ($this->isOpenpayException($exception)) { return $this->renderOpenpayException($request, $exception); } return parent::render($request, $exception); } }
To render the error response in blade you could use the follow snippets.
Show errors with bootstrap
@if($errors->cashier->isNotEmpty()) <div class="alert alert-danger" role="alert"> @foreach ($errors->cashier->keys() as $key) <strong>{{ $key }} :</strong> {{ $errors->cashier->get($key)[0] }} <br> @endforeach </div> @endif
Show errors with tailwindcss
@if($errors->cashier->isNotEmpty()) <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert"> @foreach ($errors->cashier->keys() as $key) <strong class="font-bold">{{ $key }} :</strong> {{ $errors->cashier->get($key)[0] }} <br> @endforeach </div> @endif
Your own Openpay Exceptions Handler (Optional)
You can modify the response creating your own handler.
trait MyOpenpayExceptionsHandler { use OpenpayExceptionsHandler { OpenpayExceptionsHandler::renderOpenpayException as parentRenderOpenpayException; } public function renderOpenpayException(Request $request, OpenpayApiError $exception) { $this->parentRenderOpenpayException($request, $exception); //your code } }
Use
Customers
On a User:
Add a new customer to a merchant:
$user->createAsOpenpayCustomer(); //Or you can send additional data $data = [ 'name' => 'Teofilo', 'last_name' => 'Velazco', 'phone_number' => '4421112233', 'address' => [ 'line1' => 'Privada Rio No. 12', 'line2' => 'Co. El Tintero', 'line3' => '', 'postal_code' => '76920', 'state' => 'Querétaro', 'city' => 'Querétaro.', 'country_code' => 'MX' ] ]; $openpay_customer = $user->createAsOpenpayCustomer($data);
Get a customer:
$openpay_customer = $user->asOpenpayCustomer();
Update a customer:
$openpay_customer = $user->asOpenpayCustomer(); $openpay_customer->name = 'Juan'; $openpay_customer->last_name = 'Godinez'; $openpay_customer->save();
Delete a customer:
$openpay_customer = $user->asOpenpayCustomer(); $openpay_customer->delete();
On a merchant:
Add a new customer to a merchant:
use Perafan\CashierOpenpay\Openpay\Customer as OpenpayCustomer; OpenpayCustomer::create([ 'name' => 'Teofilo', 'last_name' => 'Velazco', 'email' => 'teofilo@payments.com', 'phone_number' => '4421112233', 'address' => [ 'line1' => 'Privada Rio No. 12', 'line2' => 'Co. El Tintero', 'line3' => '', 'postal_code' => '76920', 'state' => 'Querétaro', 'city' => 'Querétaro.', 'country_code' => 'MX' ] ]);
Get a customer:
use Perafan\CashierOpenpay\Openpay\Customer as OpenpayCustomer; $customer = OpenpayCustomer::find('a9ualumwnrcxkl42l6mh');
Get the list of customers:
use Perafan\CashierOpenpay\Openpay\Customer as OpenpayCustomer; $customer_list = OpenpayCustomer::all(); // with filters $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $customer_list = OpenpayCustomer::all($filters);
Update a customer:
use Perafan\CashierOpenpay\Openpay\Customer as OpenpayCustomer; $customer = OpenpayCustomer::find('a9ualumwnrcxkl42l6mh'); $customer->name = 'Juan'; $customer->last_name = 'Godinez'; $customer->save();
Delete a customer:
use Perafan\CashierOpenpay\Openpay\Customer as OpenpayCustomer; $customer = OpenpayCustomer::find('a9ualumwnrcxkl42l6mh'); $customer->delete();
Cards
On a user:
Add a card:
$card_data = [ 'holder_name' => 'Teofilo Velazco', 'card_number' => '4916394462033681', 'cvv2' => '123', 'expiration_month' => '12', 'expiration_year' => '15' ]; $card = $user->addCard($card_data); // with token $card_data = [ 'token_id' => 'tokgslwpdcrkhlgxqi9a', 'device_session_id' => '8VIoXj0hN5dswYHQ9X1mVCiB72M7FY9o' ]; $card = $user->addCard($card_data); // with address $address_data = [ 'line1' => 'Privada Rio No. 12', 'line2' => 'Co. El Tintero', 'line3' => '', 'postal_code' => '76920', 'state' => 'Querétaro', 'city' => 'Querétaro.', 'country_code' => 'MX' ]; $card = $user->addCard($card_data, $address_data);
Get a card:
use Perafan\CashierOpenpay\Card; $card = $user->cards->first; //or $card = Card::find(1); $openpay_card = $card->asOpenpayCard();
Get user cards:
use Perafan\CashierOpenpay\Card; $cards = $user->cards; // or $cards = Card::where('user_id', $user->id)->get();
Get user cards from Openpay
use Perafan\CashierOpenpay\Card; use Perafan\CashierOpenpay\Openpay\Card as OpenpayCard; $cards = $user->cards; $openpay_cards = $cards->map(function($card) { return $card->asOpenpayCard(); }); // or $cards = Card::where('user_id', $user->id)->get(); $openpay_cards = $cards->map(function($card) { return $card->asOpenpayCard(); }); // or $openpay_customer = $user->asOpenpayCustomer(); $openpay_cards = OpenpayCard::all([], $openpay_customer); // with filters $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $openpay_cards = OpenpayCard::all($filters, $openpay_customer);
Delete a card
use Perafan\CashierOpenpay\Card; $card = $user->cards->first; //or $card = Card::find(1); $openpay_card = $card->asOpenpayCard(); $deleted_card = $openpay_card->delete(); if (!is_array($deleted_card)) { //The card was deleted in Openpay $card->delete(); }
On a merchant:
Add a card:
use Perafan\CashierOpenpay\Openpay\Card as OpenpayCard; $card_data = [ 'holder_name' => 'Teofilo Velazco', 'card_number' => '4916394462033681', 'cvv2' => '123', 'expiration_month' => '12', 'expiration_year' => '15' ]; $openpay_card = OpenpayCard::add($card_data); // with token $card_data = [ 'token_id' => 'tokgslwpdcrkhlgxqi9a', 'device_session_id' => '8VIoXj0hN5dswYHQ9X1mVCiB72M7FY9o' ]; $openpay_card = OpenpayCard::add($card_data); // with address $address_data = [ 'line1' => 'Privada Rio No. 12', 'line2' => 'Co. El Tintero', 'line3' => '', 'postal_code' => '76920', 'state' => 'Querétaro', 'city' => 'Querétaro.', 'country_code' => 'MX' ]; $card_data['address'] = $address_data; $openpay_card = OpenpayCard::add($card_data);
Get a card:
use Perafan\CashierOpenpay\Openpay\Card as OpenpayCard; $openpay_card = OpenpayCard::find('k9pn8qtsvr7k7gxoq1r5');
Get the list of cards:
use Perafan\CashierOpenpay\Openpay\Card as OpenpayCard; $openpay_card = OpenpayCard::all(); // with filters $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $openpay_card = OpenpayCard::all($filters);
Delete a card:
use Perafan\CashierOpenpay\Openpay\Card as OpenpayCard; $openpay_card = OpenpayCard::find('k9pn8qtsvr7k7gxoq1r5'); $openpay_card->delete(); //Card was not delete on your database, only was deleted in openpay
Bank Accounts
Add a bank account to a customer:
$bank_data = [ 'clabe' => '072910007380090615', 'alias' => 'Cuenta principal', 'holder_name' => 'Teofilo Velazco' ]; $bank_account = $user->addBankAccount($bank_data);
Get a bank account
use Perafan\CashierOpenpay\BankAccount; $bank_account = $user->bank_accounts->first; // or $bank_account = BankAccount::where('user_id', $user->id)->first(); $openpay_bank_account = $bank_account->asOpenpayBankAccount();
Get user bank accounts:
use Perafan\CashierOpenpay\BankAccount; $bank_accounts = $user->bank_accounts; // or $bank_accounts = BankAccount::where('user_id', $user->id)->get();
Get user bank accounts from Openpay:
use Perafan\CashierOpenpay\BankAccount; use Perafan\CashierOpenpay\Openpay\BankAccount as OpenpayBankAccount; $bank_accounts = $user->bank_accounts; $openpay_bank_accounts = $bank_accounts->map(function($bank_account) { return $bank_account->asOpenpayBankAccount(); }); // or $bank_accounts = BankAccount::where('user_id', $user->id)->get(); $openpay_bank_accounts = $bank_accounts->map(function($bank_account) { return $bank_account->asOpenpayBankAccount(); }); // or $openpay_customer = $user->asOpenpayCustomer(); $openpay_bank_accounts = OpenpayBankAccount::all([], $openpay_customer); // with filters $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $openpay_bank_accounts = OpenpayBankAccount::all($filters, $openpay_customer);
Delete a bank account:
use Perafan\CashierOpenpay\BankAccount; $bank_account = $user->bank_accounts->first; // or $bank_account = BankAccount::where('user_id', $user->id)->first(); $openpay_bank_account = $bank_account->asOpenpayBankAccount(); $deleted_bank_account = $openpay_bank_account->delete(); if (!is_array($deleted_bank_account)) { //The card was deleted in Openpay $bank_account->delete(); }
Charges
On a Customer:
Make a charge on a customer:
$charge_data = [ 'source_id' => 'tvyfwyfooqsmfnaprsuk', 'method' => 'card', 'currency' => 'MXN', 'description' => 'Cargo inicial a mi merchant', 'order_id' => 'oid-00051', 'device_session_id' => 'kR1MiQhz2otdIuUlQkbEyitIqVMiI16f', ]; $openpay_charge = $user->charge(100, $charge_data);
Get a charge:
use Perafan\CashierOpenpay\Openpay\Charge as OpenpayCharge; $openpay_charge = OpenpayCharge::find('a9ualumwnrcxkl42l6mh');
Get list of charges per user:
use Perafan\CashierOpenpay\Openpay\Charge as OpenpayCharge; $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $openpay_customer = $user->asOpenpayCustomer(); $openpay_charge = OpenpayCharge::all($filters, $openpay_customer);
Make a capture:
use Perafan\CashierOpenpay\Openpay\Charge as OpenpayCharge; $capture_data = ['amount' => 150.00]; $openpay_charge = OpenpayCharge::find('a9ualumwnrcxkl42l6mh'); $openpay_charge->capture($capture_data);
Make a refund:
// Send charge id as first param $charge_id = 'tvyfwyfooqsmfnaprsuk'; $user->refund($charge_id); //or $description = 'Reembolso'; $user->refund($charge_id, $description); //or $amount = 150.00; $user->refund($charge_id, $description, $amount);
On a Merchant:
Make a charge on a merchant:
use Perafan\CashierOpenpay\Openpay\Charge as OpenpayCharge; $charge_data = [ 'method' => 'card', 'source_id' => 'krfkkmbvdk3hewatruem', 'amount' => 100, 'description' => 'Cargo inicial a mi merchant', 'order_id' => 'ORDEN-00071' ]; $openpay_charge = OpenpayCharge::create($charge_data);
Get a charge:
use Perafan\CashierOpenpay\Openpay\Charge as OpenpayCharge; $openpay_charge = OpenpayCharge::find('tvyfwyfooqsmfnaprsuk');
Get list of charges:
use Perafan\CashierOpenpay\Openpay\Charge as OpenpayCharge; $openpay_charges = OpenpayCharge::all(); // with filters $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $openpay_charges = OpenpayCharge::all($filters);
Make a capture:
use Perafan\CashierOpenpay\Openpay\Charge as OpenpayCharge; $capture_data = ['amount' => 150.00]; $openpay_charge = OpenpayCharge::find('tvyfwyfooqsmfnaprsuk'); $capture_data->capture($capture_data);
Make a refund:
use Perafan\CashierOpenpay\Openpay\Charge as OpenpayCharge; $refund_data = ['description' => 'Devolución']; $openpay_charge = OpenpayCharge::find('tvyfwyfooqsmfnaprsuk'); $openpay_charge->refund($refund_data);
Transfers
Make a transfer:
$transfer_data = [ 'customer_id' => 'aqedin0owpu0kexr2eor', 'amount' => 12.50, 'description' => 'Cobro de Comisión', 'order_id' => 'ORDEN-00061' ]; $openpay_customer = $user->asOpenpayCustomer(); $transfer = $openpay_customer->transfers->create($transfer_data);
Get a transfer:
$openpay_customer = $user->asOpenpayCustomer(); $transfer = $openpay_customer->transfers->get('tyxesptjtx1bodfdjmlb');
Get list of transfers:
$filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $openpay_customer = $user->asOpenpayCustomer(); $transfer_list = $openpay_customer->transfers->getList($filters);
Payouts
On a Customer:
Make a payout on a customer:
$payout_data = [ 'method' => 'card', 'destination_id' => 'k9pn8qtsvr7k7gxoq1r5', 'amount' => 1000, 'description' => 'Retiro de saldo semanal', 'order_id' => 'ORDEN-00062' ]; $openpay_customer = $user->asOpenpayCustomer(); $payout = $openpay_customer->payouts->create($payout_data);
Get a payout:
$openpay_customer = $user->asOpenpayCustomer(); $payout = $openpay_customer->payouts->get('tysznlyigrkwnks6eq2c');
Get list pf payouts:
$filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $openpay_customer = $user->asOpenpayCustomer(); $payout_list = $customer->payouts->getList($filters);
Fees
Pending ...
Plans
Add a plan:
use Perafan\CashierOpenpay\Openpay\Plan as OpenpayPlan; $plan_data = [ 'amount' => 150.00, 'status_after_retry' => 'cancelled', 'retry_times' => 2, 'name' => 'Plan Curso Verano', 'repeat_unit' => 'month', 'trial_days' => '30', 'repeat_every' => '1', 'currency' => 'MXN' ]; $openpay_plan = OpenpayPlan::add($plan_data);
Get a plan:
use Perafan\CashierOpenpay\Openpay\Plan as OpenpayPlan; $openpay_plan = OpenpayPlan::find('pduar9iitv4enjftuwyl');
Get list of plans:
use Perafan\CashierOpenpay\Openpay\Plan as OpenpayPlan; $openpay_plans = OpenpayPlan::all(); // with filters $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $openpay_plans = OpenpayPlan::all($filters);
Update a plan:
use Perafan\CashierOpenpay\Openpay\Plan as OpenpayPlan; $openpay_plan = OpenpayPlan::find('pduar9iitv4enjftuwyl'); $openpay_plan->name = 'Plan Curso de Verano 2021'; $openpay_plan->save();
Delete a plan:
use Perafan\CashierOpenpay\Openpay\Plan as OpenpayPlan; $openpay_plan = OpenpayPlan::find('pduar9iitv4enjftuwyl'); $openpay_plan->delete();
Get list of subscriptors of a plan:
use Perafan\CashierOpenpay\Openpay\Plan as OpenpayPlan; $openpay_plan = OpenpayPlan::find('pduar9iitv4enjftuwyl'); $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $subscription_list = $openpay_plan->subscriptions->getList($filters);
Subscriptions
Add a subscription:
$plan_id = 'pduar9iitv4enjftuwyl'; $subscription = $user->newSubscription($plan_id); // Add the name of subscription $options = [ 'trial_end_date' => '2021-01-01', 'card_id' => 'konvkvcd5ih8ta65umie' ]; $subscription = $user->newSubscription($plan_id, $options); // Add the name of subscription $name = 'plan_verano_2021'; $subscription = $user->newSubscription($plan_id, $options, $name);
Checking Subscription Status
$name = 'plan_verano_2021'; $user->subscribed($name); $name_2027 = 'plan_verano_2027'; $user->subscribed($name_2027); $plan_id = 'pduar9iitv4enjftuwyl'; $user->subscribed($name, $plan_id); $user->subscribed($name, 'ptyui9iit40nfwftuwyl');
$plans = [ 'pduar9iitv4enjftuwyl', 'ptyui9iit40nfwftuwyl' ]; $user->subscribedToPlan($plans);
Subscription Trial
$subscription = $user->subscription(); $subscription->onTrial();
Checking User Trial
$subscription_name = 'plan_verano_2027'; $user->onTrial($subscription_name);
Get a subscription:
use Perafan\CashierOpenpay\Subscription; $subscription = $user->subscriptions->first; // or $subscription = Subscription::find('s7ri24srbldoqqlfo4vp'); $subscription->asOpenpaySubscription();
Get list of subscriptions:
$openpay = Openpay::getInstance('moiep6umtcnanql3jrxp', 'sk_3433941e467c1055b178ce26348b0fac'); $filters = [ 'creation[gte]' => '2020-01-01', 'creation[lte]' => '2020-12-31', 'offset' => 0, 'limit' => 5 ]; $customer = $openpay->customers->get('a9ualumwnrcxkl42l6mh'); $subscriptionList = $customer->subscriptions->getList($filters);
Update a subscription:
$openpay = Openpay::getInstance('moiep6umtcnanql3jrxp', 'sk_3433941e467c1055b178ce26348b0fac'); $customer = $openpay->customers->get('a9ualumwnrcxkl42l6mh'); $subscription = $customer->subscriptions->get('s7ri24srbldoqqlfo4vp'); $subscription->trial_end_date = '2021-12-31'; $subscription->save();
Delete a subscription:
$openpay = Openpay::getInstance('moiep6umtcnanql3jrxp', 'sk_3433941e467c1055b178ce26348b0fac'); $customer = $openpay->customers->get('a9ualumwnrcxkl42l6mh'); $subscription = $customer->subscriptions->get('s7ri24srbldoqqlfo4vp'); $subscription->delete();
Openpay SDK
Many of Cashier's objects are wrappers around Openpay SDK objects. If you would like to interact with the Openpay objects directly, you may conveniently retrieve them using the asOpenpay...
methods:
$openpayCustomer = $user->asOpenpayCustomer(); $openpayCustomer->name = 'Pedro'; $openpayCustomer->save(); $openpaySubscription = $subscription->asOpenpaySubscription(); $subscription->trial_end_date = '2021-12-31'; $openpaySubscription->save();
Testing
To get started, add the testing version of your Openpay keys to your phpunit.xml file:
<env name="OPENPAY_PUBLIC_KEY" value=""/> <env name="OPENPAY_PRIVATE_KEY" value=""/> <env name="OPENPAY_ID" value=""/>
Then you can run on your term
$ composer install $ vendor/bin/phpunit
Contributing
Please see contributing.md for details and a todolist.
Security
If you discover any security related issues, please email pedro.perafan.carrasco@gmail.com instead of using the issue tracker.
Credits
License
MIT. Please see the license file for more information.