In App Purchase Verify Using Cloud Function - android

After Researching for last 24 hour i have found a very effective way to verify in app purchase but didn't get proper Information . I am looking to verify product purchase .
I tried to deploy the js file to firebase cloud function but showing i have error in exports.validatePurchases = functions.database method . Can anyone please have a look on it and fix the error ?
Here is the code :
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {google} = require("googleapis");
const publisher = google.androidpublisher('v2');
const authClient = new google.auth.JWT({
email: '',
key: '',
scopes: ['https://www.googleapis.com/auth/androidpublisher']
});
admin.initializeApp();
exports.validatePurchases = functions.database
.ref('/purchases/{uId}/{orderId}')
.onCreate((event, context) => {
const purchase = event.val();
if (purchase.is_processed === true) {
console.log('Purchase already processed!, exiting');
return null;
}
const orderId = context.params.orderId;
const dbRoot = event.ref.root;
const package_name = purchase.package_name;
const sku = purchase.sku;
const my_token = purchase.token;
authClient.authorize((err, result) => {
if (err) {
console.log(err);
}
publisher.purchases.products.get({
auth: authClient,
packageName: package_name,
productId: sku,
token: my_token
}, (err, response) => {
if (err) {
console.log(err);
}
// Result Status must be equals to 200 so that the purchase is valid
if (response.status === 200) {
return event.ref.child('is_validated').set(true);
} else {
return event.ref.child('is_validated').set(false);
}
});
});
return null;
});
The Error i have got while deploy :
Functions deploy had errors with the following functions:
validatePurchases
To try redeploying those functions, run:
firebase deploy --only functions:validatePurchases
To continue deploying other features (such as database), run:
firebase deploy --except functions
Error: Functions did not deploy properly.
In Firebase Function Log :
Code in file index.js can't be loaded.
Did you list all required modules in the package.json dependencies?
Detailed stack trace: Error: Cannot find module 'googleapis'
at Function.Module._resolveFilename (module.js:548:15)
at Function.Module._load (module.js:475:25)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/srv/index.js:3:18)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)

First, run cmd on Function Folder of your project :
Then, In order to add it as a dependency, run the following command:
$ npm install googleapis
Now Check if any functions are live on your project. If there are functions in the firebase console remove it. Now Try Deploy.

Related

Keep getting error Invalid ID Token with react-native-app-auth

I'm currently trying to authenticate users with google oauth in a react-native app with react-native-app-auth.
This is my code
import * as AppAuth from 'react-native-app-auth';
import { AuthorizationError } from '../errors';
import { GooglePeopleApis } from '#apis';
import { Platform } from 'react-native';
const IOS_CLIENT_ID = "placeholder_client_id"
const ANDROID_CLIENT_ID = "placeholder_client_id"
const IOS_REDIRECT_URI = "placeholder_ios_redirect_url"
const ANDROID_REDIRECT_URI = "placeholder_android_redirect_url"
const config = {
issuer: 'https://accounts.google.com',
clientId: Platform.select({ios: IOS_CLIENT_ID, android: ANDROID_CLIENT_ID})!,
redirectUrl: Platform.select({ios: IOS_REDIRECT_URI, android: ANDROID_REDIRECT_URI})!,
scopes: ['https://mail.google.com/', "profile", "email"]
};
export interface AuthorizationResponse {
accessToken: string;
accessTokenExpirationDate: string;
refreshToken: string;
emailAddress: string;
}
export const authorize = async (): Promise<AuthorizationResponse> => {
try {
let result = await AppAuth.authorize(config);
const emailAddress = await GooglePeopleApis.fetchMyEmailAddress(result.accessToken)
return {
accessToken: result.accessToken,
accessTokenExpirationDate: result.accessTokenExpirationDate,
refreshToken: result.refreshToken,
emailAddress
}
} catch(err) {
const error = err as Error
throw new AuthorizationError(error.message);
}
}
On ios it works fine, on android it worked the first time but then when i came back to the project the day after it started giving me an error like the following
ReactNativeJS: [Error: Invalid ID Token]
I can't understand the problem since i'm not passing any id token in the auth request.
The browser opens as expected, i select my google account but then it returns this error.
react-native: 0.66.3
react-native-app-auth: 6.4.0
Check if the emulator date and time are correct.
I was getting the same error. I went ahead and deleted the emulated device and created a new one, then it worked. Hopefully that helps you.
How to delete emulated device

Connecting to cloud function running on emulator from android emulator in react native

I am building an application and using firebase for the backend. I used react-native-firebase to use firebase in my application. I have developed a login cloud function
exports.login = functions.https.onCall((data, context) => {
console.log("data", data);
console.log("context", context);
return "Login successful";
});
On running npm run serve in the functions folder I am getting these configurations in my console.
Console output after running npm run serve inside functions folder for firebase
Also I have added the following code to connect to the cloud function from my android emulator running the application.
import functions from "#react-native-firebase/functions"
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleLogin = () => {
// console.log(email, password);
functions()
.useFunctionsEmulator("URL")
.httpsCallable("login")({ email, password })
.then((response) => {
alert(response);
});
}
for URL I have tried "http://localhost:5001/" as it is the port on which the functions emulator is listening
Port on which cloud functions is listening. But on running the application I am getting this error
Error on clicking login button in app console. I tried searching for the error but nothing relevant comes up. Any help will be appreciated.
These are my cloud functions that I have defined
exports.helloWorld = functions.https.onRequest((request, response) => {
functions.logger.info("Hello logs!", { structuredData: true });
response.send("Hello from Firebase!");
});
exports.signup = functions.https.onRequest((request, response) => {
console.log("request", request);
response.send("SignUp successfull");
});
exports.login = functions.https.onCall((data, context) => {
console.log("data", data);
console.log("context", context);
return "SignIn successfull";
});
I was able to work it out finally
const handleLogin = async () => {
functions().useFunctionsEmulator("http://localhost:5001")
const response = await functions().httpsCallable("login")({ email, password });
console.log("response", response);
}
This is all the code required to successfully call cloud function locally inside an emulator from your running android emulator.

React Native : Native method ExpoLocalAuthentication.authenticateAsync expects 0 arguments but received 1

I'm in need of your expertise in React Native.
I'm trying to use expo-local-authentication for local fingerprint authentication for my application.
My project was created using expo init command.
I have done the setup as per the documentation and still running into a strange issue:
Below is the error I'm facing for LocalAuthentication.authenticateAsync(options):
Native method ExpoLocalAuthentication.authenticateAsync expects 0
arguments but received 1
Here is the required part of my code:
import * as LocalAuthentication from 'expo-local-authentication';
const authenticate = async () => {
const hasHardwareAsync = await LocalAuthentication.hasHardwareAsync();
if (hasHardwareAsync) {
const supportedAuthentications = await LocalAuthentication.supportedAuthenticationTypesAsync();
if (supportedAuthentications.indexOf(1) !== -1) {
// Finger print supported
const isFingerprintEnrolled = await LocalAuthentication.isEnrolledAsync();
if (isFingerprintEnrolled) {
const options = {
promptMessage: 'Authenticate yourself',
};
try {
// Also tried with await but it throws the same error
// await LocalAuthentication.authenticateAsync(options)
LocalAuthentication.authenticateAsync(options).then(result => {
// I never get inside this block
console.warn(result)
})
.catch(error => {
console.warn('Authentication Error: ', error)
})
} catch (error) {
console.warn(error)
}
}
}
}
}
Not sure what I'm missing. Seems like there is no information available about the error. I also tried to run the LocalAuthentication.authenticateAsync() without any arguments but it still throws the same error.
Any help on what could be the root cause of the issue and how can I resolve it or any other alternative for local authentication would be highly appreciated.
Update your app to the latest version of expo (38 in my case) and to the latest version of expo-local-authentication, and the error goes away.

FeathersJS login error when building for Android

I am building an Android app using Ionic. And using the following feathers_client.js
const feathers = require('#feathersjs/feathers');
const socketio = require('#feathersjs/socketio-client');
const auth = require('#feathersjs/authentication-client');
const io = require('socket.io-client');
const socket = io('http://mydomain.example:3030');
const feathers_client = feathers();
feathers_client
.configure(socketio(socket))
.configure(auth({ storage: window.localStorage }));
module.exports = feathers_client;
When I run the app at the browser it works fine. But when I run it at an Android device I only get "NotAuthenticated".
I am assuming this is happening because FeathersJS stores the JWT token at window.localStorage and this is not available at the Android app userspace.
Two questions:
1) Is there any way to tell FeathersJS to store this token somewhere else?
2) If not, anyone faced this situation and may provide me a solution?
By the way, this is my code for authenticating:
export class SSHSettingsPage implements OnInit {
public inputEmail: string;
public inputPassword: string;
constructor() { }
ngOnInit() {
}
public performLogin($event) {
let authObj: object = { "strategy": "local", "email": this.inputEmail, "password": this.inputPassword};
client.authenticate(authObj)
.then(res => {
console.log(res);
window.localStorage.setItem("user",JSON.stringify(res.user));
window.location.href = "/download";
})
.catch(err => {
console.log(err);
window.location.href = "/login-error";
})
}
}
As mentioned in the configuration API the storage option can be passed an instance of the React Native AsyncStorage:
import {AsyncStorage} from 'react-native';
// Available options are listed in the "Options" section
app.configure(auth({
storage: AsyncStorage
}))

Expo in-app-purchases: ReferenceError: Can't find variable: connectAsync

I'm trying to follow along with expo's in app purchases documentation.. I have the android developer account and set up my in-app-purchase on that account for the same app. I'm just trying to get started with the documentation and receive an error immediately.
If you look at the documentation, I'm just trying to enter in what's in the first example. I call this function at the beginning of the render method of my app.
import * as InAppPurchases from 'expo-in-app-purchases';
...
const getHistory = async function(){
const history = await connectAsync();
if (history.responseCode === IAPResponseCode.OK) {
history.results.forEach(result => {
console.log(result)
});
}
}
And I receive these errors
[Unhandled promise rejection: ReferenceError: Can't find variable: connectAsync]
* App.js:57:19 in getHistory
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:271:30 in invoke
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:135:28 in invoke
- node_modules/regenerator-runtime/runtime.js:170:17 in Promise$argument_0
- node_modules/promise/setimmediate/core.js:45:7 in tryCallTwo
...
You need to import in-app purchases module first. Like this:
import * as InAppPurchases from 'expo-in-app-purchases';
const getHistory = async function(){
const history = await InAppPurchases.connectAsync();
if (history.responseCode === IAPResponseCode.OK) {
history.results.forEach(result => {
console.log(result)
});
}
}
Also, note this from the documentation you linked:
You must ensure that you have installed and configured the react-native-unimodules package before continuing.
and this:
Note that in-app purchases require physical devices to work on both platforms and therefore cannot be tested on simulators.
Since you used:
import * as InAppPurchases from 'expo-in-app-purchases';
That means your code should look like:
...
const getHistory = async function(){
const history = await InAppPurchases.connectAsync();
if (history.responseCode === InAppPurchases.IAPResponseCode.OK) {
history.results.forEach(result => {
console.log(result)
});
}
}

Categories

Resources