Paypal token mystery

Hey guys,

Here is a mystery for ya. I’ve set up a recurring invoice and when Invoice Ninja generated the actual invoice, I sent him the link to view the invoice and pay via Paypal.

He told me then that when he tried to do it via Paypal, Invoice Ninja returned “Paypal_express: Invalid token”. Also, dunno if relevant, but he’s using Chrome.

I viewed the same invoice, clicked the same payment via Paypal, and it redirected successfully to the Paypal checkout.

Anyone seen this before?

The mystery is now one step closer to being solved.

Just got off the phone with the aforementioned client. He told me that after clicking on Paypal it would indeed redirect him to the payment screen, but after he selected his card, this message is shown.

I think I configured Paypal Express correctly. Got the API username and password, and signature, from the link ( So, any ideas?

I’m not sure, I haven’t seen this error.

I found this comment, maybe it’s related?

You may want to enable test mode and try submitting a test payment.

Another customer just complained that he couldn’t complete his payment via Paypal.

While searching I kept finding that same comment on Github, with DanielHitchen commenting “the CMS I am using was stripping the query parameters off”.

So, can we interpret this as Invoice Ninja stripping off something?

Are you using the iFrame feature? It could affect the URL.

No, I’m using the subdomain option.

Also, dunno if relevant, but HTTPS is activated, and under Payments I saw the option TOKEN CHARGE(?) with DISABLED/OPT-IN/OPT-OUT/ALWAYS, currently set as ALWAYS.

If you’re using PayPal Express the ‘Token Billing’ option won’t have any effect.

We don’t recommend self-hosters use the subdomain setting, in the latest versions it’s hidden. If you’re using a subdomain you’ll want to include it in the APP_URL setting. Not sure if it’s causing the problem though…

Okay, will try to use SITE instead of SUBDOMAIN. If the option is hidden in the latest versions then there’s no point in using it. Anyway, I’ve activated it and I’m having some trouble. The VIEW AS RECIPIENT link is not working. I’ve set the SITE URL to https:///fatura .

The URL in the VIEW AS RECIPIENT link is now

whereas in the SUBDOMAIN option it was

Second one still works, first one don’t, even if I add a / at the end (fatura/).

Try removing /fatura from APP_URL

When you say APP_URL you mean the configuration option in the panel, or a setting in the config file?

I was referring to the .env file but if’s displayed as URL on /settings/system_settings

Nope. Link is now https://[domain]/?[invoice_key] but it still doesn’t work, redirects to the dashboard.

There shouldn’t be a question mark in the URL, it’s only added if the website/iframe feature is enabled.

Yes, I’ve changed to the WEBSITE option, as you said the SUBDOMAIN option is not recommended for self hosters. But the question mark was added by Invoice Ninja, not me.

So what do I do?

Clear the value for website, it should only be set if you want to display the invoice in an iFrame.

You want to set the APP_URL value in the .env file.

Okay, so I cleared the URL in settings/client_portal and saved, and it reverted to the SUBDOMAIN option. Now the invoice links are working.

I guess it is correct, now? If so, now on to test Paypal.

As mentioned previously, I’d suggest not using the subdomain option.

It’s intended for our hosted users, self-host users should set the APP_URL value instead.

Hey guys,

Came back to report that this problem seems to have sorted itself out. Looks like after the latest update (or the change from the subdomain option) everything seems to be working as expected. I noticed that a recurring invoice has been paid via Paypal (looks like the name changed to Paypal Express in Invoice Ninja configuration) and then I called the client to ask if he had any problems during the process. He said that everything proceeded as expected, and the transaction ID has been automatically saved with the payment.

So, hooray!

Now, on to create a new payment method: boleto :smiley:

Thanks for letting us know!