"I Paid but Can't Get In": Why Customers Get Locked Out of AI-Built Apps (and How to Fix It)

Customer paid but can't get in? A calm, plain-English fix guide for AI-built apps: what to do first, the five usual causes, and a 10-minute test to run.

By Deepak · · 7 min read

It's the email every app maker dreads: "I just paid. Why can't I get in?"

The checkout worked, the money moved, and your customer is still looking at a locked page. If you built your app with Claude Code, Cursor or Codex, it's worth being ready for this before it happens.

I'm Deepak, a solo developer in Hyderabad, and I spend a lot of my time wiring payments into apps built with AI agents. This is the calm, step-by-step guide I'd want open the moment that email lands: what to do first, where the problem usually hides, and how to stop it happening again. No code needed.

If you haven't set up payments yet, start with my bigger guide on how to add payments to an app you built with AI. This post zooms in on the most painful bug from that list.

First, the next 10 minutes

Don't start debugging yet. Look after the person first.

  1. Check the payment is real. Open your Polar or Stripe dashboard and search for their email. If you see a successful payment, they paid. If not, ask for their receipt; they may have used another email.
  2. Give them access by hand. Mark their account as paid yourself, or ask your agent to update that one user. Do it now.
  3. Reply kindly. Something like: "Thanks for buying, and sorry about that. You should have full access now. Could you log out, log back in, and tell me if it works?" Short, human, no excuses.
  4. Write down the details. Their checkout email, login email, plan and payment time.

Fixing one account by hand is a rescue, not a fix. If it happened once, it will happen again.

How access is supposed to work (30-second recap)

When someone pays, this is what should happen:

  1. Your customer pays on the payment company's checkout page.
  2. The payment company sends your app a payment message saying "this person paid for this plan." Developers call this a webhook. It's just an automatic message from Polar or Stripe to a web address in your app.
  3. Your app checks that the message is genuine, using a secret from the payment dashboard.
  4. Your app finds the right user and saves "this person has Pro" in your database.
  5. Your paid pages read that saved note and let the person in.

Notice what's missing: the thank-you page. It proves nothing. Access should come from step 4. When someone is locked out, one of steps 2 to 5 broke. Here they are in the order I check them.

Where it breaks, and how to tell

1. The payment message never arrives

What happened: the payment company tried to tell your app, but the message went nowhere. Usually the address saved in the payment dashboard is wrong: a typo, an old address, or one that only worked on your own computer. Or you set it up in test mode and never added it in live mode, which has its own separate settings.

Two sneakier ones: the saved address redirects (say, it has no "www" and your host forwards to "www"), which payment companies count as a failed delivery, or your app's login protection blocks it.

How to tell: open the payment dashboard and find the list of payment messages it has sent (both Polar and Stripe show this in their webhook settings). Find the attempts for this customer's payment. Failed deliveries mean this is your problem. No attempts at all usually means no address is saved for live mode.

What to ask your agent: "This is the address saved in my live payment dashboard for payment messages. Does my live app actually accept messages there, without a redirect or a login check in the way? List everything that differs between my test and live setup."

2. It arrives, but your app rejects it

What happened: the message reached your app, but the "is this real?" check failed, so your app threw it away. Right for fake messages, wrong for real ones. The usual cause is the wrong secret: the test secret is still saved in your live app, or the live secret was pasted with a character missing.

How to tell: in the same dashboard list, the delivery shows an error from your app instead of success. Your hosting logs often show it too.

What to ask your agent: "My live payment messages are being rejected. Check which secret my live app uses and whether it's the live one from the dashboard. Don't turn off the check. Fix the secret."

Never "fix" this by switching the check off. That's the door fake payment messages walk through.

3. It's accepted, but matched to the wrong person

What happened: your app got a genuine message but couldn't tell which of your users it belongs to. This happens when someone logs in with one email and types another at checkout, or when checkout was never linked to the logged-in user, so the app only has an email to go on.

How to tell: compare the email on the payment with the email they log in with. If they differ, this is probably it. You may also find a new, empty account under the checkout email.

What to ask your agent: "When a logged-in user starts checkout, link the checkout to their account, so the payment message points back to that exact user instead of matching by email."

4. It's matched, but the wrong plan is saved

What happened: your app found the right person but saved the wrong thing. Maybe it saved a product name your paid pages don't recognize, or the paid pages look for "Pro" while the app saved "Pro Monthly." Or the product was re-created in live mode and your app only knows the test one.

How to tell: look at what your database says about this user. If it says they paid but names a plan your paid pages don't know, that's the gap.

What to ask your agent: "List every product and price my app knows about, for test and live, and compare them with my live dashboard. Then show me exactly what my paid pages check before letting someone in."

5. Everything is saved, but the app shows old info

What happened: your database is correct, but the customer's login still carries their old "free" status.

How to tell: ask the customer to log out and back in. If that fixes it, this is your problem.

What to ask your agent: "After a payment, make sure paid pages read the user's current plan from the database, not from old login info, so access updates without logging out."

A 10-minute test you can run yourself

Once you think it's fixed, prove it. Do this in test mode, the practice mode where you use test cards and no real money moves:

  1. Sign up as a brand-new user with an email you've never used.
  2. Buy your plan with a test card from the payment company's docs.
  3. Open the payment dashboard and check the payment message was delivered successfully.
  4. Go back to your app without touching anything. Are the paid pages unlocked?
  5. Log out, log back in, and check again.
  6. Sign up as another new user, and this time type a different email at checkout. Does the right account get access?
  7. If you sell several plans, check that the cheapest one doesn't open a pricier plan's pages.

If every step passes, do one real purchase yourself in live mode, check access the same way, then refund it.

Make it impossible to miss next time

You can't promise a bug never comes back, but you can hear about it before a customer has to write.

  • Watch for failure emails. Polar and Stripe both email you when messages to your app keep failing. Make sure those emails reach an inbox you actually read.
  • Give customers a way out. Put a small "Paid but still locked? Restore my purchase" button, or at least a support email, on your paid pages. A restore button just asks the payment company again about that user.
  • Re-test after every payment change. New price, new plan, new secret, new domain: run the 10-minute test again. The pre-launch checklist in my first guide covers the rest.
  • Keep test and live in step. When you change something in test mode, note the matching change for live mode.

If you're still choosing between one-time, subscription or credits, my guide on how to charge for your vibe-coded app helps you decide. Subscriptions add a few more things to test, like cancellations and failed renewals.

Where ShipToPaid fits

I wrote ShipToPaid so AI agents get these steps right the first time. Its skills cover linking checkout to the logged-in user, checking every payment message is genuine, and a launch audit that walks you through a test like the one above. The free lite pack has the Polar pieces. The full pack adds Stripe and access that follows payments. You don't need either to use this guide.