orcarail / cashier-orcarail
Laravel Cashier driver for OrcaRail — subscriptions, checkout, and webhooks for stablecoin payments
Requires
- php: ^8.1
- ext-json: *
- illuminate/contracts: ^10.0|^11.0|^12.0
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/routing: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- orcarail/orcarail-php: ^1.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- orchestra/testbench: ^8.0|^9.0|^10.0
- phpstan/phpstan: ^1.12 || ^2.0
- phpunit/phpunit: ^10.5 || ^11.0
README
Laravel Cashier-style billing for OrcaRail — subscriptions, one-off checkout, and webhook sync for stablecoin payments.
Requires the official PHP SDK orcarail/orcarail-php.
Requirements
- PHP 8.1+
- Laravel 10, 11, or 12
Installation
composer require orcarail/cashier-orcarail
Publish the config and run migrations:
php artisan vendor:publish --tag=orcarail-cashier-config php artisan migrate
Configuration
Add credentials to your .env:
ORCARAIL_API_KEY=ak_live_xxx ORCARAIL_API_SECRET=sk_live_xxx ORCARAIL_WEBHOOK_SECRET=whsec_xxx ORCARAIL_BASE_URL=https://api.orcarail.com/api/v1 ORCARAIL_PAY_URL=https://pay.orcarail.com ORCARAIL_CURRENCY=usd
Billable model
Add the Billable trait to your user (or other billable) model:
use OrcaRail\Cashier\Billable; class User extends Authenticatable { use Billable; }
Subscriptions
Create a subscription and redirect the payer to the hosted pay page:
use Illuminate\Http\Request; Route::post('/subscribe', function (Request $request) { $checkout = $request->user() ->newSubscription('default', 'price_xxx') ->trialDays(14) ->create([ 'payer_email' => $request->user()->email, 'return_url' => route('billing.return'), 'cancel_url' => route('billing.cancel'), ]); return $checkout; // RedirectResponse to hosted pay URL });
Check subscription state locally (synced via webhooks):
$user->subscribed(); // active / trialing / grace period $user->onTrial(); $user->subscription()?->cancel(); $user->subscription()?->resume();
Direct amount (no catalog price):
$user->newSubscription('default') ->withAmount([ 'amount' => '10.00', 'currency' => 'usd', 'token_id' => '...', 'network_id' => '...', 'interval' => 'month', ]) ->create();
One-off checkout
// Catalog price return $user->checkout('price_xxx', [ 'return_url' => route('orders.return'), ]); // Direct amount return $user->charge([ 'amount' => '25.00', 'currency' => 'usd', 'tokenId' => '...', 'networkId' => '...', 'return_url' => route('orders.return'), ]);
Cashier creates a Payment Intent, confirms it when needed, and redirects to the hosted pay URL from next_action.redirect_to_url.url (or pay_url / payment_link.link).
Webhooks
Cashier registers POST /orcarail/webhook (configurable via ORCARAIL_WEBHOOK_PATH) and verifies the x-webhook-signature HMAC header.
Point your OrcaRail API key webhook URL at:
https://your-app.test/orcarail/webhook
Handled subscription events sync the local subscriptions table (status, trial_ends_at, ends_at). Unknown event types return 200 so you can listen to:
OrcaRail\Cashier\Events\WebhookReceivedOrcaRail\Cashier\Events\WebhookHandled
Customization
use OrcaRail\Cashier\Cashier; Cashier::ignoreMigrations(); Cashier::ignoreRoutes(); Cashier::useSubscriptionModel(App\Models\Subscription::class);
Access the underlying PHP SDK client:
Cashier::api()->rates->list();
Testing
Unit / feature (testbench):
cd sdks-laravel-cashier composer test composer analyse composer cs-check
Docker real-flow E2E
Full harness (mirrors WooCommerce bin/run-woo-real-flow.sh): starts/reuses the local real-flow API + pay app, spins up a fresh Laravel container with this package, then runs subscribe + checkout + signed webhook sync.
cd sdks-laravel-cashier
./bin/run-laravel-real-flow.sh
Leave the Laravel stack up after a run:
ORCARAIL_KEEP_LARAVEL=1 ./bin/run-laravel-real-flow.sh
Requires Docker, curl, jq, openssl, and the usual real-flow Redis/MailDev stack under api/.
License
MIT