Lara Payments Ma
A Laravel payment gateway package that provides a unified API for integrating multiple payment providers, including Stripe and Paymob, with support for payments, payment verification, retries, refunds, transactions, and webhooks.
MA Lara Payment
A unified Laravel payment package for integrating multiple payment gateways through a consistent API, including Paymob subscriptions.
Documentation • Quick Start • Version • Testing • Contributing • License
#What is this package?
ma-lara/payments gives Laravel applications one API for multiple payment providers, plus a subscription API for Paymob:
use Ma\Payment\Facades\MaPayment; $payment = MaPayment::driver('paymob'); // Payments $paylink = $payment->pay([...]); $payment->verify($request->all()); $payment->refund($transactionId, 50); // Subscriptions $payment->subscription()->createPlan([...]); $result = $payment->subscription()->subscribe($plan, $customerData); $payment->subscription()->lifeCycle($request->all());
Provider-specific API calls, authentication, response mapping, and callback handling stay isolated inside each gateway. The backend is frontend-agnostic — an optional Stripe Blade card component is included but never required.
#Capabilities
- Unified gateway contract with runtime driver selection (
MaPayment::driver(...)). - Stripe card payments using PaymentIntents, signed webhooks, retries, refunds.
- Paymob card payments (hosted iframe), mobile wallet payments, HMAC callbacks, retries, refunds, and subscriptions.
- Normalized
PaymentStatusandSubscriptionStatusenums. - Local persistence of customers, transactions, refunds, saved card records, plans, subscriptions, and webhook events.
- Queued jobs for async refund updates and subscription lifecycle updates.
- Extensible architecture for adding gateways and subscription implementations.
Not implemented: capture, void, Stripe subscriptions, charging a stored card through the package API, and persisted recurring (renewal) transactions. See 1. Introduction for the full list.
#Supported gateways
| Gateway | Card | Wallet | Retry | Refund | Webhook / Callback | Subscription |
|---|---|---|---|---|---|---|
| Stripe | ✅ | ❌ | ✅ | ✅ | ✅ Signed | ❌ |
| Paymob | ✅ | ✅ | ✅ | ✅ | ✅ HMAC | ✅ |
Subscriptions are exposed by gateways that implement SubscrptionableInterface:
MaPayment::driver('paymob')->subscription(); // ✅
#Requirements
| Requirement | Version |
|---|---|
| PHP | >=8.1 |
| Laravel | >=9.0 <14.0 |
| JSON | ext-json |
| cURL | ext-curl |
| Stripe SDK | stripe/stripe-php |
#Installation
composer require ma-lara/payments php artisan vendor:publish --tag=ma-payment-config php artisan vendor:publish --tag=ma-payment-migrations php artisan migrate
Then set your provider credentials in .env and expose your own callback routes —
the package does not register routes for you.
Full instructions, including the queue worker requirement and the subscription webhook URL: 2. Installation.
#Quick Start
use Ma\Payment\Facades\MaPayment; Route::post('/pay', function (Illuminate\Http\Request $request) { $paymob = MaPayment::driver('paymob'); $paylink = $paymob->pay([ 'amount' => 150.50, // major units 'currency' => 'EGP', 'customer' => [ 'id' => auth()->id(), 'first_name' => 'John', 'last_name' => 'Doe', 'email' => 'john@example.com', 'phone' => '01010101010', ], 'source' => 'card', // or 'wallet' ]); return redirect($paylink); });
// Provider callback (your own route) Route::post('/paymob/callback', function (Illuminate\Http\Request $request) { return response()->json( MaPayment::driver('paymob')->verify($request->all()) ); });
More: 3. Quick Start — including a minimal subscription example.
#Documentation
The documentation is organized by what you are trying to do. Start here:
| # | Chapter | You will find |
|---|---|---|
| 1 | Introduction | What the package does, capabilities, supported gateways, requirements, what is intentionally not implemented |
| 2 | Installation | Composer install, configuration, migrations, callback routes, subscription webhook URL, queue worker |
| 3 | Quick Start | The minimum steps for a normal payment and for a Paymob subscription |
| 4 | Payments | Creating a Payment · Payment Response · Payment Status · Payment Callbacks / Webhooks · Retry Payment · Refunds · Transactions · Saved Cards |
| 5 | Subscriptions | Subscription Overview · Creating a Subscription Plan · Listing Plans · Updating a Plan · Suspending/Resuming a Plan · Creating a Subscription · Subscription Lifecycle · Updating a Subscription · Subscription Callbacks / Webhooks · Subscription Transactions |
| 6 | Gateway Architecture | How gateways are resolved, the public contracts, and $payment->subscription() |
| 7 | Configuration | Every config file, environment variable, publish tag, and capability requirement |
| 8 | Troubleshooting | Real errors thrown by the package and how to resolve them |
| 9 | Advanced / Developer Documentation | Architecture, DTOs, value objects, repositories, webhook internals, testing, extending gateways, adding another subscription implementation |
A short answer for the most common questions:
| Question | Answer |
|---|---|
| How do I install the package? | 2. Installation |
| How do I make a payment? | 3. Quick Start → 4. Payments |
| How do I create a subscription plan? | 5. Subscriptions → Creating a Subscription Plan |
| How do I create a subscription? | 5. Subscriptions → Creating a Subscription |
| How do I suspend or resume it? | 5. Subscriptions → Subscription Lifecycle |
| How do refunds, retries, and callbacks work? | 4. Payments |
| Where do I find implementation details? | 9. Advanced / Developer Documentation |
#Key subscription methods at a glance
$payment = MaPayment::driver('paymob'); $payment->subscription()->createPlan([...]); // create a plan (local + gateway) $payment->subscription()->listPlans(); // local plans $payment->subscription()->findPlanByLocalId($id); // local plan $payment->subscription()->updateSubscriptionPlan($gatewayPlanId, [...]); $payment->subscription()->suspendPlan($gatewayPlanId); $payment->subscription()->resumePlan($gatewayPlanId); $payment->subscription()->subscribe($plan, $customerData); // initial payment $payment->subscription()->paginateLocalSubscrptions(15); // local subscriptions $payment->subscription()->findSubscrptionByLocalId($id); // local subscription $payment->subscription()->suspendSubscription($gatewaySubscriptionId); $payment->subscription()->resumeSubscription($gatewaySubscriptionId); $payment->subscription()->updateGatewaySubscription($gatewaySubscriptionId, [...]); $payment->subscription()->lifeCycle($request->all()); // lifecycle webhook
Method names are reproduced exactly as implemented (
findSubscrptionByLocalId,paginateLocalSubscrptions).$gatewayPlanId/$gatewaySubscriptionIdare Paymob IDs; the...ByLocalIdmethods take local database IDs.
#Version
These documents describe v2.1.0.
v2.1.0 is a backward-compatible feature release that introduces Paymob subscription
support. Existing payment behaviour, public methods, configuration keys, and previously
existing database tables are unchanged.
Schema additions in this release:
- new tables:
subscription_plans,subscriptions,subscription_webhook_events,customer_cards - two nullable columns on
payment_transactions:subscription_id,subscription_transaction_type
Only version references related to this release were updated. Historical release notes are not maintained in this repository.
#Testing
composer test composer test -- --testdox
- PHPUnit treats
tests/Unitandtests/Featureas separate suites (phpunit.xml). - Tests run against SQLite
:memory:using Orchestra Testbench (tests/TestCase.phpregisters the provider and migrates the package migrations). - Existing tests cover the Paymob payment happy path, the failed-payment path, and the payment DTOs. Subscription behaviour is not covered by automated tests yet — see 9. Advanced → Testing.
- CI runs the suite on a PHP/Laravel matrix (
.github/workflows/test.yaml), and a localpre-pushhook (.github/hooks/pre-push) runscomposer testbefore pushing.
#Contributing
Contributions are welcome.
When adding or modifying functionality:
- follow the existing architecture;
- keep gateway-specific code inside its gateway directory;
- avoid changing the shared payment workflow unnecessarily;
- add or update tests and run
composer test; - update the documentation and the capability tables;
- preserve backward compatibility.
#Security
- Never commit provider secrets — use
.envand keep the config cache cleared after changes. - The package does not register routes; you own the callback endpoints. Exclude them from CSRF protection where needed.
- Stripe webhooks are signature-verified. Paymob payment callbacks are HMAC-verified. Paymob subscription lifecycle webhooks are not signature-verified by the package — protect that endpoint in your application (see 5. Subscriptions → Subscription Callbacks / Webhooks).
- Report security issues privately to the author rather than in a public issue.
#Author
#License
MIT © Mohamed Allam
