#gecko - stripe endpoint http vs https

1 messages · Page 1 of 1 (latest)

ashen laurel
#

Hi!

worthy ridge
#

Hi...apologies, I"m not a web guru

#

so I have a stripe checkout, and used it to test webhooks....and all is good

#

using test webhook, I can see the checkoutsession stuff all fine

#

so last step in the integration process is to enable a production webhook

#

and this requires an https access point in my website

#

all good, and agree so far, yes?

ashen laurel
#

Yes

worthy ridge
#

ok...so what I had was a simple web page with a link to test, and the action was a URL:port/checkout....which all works fine

#

so once I have to switch to an https style, in support of the webhook event listener, then I get into trouble

#

i think the port number desgination begins to conflict with the https need....yes?

#

the endpoint still wants to listen to some random port....but https requires the 443?

remote goblet
#

@worthy ridge I'm sorry but that is still really vague and unclear to help you

worthy ridge
#

ok let me try again

remote goblet
#

What port to use depends on your overall system and how you as the developer built it

#

you control this in your system however you want to configure. I use my own PHP server and my port is 8888

worthy ridge
#

and my endpoint listens for 1234

#

all good?

remote goblet
#

not really good no. Whether to use 1234 depends on your own server's configuration

worthy ridge
#

explain more please?

#

you're asking about proxy servers vs. direct webserver?

remote goblet
#

I'm not really asking anything yet unfortunately. I'm trying to understand your question. You said "all good" so I explained that I still don't get it. What's insecure about port 80? Where does port 1234 comes from?

worthy ridge
#

ok let me start over

#

i have www.mywebsite.com up and running. there is an index.html and a single link on there, to start a checkout

#

i have an endpoint that listens on 1234

#

it handles the checkout and creates a checkout session for the customer

#

all boiler plate template stripe docs based implementation...do you agree so far?

remote goblet
#

Let's say yes, what's your real question, if possible all clearly in one paragraph

worthy ridge
#

😅

#

so i am trying to implement production webhook listener. in order for me to do this, I have to have an https interface for stripe to send webhook events to

#

if i change my website and just run on secure (https) format instead, and try the same line: https:// www.mywebsite.com:1234/checkout, it won't work I get errors...I believe because of the port...am I wrong?

#

http to https change only in the URL

remote goblet
#

Unfortunately yes I think you are wrong

worthy ridge
#

this should work ok?

remote goblet
#

Taking a step back
1/ How did you build your website: which exact programming language and which exact framework are you using?
2/ How did you configure HTTPS/TLS on your server
3/ In theory you never have a port in your URL, you only do this locally for testing

worthy ridge
#

sorry, as I said in the intro I'm a website n00b

#
  1. JS/html
#
  1. apache and added SSL certificates today
#
  1. can I remove all the ports? I thought this was required for listening by the endpoint...?
remote goblet
#

What other language than JS. JS is client-side usually. ARe you using Node.js and Express for example? Something else?

worthy ridge
#

node, express

remote goblet
worthy ridge
#

like....express.listen() requires a port number to monitor

remote goblet
#

and you are not supposed to have a port in your URL no

#

you have a website like https://www.example.org that is your domain and your server's configuration knows to redirect that incoming request to your Node.js application

worthy ridge
#

i don't want it either....I assumed I'd have to proxy server that to hide it....can I get rid of the ports in general and have express listen without specifying?

#

yes, by an express port listener....

plain fjord
#

(NOT with Stripe) Clarification question: are you serving your website (client) and webhooks from the same domain?

worthy ridge
#

yes

plain fjord
#

(NOT with Stripe) Is your website (client) server using express, and routes in express?

worthy ridge
#

express yes, routes no. just post, listen, use, get, send

#

the implication is routes are my way of solving the port problem?

plain fjord
#

(NOT with Stripe) Sort of...

#

my webhook endpoints:

// build multiple CRUD interfaces:
webhook_app.post("/direct", async (request, response) => {
  //send the response early - the only valid response is "received"
  await commonHandler(request, response, endpointDirectSecret);
  response.json({ received: true });
});

webhook_app.post("/connect", async (request, response) => {
  //send the response early - the only valid response is "received"
  await commonHandler(request, response, endpointSecret);
  response.json({ received: true });
});

#

webhook_app is the Express instance

worthy ridge
#

i have something just like this...posts....for a '/checkout' for example

plain fjord
#

(NOT with Stripe) Yep, so add the endpoints as above, and you'll be good to go

worthy ridge
#

add what endpoints?

#

direct and connect?

plain fjord
#

(NOT with Stripe) express.post("/direct") (or whichever path you choose) can become your webhook endpoint : mywebsite.com/direct

worthy ridge
#

yeah....but that's not answering my question

#

and express.listen(portnum)

#

and it works fine

remote goblet
#

the same works exactly identically for webhooks

plain fjord
#

I, as koopajah, fail to see the NEED for the port #'s

worthy ridge
#

so the express.listen is useless?

remote goblet
worthy ridge
#

agree

#

and I've coded the dev environment with a specific port, per the docs

#

can I just remove them all?

plain fjord
#

(NOT with Stripe) I'm not sure whoo pointed at a webport UNLESS you are using a local server

worthy ridge
#

so the listen is also only for localhost type stuff, and not needed in production?

plain fjord
#

(NOT with Stripe) many concepts being thrown in the pot here

worthy ridge
#

sorry....I'm a web novice, as I said

remote goblet
#

yeah agreed. You might want to hire a freelancer to teach you all of this @worthy ridge

worthy ridge
#

probably

#

ok thx

remote goblet
#

if you're going to accept live payments, that's a safer option and in a few hours they can show you the ropes

#

But overall the first step would be to debug what isn't working.

plain fjord
#

(not) as an example of unneeded complexity (and possibly limited understanding) express.listen is for a "socket", which is essentially a long-lived stream listener. If that doesn't make sense, you kinda gotta go back to basics

worthy ridge
#

yes I understand that I think

#

the removal of the socket listener, means the endpoint has to handle events from the webserver another way, which is what I think I'm missing on understanding, and the core of the question

#

but appreciate the time in chat gents/gals

remote goblet
#

What we are trying to say is that your webhook handler is in no way different to how you handle other routes in your code. For your server/Express app it's all the same

worthy ridge
#

i understand that, and agree my question isn't webhook specific

#

it's about getting the handshake between the client and the endpoint without using socket ports

plain fjord
#

(NOT with Stripe) Webhooks are NOT special in any way compared to a website entry point - express, pased on the .post(route, callback), simple calls the "callback" code when the "route" matches a POST event path. A website "server" is just code that ultimately send back some sort of response.

#

(NOT with Stripe) so your concern is NOT "catching" the webhook (which is nothing special), but sending things like the client secret back to the client?

remote goblet
#

(what does client secret have to do with their question, they are asking about a webhook handler)

worthy ridge
#

no

plain fjord
#

I think he's confusing the various flows

worthy ridge
#

it's more simple, I think

#

let's ignore webhook

#

and it all worked fine

#

I want to get rid of all the ports in URL

#

so....if the app.listen is removed, how does the endpoint see the /checkout post ?

plain fjord
#

(NOT with Stripe) When express sees a POST to mywebsite/checkout, it calls the code supplied in the app.post('/checkout', callback). That's what app.post does, it "registers" the callback as the thing to do when a POST occurs to '/checkout'

worthy ridge
#

agree

plain fjord
#

(NOT with Stripe) app.post does NOT execute anything by itself; EXPRESS just now knows to call the 'callback' code when a POST to 'mywebsite.com/checkout' occurs

worthy ridge
#

agree

#

and my question is still, how does express know to look for this without a listener?

plain fjord
#

(NOT with Stripe) It's PRECISELY what Express was written to DO

worthy ridge
#

you're saying, that if I simply call express(), and the post(/checkout) then it will handle it without other needs?

plain fjord
#

(NOT with Stripe) Express is actively RUNNING on your server, looking for such events

worthy ridge
#

ok....then I've got bugs elsewhere, and I'll go debug that

#

thanks

plain fjord
#

(NOT with Stripe) I can share my webhooks code, using express, if you like

worthy ridge
#

sure, that would be great

plain fjord
#
// If you are testing your webhook locally with the Stripe CLI you
// can find the endpoint's secret by running `stripe listen`
// Otherwise, find your endpoint's secret in your webhook settings in the Developer Dashboard
export const endpointSecret = configs?.stripe?.stripe_endpoint_secret
  ? configs.stripe.stripe_endpoint_secret
  : process.env.STRIPE_ENDPOINT_SECRET;

export const endpointDirectSecret = configs?.stripe
  ?.stripe_endpoint_secret_direct
  ? configs.stripe.stripe_endpoint_secret_direct
  : process.env.STRIPE_ENDPOINT_SECRET_DIRECT;

// This example uses Express to receive webhooks
export const webhook_app = webhook_app_creator();
// The Firebase Admin SDK to access Cloud Firestore.
//const cors = require("cors");

// Automatically allow cross-origin requests
webhook_app.use(cors({ origin: true }));

// build multiple CRUD interfaces:
webhook_app.post("/direct", async (request, response) => {
  //send the response early - the only valid response is "received"
  await commonHandler(request, response, endpointDirectSecret);
  response.json({ received: true });
});

webhook_app.post("/connect", async (request, response) => {
  //send the response early - the only valid response is "received"
  await commonHandler(request, response, endpointSecret);
  response.json({ received: true });
});

const commonHandler = async (request, response, secret) => {
  const sig = request.headers["stripe-signature"];

  try {
    request.fullEvent = stripe.webhooks.constructEvent(
      request.rawBody,
      sig,
      secret
    );
  } catch (err) {
    logger(`Webhook Error: ${err.message}`);
    return;
  }

  return writeRecord("Stripe_logs", {
    Id: request.fullEvent.id,
    timestamp: serverTimestampFieldValue,
    event: request.fullEvent
  });
};

#

webhook_app_creator comes from:

import webhook_app_creator from "express";
#
export const webhook_app = webhook_app_creator();
worthy ridge
#

yep looks very close to what I have too

plain fjord
#

literally creates and starts an Express server

#
webhook_app.post("/direct", async (request, response) => {
  //send the response early - the only valid response is "received"
  await commonHandler(request, response, endpointDirectSecret);
  response.json({ received: true });
});

tells the running express server that any POST event to '/direct' should be sent to the anonymous/arrow function

#

Each endpoint is using

const commonHandler = async (request, response, secret) => {
  const sig = request.headers["stripe-signature"];

  try {
    request.fullEvent = stripe.webhooks.constructEvent(
      request.rawBody,
      sig,
      secret
    );
  } catch (err) {
    logger(`Webhook Error: ${err.message}`);
    return;
  }

  return writeRecord("Stripe_logs", {
    Id: request.fullEvent.id,
    timestamp: serverTimestampFieldValue,
    event: request.fullEvent
  });
};

to process the POST event - in this case, just queung up the event in a database

worthy ridge
#

yeah I read the code and it's basically what I have too

#

I really don't think that's my issue

plain fjord
#

(NOT with Stripe) in essence, Express is a listener already

worthy ridge
#

i have webpage not found 404, when trying to access /checkout

plain fjord
#

then more likely is Express isn't even running, OR you have a higher-priority endpoint taking precedence

#

(NOT with Stripe) For example: if your Express app has someone declare app.post('/', callback), that can take precendence without allowing for the other path to be reached

worthy ridge
#

yeah I don't see that either

#

i know the express is running

plain fjord
#

wihtout seeing you actual code, not much more - and to be honest, as I make painfully clear (NOT with Stripe) so there's not much more time I can do.

worthy ridge
#

you're being very patient with me, I really appreciate it

#
const app = express();
// get the URL encoded form data
app.use(express.urlencoded({extended: false}));
app.use(express.json());
console.log('express running!');

app.post('/checkout', async (req, res) => {
#

app.get('/order/success', async (req, res) => {

#

and those are the only two I have in that file

plain fjord
#

(NOT with Stripe) basic debug question: HOW do you know Express is running? In debug, most important point to remeber is "you don't know ANYTHING if you haven't seen it recently"

worthy ridge
#

simplest case...I go to terminal, node endpoint.js, put a console.log(express running) you see above...and process is still running....and I go try a website /checkout url

plain fjord
#

HOW do you know it is still running?

#

(NOT with Stripe) You know it STARTED (the console.log) - do you know it is RUNNING?

worthy ridge
#

how would you suggest I confirm? the endpoint process didn't terminate and the app is at file scope

plain fjord
#

(NOT with Stripe) also - that express.json() middleware may well interfere with endpoint verification - it needs the RAW, entirely unprocessed post body - yes it can be PARSED as JSON, but verification is EXTREMELY (deliberately) picky about spaces, line-feeds, etc

#

(NOT with Stripe) well you could add some timer/interval that hits the console at regular intervals

#

(NOT with Stripe) To be extremely didactic, the verification process probably uses stegonography to encode extra information

#

(NOT with Stripe) You're gonna have to go debug on your own, here - but you're back onto a more reasonable path

worthy ridge
#

thanks again

#

really appreciate the time

worthy ridge
#

(it's the error I see anyway)

plain fjord
#

(NOT with Stripe) I'm not using Apache, so I don't know

#

(not) Well, not for at least a decade, anyway

#

(NOT with Stripe) Is your Node instance running under Apache?

worthy ridge
#

node is running on same server as apache....