Handle Stripe response in Express app - node.js

I'm trying to write a simple Stripe integration using Express. My code creates the customer and charge and completes, appearing in my dashboard. However I'm struggling to understand how to handle the response from Stripe. The following just outputs the whole response from Stripe - what I would like is to be able to output a friendly message dependent on the content of this response:
stripe.customers.create({
card: stripeToken
})
.then(customer =>
stripe.charges.create({
amount: fee,
description: "Client Ref: " + clientref,
currency: "gbp",
customer: customer.id,
metadata: {
'allocation:': allocate
}
}))
.then(charge => response.send(charge))
.catch(err => {
console.log("Error:", err);
response.status(500).send({error: "Purchase Failed"});
});
How can I look at the response and handle it accordingly? I've tried using the response.send promise and I can get it to display parts of the response, but is this a 'charge' page? How can I display this as html and not just plaintext??
I have looked in the Stripe docs and haven't found anything similar. I want to be able to account for failed payments, declines etc as well as successful charges.
Any help or other examples much appreciated!
Thanks
edit: ok I handle the 'errors' in the catch block. I didn't realise Stripe doesn't throw exceptions, so that makes life easier. My point about formatting the messages still stands however. '/charge' just outputs plain text.

How can I look at the response and handle it accordingly?
The Stripe docs clearly show you what the response for a successful charge is here: https://stripe.com/docs/api/node#create_charge (under Example response). It gives you back a large JSON object.
You need to figure out what part of that response is useful to you to display in your client-side application. If none of the information is needed, then you can simply ignore the response.
(...) but is this a 'charge' page? How can I display this as html and not just plaintext??
What you are doing now is simply sending the whole JSON object to your client via res.send. And you are not doing anything with the response other than simply sending it back as plain text. You need to configure your view to display the response: http://expressjs.com/en/guide/using-template-engines.html
Or if your producing an API for others to consume, then use res.json to send back the JSON you got back from Stripe. http://expressjs.com/en/4x/api.html#res.json
I want to be able to account for failed payments, declines etc as well as successful charges.
Then you need to handle the error that occurs. You are handling the error via .catch, but you aren't inspecting the error object. Again, the stripe have documentation on errors as well: https://stripe.com/docs/api#errors
And they even tell you how to handle errors as well: https://stripe.com/docs/api#handling-errors

Related

Express server Error 400 is not returning json message

I am submitting a form and if the form id already exists in the database, I am returning status 400 with a message saying that the form exists.
res.status(400).send({
status: 400,
message: "Form exists"
})
When I read the response sent back from my express server, I am getting Bad request message instead of the custom message object that I am returning. If I replace res.status(400) with res.status(200), I am getting the expected custom message object.
Weird enough, I can get the custom message object when making the server call in development environment. I get Bad Request message from my production server and I don't know why the response is different when the environment is different. I am hosting this server on IIS Manager v10
So my question is should I use status code of 200 instead of 400 in this scenario? Is there a way to return a custom message from status 400? Based on my understanding, I should use 4xx status code if there is a client input errors eg there is already an existing ID or invalid inputs.
Edit: This is my code from my React app.
axiosInstance
.post("/form/some-endpoint", formData)
.then(function () {
navigate(ROUTE_SUCCESS_PAGE);
})
.catch(function (error) {
// eslint-disable-next-line no-console
console.log(error);
alert(error.response !== undefined ? error.response.data.message : error.message);
});
This is the actual screenshot of the response from prod server (I console log it)
But in development environment, I am getting the response that I wanted.
Postman response from Prod server:
<system.webServer>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
Adding the <httpErrors existingResponse="PassThrough" /> to the server's web.config file on IIS Manager resolved my issue. Based on my understanding, bypassing the http error handler and not letting IIS to send its response is the solution that I need.
should I use status code of 200 instead of 400 in this scenario
TLDR: It depends on the usage.
If your intent is to Update a form, like using a PUT request, you should require an id and if that id does not exist, return 404.
If you are looking to Create a new form, like using a POST request, with an id or other meta data and one already exists matching the id or meta data (e.g. groupId), then 400 is fine but it could be better to use 409 stating that there is a conflict with the existing state, that being a preexisting form id or meta data. Though you don't often pass an id to a POST create request.
The full list of codes is a great place to start, but sometimes it helps to see how certain codes are used in production APIs. A good place to look is the GitHub API which shows the possible status codes for each endpoint along with a description. Take the Pulls API for example, just searching for 40 on the page gives you a lot of insight about when certain codes are used.
Comparing these statuses with your example, if you look at the PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge route, they use 409 whenever the state is not matching as they describe...
Conflict if sha was provided and pull request head did not match
This seems similar in nature to the POST request described above.
At the end of the day the crucial part is to get in the correct grouping (i.e 2xx, 4xx, etc.) after that it's more about being consistent across your API than matching the codes to exact best option. Also everyone is different and some may choose different codes for the same use case.
As far as changing the response itself on 400 status, you should be able to achieve this by setting statusMessage directly and then call res.end.
function(req, res) {
res.statusMessage = "Form exists";
res.status(400).end();
}
Also see https://stackoverflow.com/a/36507614/6943587

Why would I want to return a json object with a custom status field and message?

I am learning node and express and I noticed some tutorials like to send a response that looks like this:
{status: “Success”, message: “custom message”, response: {actual response object}}
My question is, what is the point of adding the extra status and message fields? Why not just return the response object by itself?
The simple reason is convenience. It sends a clear message to the client about the status of the request and what message to display based on that status. Its just a good programming practice that helps to structure your code base on how to handle errors from requests in the client side.

Stripe Elements not talking to stripe server - No such token: tok_xxxx

So I'm migrating from the stripe checkout to elements so that I can register and charge a customer in a single form.
I'm following their documentation:
https://stripe.com/docs/stripe-js/elements/quickstart
Specifically in Step 3 where the token is created with the following code:
// Create a token or display an error when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
The documentation states:
The handler sends the fields to Stripe for tokenization...
However, it seems nothing is being sent to Stripe at all!
The bottom two requests show the two api calls made using the old checkout: First the card info is sent to /tokens and then my server handles this and makes the /customers request fine.
But when using the elements code nothing seems to be sent to stripe, even though a token is generated and sent to my server. So then I get the 'No such token' error!?
I can't for the life of me workout why stripe.createToken(card) isn't sending the details to their server and yet generates a token?? I've triple checked api keys and everything I can think of. Please help!!
What the actual heck... I got it to work but I don't know why this fixed it.
I'm using stripe elements on a .net mvc website and i'm initializing the Stripe class in a view so I can easily pass the key from my viewmodel like so:
var stripe = Stripe('#Model.StripePublicKey');
Which should work fine, right? No JS errors or anything and it was creating the token, just not posting to stripe's servers....
Anyway, I moved that line into the JS file so it's directly above the other stripe related JS and now it works!?

getting error in a simple api request using node JS request lib

I'm trying to preform a simple API request with node:
const request = require('request');
request({
url: 'https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=MYAPIKEY',
json: true
} , (error , response , body) => {
console.log(body);
});
and getting the following error on console:
{
error_message: 'You have exceeded your daily request quota for this API. If you did not set a custom daily request quota, verify your project has an active billing account: http://g.co/dev/maps-no-account',
results: [],
status: 'OVER_QUERY_LIMIT'
}
while on the browser the request completes successfully with the exact same request.
I activated my billing account with no change.
Any suggestions what might be the problem?
so after some digging I found out that new rules have been applied by google, and in order to get the response you need to activate billing on every project through the console.
First you need to set up billing account for google cloud platform, which won't charge you unless you want to. after you done that, you need to go to your specific project and activate billing for that project, which wasn't very intuitive to understand.

Sending POST from node.js - how does a website identify me?

there is a website that works with virtual items for an online game. I made a chrome extension that automates some actions on that website. Since I'd like to make this run on my raspberryPi (and chromium with the extension seems to be too slow and unefficient) I am trying to move this into node.js.
The login for the website works with Steam OpenID. It allows you to select items from a list, click a few buttons, then it sends you a tradeoffer on steam.
My extension works with the website while I was logged in there. It receives their database with jQuery getJSON, loops through the array, pushes some values into an array and then sends a post request telling the website which items I want and which items I am offering.
Here is how I am sending the request from chrome:
function withdrawXHR(botId, playerItems, botItems) {
$.ajax({
url: websiteURL,
type: 'post',
data: {
"steamid": botId,
"peopleItems": playerItems,
"botItems": botItems
},
success: function (data) {
console.error('>> Done: ' + data)
console.log("")
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.error('>> Error: ' + errorThrown)
console.log("")
}
});
}
I can do everything in node so far like receiving their database, working through it, filter out the values I need, but I can't manage to send a working request. The problem is probably the login / how the website knows who I am.
I used wrapAPI (a chrome extension) to catch the request that is being sent when manually working with the website. Here is what it looks like:
So these are the things I am wondering about:
How would I send this request from node?
How does the website know who I am? They obviously know, because they are sending me an offer, but I can't see any "personal" data in that request.
Would I need to log into Steam OpenId from Node in some way? Is that possible?
What is a CF-RAY? (See the end of the captured request).
I am quite new to JS and requests in general and even "newer" to Node.js. I don't fully understand how the background of sending requests works. I would just need some tips, ideas on how to achieve my goal here.
Any help is greatly appreciated! Thank you! :)
You cannot use XMLHttpRequest for resources across domains. ( incidentally, unless you are using an extension)
I would look into grabbing express.js, and something called CORS. CORS permits cross-domain requests.
Here: http://enable-cors.org/server_expressjs.html
And here is some information on XHR requests in browser extensions: https://developer.chrome.com/extensions

Resources