Weave 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

Laravel Paytm Wallet Laravel Package

anandsiddharth/laravel-paytm-wallet

A Laravel package for integrating Paytm Wallet payments into your application. It simplifies payment initiation, checksum generation, callback handling, and transaction verification, giving you a clean, configurable API for accepting Paytm wallet payments without writing low-level integration code.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require anandsiddharth/laravel-paytm-wallet. v2.0.0 is a major release, so expect breaking changes if you're coming from 1.x — read the upgrade diff (issue #58 / PR #61) before bumping an existing app.
  • Publish and review the config file first (php artisan vendor:publish --tag=paytm-config or the provider's publish group). This is where MID, merchant key, industry type, channel, website, and the callback URL live. Everything else in the package reads from here.
  • Put credentials in .env and reference them from config/paytm.php — never commit the merchant key. Add PAYTM_MID, PAYTM_MERCHANT_KEY, PAYTM_ENV (staging/production), PAYTM_CALLBACK_URL.
  • First use case: a one-off "add money to wallet" flow. Build a controller action that creates an order/transaction record locally, hands off to the package's payment-initiation call, and redirects to Paytm. Then a second route that receives the callback and verifies the checksum before marking the order paid.
  • Look first at: the service provider bindings (what's registered as a singleton/facade), the config file, and the callback/checksum verification class. Those three tell you 80% of how the package is meant to be used.

Implementation Patterns

Order-then-pay (recommended) Create your own orders/transactions row before calling Paytm, store the order_id, and pass that same ID through the payment request. Paytm's callback is the only reliable source of truth — never trust the browser redirect alone.

$order = Order::create(['user_id' => auth()->id(), 'amount' => $amount, 'status' => 'pending']);

$payment = Paytm::initiate([
    'order_id'   => (string) $order->id,
    'amount'     => $order->amount,
    'cust_id'    => (string) auth()->id(),
    'email'      => auth()->user()->email,
    'mobile'     => auth()->user()->phone,
    'callback_url' => route('paytm.callback'),
]);

return redirect($payment->getRedirectUrl());

Callback handling as a single entry point One route handles both success and failure; branch on STATUS/RESPCODE after checksum verification. Wrap the verification in a transaction and make the handler idempotent — Paytm retries callbacks.

public function callback(Request $request)
{
    abort_unless($this->paytm->verifyChecksum($request->all()), 403);

    $order = Order::whereKey($request->input('ORDERID'))->lockForUpdate()->firstOrFail();

    if ($order->status !== 'pending') {
        return response('OK'); // already processed, ack the retry
    }

    $order->update([
        'status'        => $request->input('STATUS') === 'TXN_SUCCESS' ? 'paid' : 'failed',
        'txn_id'        => $request->input('TXNID'),
        'payment_meta'  => $request->all(),
    ]);

    return response('OK');
}

Reconciliation as a safety net Don't rely solely on callbacks. Schedule a job that polls transaction status for orders stuck in pending for more than N minutes, using the order ID against the package's status/transaction lookup. This is the pattern that saves you when callbacks get dropped.

Refunds Keep refunds as their own model/audit trail (refund_id, order_id, amount, status, raw_response). Refunds are asynchronous on Paytm's side and can partially succeed — treat the initial response as an acknowledgement, not a settlement.

Environment switching Drive staging vs production from config only, not from code branches. Many bugs come from a staging MID accidentally shipped to production (or vice versa) — assert the environment in a boot-time check in non-production.

Testing integration Swap the package's client for a fake in tests (bind a stub in a service provider under APP_ENV=testing), or at minimum fake the callback route with a pre-computed checksum payload. Never hit the real Paytm sandbox from CI.

Gotchas and Tips

  • v2.0.0 is breaking. Before upgrading, diff the public API surface: constructor signatures, config key names, facade/alias registration, and return types (array vs. DTO/object). Pin ^1.0 in apps you can't migrate yet.
  • Checksum verification is directional. Paytm signs its responses with your merchant key; verifying is not the same as generating a request checksum. Verify before any DB reads keyed on user input from the callback.
  • Amount formatting is a classic footgun. Paytm expects strings, and a decimal amount (99.50) must not be cast to 99.5 by your model. Use number_format($amount, 2, '.', '') at the boundary.
  • Callback POST, not GET. Ensure the route is registered for POST and excluded from CSRF (VerifyCsrfToken::$except) — otherwise you'll see 419s in production logs and orders that silently never settle.
  • order_id uniqueness. If your order IDs aren't globally unique across retries/environments, Paytm rejects duplicates. Prefix with an environment or timestamp if you reuse sequences.
  • Log the raw payload. Store the full callback body (and request body) in a payment_logs table. Debugging checksum mismatches without the original payload is guesswork. Strip nothing on write; redact on display.
  • Merchant key rotation breaks in-flight callbacks signed with the old key — plan rotations for quiet windows, and keep the old key around briefly if the package supports key fallback.
  • Config caching. After changing config/paytm.php or .env, run php artisan config:clear. Stale cached config is the most common "it works locally but not on the server" cause.
  • Extension points: the service provider's bindings are usually the cleanest place to inject a custom HTTP client (for retries/timeouts) or a logging decorator around the package client — prefer that over editing vendor files.
  • Upgrade checklist for v2: bump composer constraint → republish config and diff → re-run a full sandbox pay/fail/refund cycle → check callback verification still passes → grep for removed method names → deploy behind a feature flag if you can.

If you can share the PR #61 diff or issue #58 details, the migration notes above can be tightened into exact symbol-level changes.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource