Stripe charge not going through - javascript

I'm using the Stripe API to test out charges and the charge is not going through. I tokenize the credit card then use the token as a "source" parameter. I did the exact same thing in Python and it worked fine, but when I tried using this with Node.js, it didn't work.
Here's my code:
var stripe = require("stripe")(<key>);
var pay = stripe.tokens.create({
card: {
number: '<number>', // note, for now I'm just using the stripe test credentials
exp_month: <exp>,
exp_year: <year>,
cvc: '<cvc>'
}
}, function(err, token) {
console.log(err); // null
console.log(token); // token information (works fine)
return token;
});
stripe.charges.create({
amount: 500,
currency: "usd",
source: pay,
description: "Test charge"
}, function(err, charge) {
console.log(err); // error message 400, missing parameter
console.log(charge); // still null
});
What am I doing wrong? As I said, when I did this using Python it worked fine.
Update: I've tried all solutions posted below and they all still return a error 400 code. If anyone has another solution it would be appreciated.
_____________________________________________________________________________
Update 2: For anyone looking for an answer, I figured it out and posted it below.

A few things:
stripe.tokens.create returns a Promise, not a value. You have to assign token to something in the right scope to use it elsewhere, or just pass it to a function that uses it:
stripe.tokens.create({
card: {
number: '<number>', // note, for now I'm just using the stripe test credentials
exp_month: <exp>,
exp_year: <year>,
cvc: '<cvc>'
}
}, function(err, token) {
console.log(err); // null
console.log(token); // token information (works fine)
// call a function which in turn calls stripe.charges.create
makeCharge(token);
});
You shouldn't be generating tokens on your backend, this subjects you to the widest scope of PCI compliance https://stripe.com/docs/security#validating-pci-compliance. Instead use Stripe Elements or legacy Checkout on your frontend to tokenize cards.
JavaScript is asynchronous rather than synchronous, look into using async/await if you want synchronous operations.

The create methods run asynchronously. If you want to use the token you just created, then you need to do so in the callback. To better understand this, check this code:
var stripe = require("stripe")(<key>);
var pay = stripe.tokens.create({
card: {
number: '<number>', // note, for now I'm just using the stripe test credentials
exp_month: <exp>,
exp_year: <year>,
cvc: '<cvc>'
}, function(err, token) {
console.log(err); // null
console.log(token); // token information (works fine)
return token;
});
console.log(pay); // This will not be what you expected.
pay is not going to be the value of token because the request hasn’t finished yet.
Instead, you need to create your charge inside the callback for the token. This callback function is executed once the web request for the token creation is finished.
var stripe = require("stripe")(<key>);
stripe.tokens.create({
card: {
number: '<number>', // note, for now I'm just using the stripe test credentials
exp_month: <exp>,
exp_year: <year>,
cvc: '<cvc>'
}, function(err, token) {
console.log(err); // null
console.log(token); // token information (works fine)
stripe.charges.create({
amount: 500,
currency: "usd",
source: token, // note I changed this to token
description: "Test charge"
}, function(err, charge) {
console.log(err); // hopefully null now
console.log(charge); // hopefully has charge info now
// add code to display a confirmation message or whatever you want to do with the successful charge here
});
});
Disclaimer: I’m not familiar with the Stripe code. I just understand how asynchronous JS works. Creating the token every time may or may not be best practice.

You can do one think just use the default source from the stripe customer id created by user.
return stripe.customers.retrieve(stripeCustomerId)
.then((customer) => customer.default_source)
You will get the customer default source if available and after that just create charge using this source.
const strpChrg = {
customer: stripeCustomerId,
amount: _.round(amount * 100), // convert to cents
currency: _.toLower(currency), // usd
source: sourceId
};
// create stripe charge using customer token
return stripe.charges.create(strpChrg).then((charge) => {
// add charge to data
return charge;
});
You should not create a token at the backend, use stripe default source added by the customer instead.

For anyone who wants to create charges this way, here is how i figured it out with Node.js (for people like me who came from python, this will be very helpful):
stripe.tokens.create({
card: {
number: '<card number>',
exp_month: <exp>,
exp_year: <year>,
cvc: '<cvc>'
}
}, function(err, token) {
console.log(token.id); // you can log the entire token, or you can just check for the piece you need
stripe.charges.create({
amount: 800,
currency: "usd",
source: token.id, // instead of in python where you can use a variable, in node you have to use specifically the id
description: "Test charge"
}, function(err, charge) {
console.log(err); // if it does not work, make sure to print the error
console.log(charge) // print the charge to make sure it went through
});
});
Hopefully this will help someone along the road!
Note: As others mentioned, for production this is probably not what you want to do, this solution would more be for getting to know the Stripe API or testing out quick charges.

Related

getting StripeInvalidRequestError: No such payment_intent: 'pi_3LVwOn4IimzjyVut1GNg6Urh' when stripe.paymentIntents.confirm

I want to use OptionalHandle the Alipay redirect manually, but get StripeInvalidRequestError: No such payment_intent: 'pi_3LVwOn4IimzjyVut1GNg6Urh'
const paymentIntent = await stripe.paymentIntents.create(
{
payment_method_types: ['alipay'],
amount: 1000,
currency: 'hkd',
application_fee_amount: 0,
},
{
stripeAccount: connectedStripeAccountId,
},
);
const comfirmpaymentIntent = await stripe.paymentIntents.confirm(
paymentIntent.id,
{
return_url: 'https://....',
},
);
You’re creating a Direct Charge PaymentIntent on the Connect Account but when you’re confirming that PaymentIntent you’re using not passing the stripeAccount id the same way you did for the creation. What happens is that Stripe will try to look at the PaymentIntent in your Platform Account and it’s not finding it. If you don’t have a logic between creating the PaymentIntent and confirming it, you could always pass confirm: true param when creating the PaymentIntent.

Google Pay Implementaion On The Web [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I want to add the google pay buy now button on my website, I used the below documentation for reference.
https://codelabs.developers.google.com/codelabs/pay-web-checkout/index.html?index=..%2F..index#0
and everything works fine and here is the code that I created.
<div id="buy-now"></div>
<script async
src="https://pay.google.com/gp/p/js/pay.js"
onload="onGooglePayLoaded()">
</script>
<script>
let googlePayClient;
const baseCardPaymentMethod = {
type: 'CARD',
parameters: {
allowedCardNetworks: ['VISA','MASTERCARD'],
allowedAuthMethods: ['PAN_ONLY','CRYPTOGRAM_3DS']
}
};
const googlePayBaseConfiguration = {
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: [baseCardPaymentMethod]
};
function onGooglePayLoaded() {
googlePayClient = new google.payments.api.PaymentsClient({
environment: 'TEST'
});
// check compatability
googlePayClient.isReadyToPay(googlePayBaseConfiguration)
.then(function(response) {
if(response.result) {
createAndAddButton();
} else {
alert("Unable to pay using Google Pay");
}
}).catch(function(err) {
console.error("Error determining readiness to use Google Pay: ", err);
});
}
function createAndAddButton() {
const googlePayButton = googlePayClient.createButton({
// currently defaults to black if default or omitted
buttonColor: 'default',
// defaults to long if omitted
buttonType: 'long',
onClick: onGooglePaymentsButtonClicked
});
document.getElementById('buy-now').appendChild(googlePayButton);
}
function onGooglePaymentsButtonClicked() {
// TODO: Perform transaction
const tokenizationSpecification = {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'example',
gatewayMerchantId: 'gatewayMerchantId'
}
};
const cardPaymentMethod = {
type: 'CARD',
tokenizationSpecification: tokenizationSpecification,
parameters: {
allowedCardNetworks: ['VISA','MASTERCARD'],
allowedAuthMethods: ['PAN_ONLY','CRYPTOGRAM_3DS'],
billingAddressRequired: true,
billingAddressParameters: {
format: 'FULL',
phoneNumberRequired: true
}
}
};
const transactionInfo = {
totalPriceStatus: 'FINAL',
totalPrice: '123.45',
currencyCode: 'USD'
};
const merchantInfo = {
merchantId: 'BCR2DN6TRPZNDYLL', Only in PRODUCTION
merchantName: 'Example Merchant Name'
};
const paymentDataRequest = Object.assign({}, googlePayBaseConfiguration, {
allowedPaymentMethods: [cardPaymentMethod],
transactionInfo: transactionInfo,
merchantInfo: merchantInfo
});
googlePayClient
.loadPaymentData(paymentDataRequest)
.then(function(paymentData) {
processPayment(paymentData);
}).catch(function(err) {
// Log error: { statusCode: CANCELED || DEVELOPER_ERROR }
});
}
function processPayment(paymentData) {
// TODO: Send a POST request to your processor with the payload
// https://us-central1-devrel-payments.cloudfunctions.net/google-pay-server
// Sorry, this is out-of-scope for this codelab.
return new Promise(function(resolve, reject) {
// #todo pass payment token to your gateway to process payment
const paymentToken = paymentData.paymentMethodData.tokenizationData.token;
console.log('mock send token ' + paymentToken + ' to payment processor');
setTimeout(function() {
console.log('mock response from processor');
alert('done');
console.log(paymentData);
resolve({});
}, 800);
});
}
</script>
I am familiar with PHP and Ruby and I don't want to use third-party payment gateways for tokenization specification want to do it with the DIRECT method. I don't know what to do next and how to compare the token after payment success and don't have any idea about tokenization specification with the DIRECT method help me.
thanks, everyone.
If you're doing a web integration, consider using the Google Pay components. There's a React version if using React, and a Web Component version for most of the other frameworks.
As for DIRECT integration, it is strongly discouraged due to additional compliance obligations. From https://developers.google.com/pay/api/web/reference/request-objects#direct:
Key Point: The Direct integration allows merchants to decrypt the Google Pay response on their servers. To qualify, you must be Payments Card Industry (PCI) Data Security Standard (DSS) Level 1 compliant. Your servers also need to have the required infrastructure to securely handle users' payment credentials.
Third parties that supply gateway or processing services on behalf of actual merchants aren't eligible to use the Direct integration. For questions about your integration as a payment service provider, contact us.
If you don't meet the necessary prerequisites, we recommend that you use a supported gateway to receive a payment token.
Out of interest, why don't you want to use a payment gateway?
If you still feel like you need DIRECT integration, resources on how to decrypt the token can be found at: https://developers.google.com/pay/api/web/guides/resources/payment-data-cryptography.
I don't know what to do next and how to compare the token after payment success and don't have any idea about tokenization specification with the DIRECT method help me.
You need to generate a public/private key pair and register the public key with the Google Pay console. You'll also need to update the tokenizationSpecification to include the public key (example below)
"tokenizationSpecification": {
"type": "DIRECT",
"parameters": {
"protocolVersion": "ECv2",
"publicKey": "BOdoXP1aiNp.....kh3JUhiSZKHYF2Y="
}
}
how to compare the token after payment success
Google Pay won't handle the payment, you will. You'll need to decrypt the payment token and get the payment details and process the payment yourself.
DIRECT integration is a more difficult integration process, so I would strongly encourage exploring other alternatives first and only consider this if you cannot use a payment gateway.

Cannot find name 'require'. ANGULAR 2

I have an angular2 app where I need to use a payment API.
https://stripe.com/docs/quickstart
In this code sample on the nodejs section they say to use it like this:
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
var stripe = require("stripe")("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
// Token is created using Stripe.js or Checkout!
// Get the payment token submitted by the form:
var token = request.body.stripeToken; // Using Express
// Charge the user's card:
var charge = stripe.charges.create({
amount: 1000,
currency: "usd",
description: "Example charge",
source: token,
}, function(err, charge) {
// asynchronously called
});
We installed requireJS with NPM, however when we run it we get this error:
Cannot find name 'require'.
L48: pagar() {
L49: var stripe = require("stripe")("sk_test_ayzCMDmjq2QOIW0s3dTihxNR");
Try this instead:
import * as stripe from "stripe";
public stripeKey = stripe("sk_test_BQokikJOvBiI2HlWgH4olfQ2");

paypal checkout button get json response in javascript

In the paypal API reference page it says after creating a payment it will return a response. I would like to use the transaction information after payment is completed, but I'm not sure how to obtain this response json from the basic integration scenario here. After going through the documentation, I don't see where I can get this response. Am I missing a missing a option here? Thanks in advance.
The following is my code
paypal.Button.render({
// Set your environment
env: 'sandbox', // sandbox | production
// Pass the client ids to use to create your transaction on sandbox and production environments
client: {
sandbox: 'removed for security', // from https://developer.paypal.com/developer/applications/
production: 'removed for security' // from https://developer.paypal.com/developer/applications/
},
// Pass the payment details for your transaction
// See https://developer.paypal.com/docs/api/payments/#payment_create for the expected json parameters
payment: function() {
return paypal.rest.payment.create(this.props.env, this.props.client, {
transactions: [
{
amount: {
total: total,
currency: 'USD'
},
custom: purchaseOrderNumber
}
]
});
},
// Display a "Pay Now" button rather than a "Continue" button
commit: true,
// Pass a function to be called when the customer completes the payment
onAuthorize: function(data, actions) {
console.log("data", data);
console.log("actions", actions);
return actions.payment.execute().then(function() {
console.log('The payment was completed!');
//use transaction information from json response here
});
},
// Pass a function to be called when the customer cancels the payment
onCancel: function(data) {
console.log('The payment was cancelled!');
}
}, '#paypal-button');
EDIT:
console results for data
{
"paymentToken":"EC-8T213183GM917341N",
"payerID":"784ARKSZGWBPG",
"paymentID":"PAY-00M809553A479072XLEBN4RI",
"intent":"sale",
"returnUrl":"https://www.sandbox.paypal.com/?paymentId=PAY-00M809553A479072XLEBN4RI&token=EC-8T213183GM917341N&PayerID=784ARKSZGWBPG"
}
console results for actions
{
"payment":{}
}
//see below for console screenshot
EDIT2:
request to paypal framework and response
It would appear that The last picture is the response that I actually need. Is there a way to obtain this data from a basic paypal button?
Add a parameter to actions.payment.execute().then() to catch the response
paypal.Button.render({
// Set your environment
env: 'sandbox', // sandbox | production
// Pass the client ids to use to create your transaction on sandbox and production environments
client: {
sandbox: 'removed for security', // from https://developer.paypal.com/developer/applications/
production: 'removed for security' // from https://developer.paypal.com/developer/applications/
},
// Pass the payment details for your transaction
// See https://developer.paypal.com/docs/api/payments/#payment_create for the expected json parameters
payment: function() {
return paypal.rest.payment.create(this.props.env, this.props.client, {
transactions: [
{
amount: {
total: total,
currency: 'USD'
},
custom: purchaseOrderNumber
}
]
});
},
// Display a "Pay Now" button rather than a "Continue" button
commit: true,
// Pass a function to be called when the customer completes the payment
onAuthorize: function(data, actions) {
return actions.payment.execute().then(function(param) {
console.log('The payment was completed!');
//param is the json response
});
},
// Pass a function to be called when the customer cancels the payment
onCancel: function(data) {
console.log('The payment was cancelled!');
}
}, '#paypal-button');
The setup seems all good, all you need now is to decide what and how you want to handle your response.
In the onAuthorize function you can do something like (github paypal checkout button) this for all of your aproved sales (check for data.status to be approved (credit card) or created (for payment with paypal), then you should have a data.payer with all the info):
jQuery.post('/my-api/execute-payment', { paymentID: data.paymentID, payerID: data.payerID });
.done(function(data) { /* Go to a success page */ })
.fail(function(err) { /* Go to an error page */ });
or use directly the data json object in the function.

Server side validation in Express compatible with a single page Angular application

I would like to perform server side validation, preferably with expressValidator. When saving a resource, I check to see if it is valid. If it's not valid what should I return?
There are examples:
http://blog.ijasoneverett.com/2013/04/form-validation-in-node-js-with-express-validator/
https://github.com/ctavan/express-validator
Unfortunately, I can't figure out my answer from that.
In Angular, I am using the $resource service. When I do a save, and there is a validation error, how should the server send this back? Note, this is a single page application.
Also, how should I handle this on the client side? Is this technically a success call?
Please, I am not looking for any instant, ajax, check per field solution. I want to submit save, if there is a problem, I would like to return the errors so that Angular can handle them. This does not need to be the perfect solution, just something to set me on the right track.
I am not handing the Angular code in an special way at the moment:
Controller:
$scope.saveTransaction = function (transaction) {
transactionData.saveTransaction(transaction);
}
Service
saveTransaction: function(transaction) {
return resource.save(transaction);
}
The server side code looks as follows:
app.post('/api/transactions', function (req, res) {
var transaction;
req.assert('amount', 'Enter an amount (numbers only with 2 decimal places, e.g. 25.50)').regex(/^\d+(\.\d{2})?$/);
var errors = req.validationErrors();
var mapped = req.validationErrors(true);
if (mapped) {console.log("MAPPED")};
//console.log(mapped);
if(!errors) {
console.log("Passed");
transaction = new TransactionModel({
date: req.body.date,
description: req.body.description,
amount: req.body.amount
});
transaction.save(function (err) {
if (!err) {
return console.log("created");
} else {
return console.log("err");
}
return res.send(transaction);
})
}
else {
console.log("Errors");
res.send(errors);
// res.render('Transaction', {
// title: 'Invalid Transaction',
// message: '',
// errors: errors
// });
}
});
You could send and handle "better" errors:
SERVER
res.json(500, errors)
CLIENT
resource.save(tran).then(function(){
//it worked
},
function(response) {
//it did not work...
//see response.data
});

Categories

Resources