#notigate - checkout

1 messages · Page 1 of 1 (latest)

crisp ginkgo
#

hey there, can you link to this example you're referring to?

main yew
crisp ginkgo
#

thanks! just a sec...

main yew
#

Np thx

crisp ginkgo
#

I'm not seeing any amount parameter, can you clarify what you're referring to?

#

do you mean the quantity set in the input? This is form data and form submission, if so

main yew
#

Quantity sorry

#

I don't understand where he gives it

main yew
#

But

#

...

#

which line sends it the quantity?

crisp ginkgo
#

Yep looking at it now

main yew
crisp ginkgo
#

I'm not sure yet - bear with me

main yew
#

Okay

crisp ginkgo
#

When you get the request on the server, what data are you seeing in the req.body?

#

Can you log that out to inspect?

main yew
#

Oh wait

crisp ginkgo
#

I'm pretty sure this is supposed to be set by the name=quantity on the input

#

Is it not working?

main yew
#

Oh okay

#

I understand

crisp ginkgo
#

It's a bit of ~magic with the default behaviour of a form submission IIRC -- if you don't want that you can always add an explicit handler function (and block the default submit behaviour) to create your own explicit request to your back end

main yew
#

What ?

#

server.js

app.post('/create-checkout-session', async (req, res) => {
  const domainURL = process.env.DOMAIN;
  const { quantity } = req.body;
  const session = await stripe.checkout.sessions.create({
    mode: 'payment',
    line_items: [
      {
        price: process.env.PRICE,
        quantity: quantity
      },
    ],
    success_url: `${domainURL}/success.html?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${domainURL}/canceled.html`,
  });

  return res.redirect(303, session.url);
});```
crisp ginkgo
#

WHat's the issue you're having here?

crisp ginkgo
#

Can you copy paste that request id please? req_123

main yew
#

?

#

If you want

crisp ginkgo
main yew
#

Oh okay

crisp ginkgo
#

theres a request id

main yew
#

req_qm7FnxC3LZKSls

crisp ginkgo
#

thx

#

The error is something in your application

main yew
#

Oh

#

Okay

#

Why

#

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
  <title>Payment App</title>
</head>

<body class="bg-gray-900">
  <nav class="bg-purple-900 h-20 flex justify-center">
    <h1 class="text-white text-5xl">Payment App</h1>
  </nav>

  <form action="/create-checkout-session" method="POST" class="flex justify-center mt-32">
    <div class="flex flex-col w-1/3">
      <input class="bg-transparent text-white p-2 h-10 mb-4" type="text" name="name" placeholder="Name">
      <input type="email" class="bg-transparent text-white p-2 h-10 mb-4" name="email" placeholder="Email">
      <input class="bg-transparent text-white p-2 h-10 mb-4" type="number" id="quantity-input" min="1" placeholder="Amount (€)" name="quantity" />

      <div id="card-element" class="bg-transparent text-white p-2 h-10 mb-4"></div>
      <div id="card-errors" role="alert"></div>
      <button class="text-white bg-purple-900 p-4 rounded" id="submit">Pay</button>
    </div>
  </form>
</body>

<script src="https://js.stripe.com/v3/"></script>


</html>

<style>
  /* Firefox */
input[type=number] {
    -moz-appearance: textfield;
}
 
/* Chrome */
input::-webkit-inner-spin-button,
input::-webkit-outer-spin-button { 
    -webkit-appearance: none;
    margin:0;
}
 
/* Opéra*/
input::-o-inner-spin-button,
input::-o-outer-spin-button { 
    -o-appearance: none;
    margin:0
}
</style>```
#

server.js

const express = require('express');
const app = express();
const { resolve } = require('path');
require('dotenv').config({ path: './.env' });

checkEnv();


app.use(express.static(process.env.STATIC_DIR));
app.use(express.urlencoded());
app.use(
  express.json({
    verify: function (req, res, buf) {
      if (req.originalUrl.startsWith('/webhook')) {
        req.rawBody = buf.toString();
      }
    },
  })
);

app.get('/', (req, res) => {
  const path = resolve(process.env.STATIC_DIR + '/index.html');
  res.sendFile(path);
});

app.get('/config', async (req, res) => {
  const price = await stripe.prices.retrieve(process.env.PRICE);

  res.send({
    publicKey: process.env.STRIPE_PUBLISHABLE_KEY,
    unitAmount: price.unit_amount,
    currency: price.currency,
  });
});

app.get('/checkout-session', async (req, res) => {
  const { sessionId } = req.query;
  const session = await stripe.checkout.sessions.retrieve(sessionId);
  res.send(session);
});

app.post('/create-checkout-session', async (req, res) => {
  const domainURL = process.env.DOMAIN;
  const { quantity } = req.body;
  const session = await stripe.checkout.sessions.create({
    mode: 'payment',
    line_items: [
      {
        price: process.env.PRICE,
        quantity: quantity
      },
    ],
    success_url: `${domainURL}/success.html?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${domainURL}/canceled.html`,
  });

  return res.redirect(303, session.url);
});

app.post('/webhook', async (req, res) => {
  let data;
  let eventType;
  if (process.env.STRIPE_WEBHOOK_SECRET) {
    let event;
    let signature = req.headers['stripe-signature'];

    try {
      event = stripe.webhooks.constructEvent(
        req.rawBody,
        signature,
        process.env.STRIPE_WEBHOOK_SECRET
      );
    } catch (err) {
      console.log(`⚠️  Webhook signature verification failed.`);
      return res.sendStatus(400);
    }
    data = event.data;
    eventType = event.type;
  } else {
    data = req.body.data;
    eventType = req.body.type;
  }

  if (eventType === 'checkout.session.completed') {
    console.log(`🔔  Payment received!`);
  }

  res.sendStatus(200);
});

app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));


function checkEnv() {
  const price = process.env.PRICE;
  if(price === "price_12345" || !price) {
    console.log("You must set a Price ID in the environment variables. Please see the README.");
    process.exit(0);
  }
}
#

I dont understand 😭

crisp ginkgo
#

Ok take a step back, when does this happen?

#

Can i repro easily on your site?

main yew
#

Yep

#

Just fill input

#

Clic pay

crisp ginkgo
#

Something about your server handling is incomplete/unexpected, and its not responding to the client as needed

#

The API request to Stripe to create the session is successful

main yew
#

Yep

#

But what

crisp ginkgo
#

But the browser isn't being routed as expected

main yew
#

Hmmm

#

Okay

#

How to fix that

crisp ginkgo
#

Ah, correction, it looks like your server is hitting an error, and the request isn't working as expected

main yew
#

Okay...

#

And ?

crisp ginkgo
#

you need to add some logging to your server code and see where it fails

#

Do you have the expected env vars set up?

main yew
#

Yep

#

STRIPE_PUBLISHABLE_KEY=
STRIPE_SECRET_KEY=

STRIPE_WEBHOOK_SECRET=whsec_1234...

STATIC_DIR=../views/index

PRICE=price_1KEDmJANbuz0wK88TStBeAkh
DOMAIN=https://payment.notigate.fr

PAYMENT_METHOD_TYPES="card"

crisp ginkgo
#

ok, and do you get a session back?

main yew
#

Idk

#

Why

crisp ginkgo
#

ok, so you'll need to do some debugging to figure that out

main yew
#

Okay

#

But with pleask

#

Debugging is impossible

crisp ginkgo
#

what do you mean? You can add logging and inspect your log output (terminal, file, service, etc) if this is running remotely

main yew
#

I cant with pleask

crisp ginkgo
#

what is pleask?

main yew
#

Plesk*

#

Sorry

#

Okay wait

#

I'm going to deploy a VPS

main yew
crisp ginkgo
#

Whatever you need to figure out where it fails. THere's going to be an exception raised somewhere that you need to inspect and handle.

main yew
#

Yeah i know

crisp ginkgo
#

Did you test this locally first?

main yew
#

I cant

crisp ginkgo
#

I don't know how to access log files with Plesk, you'll need to work with them to figure out how you can do that.

#

You would run a node server locally to host the endpoint

main yew
#

Oh

#

I'm a noob

#

Wait x)

crisp ginkgo
#

This explains how to run the example locally to test/develop before going live

main yew
#

Yeah yeah

#

OH

#

WTF

crisp ginkgo
#

found something?

main yew
#

Stripe is not defined...

crisp ginkgo
#

Have you installed the package?

main yew
#

Yep

#

Oh...

#

I'm really stupid

#

Its work

#

...

#

I feel really stupid

crisp ginkgo
#

Did you forget to import stripe and initialize in your server file?

main yew
#

Yep

crisp ginkgo
#

that would do it!

#

hopefully everything works now, more or less?

main yew
#

Ah also I had a question, with a discord webhook, then I receive notifications when a payment is completed

crisp ginkgo
#

what's the question about webhooks?

main yew
#

can I receive notifications in a discord room using your events?

#

...

#

No

#

Yes i can

#

But how get events ?

crisp ginkgo
#

You can subscribe to successful payment events, yes, but I need to step away so my colleagues @plucky nova / @radiant copper will join to help with that

#

You'd likely want to handle the webhook event yourself and make another call to the discord api/endpoint, but it depends on what they support and what youre trying to do

main yew
#

Docs ?

plucky nova
main yew
#

Thx

#

Oh ! Another question, how can I test without being debited on my card, because when I put the test cards, it puts me that I am not in a test environment, what should I do?

plucky nova
#

Make sure you're using the test API keys

main yew
#

Yep

#

Wait

plucky nova
#

should look something like pk_test_xxx and sk_test_xxxx

main yew
#

(node:12296) UnhandledPromiseRejectionWarning: Error: You did not provide an API key. You need to provide your API key in the Authorization header, using Bearer auth (e.g. 'Authorization: Bearer YOUR_SECRET_KEY'). See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.

#

Uh

#

Ooh yep wait

#

Oh no

#

?

#

I dont understand

radiant copper
#

What are you currently running in to?

main yew
radiant copper
#

So is it working now? Are you running in to some kind of Stripe error if not?

main yew
#

...

main yew
# radiant copper So is it working now? Are you running in to some kind of Stripe error if not?

(node:12296) UnhandledPromiseRejectionWarning: Error: You did not provide an API key. You need to provide your API key in the Authorization header, using Bearer auth (e.g. 'Authorization: Bearer YOUR_SECRET_KEY'). See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.

radiant copper
#

Can you confirm that your server side code is hitting the place where you initialize Stripe?
const stripe = Stripe('sk_test_123');

#

And that that secret key variable is actually being set to what is in your env file?

main yew
#

Const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)

#

Yep

#

Ping me

radiant copper
#

And to confirm, this is the stripe.checkout.sessions.create call from the /create-checkout-session endpoint in your server.js file?

main yew
#

Yep

radiant copper
#

I get the same error with:
const stripe = require('stripe')('')
So it seems like that environmental variable might not be loading properly

main yew
#

Ok

#

OH

#

IM STUPID

#

Find the problem 😭

radiant copper
#

Glad you could find it!

#

Ah did that first line have to come after the second one?

main yew
#

Yep :'

cunning girder
#

Hello! I'm taking over... did you have another question a moment ago?

#

I thought I saw something about test mode?

main yew
#

No sorry, i'm just stupid

#

But i have another problem, wait please

main yew
cunning girder
#

Not sure what "paying with the link (by the API)" means, can you provide more details?

main yew
#

Uh

#

Clic pay button, you have stripe checkout

cunning girder
#

What does the "(by the API)" mean if it's being done on your website in Checkout?