PaddleHQ / paddle-js-wrapper

Wrapper to load Paddle.js as a module and use TypeScript definitions when working with methods.
Apache License 2.0
44 stars 6 forks source link

[Bug]: Paddle Sandbox testing from localhost #42

Closed bergwerf closed 6 months ago

bergwerf commented 6 months ago

What happened?

I am integrating with a sandbox account. I use @paddle/paddle-js from NPM. I initiate Paddle with environment 'sandbox' and a client token generated in the sandbox account. I then initiate the overlay checkout, which triggered the following failing HTTP request:

POST https://checkout-service.paddle.com/transaction-checkout

Which returned with a 403 and the following payload:

{"errors":[{"status":403,"code":"unauthorized","details":"Failed to retrieve JWT"}]}

I am testing from a local IP address (192.168..), I don't use localhost because I also test on other devices that are in the same network. I also noticed a CSP error, but I assumed that would be because my local dev server doesn't have HTTPS, so I created a Firefox profile for testing that disableds CSP.

These are the requests that are made after initiating the checkout: image

Steps to reproduce

See above.

What did you expect to happen?

The overlay checkout should open.

How are you integrating?

I use the NPM package @paddle/paddle-js

Logs

No response

vijayasingam-paddle commented 6 months ago

Hi @bergwerf, Thank you for reaching out to us.

Looking at the URL and the screenshot, it appears that you are trying to access production env with the token from sandbox. Maybe there is some misconfiguration while setting the environment to sandbox.

Can you please share the code you are using to initialize paddle so that we can help you further.

Thank you.

bergwerf commented 6 months ago

I use the following code:

const paddle = await initializePaddle({
  environment: 'sandbox',
  token: CONFIG.PADDLE.TOKEN
})
if (paddle) {
  const customer_id = await api.get_customer_id()
  paddle.Checkout.open({
    settings: {
      displayMode: 'overlay',
      theme: 'light'
    },
    customer: {
      id: customer_id
    },
    items: [
      {
        quantity: 1,
        priceId: CONFIG.PADDLE.PRICE[sub()]
      }
    ]
  })
}
vijayasingam-paddle commented 6 months ago

Hi @bergwerf,

Thank you for sharing the snippet.

I tried to run it using the latest version (and some older versions of this package) and I was not able to replicate the issue. The checkout is opening for me.

Can you please share a reproducible example to help debug the problem.

Thank you.

bergwerf commented 6 months ago

@vijayasingam-paddle I created a reproducible example that includes IDs from my Sandbox account. If you send me your email address I can send the example to you.

vijayasingam-paddle commented 6 months ago

Hi @bergwerf, Thank you.

Please send it to team-dx@paddle.com. Ensure that you have removed all tokens and ids.

Thank you,

bergwerf commented 6 months ago

@vijayasingam-paddle Without token IDs the code is pretty much just the above, so I can share it here as well.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Paddle Checkout</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <h1>Paddle Checkout</h1>
  <button id="button">Checkout!</button>
  <script src="main.js"></script>
</body>
</html>

main.ts

// npx esbuild --bundle main.ts > main.js

import { initializePaddle } from '@paddle/paddle-js'

const access_token = 'test_xxx'
const customer_id = 'ctm_xxx'
const price_id = 'pri_xxx'

async function checkout() {
  const paddle = await initializePaddle({
    environment: 'sandbox',
    token: access_token
  })
  if (paddle) {
    paddle.Checkout.open({
      settings: {
        displayMode: 'overlay',
        theme: 'light'
      },
      customer: {
        id: customer_id
      },
      items: [
        {
          quantity: 1,
          priceId: price_id
        }
      ]
    })
  }
}

document.querySelector('#button')!.addEventListener('click', checkout)

To build the TypeScript file, install @paddle/paddle-js, install esbuild, and run npx esbuild --bundle main.ts > main.js. I serve the file from localhost. The same problem appears when I click the button:

image

I am happy to share my access token and other IDs with the development team, since they are only associated with my sandbox account (so no actually sensitive information is there).

vijayasingam-paddle commented 6 months ago

Hi @bergwerf, This is interesting.

I ran the same code and i was able to launch a checkout 😅 The code I used to test is here

Can you please check this repo to see if there are any differences?

Additionally, please check if this function Paddle.Environment.get() is returning sandbox once paddle is initialized.

Thank you.

bergwerf commented 6 months ago

The repository worked for me, but I had to set a value for the Default payment link (I am not yet sure what this is used for). However there was an instructive error somewhere that pointed me in this direction. In my other code I made an error somewhere that caused the environment constant I passed to it to be undefined, and thus it ended up in 'production'. By the way Paddle.Environment.get is not in the TypeScript definition.

Anyway, it turns out this was my error and the library works fine. Thanks for the support!

vijayasingam-paddle commented 6 months ago

Hi @bergwerf, I am happy that you were able to make it work.

The function Paddle.Environment.get is not part of the typescript definition nor our documentation because it is an internal function used for debugging and doesn't have any functional usage.

Please feel free to reach out to us if you need any other help.

saddam-azad commented 6 months ago

We have been struggling with the same issue on Vue/Nuxt.

  1. Paddle instance can be initiated (client-side only)
  2. Environment is set to sandbox
  3. The sandbox checkout service issues a 403 "Failed to retrieve JWT"

Reproduced here:

https://github.com/saddam-azad/nuxt-paddle/blob/master/app.vue

vijayasingam-paddle commented 6 months ago

Hi @saddam-azad, Thank you for sharing an example.

I tried to run the code after replacing token and priceId and I was able to launch a checkout without any error.

Please let us know if you are still facing any issues. Maybe there is some misconfiguration similar to Herman's problem?

Thank you.

saddam-azad commented 6 months ago

Solved the problem. I was using production products and prices wrongly assuming that setting the environment to sandbox allowed testing locally.

Just wanted to document my steps to help future users.

  1. For local testing and staging environments, users have to create another account in https://sandbox-vendors.paddle.com and duplicate the products and prices in the Catalog.

  2. The Default payment link in Checkout > Checkout Settings must be set to your local development environment (e.g. https://localhost:3000/pay)

I wish the documentation around sandbox testing was better.

talonx commented 2 months ago

Solved the problem. I was using production products and prices wrongly assuming that setting the environment to sandbox allowed testing locally.

Just wanted to document my steps to help future users.

1. For local testing and staging environments, users have to create another account in https://sandbox-vendors.paddle.com and duplicate the products and prices in the Catalog.

2. The `Default payment link` in Checkout > Checkout Settings must be set to your local development environment (e.g. `https://localhost:3000/pay`)

I wish the documentation around sandbox testing was better.

Thanks for this. However, the sandbox does not seem to accept localhost or any IP address (i.e. I tried 127.0.0.1). I can always map a local domain in my /etc/hosts but this process needs to be simpler IMO.

vijayasingam-paddle commented 2 months ago

Hi @talonx, I am sorry that you are running into this issue.

Can you please share some details on where you are trying to set the value as localhost or 127.0.0.1? Is it for the default payment link? If yes, please try http://127.0.0.1 or http://localhost:3000.

Additionally, in sandbox, you can launch checkout from any domain and it doesn't have to exactly match the value provided in the default payment link. So you can configure your staging URL as default payment link and test it on your local machine.

Please let us know if this solves your issue.

Thank you.

talonx commented 1 month ago

What finally worked for me was setting the default payment link in the sandbox settings as

https://localhost.localdomain:3000/subscription

I think the docs need updating.