Authentication error while implementing Stripe in Node js - node.js

I am trying to implement Stripe in my backend which is in node js. While calling it from front end I am getting this error:
You did not provide an API key, though you did set your Authorization header to "null". Using Bearer auth, your Authorization header should look something like 'Authorization: Bearer YOUR_SECRET_KEY'. See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.
Here is my code:
const stripe = require("stripe")(process.env.keySecret);
if(req.body.type == 'stripe') {
const token = req.body.token;
const amount = req.body.amount;
let charge = stripe.charges.create({
amount: amount,
source: token,
currency: 'USD'
},(err, chargeData) => {
if(err) {
console.log('error in buy premium api error... ', err);
return;
}
let payment = [];
payment.push({
amount: chargeData.amount,
address: chargeData.billing_details.address,
email: chargeData.billing_details.email,
payment_method_details: chargeData.payment_method_details.card
})
console.log('charge... ', charge);
if(charge) {
register.findByIdAndUpdate({ _id: therapist._id },
{
$set:
{
payment_details: payment
}
}, {new:true}, (e1, updatedUser) => {
if(e1) {
return;
}
resolve(updatedUser);
})
}
})
}
else {
let err = 'No payment type define..';
return reject(err);
}
My req.body is:
{
"token": "tok_1F2XPBG04BYg8nGtLoWnQwRU", // coming from front end
"amount": "250",
"type":"stripe"
}
The secret key is test secret key which is like sk_test_xxxxxxxxxxxxxxxx.
My front end is in Angular 6 and from front end I am passing my test publishable key i.e. pk_test_xxxxxxxxxxxxxxxxx. I am passing proper data to the both front end as well as backend. Where am I mistaken?

Since you are calling .env file, you have to include the following line before requiring stripe:
require ("dotenv").config();
const stripe = require("stripe")(process.env.keySecret);

Related

Server-side user verification with AWS Cognito user pool via MFA verification code (without password)

On the server side using NodeJS + NestJS, TS: 4.7.4, "aws-sdk": "^2.1138.0".
Trying to send a request to AWS Cognito, to obtain a verification code on mobile phone.
It's far away from achieving SMS quota.
An example of my method from the service:
async sendVerificationCode(phoneNumber: string) {
const params = {
AuthFlow: 'USER_SRP_AUTH',
ClientId: process.env.AWS_COGNITO_CLIENT_ID,
// UserPoolId: process.env.AWS_COGNITO_USER_POOL,
AuthParameters: {
USERNAME: phoneNumber,
SRP_A: generateSRPA(),
},
};
console.debug('=========== params: ', params);
try {
const result = await this.cognitoIdentityServiceProvider
.initiateAuth(params)
.promise();
console.log('=========== result: ', result);
return result;
} catch (error) {
if (error instanceof Error) {
console.debug('=========== Error: ', error.message);
throw error;
}
}
}
example of generation SRP_A:
const N_HEX ='EEAF0AB9ADB38DD69C33F80AFA...';
export function generateSRPA() {
const random = randomBytes(32);
const randomHex = random.toString('hex');
const srpA = createHash('sha256').update(randomHex).digest('hex');
return createHash('sha256').update(srpA).update(N_HEX).digest('hex');
}
Now requests are successfully sending to AWS and getting response:
=========== result: {
ChallengeName: 'PASSWORD_VERIFIER',
ChallengeParameters: {
SALT: '4e9b...',
SECRET_BLOCK: '4x1k...',
SRP_B: '161d...',
USERNAME: 'b1d9...',
USER_ID_FOR_SRP: 'b1d9...'
}
}
But I'm not receiving verification code on my phone.
In the same time with the same user pool and same mobile phone all the flow works fine on mobile app which is connected to Cognito.

Checkout flow: how should I process a new order?

I'm trying to build an App which allows the customer to download a custom document after his order (so, the product I'm selling it's a digital custom document in pdf).
I'm trying to build that using React for the frontend, Node and Express for the backend, and PayPal Express Checkout (full-stack implementation) as payment.
What is not clear to me is what steps I should take to process an order.
I'm a this point:
Once customer clicks on PayPal button on client side it starts a call on http://localhost/api/paypal/orders endpoint which create the order on the Paypal side and return the PayPal order ID (e.g. id12345)
After the customer approves the payment on the PayPal popup, the client starts a call on http://localhost/api/paypal/orders/id12345/capture endpoint
then? What other endpoints should I crete on the server and what they should return? Maybe... 1 for save the actual store order on my MongoDB and the transaction details, 1 for create the invoice for the order, 1 for allowing the product download ???
Could you please clarify what steps I need to take, what are the endpoints I should create, and what each endpoints should return?
Maybe something like this?
You're trying to do too many things in too many routes. just create a route called something like process-order then you could have an async controller of that route which would contain separate functions for
Storing the order details in mongodb.
Create an invoice
Send a token that allows access to download page.
first , just await the function to complete then call the next.
exports.processOrder = async (req, res, next) => {
try {
const newOrder = await Order.create({
order: req.params.id,
details: req.body.details
})
const createInvoice = () => {
return newOrder._id;
}
const invoice = createInvoice();
const token = jwt.sign(
{
invoiceId = newOrder._id,
},
process.env.JWT_SECRET,
{
expiresIn: '24h'
}
);
return res.status(200).json({status: 'success', message: 'you have 24 hours to download your digital goods', token})
} catch (error) {
res.status(500).send(error)
}
}
This is a very basic idea, but basically store all of your info in one controller, then send a token with the id of the invoice, then when they go to download the book you would have a route where you verify the token. If it succeeds then the book is sent. like this:
app.use(
'/book-download',
expressJwt({ secret: process.env.JWT_SECRET, algorithms: ['HS256'] })
);
app.get('/book-download/success', async (req, res) => {
try{
const invoiceId = req.user.invoiceId;
const invoice = await Invoice.find({_id: invoiceId})
if (invoice) {
return res.status(200).json({status: 'success', message: 'congratulations on your new download', data: {E-book})
} else {
return.res.status(404).json({status: 'fail', message: 'could not find an invoice with that ID'})
} catch (error) {
return res.send(error)
}
});
You can choose to send the pdf via express, or you can allow them to enter a certain part of the website if the return is valid. There you go, that's an idea.
In Express check out, you need to define success / cancel handler
Ref here : https://www.section.io/engineering-education/nodejs-paypal-checkout/
In the success handler, based on the returned URI => you will get a Payer ID and payment ID. Based on that retrieve the transactio information (that internally contains yours order ID). Update your Order id as scucess / cancelled based on the paypal response.
app.get('/success', (req, res) => {
const payerId = req.query.PayerID;
const paymentId = req.query.paymentId;
const execute_payment_json = {
"payer_id": payerId,
"transactions": [{
"amount": {
"currency": "USD",
"total": "25.00"
}
}]
};
// Obtains the transaction details from paypal
paypal.payment.execute(paymentId, execute_payment_json, function (error, payment) {
//When error occurs when due to non-existent transaction, throw an error else log the transaction details in the console then send a Success string reposponse to the user.
if (error) {
console.log(error.response);
throw error;
} else {
console.log(JSON.stringify(payment));
res.send('Success');
}
});
});

OAuth2 idToken is verified, but Login Required error persists

So cutting right to the chase...
I'm integrating an Angular front-end with an express back-end.
The login happens using angularx-social-login in the front-end(trying to avoid redirects) and the idToken is sent to the back-end for verification. The scopes are added during the login at the front-end.
After using google-auth-library to verify the token everything is good and correct.
But once a service.people.connections.list() for getting google contacts is called a Login Required error persist. I've tried using the access token I get at the front-end, the payload I get from the verification and all that... I'm sure I'm missing a single step, but I have no clue.
req.headers.authorization here is the idToken.
const client = new OAuth2Client(CLIENT_ID);
async function verify() {
const ticket = await client.verifyIdToken({
idToken: req.headers.authorization,
audience: CLIENT_ID
});
const payload = ticket.getPayload();
console.log(payload);
const userid = payload['sub'];
const service = google.people({ version: 'v1' });
service.people.connections.list({
resourceName: 'people/me',
pageSize: 10,
personFields: 'names,emailAddresses',
}, (err, res) => {
if (err) return console.error('The API returned an error: ' + err);
const connections = res.data.connections;
if (connections) {
console.log('Connections:');
connections.forEach((person) => {
if (person.names && person.names.length > 0) {
console.log(person.names[0].displayName);
} else {
console.log('No display name found for connection.');
}
});
} else {
console.log('No connections found.');
}
});
};

Stripe - Creating Charge

Working on integrating stipe. Everything seems to work on the front end but on the server side code the token is empty and it is not successfully charging to Stripe. Can't seem to figure out where I'm going wrong.
app.post('/apple-pay', function(req, res, next) {
// 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_XXX");
// Token is created using Checkout or Elements!
// Get the payment token ID submitted by the form:
const token = req.body.stripeToken;
console.log(token)
const charge = stripe.charges.create({
amount: 999,
currency: 'usd',
description: 'Example charge',
source: token,
}, function(err, charge) {
if(err){
req.flash("error", err.message);
res.redirect("back");
} else {
}
});
});
Before Creating charge, You should create Customer. After Charge Works.
Sample Code. (ES6)
let customer = await payStripe.customers.create({
email: req.body.stripeEmail,
source: req.body.stripeToken
});
//After Created Customer...
if(customer){
let charge = await payStripe.charges.create({
amount: req.body.amount,
description: req.body.description,
currency: 'usd',
customer: customer.id
});
}
I hope it's work fine.
In your frontend code from the other question you passed the POST body as
JSON.stringify({token: ev.token.id})
which means that the Stripe token is actually in the token POST parameter, not stripeToken. So you need to do
const token = req.body.token;
instead.

Azure BotBuilder - How to get the user information of the OAuth Connection Settings

I've created a Azure Web App Bot and added a OAuth Connection Setting which takes the user to Salesforce. Everything works well, I'm able to authenticate the user through my bot and also, I can get the access token from Salesforce.
Problem
Can someone help me to get the user information from Salesforce? Because, I am able to get the access token alone and not sure, how to get the user id from Salesforce.
I've written the below code,
var salesforce = {};
salesforce.signin = (connector, session, callback) => {
builder.OAuthCard.create(connector,
session,
connectionName,
"Sign in to your Salesforce account",
"Sign in",
(createSignInErr, createSignInRes) => {
if (createSignInErr) {
callback({
status: 'failure',
data: createSignInErr.message
});
return;
}
callback({
status: 'success',
data: createSignInRes
});
});
};
salesforce.getUserToken = (connector, session, callback) => {
connector.getUserToken(session.message.address,
connectionName,
undefined,
(userTokenErr, userTokenResponse) => {
if (userTokenErr) {
callback({
status: 'failure',
data: userTokenErr.message
});
return;
}
callback({
status: 'success',
data: userTokenResponse
});
});
};
salesforce.accessToken = (connector, session, callback) => {
salesforce.getUserToken(connector, session, (userTokenResponse) => {
if (userTokenResponse.status == 'failure') {
// If the user token is failed, then trigger the sign in card to the user.
salesforce.signin(connector, session, (signinResponse) => {
// If the sign in is failed, then let the user know about it.
if (signinResponse.status == 'failure') {
session.send('Something went wrong, ', signinResponse.message);
return;
}
// If the sign in is success then get the user token and send it to the user.
salesforce.getUserToken(connector, session, (newUserTokenResponse) => {
if (newUserTokenResponse.status == 'failure') {
session.send('Something went wrong, ', newUserTokenResponse.message);
return;
}
callback(newUserTokenResponse);
return;
});
});
}
callback(userTokenResponse);
});
};
I can get the userTokenResponse here. But I need Salesforce user id so that I can start interacting with Salesforce behalf of the user.
If you have only OAuth access token you may query details about the user by invoking http GET against:
https://login.salesforce.com/services/oauth2/userinfo for PROD or
https://test.salesforce.com/services/oauth2/userinfo for sandbox
Add only Authorization: Bearer Y0UR0AUTHTOKEN to the header of the http GET request.
Based on my recent test the result returned from the server looks like:
{
"sub": "https://test.salesforce.com/id/[organizationid]/[userId]",
"user_id": "000",
"organization_id": "000",
"preferred_username": "me#mycompany.com",
"nickname": "myNick",
"name": "name lastname",
"urls": {
...
},
"active": true,
"user_type": "STANDARD",
...
}
You don't need a userId to get the user information where an accessToken is enough. I've installed jsforce and used the below code to get the identity information.
Solved by doing,
const jsforce = require('jsforce');
var connection = new jsforce.Connection({
instanceUrl: instanceUrl,
sessionId: accessToken
});
connection.identity((error, response) => {
if(error) {
callback({
status: 'failure',
message: error.message
});
return;
}
callback({
staus: 'success',
data: response
});
});

Resources