Connect the Billing Form

Link to chapter - https://serverless-stack.com/chapters/connect-the-billing-form.html

Hi, I am having trouble when I do a purchase from the website settings page. I get a 500 error “Invalid API key” in the lambda logs on Seed. In my Stripe logs it shows the request to POST v1/tokens status 200 OK and the details of that show the correct key, but I don’t get a POST v1/charges request logged.

Payments work fine when I run the API test using $ serverless invoke local --function billing --path mocks/billing-event.json

Any clues on what is happening and where I have gone wrong?

The 500 error is likely coming from the Lambda function. You can do a console.log and check the Lambda logs to see what is going on.

Yes the lambda logs tell me I have an invalid API key but I have checked both my stripe keys and they are correct, and I do see requests in the stripe logs, and I can successfully charge when I use the invoke local test. Error below. The only place I didn’t follow the instructions was by verifying my email address with stripe, could that be it?

Note this is happening when running the client locally, I haven’t deployed the client with the billing feature yet.

{ Error: Invalid API Key provided: ****************2x7n at Constructor._Error (/var/task/node_modules/stripe/lib/Error.js:12:17) at Constructor (/var/task/node_modules/stripe/lib/utils.js:134:13) at new Constructor (/var/task/node_modules/stripe/lib/utils.js:134:13) at IncomingMessage.<anonymous> (/var/task/node_modules/stripe/lib/StripeResource.js:149:21) at emitNone (events.js:111:20) at IncomingMessage.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1064:12) at _combinedTickCallback (internal/process/next_tick.js:138:11) at process._tickDomainCallback (internal/process/next_tick.js:218:9) type: 'StripeAuthenticationError', stack: 'Error: Invalid API Key provided: ****************2x7n\n at Constructor._Error (/var/task/node_modules/stripe/lib/Error.js:12:17)\n at Constructor (/var/task/node_modules/stripe/lib/utils.js:134:13)\n at new Constructor (/var/task/node_modules/stripe/lib/utils.js:134:13)\n at IncomingMessage.<anonymous> (/var/task/node_modules/stripe/lib/StripeResource.js:149:21)\n at emitNone (events.js:111:20)\n at IncomingMessage.emit (events.js:208:7)\n at endReadableNT (_stream_readable.js:1064:12)\n at _combinedTickCallback (internal/process/next_tick.js:138:11)\n at process._tickDomainCallback (internal/process/next_tick.js:218:9)', rawType: 'invalid_request_error', code: undefined, param: undefined, message: 'Invalid API Key provided: ****************2x7n', detail: undefined, raw: { message: 'Invalid API Key provided: ****************2x7n', type: 'invalid_request_error', headers: { server: 'nginx', date: 'Sat, 06 Oct 2018 17:51:33 GMT', 'content-type': 'application/json', 'content-length': '122', connection: 'close', 'access-control-allow-credentials': 'true', 'access-control-allow-methods': 'GET, POST, HEAD, OPTIONS, DELETE', 'access-control-allow-origin': '*', 'access-control-expose-headers': 'Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required', 'access-control-max-age': '300', 'cache-control': 'no-cache, no-store', 'stripe-version': '2018-09-24', 'www-authenticate': 'Bearer realm="Stripe"', 'strict-transport-security': 'max-age=31556926; includeSubDomains; preload' }, statusCode: 401, requestId: undefined }, headers: { server: 'nginx', date: 'Sat, 06 Oct 2018 17:51:33 GMT', 'content-type': 'application/json', 'content-length': '122', connection: 'close', 'access-control-allow-credentials': 'true', 'access-control-allow-methods': 'GET, POST, HEAD, OPTIONS, DELETE', 'access-control-allow-origin': '*', 'access-control-expose-headers': 'Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required', 'access-control-max-age': '300', 'cache-control': 'no-cache, no-store', 'stripe-version': '2018-09-24', 'www-authenticate': 'Bearer realm="Stripe"', 'strict-transport-security': 'max-age=31556926; includeSubDomains; preload' }, requestId: undefined, statusCode: 401 }

Seems like something is up with the way you are setting up Stripe? I found this, maybe it’ll help.

Resolved. It was, unsurprisingly, as the error message said. The API key was wrong. I made the mistake of checking the secret key in the env.yml file but that of course doesn’t mean anything if I am deploying with Seed. The env variable setting in Seed was wrong. Thanks for your help.

1 Like

Ah yeah that makes sense.

Good morning, after I ran through this part of the tutorial I am getting a popup stating “network error” when signing in with my user. I get the same message when trying to update the billing info or updating or editing a note. Any ideas? I am working through all the logistics and logs now. Thanks in advance.

Yeah not sure what the issue is, unless we look at the logs.

@jayair

Im working through the connection of the BillingForm component and I am receiving a Request failed with status code 500 Error alert.

When I look through the JavaScript console in my browser’s DevTools I see the following error in the console:

Blocked a frame with origin "http://localhost:3000" from accessing a frame with origin "https://js.stripe.com". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "https". Protocols must match.

It seems that since I am on the localhost dev environment, React, from the browser, as http is not letting me access the Stripe iFrame CardElement which is an https resource.

Looking at the logs in seed first for the deployment itself i see the following:

Dec 6, 11:30:54 AM
134.56.130.56 - - [06/Dec/2018:16:30:54 +0000] "OPTIONS /billing HTTP/1.1" 200 0 4d1eda09-f974-11e8-9295-355450434bf5
Dec 6, 11:30:54 AM
134.56.130.56 AROAJ52RLDUSSCLAVHIPS:CognitoIdentityCredentials AROAJ52RLDUSSCLAVHIPS:CognitoIdentityCredentials [06/Dec/2018:16:30:54 +0000] "POST /billing HTTP/1.1" 500 57 4d2f0625-f974-11e8-8a69-f1c7066f0985

So the app is definitely trying to access the billing resource at my serverless backend. Here are the logs for the Lamda function itself:

Dec 6, 11:30:54 AM
START RequestId: 4d3261df-f974-11e8-9619-05a5a6b29c97 Version: $LATEST
Dec 6, 11:30:54 AM
END RequestId: 4d3261df-f974-11e8-9619-05a5a6b29c97
Dec 6, 11:30:54 AM
Duration: 411.46 ms	Billed Duration: 500 ms Memory Size: 1024 MB	Max Memory Used: 32 MB

It looks from the console that React is blocking the exchange… Im not sure.

Here is an image of the error I am getting and the outputs to console:

Separately I can also see that the stripe frame is in fact able to capture the data entered by the user and the BillingForm is tokenizing the card correctly as can be seen by the output to the console showing the child attributes for the token created as can be seen below:

Ultimately it looks like I am not able to access my serverless /billing resource…

When I look at the header in the error message this is what it looks like and it says the Error is coming from CloudFront:

Summary
URL: https://laiwbpgoji.execute-api.us-east-1.amazonaws.com/prod/billing
Status: 500
Source: Network

Request
Accept: application/json, text/plain, */*
Content-Type: application/json; charset=UTF-8
Authorization: AWS4-HMAC-SHA256 Credential=ASIA6C4EOESDVI2T2TPU/20181206/us-east-1/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-security-token, Signature=0318801002fcc8783b46e2db59e478520582023771332f48a57431983975c8cc
Origin: http://localhost:3000
Referer: http://localhost:3000/settings
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.1 Safari/605.1.15
x-amz-date: 20181206T203238Z
X-Amz-Security-Token: AgoGb3JpZ2luEFAaCXVzLWVhc3QtMSKAApJvNCOvPm8DuGI995rwSvOHHKkLgcsrVli97QmzqNCSfrBgMXMZjRW5Ihw/4LCZhNfswkMqoiWPvvQhM77z7jAQTc4OhaQCGi1XNuvOdnr2xvTJcxd+pBzk1xJ+B+iYTMyR1ghQ+8d8jkX1CKoq1QM2HQ5efL3woyX7zExEEDsWCG+IdM2cokQLJ1Seqxx9iVbvT9xHcyTH1OSZLUR95rf3/QTnOdd6KCQDlg6cy1xMymwCrPNxanwSKEZo/meK3Cdf23eDSmofjPrImGP3YpytCKPXXE/vag/TU5qArMOMtAonZGygJtgT1obWgNzRTZpPxtPwdwIun64qQnb6GCcqrwUI9v//////////ARAAGgw5NjgyNTYwMDUyNTUiDGaTpvDuc8mB+dnM0CqDBUbvAY1cTCq69CmD4lP7XIbvHT39N3GA9YuGyNb6CWzj97iDFp6gsxZPPyFrLFYauHw1AwIU/fXCs1NvG/uqzn5IAb7QK7dyZvu7XQypKNVpqw2zaj4xNzNB8T3t3I5m5gKPRsSKDEygRC6t3yAXTAjiXom/9ZIBXkcMxlJS4w2wEHghymG101O+sVdLHQS+SHxf7nDNxqvidebmXCpQ0jPzTkalfB/emcHxiERyDRUcB7qypoYhypcYV6wCkzhshE1aljRvF47ucvKrDjpId5IqOdnaF/QJhHtk8cxwlCVHGbx1CsJHiBNRPXXxmt1IRGG+RPWr/wMaFdZKhLA5OKKCvSkol4Pw5roMHPsSZQAsre/20y058GdeFmi8u8Eip8as27gG9AZt+d7MpXSbLvCmphqQCyGZuFL7Hz7aTNLMAvRMtbU2YEhR+uTqBLeY6xWhGpsoncuSU18uajAtWEb493tjmNcmsA9VVnUbkBO6nfZpWgmhT1ODqUwcgsbwTYEGv6OGFN5Tmt7qrHrhXnGgH/2muFAmiOV4H3AZFyodCdkQSDoY3DI3NWFcYbMQCr6m0YOvRv7SRUEfwzFyf61b8eYadOP41M68FTWgRruCtcwNKrw80RXzDaEU/FDwZVx4aZJ5WhDX+8E6NdqPD8Dm07DMvxCIywsuupfgcOUkCBhvtJCwSCDelsatFwT76ygFxpFOJoK5quEsnMGfzRCHW6+ykhMikWybQ3ikzOtZqqW60JHQGN75Q3wZrn/or5gZ3A+KoXgZrW0dC5W+ni1jstPw/QA8OL3MeOD42uX0feBJytzBqD+g6xmu5K8ZCPkz2imUQdbHRUzardXvZdTBe+Aw0Y6m4AU=

Response
Access-Control-Allow-Credentials: true
Content-Type: application/json
Via: 1.1 044b06becff164c5ab784f66cdbee17d.cloudfront.net (CloudFront)
Date: Thu, 06 Dec 2018 20:32:39 GMT
Content-Length: 57
Access-Control-Allow-Origin: *
x-cache: Error from cloudfront
x-amzn-requestid: 12986d0d-f996-11e8-8a8e-3118299295ca
x-amz-apigw-id: RgIYDH0qoAMFbvA=
x-amzn-trace-id: Root=1-5c098766-275504973c96e8752839b698;Sampled=0
x-amz-cf-id: x34o2HCNEwcQ_nTlA06Li8sab2pxYQEsrCyqQYCuhqSNconnvki04w==

Request Data
MIME Type: application/json
Encoding: UTF-8
Request Data: 

Here is the request object that is sent with the request and it too looks correct as it is holding the data that the backend /billing API is expecting:

{"txnQty":"1","txnType":"SubscriptionFee","source":"tok_1DeTWULcSK7HST3BCK1k6WrJ"}

It looks like since my localhost is on http its not letting me access the endpoint correctly. Not sure why AWS is preventing this since I have my CORS Policy set as per specs and all of the other endpoints work fine from http…

Not really sure what is wrong here, and I could use some help, what else can I look for to pinpoint this error?

Thanks again!

@jayair This is the thread I needed some help with please.

Yeah this is a browser policy. You can run your localhost through HTTPS. We do this in one of our other Extra Credit chapters. You can set the following option while starting your Create React App.

Awesome! thanks so much. Im assuming ill have to npm start again according to the stage I’m on to get it going correct?

Also should I remove this to deploy to production on AWS? or can I keep it as is?

Thanks again I really appreciate the help, I’ve been stuck on this one for quite a bit.

1 Like

Yeah npm start again. Here is the doc on it https://facebook.github.io/create-react-app/docs/using-https-in-development.

Deployment should not be affected by the flag, it’s only for local.

@jayair

That didn’t work. I get an https:// on local host now but when I enter data into the Stripe CardElement fields I get the following error in the console:

Blocked a frame with origin "https://localhost:3000" from accessing a frame with origin "https://js.stripe.com". Protocols, domains, and ports must match.

I also get this error showing I am not accessing the /billing resource:

Furthermore when I look at the headers in the response it says I get:

x-cache: Error from cloudfront

Not sure what to do here as I have it all as specified on docs.

Any suggestions as to how to approach?

The error still has http in it (or at least the screenshot does). Has it been setup properly?

Yeah sorry I just reused an old screenshot. Here is the updated screenshot asking for the ports to match now also:

@jayair

So the 500 error is different from the blocked origin error. And it appears as though the blocked origin error isn’t preventing the users from making the purchase. 500 errors are thrown by our own code in the Lambda function and you should be able to debug them using a simple console.log.

@jayair

Here is a picture of my /billing lambda function in my billing.js file:

I have been trying to figure out how to console.log those lambda’s but it’s not clear how to get them to print to the node console. As you can see aslant doesn’t accept them as valid syntax in the lambda itself.

Also, I know the request is sending the correct info. When I look at the request object being sent, in the developer tools I can see that it is being passed properly as such:

{"txnQty":"1","txnType":"SubscriptionFee","source":"tok_1DeTWULcSK7HST3BCK1k6WrJ"}

I am generating a token as needed by Stripe and I am getting the data to the backend as needed. Where can I put the console.log methods so I can get meaning full feedback from the service on the node console.

Thanks again.

Any clues on how to get the console.log working on the back end?