I want to integrate Stripe 3d secure in my react native app. Using this lib: https://github.com/tipsi/tipsi-stripe, and with simple payment it works well. But with 3D I have several problem on iOS and also on Android:
iOS: createCardSource: true (at line 7 crashing the app).(Solved)
iOS: Stucked before redirection on the secure page
Android: How I know if the user paid or decline the payment at the remote page?(At line 27 no any data in the secure3dSourceResponse object)
import stripe from "tipsi-stripe";
paymentRequest = async (mutation, deal) => {
let paymentRequest;
try {
paymentRequest = await stripe.paymentRequestWithCardForm({
...options,
createCardSource: true
});
//iOS and Android gets back different objects.
const threeDSecure = Platform.OS === "android"
? paymentRequest.card.three_d_secure
: paymentRequest.details.three_d_secure;
if (
threeDSecure === "recommended"
|| threeDSecure === "required"
) {
let prefix = Platform.OS === "android"
? `appName://appName/`
: `appName://`;
let secure3dSourceResponse = null;
try {
const { dealFeeUSD } = this.state;
// On iOS the process stucked here, without any error message
secure3dSourceResponse = await stripe.createSourceWithParams({
type: "threeDSecure",
amount: dealFeeUSD || 3000,
currency: "USD",
flow: "redirect",
returnURL: prefix,
card: paymentRequest.sourceId
});
// On android I have no any data in secure3dSourceResponse after Stripe returns from their page.
} catch (error) {
console.log('secure3dSourceResponse', secure3dSourceResponse)
}
} else {
if (paymentRequest && paymentRequest.tokenId) {
this.handlePayDeal(mutation, deal, paymentRequest.tokenId);
}
}
} catch (error) {
console.log("paymentRequest: " + JSON.stringify(error));
}
};
Related
I am implementing RevenueCat first time in my react native. I have one non-renewable subscription available on App Store. and now I want to buy that subscription by revenueCat sdk.
The payment is successfully happening at my and but I have to validate receipt again at my backend so I need the payment receipt.
How can I get the payment receipt while doing the payment from the revenueCat.
Here is code which I am following to do the payment by revenueCat.
if (!subscriptionModule) {
if (constant.isIOS) {
Purchases.setDebugLogsEnabled(true);
Purchases.setup('appl_TTTTTTTTTTTTTTT');
console.log('sdk initialized');
}
}
}
async getOffer() {
try {
const doubleJoinProduct = await Purchases.getOfferings();
if (
doubleJoinProduct.current !== null &&
doubleJoinProduct.current.availablePackages.length !== 0
) {
console.log('the offer list is = ', doubleJoinProduct);
if (
doubleJoinProduct.all['com.pozzleplanet.test.doubleJoinMonth']
.availablePackages.length !== 0
) {
let inapp_package =
doubleJoinProduct.all['com.pozzleplanet.test.doubleJoinMonth']
.availablePackages[0];
console.log('The available package is = ', inapp_package);
this.purchaseProduct(inapp_package);
}
}
} catch (e) {
console.log('Error while getting offer', e);
}
}
async purchaseProduct(inapp_package: any) {
console.log('package purchasing....', inapp_package);
try {
const purchaseMade = await Purchases.purchasePackage(inapp_package);
console.log('before purchase info is = ', JSON.stringify(purchaseMade));
if (
typeof purchaseMade.purchaserInfo.entitlements.active[
'com.pozzleplanet.test.doubleJoinMonth'
] !== 'undefined'
) {
console.log('purchase info is = ', JSON.stringify(purchaseMade));
}
} catch (e) {
console.log('the purchase error is ', e);
}
}
}
Can some please suggest me to get payment receipt
I hope you are doing well.
I have a problem when I connect with google on the emulator with android.
If I go through Expo Go on either Android or Ios, it works fine. But when I build my apk, and I install it on the emulator it sends me back to the same login page without redirecting me to the application.
Do you have an idea of the origin of the problem?
My google login function :
try {
const result = await promptAsync();
if (result.type === "success") {
/* `accessToken` is now valid and can be used to get data from the Google API with HTTP requests */
const { id_token } = result.params;
const provider = new firebase.auth.GoogleAuthProvider();
const credential =
firebase.auth.GoogleAuthProvider.credential(id_token);
auth.signInWithCredential(credential)
.then((res) => {
const user = res.additionalUserInfo.profile;
let action = addUserOnFirestore(
res.user?.uid,
user.email,
user.given_name,
user.family_name,
user.picture,
res
);
setIsLoading(true);
try {
dispatch(action);
} catch (err) {
setError(err.message);
}
setIsLoading(false);
})
.catch((error) => {
console.log("firebase cred err:", error);
});
} else {
console.log("cancelled");
}
} catch (e) {
console.log("general error : ", e);
return { error: true };
}
}
And the properties define :
const [request, response, promptAsync] = Google.useIdTokenAuthRequest({
clientId: "XXXX",
iosClientId: "XXX",
androidClientId: "XXX",
androidStandaloneAppClientId: "XXX",
redirectUri: Platform.select({
// iOS handles redirectUri perfectly fine on it's own
ios: undefined,
// Due to Expo's bug, we need to manually encode the redirectUri
// https://github.com/expo/expo/issues/12044
android: makeRedirectUri({
// intent filter set up in app.config.js
// must be the same as "package name" in Google Cloud Console
native: 'packagename://oauthredirect',
}),
})
});
Thanks in advance for your responses.
I got this problem when i expo publish my react native app with or without --release-channel dev flag.
I set up a config file environment.js to get different release version like this :
import Constants from "expo-constants";
import { Platform } from "react-native";
const localhost = Platform.OS === "ios" ? "localhost:8080" : "10.0.2.2:8080";
const ENV = {
localhost: {
//apiUrl: localhost,
apiUrl: "http:xxxx",
},
dev: {
apiUrl: "http:xxxx",
},
staging: {
apiUrl: "http:xxxx",
// Add other keys you want here
},
prod: {
apiUrl: "http:xxxx",
// Add other keys you want here
},
};
const getEnvVars = (env = Constants.manifest.releaseChannel) => {
// What is __DEV__ ?
// This variable is set to true when react-native is running in Dev mode.
// __DEV__ is true when run locally, but false when published.
if (__DEV__ || env === undefined || env === null || env === "") {
return ENV.localhost;
} else if (env.indexOf("dev") !== -1) {
return ENV.dev;
} else if (env.indexOf("staging") !== -1) {
return ENV.staging;
} else if (env.indexOf("prod") !== -1) {
return ENV.prod;
}
};
export default getEnvVars;
I intercept the config with creation of new intance of axios like this :
import axios from "axios";
import { getKey } from "./deviceStorage";
import getEnvVars from "../../environment";
const { apiUrl } = getEnvVars();
const instance = axios.create({
// .. where we make our configurations
baseURL: apiUrl,
});
instance.interceptors.request.use((config) => {
const token = getKey("id_token");
token.then((value) => {
config.headers.Authorization = value ? `Bearer ${value}` : "";
});
return config;
});
export default instance;
when i emulate on my device everything work fine but when i expo publish and scan QR code with my device the app crash after splash screen and i got this error say :
So if i understand well the Constants.manifest.releaseChannel is undefined, any idea why this happen ? do i miss somthing on the import ?
When i put the Api URL directly on my axios interceptors everything work fine.
import axios from "axios";
import { getKey } from "./deviceStorage";
//import getEnvVars from "../../environment";
//const { apiUrl } = getEnvVars();
const instance = axios.create({
// .. where we make our configurations
baseURL: "http://xxxx",
});
instance.interceptors.request.use((config) => {
const token = getKey("id_token");
token.then((value) => {
config.headers.Authorization = value ? `Bearer ${value}` : "";
});
return config;
});
export default instance;
export const ApiUrls = {
authPatient: "/xxx",
authPractician: "/xxx",
};
Thanks for help.
I find my problem here and maybe will help anyone on the future so :
i delete the env parameter on the getEnvVars and i declared inside the function and everything work fine :
const getEnvVars = () => {
const env = Constants.manifest.releaseChannel;
if (!__DEV__ && env) {
switch (env) {
case env.indexOf("dev") !== -1:
return ENV.dev;
case env.indexOf("staging") !== -1:
return ENV.staging;
case env.indexOf("prod") !== -1:
return ENV.prod;
default:
return ENV.localhost;
}
}
return ENV.localhost;
};
Moving the declaration of env into the function didn't work for me so I cut out the function altogether and that fixed my issue up. Going to have to figure out a way to rewrite it. But thank you for posting this anyways
I am building an app that is using Google authentication through firebase and that needs to redirect the user from a login.vue component to an /hello path upon successful authentication.
I have first tried doing it the normal vue way:
this.$router.replace('/hello')
only to realise my Samsung Galaxy J5 wasn't having it...
All is working on other devices and browsers (so far) using the normal Vue routing tools but on some Android devices Vue is refusing to collaborate. I have read here some Android versions do not like the way the Vue dynamic routing transpiles to vanilla JS so I am attempting the following (still, no success).
This is my code on the created hook of component login.vue when Google auth (with redirection, not pop up) returns to it:
created() {
firebase.auth().getRedirectResult().then(result => {
var user = result.user;
if (user) {
var ua = navigator.userAgent.toLowerCase();
var isAndroid = ua.indexOf("android") > -1;
if(isAndroid) { // NOT WORKING (stays on Login.vue although I am sure it's detecting it's an Android)
window.location.href = window.location.host + '/hello';
} else {
this.$router.replace('/hello') // this work perfectly
console.log(window.location.host + "/hello" ); // this is returning the intended address: localhost:8080/hello
}
} else {
toastr.warning("Oops something went wrong on login!");
}
}).catch(error => {
// dealing with redirection result errors from Google Authentication
});
This is my index.js routing file (I am doing some route guarding here so it may be useful for you to get a bigger picture if I paste the file):
import Vue from 'vue'
import Router from 'vue-router'
import firebase from '../firebase-config'
import {store} from '#/store/store'
import hello from '#/components/hello'
import login from '#/components/login'
import landing from '#/components/landing'
Vue.use(Router)
let router = new Router({
mode: 'history',
routes: [
{
path: '*',
redirect: '/landing'
},
{
path: '/',
redirect: '/landing'
},
{
path: '/landing',
name: 'landing',
component: landing
},
{
path: '/login',
name: 'login',
component: login
},
{
path: '/hello',
name: 'hello',
component: hello,
meta: {
requiresAuth: true
}
},
],
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
firebase.auth().onAuthStateChanged(function(user) {
if (!user) {
next({
path: '/landing'
})
} else {
next()
}
});
} else {
next()
}
})
export default router
Any thoughts?
I have used cordova- 2.5.0 & facebook-sdk 3.0.2 in fb plugin.It works fine when device does not have native app installed. when native app is installed nothing is happened.means it cant get current access token of user.Any idea? According to me there are two ways:
1) disable to get access native app just like in ios. But its not right way as if user is allready login in native then he has to login again in my plugin setup.
2)dont know how to solve this issue.There is no issue with hash key as it is right and works well in ios using my first way.
So my question is that how to prevent to accessing native app? OR Is there any other way to solve this issue?
As i dont get anything. when i am going to get user's friend list it shows An active access token must be used to query information about the current user.,"type":"OAuthException","code":2500.
cdv-pluggin-fb-connect.js
CDV = ( typeof CDV == 'undefined' ? {} : CDV );
var cordova = window.cordova || window.Cordova;
CDV.FB = {
init: function(apiKey, fail) {
// create the fb-root element if it doesn't exist
if (!document.getElementById('fb-root')) {
var elem = document.createElement('div');
elem.id = 'fb-root';
document.body.appendChild(elem);
}
cordova.exec(function() {
var authResponse = JSON.parse(localStorage.getItem('cdv_fb_session') || '{"expiresIn":0}');
if (authResponse && authResponse.expirationTime) {
var nowTime = (new Date()).getTime();
if (authResponse.expirationTime > nowTime) {
// Update expires in information
updatedExpiresIn = Math.floor((authResponse.expirationTime - nowTime) / 1000);
authResponse.expiresIn = updatedExpiresIn;
localStorage.setItem('cdv_fb_session', JSON.stringify(authResponse));
FB.Auth.setAuthResponse(authResponse, 'connected');
}
}
console.log('Cordova Facebook Connect plugin initialized successfully.');
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'init', [apiKey]);
},
login: function(params, cb, fail) {
params = params || { scope: '' };
cordova.exec(function(e) { // login
if (e.authResponse && e.authResponse.expiresIn) {
var expirationTime = e.authResponse.expiresIn === 0
? 0
: (new Date()).getTime() + e.authResponse.expiresIn * 1000;
e.authResponse.expirationTime = expirationTime;
}
localStorage.setItem('cdv_fb_session', JSON.stringify(e.authResponse));
FB.Auth.setAuthResponse(e.authResponse, 'connected');
if (cb) cb(e);
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'login', params.scope.split(',') );
},
logout: function(cb, fail) {
cordova.exec(function(e) {
localStorage.removeItem('cdv_fb_session');
FB.Auth.setAuthResponse(null, 'notConnected');
if (cb) cb(e);
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'logout', []);
},
getLoginStatus: function(cb, fail) {
cordova.exec(function(e) {
if (cb) cb(e);
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'getLoginStatus', []);
},
dialog: function(params, cb, fail) {
cordova.exec(function(e) { // login
if (cb) cb(e);
}, (fail?fail:null), 'org.apache.cordova.facebook.Connect', 'showDialog', [params] );
}
};
Thanks in Advance!!
I was able to get it working with this plugin: https://github.com/jimzim/phonegap-facebook-android-sample