Active eCommerce Marketplace CMS handles payments through server-to-server calls: your store sends a request to a gateway like Stripe, PayPal, Paystack, or Razorpay, and the gateway responds either by redirecting the customer back to a callback URL or by posting a webhook to a fixed endpoint. When money is captured at the gateway but the order stays stuck in Pending Payment, the transaction itself usually succeeded — what broke is the return trip. On shared hosting the failure almost always lives in one of three places: the outbound cURL/TLS handshake from PHP, the callback URL being rewritten or blocked before it reaches the CMS, or a credential mismatch between sandbox and live mode.

Because you are operating as an unprivileged hosting user, you cannot touch the web server config, install PHP extensions from the command line, or edit global TLS policies. Everything below is done through the Active eCommerce Admin Panel, cPanel Jupiter or DirectAdmin Evolution, phpMyAdmin, and the two files you fully control inside your document root: .htaccess and .user.ini.

How the payment and webhook flow actually works

Understanding the round trip makes every later fix obvious. When a customer clicks Place Order, Active eCommerce writes a row to the orders table with payment_status set to unpaid, then hands the browser off to the gateway. Two things must happen afterward for the order to be marked paid.

First, the customer's browser is redirected back to a callback route such as https://yourstore.com/stripe/payment/success or https://yourstore.com/paypal/payment/pay. Second — and independently — many gateways fire a webhook: a background POST from the gateway's servers to a fixed URL like https://yourstore.com/webhook or a gateway-specific route configured in the gateway dashboard. The webhook is the reliable path, because the browser redirect can be lost if the customer closes the tab. If the webhook never arrives or is rejected, the order never flips to paid even though the charge went through.

The webhook is a POST originating from an external IP, carrying a signed payload. Active eCommerce validates the signature using the webhook secret you configured under Admin Panel > Business Settings > Payment Method Settings. Two categories of failure follow from this: the request never reaches PHP (blocked by .htaccess, ModSecurity, or a redirect), or it reaches PHP but validation fails (wrong secret, sandbox/live mismatch, or a body altered in transit). Knowing which one you are facing saves hours, so start every investigation by reading logs rather than guessing.

Diagnosing with cURL, TLS, and error logs

The single most common cause of a captured-but-pending order on shared hosting is a failed outbound cURL call — the store cannot reach the gateway API to create the payment intent or verify it. This surfaces as blank checkout pages, spinning buttons, or a redirect straight back to the cart. Open cPanel > File Manager (or DirectAdmin File Manager), navigate to your document root, and enable viewing of hidden files. Active eCommerce, being a Laravel application, writes to storage/logs/laravel.log. Open the most recent entries and look for lines mentioning cURL.

The three signatures you will see most often:

  • cURL error 60: SSL certificate problem: unable to get local issuer certificate — the CA bundle is missing or stale for your PHP version.
  • cURL error 35 or error:1408F10B — a TLS version mismatch; the gateway now requires TLS 1.2 or 1.3 and your PHP build is negotiating something older.
  • cURL error 7: Failed to connect / Could not resolve host — outbound connections on that port are blocked or DNS is failing.

Switch PHP versions through cPanel > Select PHP Version (MultiPHP / PHP Selector) or DirectAdmin > PHP Version Selector. Active eCommerce runs cleanly on PHP 8.1 or 8.2; older builds such as 7.4 often ship outdated OpenSSL and CA data that modern gateways reject. Before doing anything else, set the store to a current PHP 8.x branch and confirm the curl and openssl extensions are ticked in the extensions list. Simply moving from 7.4 to 8.2 resolves the majority of TLS handshake failures because the newer runtime negotiates TLS 1.2/1.3 by default.

If a stale CA bundle persists after the PHP upgrade, you can point cURL at a fresh bundle without root. Upload the current cacert.pem from the official cURL project into a private folder such as /home/youruser/certs/cacert.pem, then add this to the .user.ini file in your document root:

curl.cainfo = "/home/youruser/certs/cacert.pem"
openssl.cafile = "/home/youruser/certs/cacert.pem"

Changes to .user.ini are picked up after the user_ini.cache_ttl window (typically five minutes) or after an LiteSpeed application restart, which you can trigger by touching a file in tmp/restart.txt for Laravel or by re-saving the PHP version. Reload the checkout and re-read storage/logs/laravel.log to confirm the error is gone.

Unblocking callback and webhook URLs

When outbound calls succeed but orders still hang, the inbound callback or webhook is being intercepted. Active eCommerce relies on Laravel's front controller, so every request must funnel through index.php. If someone added aggressive rules to the document-root .htaccess, gateway POSTs can be redirected, stripped of their body, or 403'd. Verify your .htaccess still contains the standard Laravel rewrite block and that no custom rule forces a trailing-slash redirect on the webhook path — a 301 redirect converts the gateway's POST into a GET and discards the payload.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^(.*)/$ /$1 [L,R=301]
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

If you have a forced-HTTPS or www/non-www redirect above this block, make sure it does not catch the webhook route in a way that changes the method. Gateways will not re-POST to a redirect target. The safest pattern is to register the exact HTTPS, canonical-hostname URL in the gateway dashboard so no redirect ever fires — for example use https://www.yourstore.com/webhook if your canonical host is the www version.

ModSecurity is the other frequent culprit. A signed JSON webhook body can trip generic OWASP rules and return a 403 before Laravel ever runs. You cannot disable ModSecurity server-wide, but cPanel exposes a per-domain toggle under Security > ModSecurity where you can turn it off for your domain only. As a narrower alternative, if a specific rule ID appears in your logs/ or the cPanel ModSecurity hit list, you can disable just that rule for your document root:

<IfModule mod_security2.c>
    SecRuleRemoveById 949110 942100
</IfModule>

Confirm delivery from the gateway side: Stripe, Paystack, and Razorpay dashboards all show a webhook event log with the HTTP status your server returned. A 200 means Active eCommerce accepted it; a 403 points to ModSecurity or .htaccess; a 419 means the CSRF token check ran on a route that should have been excluded; a 500 means the payload reached PHP but processing threw an exception you can read in storage/logs/laravel.log.

Credentials, sandbox mode, and transaction logging

Once transport is clean, remaining failures are configuration. In Admin Panel > Business Settings > Payment Method Settings, open each gateway and confirm you are using live keys, not test/sandbox keys — a live charge validated against a sandbox secret fails the signature check silently. Every gateway has three values that must match exactly: the public/API key, the secret key, and the webhook signing secret. Copy them without leading or trailing spaces; a stray space pasted from a dashboard is a classic cause of intermittent signature failures.

Active eCommerce stores these under the business_settings table. If the admin form refuses to save or a value looks corrupted, inspect the row directly in cPanel > phpMyAdmin by querying SELECT type, value FROM business_settings WHERE type LIKE '%stripe%';. Never run server-wide commands here — you are only reading and editing your own database rows. Correct any obviously truncated key, then clear the application cache by deleting the files inside bootstrap/cache/ and storage/framework/cache/data/ through File Manager so the CMS re-reads settings.

For ongoing reliability, keep a record of each transaction. Active eCommerce logs payment attempts in the order detail view, but you should also confirm the orders and combined_orders tables reflect the correct payment_status after a test purchase. Run a small live transaction, then check the gateway webhook log, the order status in the dashboard, and storage/logs/laravel.log together — the three should agree. If they do, your callback and webhook pipeline is healthy. This same disciplined pairing of application logs with control-panel tooling is what keeps other database-driven apps stable too, as covered in our guide on Perfex CRM database maintenance on shared hosting.

Finally, set storage/ and bootstrap/cache/ to writable permissions (755 for directories, 644 for files) via File Manager so the CMS can actually write log entries and cached configuration. A silent payment pipeline is often just an unwritable log directory hiding the real error from you.