How to handle 3D card authentication through Stripe in node - node.js

I'm new to integrate stripe payment. I confused how to integrate 3D secure authentication. In my application on Backend platform using node with Hapi framework. Here is the some of code of paymnet intent which is given below.
let params = {
amount: 100,
currency: "CAD",
payment_method_types: ['card'],
payment_method: "card_1HqytjG6OdQYWdifbWxCrVGB", //cardId
customer: "users5fc1c5ff44d8605030499c00", //userId
}
let intent = await stripe.paymentIntents.create(params {
idempotencyKey: uuidv4());
let paymetConfirm = await stripe.paymentIntents.confirm(intent.id, intend.payment_method);
It's working fine with some of the test cards which not require 3D secure authentication.
4242424242424242
2223003122003222
Not working with these cards require 3D authentication)
4000002760003184
4000002500003155
So, when I check the response of the API (with 3D authentication card) return one of the sub-object is
next_action: {
type: 'use_stripe_sdk',
use_stripe_sdk: {
type: 'three_d_secure_redirect',
stripe_js: 'https://hooks.stripe.com/redirect/authenticate/src_1Hs1zhG6OdQYWdifEWTcyUvC?client_secret=src_client_secret_okgYE1A4eOovEFL9g0sgN29U',
source: 'src_1Hs1zhG6OdQYWdifEWTcyUvC'
}
},
When I take this URL and paste on the browser it redirects the page of 3d Secure, There are two option
complete authentication
fail authentication
Note-
Stripe SDK is set up only on the backend platform(Node)
My question is that
Is there any way not to confirm from the client-side, automatically confirm from the backend platform.
For the scenario, we have to set up a stripe SDK on the client-side(android,IOS).?
when I click on the URL which are inside next_action object which are given above,There are two option inside it,that is complete and failure authentication(3D page view) how to integrate clicking on itmy API hit respectively. how to achieve it?
Please help me.Thanks

Your payments are failing with 3DS enabled cards because you aren't authenticating them on the client. Your current flow of confirming server side won't work with 3DS enabled cards, as you aren't giving the user an opportunity to do the 3DS flow.
It's not really recommended to confirm the payment server-side, as it adds unnecessary round trips to the server without really adding anything. However if you do still want to confirm server side, Stripe has a guide on how to do that here: https://stripe.com/docs/payments/accept-a-payment-synchronously

Related

How to get payment response callback to my backend while using all-in-one sdk on Android

I am trying to setup paytm in my Flutter app, I create the txn token on firebase cloud function in which the callback URL I pass it is paytm's static url, https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=order_id. While the payment flow is working on the client side, I'm not sure how do I get back the response of the payment ON MY BACKEND once the transaction is complete (succeeded or failed)? Do I set up a polling just after I create the transaction token to call the order status API? I tried setting up a webhook in the dashboard > Developer > Webhooks > payment notification, but no requests are made from the paytm servers after the transaction (same goes for refund webhooks).
There is a one plugin available for doing this called paytmkaro you can use this but it's only work with production keys.
Before starting upload the server side code on server which is available on their documentation which is available here please don't make any changes on server side code it's used to generate a txn token on paytm server.
Change the minimum sdk version to 19
and just copy paste this code
` try {
PaytmResponse paymentResponse = await _paytmKaro.startTransaction(
url: serverside code url e.g. https://arcane-temple-61754.herokuapp.com/intiateTansection.php,
mid: your Production merchant id,
mkey: your merchant key,
customerId:customer id (must be unique for every customer),
amount: transection amount,
orderId: Order Id (Order id must be unique Everytime for every order),
);
if(paymentResponse.status=="TXN_SUCCESS"){
Navigator.push(context, MaterialPageRoute(builder: (context)=>txnSuccessful(paytmResponse: paymentResponse,)));
}
else if(paymentResponse.status=="TXN_FAILURE"){
Navigator.push(context, MaterialPageRoute(builder: (context)=>txnFailed(paytmResponse: paymentResponse,)));
}
}
catch(e){
print(e);
key.currentState.showSnackBar(SnackBar(content: Text(e.toString()))); // platformVersion = 'Failed to get platform version.'
}`
and you are done.
Please raise a query to paytm -> Open paytm developer portal than go into the FAQ section and click on send a Query.

(Flutter) Paytm Payment Gateway integration

I am building a flutter app which involves online payment from users of app.
I am planning to use Paytm payment gateway. I was planning to achieve this using WebView. I understand that for this I need to set up a server to generate checksum.
Now what I want to understand is how do I set up the server?
According to this article: https://medium.com/#iqan/flutter-payments-using-paytm-7c48539dfdee
I have to clone this github project: https://github.com/iqans/paytm-checksum-api-nodejs
Where do I upload this node.js project? Can this be uploaded to Firebase?
Or does it have to be uploaded on website hosting platform like hostgator?
Please explain this a bit, I don't now much about servers, I have just started using flutter.
For your convenience, it is more easy for you to implement the payment gateway using webview.
Host the files provided by the payment SDK on your server to calculate the checksum.
Then you can initiate the transaction from your mobile app and calculate the checksum by calling your server side scripts. Then pass those values to the payment SDK.
I think more than webview use of paytm sdk is best option for you because when you start transection its take a data from paytm app which is install in customers mobile.
There is a one plugin available for doing this called paytmkaro you use this but it's only work with production keys.
Before starting upload the server side code on server which is available on their documentation which is available here please don't make any changes on server side code it's used to generate a txn token on paytm server.
Change the minimum sdk version to 19
and just copy paste this code
` try {
PaytmResponse paymentResponse = await _paytmKaro.startTransaction(
url: serverside code url e.g. https://arcane-temple-61754.herokuapp.com/intiateTansection.php,
mid: your Production merchant id,
mkey: your merchant key,
customerId:customer id (must be unique for every customer),
amount: transection amount,
orderId: Order Id (Order id must be unique Everytime for every order),
);
if(paymentResponse.status=="TXN_SUCCESS"){
Navigator.push(context, MaterialPageRoute(builder: (context)=>txnSuccessful(paytmResponse: paymentResponse,)));
}
else if(paymentResponse.status=="TXN_FAILURE"){
Navigator.push(context, MaterialPageRoute(builder: (context)=>txnFailed(paytmResponse: paymentResponse,)));
}
}
catch(e){
print(e);
key.currentState.showSnackBar(SnackBar(content: Text(e.toString()))); // platformVersion = 'Failed to get platform version.'
}`
and you are done.

Secure payment with paypal

I am trying to implement a secure payment option with react-paypal-express-checkout...
but I saw that user can easily change the amount with chrome dev tools ... shouldn't I make the API request to paypal from my server and validate the amount with my DB? I didn't saw any option to do that with paypal...
here is my code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import 'react-credit-cards/es/styles-compiled.css'
import './checkout.css';
import PaypalExpressBtn from 'react-paypal-express-checkout';
class CheckOut extends Component {
constructor(props) {
super(props);
this.state = {
amount: 40
}
}
render() {
const client = {
sandbox: 'XXXX',
production: 'Your-Production-Client-ID',
}
return (
<PaypalExpressBtn client={client} currency={'USD'} total={this.state.amount} />
);
}
}
export default connect(CheckOut);
Paypal allows both types of uses, from the client and from the server. I guess it's possible for the client to modify the request on their end to pay less. But, in the end, whatever your business is, you'll get an order and a payment. Just check if the payment is different than it should be and don't fulfil the order, make a refund.
If you want to save the trouble, then use the server option that makes the payment through your server.
In any case, like with any other payment method, I would recommend you take the time to implement it yourself following the great and well documented API provided by Paypal. They have a lot of examples and use cases, with code for the browser and the server.
Never trust values coming from the client side. You should absolutely validate the amount on the server-side.
As #jorbuedo said, you can create a server integration so the values are never exposed client side. Send a session ID or Order Number or something to your server, retrieve the order from your DB, and perform a redirect to PayPal to process the transaction server-side.
Alternatively, you can keep the client-side stuff you have, but then validate the transaction after it's been complete. You could use Instant Payment Notifications or the newer Webhooks to do this.
You could pass a custom variable into the paymentOptions property of <PaypalExpressButton ...>, and then use this value to validate the correct amount has been paid in IPN.
For example:
<PaypalExpressButton
client={client}
currency="USD"
total={this.state.amount}
paymentOptions={{
custom: this.props.sessionId
}}
/>
Then, as part of IPN, you can pull the Session ID out the DB, check the expected payment amount (which you'll need to store, or calculate based on the items/prices saved against the session ID) is the same as the payment amount Paypal provides (mc_gross for example). A full list of variables you get as part of IPN is available here.
There are no fees for using IPN. If you didn't want to build out this flow, then you'd have to manually validate every order that's made to ensure the amount is correct. If you're running something small, this might be an acceptable compromise.
Edit: Don't just send the expected amount as the Custom variable, and compare that to the mc_gross value, as this can also be changed using F12 or a browser extension. The value needs to be something opaque that you can translate server-side into something meaningful.
#jorbuedo and #Dave Salomon give great answers about Security and you should take them in to consideration.
However, If you really don't want to user to change your Component state and props, You can disable React Devtools with this hack.
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.emit = function() {};
}
Basically it mocks some methods of react-devtools and Devtool cannot find your component tree anyway.
This answer is only for disabling user to edit your components. This is not best solution for security)

How to use Firebase Auth's Google Sign-In option with Cypress.io

I need help using Google Sign-In when testing my Angular 6 app with Cypress. It can't use the sign-in popup, and so I'm trying to follow Cypress' advice to "always use cy.request() to talk to 3rd party servers via their APIs." That's from https://docs.cypress.io/guides/references/best-practices.html#Visiting-external-sites which then points us to this example: https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/logging-in__single-sign-on/cypress/integration/logging-in-single-sign-on-spec.js - more info on how to do this is seen at minute 23 in a presentation by the Cypress author: https://www.youtube.com/watch?v=5XQOK0v_YRE
I'm taking the video solution and trying to modify it for Firebase Auth according to https://firebase.google.com/docs/auth/web/google-signin#advanced-authenticate-with-firebase-in-nodejs but I'm getting stuck on how to obtain the proper id_token and so far I have this code in my commands.js file:
Cypress.Commands.add('login', () => {
var id_token = ___?____;
cy.request({
method: 'POST',
url: 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyAssertion?key=[API_KEY]',
body: {
"requestUri": "http://localhost:3500",
"postBody": `id_token=${id_token}&providerId=google.com`,
"returnSecureToken": true,
"returnIdpCredential": true
}
})
})
I believe I need to use a different API to initiate the login and request user credentials, which will include the id_token, and so I tried https://firebase.google.com/docs/auth/web/google-signin#advanced-authenticate-with-firebase-in-nodejs but am not yet skilled enough to pull in external js files (https://apis.google.com/js/platform.js) into Node (This is probably not possible in js files the way it is in html). Using this package: https://github.com/google/google-auth-library-nodejs may be my next attempt. Is there anyone who can pick it up from here?
Similar question at Is it possible to use Cypress e2e testing with a firebase auth project? - but they are signing in with user and pass.

Can A Mobile Application use TrueVault to store JSON data without a "middleman" server?

I have been reading the documentation at https://docs.truevault.com/ but I am a little confused. I read this on the true vault site:
If you plan on using any of the server-side libraries, please ensure
any hosting environment you use is HIPAA compliant.
I took this to mean that TrueValut could support a standalone (client side only) mobile application architecture. Where the TrueVault API was the only server side interaction.
However my understanding of the documentation is that:
An API_KEY is required to register a new user.
Any API_KEY provides full access to all data vaults and JSON documents stored in TrueVault.
If both of these assumptions are correct that would mean it would be impossible to register new users directly from the client side app, forcing me to use a costly and resource intensive HIPPA compliment web server. The only way to get around this would be top hard code the API_KEY into the app, an obvious no go if that API_KEY can access all of my TrueVault data.
For my use case I have the following requirements for TrueVault for me to be able to consider using it (I would imagine these requirements are the same for anyone looking to develop a client side only healthcare application):
A user can sign up via the API directly from my client side app without requiring any sensitive keys or root auth data.
A user can authenticate using only the data they provided to sign up (username/email/password). My app is multi platform I cant ask them to remember their API keys to log in.
A user can Read/Write/Update/Delete data linked to their profile. They can not access any data from another user using their credentials.
Is TrueVault able to deliver these three basic requirements?
If the answer to this is "No" I would recommend you update this text on your website as there are not going to me any viable HIPPA compliment applications that can be supported by TrueVault without an independent server side interface.
I'm currently using AWS Lambda as a solution. Lambda is HIPPA compliant, more info here. Lambda is also a low cost solution.
Here is an example of the code I'm running on Lambda using Node.js.
var request = require('request-promise');
var _ = require('lodash');
function encodeBase64(str) {
return (new Buffer(str)).toString('base64');
}
var baseUrl = 'https://api.truevault.com/v1/';
var headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
};
var req = request.defaults({
baseUrl: baseUrl,
headers: _.extend({
Authorization: 'Basic ' + encodeBase64('your api key:')
}, headers),
transform: function(body) {
return JSON.parse(body);
}
});
exports.handler = function(event, context) {
req.post('users', {
form: {
username: event.email,
password: event.password,
attributes: encodeBase64(JSON.stringify({
name: event.name
}))
}
}).then(function() {
context.succeed({user: user});
}).catch(context.fail);
}
In general, you are correct - if you include zero server-side processing between user and TrueVault, then the API keys will be public. At least, I don't know of any way to avoid this.
That being said, it is incorrect to jump to "any API_KEY provides full access to all data vaults and JSON documents stored in TrueVault." - that's not the case if setup properly.
TrueVault API keys are able to be narrowed in scope quite a lot. Limiting a key to only Write permission on {Vault#1}, a second key to only Read permission on {Vault#2}, a third key to allow uploading Blogs in {Vault#1&#3}, quite a few variations, a forth for deleting information from {Vault#2}, and on as needed. You can also limit permissions specifically to content "owned" by the API key (e.g. user-specific keys) Full documentation here.
There are also limited scope keys (set expiry time, usage count, limit to any of the prior permission scopes). Docs here.
TrueVault also offers user logins separate from API keys which may be better suited if your user are using login credentials. Docs here.
I'm still rather figuring out TrueVault myself (at time of writing at least) so be sure to research and review more for your needs. I'm still torn if the limited scoping is "good enough" for my needs - I'm leaning towards using AWS Lambda (or similar) to be a HIPAA compliant middle man, if only to better hide my access token generation and hide that my data is going to TrueVault and add some "serverless-server-side" data validation of sorts.

Resources