Stripe - Payments going missing (new Cache responsible?)

Pretty serious bug - it’s now the second time in 2 weeks that a customer paid and it shows up in the Stripe-IPN log and stripe-api.log - but is missing from gateway-core-ipn.log and s2-http-api-debug log.

Relevant strip-ipn log attached - they are very log - seems Stripe notices something is going wrong? Paypal so far has been fine.debug_logs.zip (43.1 KB)

I should have taken the effort to upload the data in the first place already - but thought it may be a once off glitch. It isn’t this is more serious.

I can provide my caching options should it be related:
I have the following notice:
s2Member CSS/JS Asset Health: Review Suggested
Frontend CSS/JavaScript asset-load health has remained substantially degraded across the latest six hours without returning to normal. Delivery may currently be improving or may still be working through fallback. This is a suggestion to review the configuration, not an emergency.• WP Loader CSS fallback is unavailable while the preferred CSS delivery is still working.
• WP Loader JS fallback is unavailable while the preferred JS delivery is still working.

S2memberonlyDynamic Loader active,
beta generate static CSS
Beta Minify CSS
Beta generate and use static CSS delivery
Load Javascript text files with static files (as I use a translation plugin)
Minify static JS
Combine each type
wait before checking - 4 seconds

User report of how it happened:
If it helps you debug, these were the steps I made

- I filled in the new user data (including the password)

- I selected CC payment and put in my credit card data

- As soon as I submitted, I received the notification from the card issuer to do the confirmation of the payment on my phone. Before I could do that, the registration form immediately gave an error saying something went wrong with the payment. I confirmed the payment on the phone (after the before mentioned error) and the page reloaded again by itself with the error “Password can’t be empty”.

…
…

the one thing for sure is - it doesn’t happen every time - there were many succesful payments too. So I guess a caching problem is likely? I deactivated all the new options for now on my websites until this is solved.

Thank you for reporting this! and for the logs and additional details. I studied them carefully.

Could you please also send me stripe-checkout.log, including the entries around this payment? That one may tell me why the pending checkout wasn’t available for recovery.

I kept inspecting the code and think I found what could be causing that kind of behavior… I reproduced a similar behavior in a test, wrote a fix for Pro, and then the same test worked fine.

I sent you the dev builds in a private message if you want to try them. :+1:

About your CSS/JS settings: I don’t have evidence yet that the new static asset delivery caused this payment problem. Stripe’s JavaScript clearly ran far enough to complete the 3D Secure authentication.

However, since you use a translation plugin, please change JavaScript Text Delivery to “Load JavaScript text with each WordPress page” if you’re using the static JS file. That’s the mode intended for multilingual sites.

While we troubleshoot this, I’d also use the Full WordPress Dynamic Loader for maximum compatibility, then refresh the generated assets. WP Admin > s2Member > General Options > CSS/JS Delivery & Optimization (Beta)

So for now:

  • Dynamic Loader: Full WordPress Dynamic Loader (compatibility)
  • Static JS Delivery: Yes
  • JavaScript Text Delivery: Load JavaScript text with each WordPress page

Then use “Refresh Static Assets”.

:slight_smile:

I don’t have a Stripe checkout log… Will that be created with the dev version you sent me? I only have the paypal-checkout log.

I did change the settings for now and will install the dev version

Sorry, my mistake. I meant the stripe logs(s), there’s the Stripe api and ipn ones.

:slight_smile:

They are both in the zip file, no?
The S2 logs are empty around that time frame

I just rechecked - there is absolutely nothing in gateway-core-ipn and gateway-core-rtn
reg.handler later has my manual registration of that user - nothing else.
Stripe API and Stripe IPN are attached in my first post inside the zip.

s2-http-api-debug.log has the earliest entry a full 15minutes later but it’s about the next payment by a different customer. There is nothing referencing the customer with the failed registration.

css-js.log - 38 minutes later there is the following:
OG ENTRY: Tue Sep 22nd, 2026 @ precisely 11:42 am UTC
PHP v8.4.6 :: WordPress v7.1.1 :: s2Member v260917 :: s2Member Pro v260917
Memory 14.06 MB :: Real Memory 22.00 MB :: Peak Memory 14.24 MB :: Real Peak Memory 22.00 MB
www.velomap.org/wp-admin/admin-ajax.php
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36
Array
(
[event] => Frontend CSS/JS runtime issue reported
[result] => suspected
[asset] => dynamic_js
[delivery] => dynamic-wordpress
[url] => https://www.velomap.org/de/index.php?ws_plugin__s2member_js_w_globals=1&qcABC=1
[event_time] => 1790077338
[page_id] => 966
[page_path] => /de/support/membership/
[trusted_confirmation_pending] => 1
)

Thanks for the additional log entry.

I checked trusted_confirmation_pending => 1. That’s from s2Member’s CSS/JS Asset Health monitoring; it isn’t related to Stripe’s PaymentIntent or 3D Secure confirmation.

It means the page hadn’t yet confirmed that the expected JavaScript became active within the configured wait period, so Asset Health had a trusted follow-up check pending. I don’t see anything in that entry that changes what we found with the Stripe/SCA issue.

I also completed a live Stripe 3D Secure test with the dev build I sent you. I specifically tested the failure mode we saw in your logs: Stripe succeeds, but the browser’s final POST back to s2Member is missing.

With the fix in place, s2Member successfully found the pending Stripe subscription from the webhook, recovered the signup, promoted the user to the correct s2Member Level, and associated the account with the completed Stripe subscription.

So the server-side recovery path that was missing in your transaction is now working in that test.

Please continue testing with the dev builds I sent you. Since your original problem was intermittent, the most useful next step is to see how they behave with your normal Stripe checkouts.

If it happens again, please send me the approximate time and affected customer/payment so I can correlate that transaction with the fresh logs.

:slight_smile:

Yeah if it happens again gonna filter out all logs again.

1 Like
  • (Pro) Fix: Improved Stripe 3D Secure recovery when browser and webhook processing overlap, or when the browser loses the final checkout response after successful authentication. s2Member now reconciles those recovery paths using the saved checkout state so successful signups can finish correctly without repeating fulfillment. Thanks to Felix for reporting it. See thread #13627.
  • (Pro) Fix: Improved Stripe subscription recovery for new customers when payment authentication continues after the initial Pro-Form request. s2Member now keeps the pending WordPress account linked to the checkout, allowing browser or webhook recovery to complete the correct signup without losing its account association.

I also used this investigation to look for nearby Stripe recovery edge cases and harden several of those paths as well. You can see them in the changelog.

:slight_smile:

1 Like

I’ve now had a case of PayPal payment ending up in nirvana - however that was on the older version - not yet the one your sent me via message. Customer simply didn’t write me until now so I did not notice it… Adding the logs right now - so the problem is clearly the cache und unlikely the stripe implementation.

Something must be going wrong there.

they all go:
[0] => IPN received on: Wed Sep 23, 2026 7:20:03 pm UTC
[1] => s2Member POST vars verified with a Proxy Key
[2] => s2Member originating domain validation was skipped.
[3] => Ignoring this IPN request. The txn_type/status does NOT require any action on the part of s2Member.

Full Log of that timeframe in zip file. Notice paypal-checkout.log is empty. Doesn’t contain anything relevant. Only Paypal-API and gateway-core-rtn contain information. Gateway-core-ipn again is empty.

Zipped Logs:logs.zip (2.4 KB)

Thanks Felix.

I took another look at your membership page and I see what you’re doing there: the PayPal button is being generated dynamically from the membership selection above it, rather than being a single static PayPal shortcode.

I’d like to look at the custom code that generates/changes that PayPal button.

Could you send me the PHP/JavaScript involved in building the PayPal button from the selected membership, especially the part where the s2Member shortcode is assembled and passed through do_shortcode()?

I want to compare the values being generated there with the transaction that reached PayPal, because the payment itself succeeded but the s2Member membership details needed for fulfillment were missing when the notifications came back.

:slight_smile:

mc_openmtbmap.zip (10.4 KB)

Here you go - it used to work without problems until you introduced caching - but it’s the first time I know of that it went wrong. It’s generating shortcodes that all could have been created by s2member too.

Thank you for sending your PHP code. I reviewed how it generates the PayPal button shortcodes, and I didn’t find anything obviously wrong with that approach.

I continued investigating the PayPal transaction you reported, and found a weakness in how the Framework PayPal Checkout buttons handled interrupted checkouts.

Previously, when PayPal activated a subscription but the browser didn’t complete its final confirmation request, the webhook could be missing the original purchase details needed to finish the signup.

I’ve now changed that. The PayPal buttons save the purchase details before contacting PayPal, so a verified activation webhook can recover and complete the signup even when the browser confirmation is missing. Repeated requests also reuse the existing subscription instead of creating another.

I also improved recovery for one-time PayPal payments when the payment succeeds but the browser loses the response.

I’ve tested the changes with real PayPal Sandbox transactions, including deliberately blocking the browser’s final confirmation. The recurring and one-time recovery tests passed, along with their normal checkout tests.

That doesn’t prove your exact intermittent problem is completely resolved, but it does address the failure mechanism we identified.

I haven’t found evidence that the new static CSS/JS caching caused these payment failures.

Would you like to try the latest Framework development build? This fix is in the Framework; it doesn’t require changes to your custom shortcode generator.

s2member-dev-v260928.1812.zip (1.6 MB)

Let me know if you try it, and keep an eye on PayPal transactions afterward. If another payment doesn’t complete its registration, please let me know and send the relevant logs so I can investigate it.

:slight_smile:

Maybe a fallback could be look at IPN? I’m not sure about how it works but my invoice provider gets all the same information on both Stripe and PayPal differently and never missed a payment with the direct integration.

Use button only for initiating a payment but then for account handling strictly go via PayPal/Stripe direct integration?

But maybe this is an old bug and just randomly happened now and for a longer time not before. I did have 1-2 missed payments per year previously always.

I will install the dev version now. But yeah I’m depending on customers complaining. It does happen customers just give up and do nothing at all

  • (Framework) Improvement: PayPal Checkout buttons now keep a recoverable record of each checkout, allowing s2Member to complete a subscription signup even if the customer closes the page or loses their connection before the final confirmation. PayPal’s verified webhook can finish the signup using the original purchase details, while checkout retries reuse the same subscription instead of creating another. Thanks to Felix for reporting the issue. See thread #13627.
  • (Framework) Fix: When a PayPal Checkout Buy Now payment succeeded but the browser lost the final response, the customer could see a payment error despite having been charged. s2Member now recovers the completed checkout and continues to the registration instructions without capturing the payment again.

:slight_smile:

2 Likes

One more small Stripe reliability improvement related to the browser/webhook timing work…

  • (Pro) Fix: Improved Stripe SetupIntent checkout reliability when webhook fulfillment is still processing, giving the webhook more time to complete the membership update before the browser reports that processing is still underway.

:slight_smile: