How ILIAS Actually Handles Payments
ILIAS does not ship with a Stripe-style webhook listener or a REST payment endpoint in the way a modern e-commerce platform does. Its monetization lives inside the Payment service, reachable from the AdminCP under Administration > Payment (historically the ecs/ Shop components). An administrator attaches a price to an object such as a course or learning module, the learner enters a shopping cart, and ILIAS forwards them to an external gateway. The only broadly supported, out-of-the-box gateway in the stock distribution is PayPal, driven through PayPal's classic redirect flow plus an Instant Payment Notification (IPN) style callback that PayPal posts back to your ILIAS URL. Everything else is typically a third-party plugin, so before chasing a bug confirm whether you are on stock PayPal or a custom integration, because the troubleshooting path differs completely.
Because ILIAS acts as the merchant redirect rather than a passive receiver, a payment has three network legs that can each fail independently. First, the learner's browser leaves your site and lands on PayPal. Second, your server opens an outbound connection to PayPal to verify the transaction (this is a server-to-server cURL call over TLS). Third, PayPal fires a return/notification request inbound to a fixed ILIAS URL so the purchase can be marked complete and access granted. On shared hosting the second and third legs are where things break: outbound cURL is subject to the PHP build and CA bundle shipped by CloudLinux, and inbound callbacks depend on your URL being reachable, not blocked by .htaccess, and not behind HTTP authentication. A learner reporting "I paid but the course is still locked" almost always means leg two or three silently failed while leg one succeeded, which is exactly why the money moved but the enrollment did not.
Keep that mental model in front of you. The symptom (locked course) is downstream; the root cause is a verification or callback step that never completed. The rest of this article isolates each leg using tools you have as an unprivileged hosting user.
Checkout, Outbound cURL and TLS Failures
When a learner clicks the purchase button and the page dies with a blank screen or an HTTP 500, the first place to look is the per-account PHP error log, not the gateway. In cPanel open File Manager and navigate to the ILIAS document root, then look for error_log alongside ilias.php; in DirectAdmin the same file appears in the site's public_html. ILIAS also writes its own application log whose path is set in Administration > System Settings > Logging — set the log level to INFO or DEBUG temporarily so the payment component records the full exchange. A cURL failure during gateway verification usually surfaces as a message mentioning SSL certificate problem, unable to get local issuer certificate, or Could not resolve host.
The unable to get local issuer certificate error is the classic shared-hosting TLS problem. It means the PHP version selected for your domain cannot validate PayPal's certificate chain because it is pointing at a stale or missing CA bundle. You cannot edit php.ini globally, but you can override the setting per-account. Create or edit .user.ini in the ILIAS document root and pin the CA bundle that CloudLinux ships:
; .user.ini in the ILIAS root
curl.cainfo = "/etc/ssl/certs/ca-bundle.crt"
openssl.cafile = "/etc/ssl/certs/ca-bundle.crt"
allow_url_fopen = OnChanges to .user.ini are cached; wait the user_ini.cache_ttl window (commonly five minutes) or touch the file again before retesting. Next, confirm the PHP build itself supports TLS. In cPanel go to Select PHP Version (PHP Selector on CloudLinux) and verify the curl and openssl extensions are ticked. ILIAS 8 and later expect PHP 8.1+, and an older selected version can ship an outdated OpenSSL that PayPal's modern endpoints reject with a handshake error. If outbound requests are being refused outright rather than failing on certificates, it is worth confirming your plan permits outbound connections to the gateway host on port 443; raise a ticket if you see Connection timed out rather than a certificate message, since that points to an egress restriction you cannot change from the panel.
One subtle trap: ILIAS caches service configuration. After editing credentials or PHP settings, clear the ILIAS cache under Administration > System Settings > Caching (flush the global cache) so the payment component re-reads its configuration instead of replaying a failed state.
Callback Delivery, Credentials and Transaction Logging
Once outbound verification works, turn to the inbound callback — the request PayPal sends to confirm payment. The target URL is derived from your configured ILIAS base URL under Administration > System Settings > General Settings > HTTP path. If that path is wrong (for example it still shows http:// after you forced HTTPS, or points at a staging subdomain), PayPal's notification lands nowhere and the purchase never finalizes. Set the HTTP path to the exact canonical HTTPS host learners use, then confirm nothing in .htaccess blocks the callback. A common self-inflicted wound is a directory-wide password prompt: if you protected the ILIAS folder with cPanel's Directory Privacy, PayPal's POST receives a 401 and gives up. Callbacks are unauthenticated machine requests, so the receiving endpoint must stay publicly reachable. If you use .htaccess to force HTTPS, make the rule total rather than selective so no callback slips through on plain HTTP:
# .htaccess in the ILIAS root
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Do not let a blanket block or auth rule catch the payment return URLCredentials are the next failure class. In the PayPal section of the AdminCP, the merchant email (or API signature, depending on the gateway variant) must match the account that will receive funds exactly, including case, and the sandbox-versus-live toggle must agree with the credentials you pasted. A frequent mistake is leaving the gateway in sandbox mode after go-live: real learners pay, PayPal's live IPN fires, and ILIAS — still expecting sandbox notifications — rejects the message as unverified. Verify the environment flag and the currency code match the price objects you attached to courses.
For transaction visibility, ILIAS records bookings in the database. Using phpMyAdmin from your panel, inspect the payment tables (names begin with payment_, such as the bookings and statistics tables) to see whether a row exists for the learner's attempt. A booking row with a pending or incomplete status, paired with real money in PayPal, is definitive proof that leg two or three failed rather than the checkout itself. Cross-reference the timestamp against the ILIAS application log you raised to DEBUG; the verification request and its response are logged there, and the response body from PayPal usually states why it was declined (INVALID versus VERIFIED). Resist the urge to hand-edit status columns in phpMyAdmin to "unlock" a course — that masks the broken callback and desynchronizes ILIAS from the gateway. Fix the reachability or credential problem, then re-trigger the notification from the PayPal merchant dashboard's IPN/activity resend tool so ILIAS processes it cleanly and grants access through its normal code path. Once a test purchase in sandbox completes end to end and writes a confirmed booking row, lower the log level back to WARNING to avoid filling your account's disk quota.