Client app calling Stripe API after card form exit, for future payment - react-native

I am adding Stripe 3D secure to a React-Native app, following the document at https://stripe.com/docs/payments/save-and-reuse
-- save the card, and charge off-session later when the service is completed.
For saving card, my app uses a WebView component to load a HTML, using <script src="https://js.stripe.com/v3/"></script> .
It successfully saved the client secret and exited the card form.
Question: At payment time later, in case next action for strong customer authentication is required, how to get a stripe object again so as to call stripe.confirmCardPayment()?
I tried below but failed -- catch(error), and error is empty.
import {loadStripe} from '#stripe/stripe-js';
confirmPayment = async () => {
try {
const stripe = await loadStripe("pk_test_...");
// stripe
// .confirmPaymentIntent('{PAYMENT_INTENT_CLIENT_SECRET}', {
// payment_method: '{PAYMENT_METHOD_ID}',
// return_url: 'https://example.com/return_url',
// })
// .then(function(result) {
//
// });
} catch(error) {
console.error(`failed to load stripe ${JSON.stringify(error)}`);
}

You can use stripe.confirmCardPayment in a variety of ways. In your case you probably already have a PaymentMethod ID, meaning you can confirm the PaymentIntent client side with that PaymentMethod ID instead of an Elements object:
stripe
.confirmCardPayment('{PAYMENT_INTENT_CLIENT_SECRET}', {
payment_method: '{PAYMENT_METHOD_ID}',
})
.then(function(result) {
// Handle result.error or result.paymentIntent
});

Related

How do I know which network currently connected in MetaMask by WalletConnet react native?

I am developing react native mobile application where user can connect their crypto wallet(MetaMask, Rainbow, etc.) to mobile application. Everything is working well. I have used this (#walletconnect/react-native-dapp) react-native package to achieve this requirement.
After connected the external wallet (MetaMask), later I have to do some transaction by my app.
To do transaction I have to get know which network currently set in MetaMask wallet.
Is there any way to know the current connected network(chainId)to Metamask by this react-native package.
To do the transaction I am using this code.
try {
let dataa = await contract.methods
.transfer(toAddress, value.toString())
.encodeABI();
let txObj = {
// gas: Web3js.utils.toHex(100000),
data: Web3js.utils.toHex(dataa),
from: userWallet,
to: POZ_TOKEN, // Contractor token address
};
try {
const transactionHash = await connector
.sendTransaction(txObj)
.catch((_err: any) => {
Toast.show({
autoHide: true,
text1: t('topUpPoz.transactionFailed'),
type: 'error',
});
});
console.log('transactionHash is =', transactionHash);
Please suggest me anyone.
With #walletconnect/react-native-dapp we can fetch chain ID using connector, sample code is given below.
Note: checkNetworkIdHandler is a custom user defined function to check chainId connected is valid or not.
import {useWalletConnect} from '#walletconnect/react-native-dapp';
//creating a wallet connect connector
const connector = useWalletConnect();
const connectExternalWallet = React.useCallback(() => {
return connector.connect();
}, [connector]);
//below code snippet to be called on wallet connect button click
async function connectWallet(){
try {
let connection = await connectExternalWallet();
let networkStatus = checkNetworkIdHandler(connection.chainId);
}catch (exception) {
console.log("Exception occurred while connecting to metamask");
}
}

Save payment for later option, Stripe, React Native, Expo

I'm trying to setup a way to setup a payment for later with a prebuilt Stripe component in a React Native Expo Project.
I'm following along with this project: https://snack.expo.dev/#charliecruzan/stripe-react-native-example?platform=mydevice
If you go to PaymentsUICustomScreen.tsx, you can see that there is an option to save payments for later when the option is rendered on the screen.
When I implement the same code, I do not get that same option.
I'm using the useStripe function.
This is the flow:
import { useStripe } from '#stripe/stripe-react-native'
...
const { initPaymentSheet, presentPaymentSheet } = useStripe();
...
await initPaymentSheet({
customerId: 'customerID',
// customerEphemeralKeySecret: ephemeralKey,
paymentIntentClientSecret: clientSecret,
customFlow: false,
merchantDisplayName: 'Example Inc.',
applePay: true,
merchantCountryCode: 'US',
style: 'alwaysDark',
googlePay: true,
testEnv: true,
});
My question is, why do I not get the save payment methods for later option?
You should use the ephemeralKeys in your Frontend and as well as in your backend so that after successful payment of the user, the payment details such as card details will be saved securely in stripe.
You need to put clientSecret inside the function presentPaymentSheet as an object property, like this:
const openPaymentSheet = async () => {
if (!clientSecret) {
return;
}
setLoadng(true);
const { error } = await presentPaymentSheet({
clientSecret,
});
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message);
} else {
Alert.alert('Success', 'The payment was confirmed successfully');
}
setPaymentSheetEnabled(false);
setLoadng(false);
};
Here, clientSecret is also a paymentIntent. For details, check how it was used in your example project.

Hot can I use the return of localforage

In my Vue SPA, I use localforage to store the Bearer token.
In a component, i need the token to upload files to the api.
I tried to get the localforage token:
let token = localforage.getItem('authtoken')
console.log(token)
It works but the result is a promise object:
Promise
result: "eyJ0eXAiOiJKV1QiyuIiwiaWF0IjoxNTg4MTUzMTkzLCJleHAiOjE1ODg…"
status: "resolved"
When i try to console.log(token.result) it returns null
How can i access the token?
The official documentation states three different approaches to reading values from the storage.
localforage.getItem('authtoken').then(function(value) {
// This code runs once the value has been loaded
// from the offline store.
console.log(value);
}).catch(function(err) {
// This code runs if there were any errors
console.log(err);
});
// Callback version:
localforage.getItem('authtoken', function(err, value) {
// Run this code once the value has been
// loaded from the offline store.
console.log(value);
});
// async/await
try {
const value = await localforage.getItem('authtoken');
// This code runs once the value has been loaded
// from the offline store.
console.log(value);
} catch (err) {
// This code runs if there were any errors.
console.log(err);
}

Google plus API shutdown, How it will affect Google auth2 login for web sites?

I am confused with shutdown notification mails from Google one of the recent mail mentioned as
projects directly requesting the “plus.me” scope are affected. This scope may have been listed in some emails, even if not directly
requested by your project. We apologize for any confusion caused.
I am using following JS code for login, may I know will it affect anyway due to Google plus api shutdown?
<script async defer src="https://apis.google.com/js/api.js" onload="this.onload=function(){};HandleGoogleApiLibrary()" onreadystatechange="if (this.readyState === 'complete') this.onload()"></script>
<script type="text/javascript">
//google login starts
function HandleGoogleApiLibrary() {
// Load "client" & "auth2" libraries
gapi.load('client:auth2', {
callback: function() {
// Initialize client library
// clientId & scope is provided => automatically initializes auth2 library
gapi.client.init({
apiKey: 'API KEY HERE',
clientId: 'XXXXXXXXXXXXXXXXX.apps.googleusercontent.com',
scope: 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'
}).then(
// On success
function(success) {
// After library is successfully loaded then enable the login button
//CODE AFTER SUCCESS
},
// On error
function(error) {
alert('Error : Failed to Load Library');
}
);
},
onerror: function() {
// Failed to load libraries
}
});
}
// Click on login button
$("#login-button").on('click', function() {
// API call for Google login
gapi.auth2.getAuthInstance().signIn().then(
// On success
function(success) {
// API call to get user information
gapi.client.request({ path: 'https://www.googleapis.com/plus/v1/people/me' }).then(
// On success
function(success) {
console.log(success);
var user_info = JSON.parse(success.body);
//VALIDATION
},
// On error
function(error) {
alert('Error : Failed to login');
}
);
},
// On error
function(error) {
$("#login-button").removeAttr('disabled');
alert('Error : Login Failed');
}
);
});
There is good news and bad news.
The good news is that you're not using any of the plus scopes.
The bad news is that you're using the plus API, which is also being shut down, and which was mentioned in a previous email that should have been sent to you.
Specifically, this chunk of code:
gapi.client.request({ path: 'https://www.googleapis.com/plus/v1/people/me' }).then(
calls the "plus.people.me" API.
Fortunately, you should be able to switch to a different API, such as the "userinfo" API, by changing endpoints to
https://www.googleapis.com/oauth2/v2/userinfo
You may also wish to look into the more modern People API, which works very similarly, and is slightly more complicated, but can provide other profile fields.

Dispatch action on Auth0's lock.on('authenticated') event

I want to implement the new Auth0 Lock 10 in my React/Redux app.
I've checked on the internet, but nothing matches my question. There's a tutorial here, but it uses the Popup mode instead of the Redirect (default now) mode. Another one parses the url, which is useless in Lock 10.
Here's the flow:
The Auth0Lock gets instantiated when my app starts
When the user clicks on the login button, it shows the Lock widget (lock.show()) and dispatches LOGIN_REQUEST
The lock does its authentication on auth0.com (redirects out of my localhost)
Redirect back to my localhost after successful login, the Auth0Lock get instantiated again
I wait for an lock.on('authenticated') event to dispatch LOGIN_SUCCESS
And here is my actions/index.js code:
import Auth0Lock from 'auth0-lock'
export const LOGIN_REQUEST = 'LOGIN_REQUEST'
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS'
export const LOGIN_ERROR = 'LOGIN_ERROR'
function loginRequest() {
return {
type: LOGIN_REQUEST
}
}
function loginSuccess(profile) {
return {
type: LOGIN_SUCCESS,
profile
}
}
function loginError(error) {
return {
type: LOGIN_ERROR,
error
}
}
// import AuthService to deal with all the actions related to auth
const lock = new Auth0Lock('secret', 'secret', {
auth: {
redirectUrl: 'http://localhost:3000/callback',
responseType: 'token'
}
})
lock.on('authenticated', authResult => {
console.log('Im authenticated')
return dispatch => {
return dispatch(loginSuccess({}))
}
})
lock.on('authorization_error', error => {
return dispatch => dispatch(loginError(error))
})
export function login() {
lock.show()
return dispatch => {return dispatch(loginRequest())}
}
Now when I click on the login button, redux logger shows me LOGIN_REQUEST action dispatched, I see the lock widget, I can login, it redirects to auth0.com then back to my localhost:3000/callback with a pretty token. Everything is fine, I see the Im authenticated message in my console, but redux logger doesn't show me that the LOGIN_SUCCESS action has been dispatched.
I'm new to Redux, and I guess I'm missing one thing, but I cannot get grab of it. Thanks!
I finally put in inside actions.js, I created a new function called checkLogin()
// actions.js
const authService = new AuthService(process.env.AUTH0_CLIENT_ID, process.env.AUTH0_DOMAIN)
// Listen to authenticated event from AuthService and get the profile of the user
// Done on every page startup
export function checkLogin() {
return (dispatch) => {
// Add callback for lock's `authenticated` event
authService.lock.on('authenticated', (authResult) => {
authService.lock.getProfile(authResult.idToken, (error, profile) => {
if (error)
return dispatch(loginError(error))
AuthService.setToken(authResult.idToken) // static method
AuthService.setProfile(profile) // static method
return dispatch(loginSuccess(profile))
})
})
// Add callback for lock's `authorization_error` event
authService.lock.on('authorization_error', (error) => dispatch(loginError(error)))
}
}
And in the constructor of my App component, I call it
import React from 'react'
import HeaderContainer from '../../containers/HeaderContainer'
class App extends React.Component {
constructor(props) {
super(props)
this.props.checkLogin() // check is Auth0 lock is authenticating after login callback
}
render() {
return(
<div>
<HeaderContainer />
{this.props.children}
</div>
)
}
}
App.propTypes = {
children: React.PropTypes.element.isRequired,
checkLogin: React.PropTypes.func.isRequired
}
export default App
See here for full source code: https://github.com/amaurymartiny/react-redux-auth0-kit
My Reactjs knowledge is limited, but this was starting to be to long for a comment...
Should you not be calling store.dispatch(...) from the lock events?
Having those events return a function won't do anything unless someone invokes the function that is returned and to my knowledge Lock does not do anything with the return value of the callback function you pass as an event handler.
I think what's happening is auth0 redirects the browser window to the login authority (auth0 itself, Facebook, Google, etc.) then redirects you back to your app, which reloads your page, essentially wiping out all state. So your dispatch is sent, then the page reloads, which wipes out your state. Logging in appears to work if you use localStorage instead of redux state, but I'm not sure how that's going to affect all the other state I will need to put in my app.