Add an API to Handle Billing

Link to chapter — https://serverless-stack.com/chapters/add-an-api-to-handle-billing.html

When we run the following command, do we expect to see anything in terminal that npx sst start is running?

npx aws-api-gateway-cli-test \
--username='admin@example.com' \
--password='Passw0rd!' \
--user-pool-id='USER_POOL_ID' \
--app-client-id='USER_POOL_CLIENT_ID' \
--cognito-region='COGNITO_REGION' \
--identity-pool-id='IDENTITY_POOL_ID' \
--invoke-url='API_ENDPOINT' \
--api-gateway-region='API_REGION' \
--path-template='/billing' \
--method='POST' \
--body='{"source":"tok_visa","storage":21}'

The thing is that I’m getting 500 - Internal Server Error:

Authenticating with User Pool
Getting temporary credentials
Making API request
{
  status: 500,
  statusText: 'Internal Server Error',
  data: {
    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/."
  }
}

So I think that the secret key from env.local is not loading, and hence I put a simple log statement into src/billing.js:

console.log(process.env.STRIPE_TEST_SECRET_KEY)

However, I don’t see any log coming out. I also tried the path for GET /notes to list all the notes, and it is successful, however, I’m not getting any log in the npx sst start tab on the terminal either.

You should see it show up in the logs. Was sst start working for you otherwise?

Hi there, I am seeing this same issue. sst start works for me as normal. Can you please advise?

There is also another issue, which is when i hardcode the secret key, i get the following error returned from stripe:

{
  status: 500,
  statusText: 'Internal Server Error',
  data: { error: 'Invalid token id: tok_visa' }
}

Hi there, are you still having this issue?

@jayair - Hi there, I am unfortunately and it’s brought me to a grinding hault.

Is this the sst start issue or the Stripe issue?

Hi,

I had a few issues with this module that I would like to clarification on. I’m sure it was something I did since no one else has seemed to have these problems.

First thing was I had an issue with the route "functions/billing.main".

This triggered an error stating that the route couldn’t be resolved. I looked at the other routes for the CRUD functions and noticed that the src directory was listed in their routes so I put the backend folder into the src directory and added src to the route. That helped get things move past this error but then it couldn’t resolve the dependency for the handler function in the src/util folder. I think this is where I got confused. Is the cost function supposed to go into the same util directory as the handler function or does it go into another util folder in the backend directory? In the billing.js file they look like they should be in the same util folder but the tutorial says they should go into separate util folders.

I ended up editing the handler depencency path by making it "../../util/handler" instead of "../util/handler" and that resolved all the errors allowing the api test to return a 200 but my solution doesn’t feel like clean code. So what is the best answer here?

Can you double check if you have this line in your code:

There was an update recently that changes these paths.

Hi Jay,

I don’t have a lot of those lines in my code lol. I was thinking that there must have been an update between when I started the tutorial and when I got to this problem. I wasn’t able to work on it consistently or at a quicker pace so that isn’t surprising. I am just going to start from the top when I have the chance to binge on the whole thing over a week or so.

Thanks,

Aaron

Hey Aaron, we restructured the repo and made it easier if for folks to build on top of it. The idea remain the same and the actual code is 97% same.

And yeah it might be easier to skim through the earlier chapters again to adopt the changes. Again, no new concepts, just reorganizing :smiley:

1 Like

Thanks @frank I’m loving what you guys are doing here. I used this tutorial to build some projects a couple of years ago and got away from web development since then. Your tutorial is really well written and easy to understand. It’s made getting back into web dev after all this time a lot easier so thank you.

I actually was able to resolve this issue by going through the tutorial again. I missed some chapters or something the first time through. I’m planning on going through it a couple more times just to get the reps in. I’m going to need to build a team soon so I need to internalize this process. Thanks for creating such a fantastic guide. It makes my work so much easier.

1 Like

This doesn’t work for us at all, one our local environment it works fine but once deployed the call to stripe just times out and never throws an error. Any idea what might be happening here?

How are you deploying it? Are you running sst deploy?

I’m using TypeScript while working through the chapters. I noticed that when I instantiate a new Stripe() it requires more than just the stripe key, it also wants an API version. I had to modify my code to look like this:

// Load our secret key from the env variables
  const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;

  if (!STRIPE_SECRET_KEY) {
    throw new Error("Missing Stripe Key");
  }

// now STRIPE_SECRET_KEY is a `string`, not a `string | undefined`
// also add missing `apiVersion`
const stripe = new Stripe(STRIPE_SECRET_KEY, { apiVersion: "2022-11-15" });

This is using the latest version of stripe as of this post:

"stripe": "^12.3.0",

Oh that’s interesting. I’ll add a note to the chapter.

I had this issue occur. I did some digging and I went to ApiSTack.ts and inserted an error log which shows up while running npx sst dev. It originally showed undefined. I did some more digging but the actual cause was that dotenv must only detect .env.* files, like .env.local, when npx sst dev is started. For me, I terminated the current terminal and restarted the command, and voila, my stripe key showed up. Please ignore the newer setup. I didn’t originally think to just restart the command and I used the new secrets manager.

ApiStack.ts:

import { Api, use, StackContext, Config } from "sst/constructs";
import { StorageStack } from "./StorageStack";

export function ApiStack({ stack, app }: StackContext) {
  const { table } = use(StorageStack);
  const STRIPE_KEY = new Config.Secret(stack, "STRIPE_KEY");

  // Create the API
  const api = new Api(stack, "Api", {
    defaults: {
      authorizer: "iam",
      function: {
        bind: [table, STRIPE_KEY],
      },
    },
    routes: {
      "POST /notes": "packages/functions/src/create.main",
      "GET /notes/{id}": "packages/functions/src/get.main",
      "GET /notes": "packages/functions/src/list.main",
      "PUT /notes/{id}": "packages/functions/src/update.main",
      "DELETE /notes/{id}": "packages/functions/src/delete.main",
      "POST /billing": "packages/functions/src/billing.main",
    },
  });

  // check if .env.local has been loaded. It should show this value I've set in my env file
  console.error(process.env.TESTING2)

  // Show the API endpoint in the output
  stack.addOutputs({
    ApiEndpoint: api.url,
  });

  // Return the API resource
  return {
    api,
  };
}