Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Jawali Payment Laravel Package

alsharie/jawali-payment

Laravel client for the Jawali payment gateway. Provides simple methods for ecommerce inquiry and cash out, with automatic token handling, configurable base URL/SSL, retries/timeouts, optional logging, and structured API responses via Laravel config/env.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require alsharie/jawali-payment
    

    Publish the config file:

    php artisan vendor:publish --provider="Alsharie\JawaliPayment\JawaliPaymentServiceProvider" --tag="config"
    
  2. Configuration Edit .env with your Jawali API credentials:

    JAWALI_API_KEY=your_api_key_here
    JAWALI_API_SECRET=your_api_secret_here
    JAWALI_ENVIRONMENT=sandbox # or 'live'
    
  3. First Use Case: Create a Payment Intent

    use Alsharie\JawaliPayment\Facades\JawaliPayment;
    
    $intent = JawaliPayment::createPaymentIntent([
        'amount' => 100.00, // in SAR
        'currency' => 'SAR',
        'description' => 'Order #12345',
        'metadata' => ['order_id' => '12345'],
    ]);
    
    return redirect()->to($intent->payment_url);
    

Key Files to Review

  • Config: config/jawali-payment.php (API endpoints, default settings).
  • Facade: app/Facades/JawaliPayment.php (if extended).
  • Service Provider: vendor/alsharie/jawali-payment/src/JawaliPaymentServiceProvider.php (for custom bindings).

Implementation Patterns

Common Workflows

1. Payment Processing

  • Create Intent:
    $intent = JawaliPayment::createPaymentIntent($request->all());
    
  • Handle Webhook (e.g., in routes/web.php):
    Route::post('/jawali-webhook', [PaymentWebhookController::class, 'handle']);
    
    // PaymentWebhookController.php
    public function handle(Request $request) {
        $event = JawaliPayment::verifyWebhook($request->all());
        // Process event (e.g., update order status)
    }
    

2. Subscription Management

  • Create Subscription:
    $subscription = JawaliPayment::createSubscription([
        'customer_id' => $customer->jawali_id,
        'items' => [['price_id' => 'price_123']],
    ]);
    
  • Cancel Subscription:
    JawaliPayment::cancelSubscription($subscription->id);
    

3. Refunds and Disputes

  • Refund a Payment:
    JawaliPayment::createRefund($payment->id, ['amount' => 50.00]);
    
  • Dispute Handling:
    $dispute = JawaliPayment::createDispute($charge->id, ['amount' => 100.00, 'reason' => 'fraudulent']);
    

4. Customer Management

  • Create/Update Customer:
    $customer = JawaliPayment::createCustomer([
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'phone' => '+966551234567',
    ]);
    
  • Attach to Order:
    $order->customer()->attach($customer->id);
    

Integration Tips

Laravel Ecosystem

  • Use Events: Listen to Jawali webhooks and trigger Laravel events:
    event(new PaymentSucceeded($intent->id, $intent->amount));
    
  • Queue Webhook Processing:
    Queue::push(new ProcessJawaliWebhook($event));
    
  • Service Layer Pattern:
    // app/Services/PaymentService.php
    public function processPayment(Order $order) {
        $intent = JawaliPayment::createPaymentIntent($order->toJawaliArray());
        return $intent;
    }
    

Testing

  • Use the sandbox environment for testing:
    JAWALI_ENVIRONMENT=sandbox
    
  • Mock the facade in tests:
    JawaliPayment::shouldReceive('createPaymentIntent')->andReturn($mockIntent);
    

Logging

Enable debug logging in config/jawali-payment.php:

'debug' => env('JAWALI_DEBUG', false),

View logs in storage/logs/laravel.log.


Gotchas and Tips

Pitfalls

  1. Webhook Verification

    • Always verify webhook signatures to avoid spoofing:
      $event = JawaliPayment::verifyWebhook($request->all(), $request->get('signature'));
      
    • Use JAWALI_WEBHOOK_SECRET in .env for local testing.
  2. Currency and Amount

    • Jawali expects amounts in halalas (smallest unit, e.g., 100.00 SAR = 10000 halalas).
    • Fix: Multiply by 100 when passing amounts:
      'amount' => $order->total * 100,
      
  3. Idempotency Keys

    • Use idempotency keys for retries to avoid duplicate charges:
      JawaliPayment::createPaymentIntent($data, ['idempotency_key' => uniqid()]);
      
  4. Rate Limits

    • Jawali enforces rate limits. Cache responses for non-idempotent operations:
      $customer = Cache::remember("jawali_customer_{$user->id}", now()->addHours(1), function() use ($user) {
          return JawaliPayment::createCustomer($user->toJawaliArray());
      });
      
  5. Error Handling

    • Jawali returns HTTP errors (e.g., 402 for insufficient funds). Handle gracefully:
      try {
          $intent = JawaliPayment::createPaymentIntent($data);
      } catch (\Alsharie\JawaliPayment\Exceptions\JawaliException $e) {
          return back()->withError($e->getMessage());
      }
      

Debugging Tips

  1. Enable Debug Mode Set JAWALI_DEBUG=true in .env to log raw API responses.

  2. Test with Sandbox Use Jawali’s sandbox tester to simulate payments.

  3. Check Headers Ensure Authorization and Content-Type headers are set:

    $response = Http::withHeaders([
        'Authorization' => 'Bearer ' . config('jawali.api_key'),
        'Content-Type' => 'application/json',
    ])->post('https://api.jawali.com/v1/payment_intents', $data);
    
  4. Common Errors

    • invalid_request_error: Validate required fields (e.g., currency, amount).
    • authentication_error: Verify JAWALI_API_KEY and JAWALI_API_SECRET.
    • resource_missing: Ensure the customer/subscription exists before acting on it.

Extension Points

  1. Custom Facade Extend the facade to add domain-specific methods:

    // app/Facades/ExtendedJawaliPayment.php
    class ExtendedJawaliPayment extends JawaliPayment {
        public function createOrderPayment(Order $order) {
            return parent::createPaymentIntent($order->toJawaliArray());
        }
    }
    
  2. Middleware for API Calls Add middleware to log or transform requests:

    // app/Http/Middleware/JawaliRequestMiddleware.php
    public function handle($request, Closure $next) {
        if ($request->routeIs('jawali.*')) {
            // Modify request data
        }
        return $next($request);
    }
    
  3. Custom Webhook Handlers Route webhooks to specific handlers:

    // routes/web.php
    Route::post('/jawali-webhook', function (Request $request) {
        $event = JawaliPayment::verifyWebhook($request->all());
        app()->call([\App\Handlers\WebhookHandlers::class, $event->type], ['event' => $event]);
    });
    
  4. Local Overrides Override API endpoints in config:

    'endpoints' => [
        'api' => env('JAWALI_API_URL', 'https://api.jawali.com'),
        'webhook' => env('JAWALI_WEBHOOK_URL', 'https://your-app.com/jawali-webhook'),
    ],
    
  5. Testing Helpers Add test helpers to app/Helpers/JawaliTestHelper.php:

    function mockJawaliResponse($status, $data = []) {
        JawaliPayment::shouldReceive('createPaymentIntent')
            ->andReturn((object) ['id' => 'pi_12
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium