So I am trying to redirect my react-native application from a stripe checkout page back to the application.
app.post('/create-checkout-session', async (req, res) => {
const prices = await stripe.prices.list({
lookup_keys: [req.body.lookup_key],
expand: ['data.product'],
});
const session = await stripe.checkout.sessions.create({
billing_address_collection: 'auto',
line_items: [
{
price: prices.data[0].id,
// For metered billing, do not pass quantity
quantity: 1,
},
],
mode: 'subscription',
success_url: `${YOUR_DOMAIN}/?success=true&session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${YOUR_DOMAIN}?canceled=true`,
});
res.redirect(303, session.url);
});
using the success URL but it won't redirect back into the application.
I'm currently using React Navigation, Deep Linking in the App.js file.
const linking = {
prefixes: [ Linking.createURL("hometrack://")],
config:{
screens:{
EmployeeSignUp:{
path:"EmployeeSignUp/:id",
parse: {
id: (id) => `${id}`,
},
},
Success:{
path:"Success"
}
}
}
};
I can't seem to make it link back into the application.
Deep link with custom URL scheme (myapp://screen..) does not work in this case. Stripe expects a valid URL that redirects to a real website. I am currently facing the same problem, and my workaround is:
Redirect the user to my website (e.g. myapp.com/redirect).
Display the "Redirect back to app" button on the website.
Deep link back to the app
I'll update my answer if I will find another solution.
Related
I'm using the following code to send a notification from one device to another using FCM. Everything works fine until before return admin.messaging().sendToDevice(...). The 'Token ID: ' log displays token ID of the receiver, but when I set the variable token_id to the sendToDevice function, the notification is not called, therefore the notification is not sent. Can someone tell me what's wrong?
var firebase = require("firebase-admin");
var serviceAccount = require("./julla-tutorial.json");
console.log("enter in then Firebase Api");
const firebaseToken = [
'e0T6j1AiRjaa7IXweJniJq:APA91bHNznSHSIey08s-C-c3gchci6wepvhP1QxQyYbmZ8LySI3wnu64iW7Q23GhA6VCdc4yodZoCFOgynfAb5C8O8VE81OcSv_LL-K3ET1IKGZ_6h35n-_q5EKFtfJWlzOqZr4IvpiB',
'dNWnSqyCQbufzv1JutNEWr:APA91bFcI9FDyRxHRBEcdw4791X0e-V0k1FjXcSstUA67l94hSojMRCd6LWr2b57azNEt3z_XLwLljMX4u2mc9cZDrAVm55Mw9CHGyue-09KofWnnHNR9XWBibc4T76xOV_DWX7T2RvW',
'cq65rtuaTCKGk5lHk7UabN:APA91bFR3kAArg6lhuBq7ktNuBk7Z9MXXk3PskqhYa8CgNaEl6MX4TQ5lo35d6XhnCQ4fEkCkyZ_j08evxE9Y4oVCRTEdqsrkccCVTE8Di47lfmDR3i1NdoL3re9oLw6F_uNsnvRoQcq'
]
firebase.initializeApp({
credential: firebase.credential.cert(serviceAccount)
})
const payload = {
notification: {
title: 'Demo 2345',
body: 'dfghj',
sound: 'default',
color: 'yellow',
android_channel_id: 'default',
channel_id: 'default'
},
data: { id: 'broadcast', channelId: 'default' }
}
const options = {
priority: 'high',
timeToLive: 60 * 60 * 24, // 1 day
};
console.log('------payload---',payload);
console.log('-----TOKEN_Array----',firebaseToken);
console.log('-------options-----',options);
firebase.messaging().sendToDevice(firebaseToken, payload, options).then(function (response) {
console.log('--------response',response);
}) .catch(function (error) {
console.log('-------rejet',reject);
});
It looks like you did not change the code from this tutorial:
https://medium.com/#jullainc/firebase-push-notifications-to-mobile-devices-using-nodejs-7d514e10dd4
you will need to change the 2nd line of code:
var serviceAccount = require("./julla-tutorial.json");
to actually point to your own firebase-push-admin.json file which holds your private keys registering your backend app with the firebase cloud messaging api. you can download this file from the firebase console as mentioned in the above article.
I recommend hiding this file from your git history by adding it to .gitignore so you dont accidentally push your private keys to a public repo.
I will link you another resource in addition to above link which helped me implement firebase push notifications in a nodeJS backend app.
https://izaanjahangir.medium.com/setting-schedule-push-notification-using-node-js-and-mongodb-95f73c00fc2e
https://github.com/izaanjahangir/schedule-push-notification-nodejs
Further I will also link you another repo where I am currently working on a fully functional firebase push notification implementation. Maybe it helps to actually see some example code.
https://gitlab.com/fiehra/plants-backend
I would like to host around 300 photo on Google drive and be able to fetch every photo on my react project, but I don't know how to start like should I need a back-end like node.js? I've seen this video (https://www.youtube.com/watch?v=iajv8y-6n3Q), but he displays only 1 photo.
I wanna display all my images from Google drive on the React and put it on a array like this following JSON
const photos = [
{
src: 'https://source.unsplash.com/2ShvY8Lf6l0/800x599',
width: 4,
height: 3,
year: '2021',
event: 'Hiking',
},
{
src: 'https://source.unsplash.com/Dm-qxdynoEc/800x799',
width: 1,
height: 1,
year: '2021',
event: 'J-On',
},
{
src: 'https://source.unsplash.com/qDkso9nvCg0/600x799',
width: 3,
height: 4,
year: '2021',
event: 'Language Exchange',
},
and so on...
You can achieve your goal in two ways:
Get the files link by manually copying the link from google drive
Fetch the data by using Next.js app and googleapis.
1. Get the files link by manually copying the link from google drive:
Open the file on google drive
Right click at the image file
Click Get Link and a pop up will open
At General Access select Anyone with the link and make sure the role is Viewer
Click Copy Link and done.
Then paste it at any text editor, and you will get the link like this:
https://drive.google.com/file/d/1WS45ByTh_e8QNJTeFMGI8TYpE4OYS2U4/view?usp=sharing
Remove the file/d and replace it with uc?export=view&id= and remove the /view?usp=sharing completely and you will get something like:
https://drive.google.com/uc?export=view&id=1WS45ByTh_e8QNJTeFMGI8TYpE4OYS2U4
And put the image information in an array:
const images = [
{
name: "Doctor Strange in the Multiverse of Madness",
src: "https://drive.google.com/uc?export=view&id=1WS45ByTh_e8QNJTeFMGI8TYpE4OYS2U4"
}
]
Please do the same with the other files, and your images constant finally looks like this:
const images = [
{
name: "Doctor Strange in the Multiverse of Madness",
src:
"https://drive.google.com/uc?export=view&id=1WS45ByTh_e8QNJTeFMGI8TYpE4OYS2U4",
},
{
name: "Minions: The Rise of Gru",
src:
"https://drive.google.com/uc?export=view&id=1eUvlVjwp2brHnyD-cWN0x-10tuS_wXfU",
},
...
,
{
name: "Fantastic Beasts: The Secrets of Dumbledore",
src:
"https://drive.google.com/uc?export=view&id=1vU64yCMdu_ns4xPP-VMYoiJPKNietxRc",
},
];
Now, it is time to render the images in our React Application by using javascript's map method:
export default function App() {
return (
<div>
<div>My Google Drive Images</div>
<ul>
{images.map((image, index) => {
return (
<li key={index}>
<h1>{image.name}</h1>
<img src={image.src} alt={image.name} />
</li>
);
})}
</ul>
</div>
);
}
2. Fetch the data by using Next.js app and googleapis.
In case we have many photos, it is better to use data fetching. Here we use Next.js app and googleapis library.
There are 3 pieces of information that we need to provide in order to be able to fetch data from https://www.googleapis.com/drive/v2 server which are:
CLIENT_ID
CLIENT_SECRET
REFRESH_TOKEN
For CLIENT_ID & CLIENT_SECRET are OAuth 2.0 Client information that can be obtained from Google Developers Console. You can read the details here. And for the REFRESH_TOKEN can be obtained from OAuth 2.0 Playground and the steps are as follows:
Go to https://developers.google.com/oauthplayground
Click the OAuth 2.0 Configuration button
Click Use your own OAuth credentials checkbox
Fill the Client ID & Client Secret input with the OAuth 2.0 CLIENT_ID & CLIENT_SECRET that we get from Google Developers Console.
Close the configuration popup by clicking the close link button.
Find and click the Drive API v3 at Step 1 Select & authorizes APIs.
Select https://www.googleapis.com/auth/drive to enable the Authorize APIs button.
Next we need to select which information that can be accessed by using the token that will be created by clicking the Authorize APIs button.
Then we will be directed to the Sign in with google page. Select the account that we used to generate the CLIENT_ID & CLIENT_SECRET.
If the Google hasn’t verified this app page appears, just click Advance and click Go to ...(unsafe) and select the access types that will be granted to our Next.js app then click Continue and you will be redirected to OAuth 2.0 Playground again.
Find the Exchange authorization code for tokens button at Step 2 Exchange authorization code for tokens, and click it to get the Refresh token and Access token
To make sure that we have generated the tokens correctly, go to https://www.googleapis.com/drive/v2/files?access_token={ACCESS_TOKEN} in your browser. Our configuration is successful if there is a raw JSON page that shows our drive items.
Now, we are ready for coding. We will use our NextJs API to communicate with googleapis server and serve the data to be consumed by our app.
Open your Nextjs app, create a /pages/api/drive-files.ts file, and import googleapis library (here we use Typescript).
import type { NextApiRequest, NextApiResponse } from "next";
import { google } from "googleapis";
...
Create types:
type DriveFile = {
kind: string;
id: string;
name: string;
mimeType: "image/jpeg";
};
type Data = {
files: DriveFile[];
};
Add the Data type at the NextApiResponse and the handler will look like this:
export default async function handler(
_req: NextApiRequest,
res: NextApiResponse<Data>
) {
...
}
Next, create oauth2Client that use CLIENT_ID and CLIENT_SECRET credentials and we use https://developers.google.com/oauthplayground as the redirect uri, setCredentials using REFRESH_TOKEN, and return the google.drive response as JSON;
# /pages/api/drive-files.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { google } from "googleapis";
export type DriveFile = {
kind: string;
id: string;
name: string;
mimeType: "image/jpeg";
};
export type Data = {
files: DriveFile[];
};
const CLIENT_ID =
"777777777777-xxxxddhsl77d7o77777xxxx0v777xx7.apps.googleusercontent.com";
const CLIENT_SECRET = "XXXXXX-777XXXX_-7-hexxxxheAzW_7mr_7_";
const REDIRECT_URI = "https://developers.google.com/oauthplayground";
export default async function handler(
_req: NextApiRequest,
res: NextApiResponse<Data>
) {
const oauth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLIENT_SECRET,
REDIRECT_URI
);
oauth2Client.setCredentials({
refresh_token:
"1//04tORk-dUiDiJCgYIARAAGAQSNwF-L9Ir1hzh14oOk6gQWMOafDZGvLuka578PwwmZB3UMbB2a0VdcjAbRjtelFoDU92ob_Ws50I",
});
const drive = google.drive({
version: "v3",
auth: oauth2Client,
params: {
q: `mimeType = 'image/jpeg'`,
},
});
const response = await drive.files.list();
res.status(200).json({ files: response.data.files as DriveFile[] });
}
And when you access http://localhost:3000/api/drive-files from the browser, you will get:
{
"files":[
{
kind: 'drive#file',
id: '1eUvlVjwp2brHnyD-cWN0x-10tuS_wXfU',
name: 'Minions: The Rise of Gru.jpg',
mimeType: 'image/jpeg'
},
{
kind: 'drive#file',
id: '1vU64yCMdu_ns4xPP-VMYoiJPKNietxRc',
name: 'Fantastic Beasts: The Secr.jpg',
mimeType: 'image/jpeg'
},
{
kind: 'drive#file',
id: '1WS45ByTh_e8QNJTeFMGI8TYpE4OYS2U4',
name: 'Doctor Strange in the M.jpg',
mimeType: 'image/jpeg'
}
]
}
Since we will use NextJs Image component, don't forget to add domain drive.google.com at next.config.js:
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
domains: ["drive.google.com"],
},
};
module.exports = nextConfig;
Finally, you can render the images as follows:
import { useEffect, useState } from "react";
import type { NextPage } from "next";
import axios from "axios";
import { DriveFile } from "./api/drive-files";
import Image from "next/image";
const DriveFiles: NextPage = () => {
const [files, setFiles] = useState<DriveFile[]>();
useEffect(() => {
axios
.get("/api/drive-files")
.then((res) => {
setFiles(res.data.files);
})
.catch((err) => {
console.log(err);
});
}, []);
useEffect(() => {
console.log(files);
}, [files]);
return (
<>
<h1>Google Drive Files</h1>
{files &&
files.map((file, i) => {
return (
<div key={i}>
<p>{file.name}</p>
<Image
width={200}
height={300}
src={`https://drive.google.com/uc?export=view&id=${file.id}`}
alt={file.name}
/>
</div>
);
})}
</>
);
};
export default DriveFiles;
I'm new to Vue / web development, ever since I started i've had a good amount of fun but now i'm stuck.
Currently I am creating an admin dashboard with Firebase authentication. Everything seems to work like it should but there is one thing that I still don't understand.
In the Vue Router I have all the different routes set up and the dashboard is inaccessible (if not logged in to Firebase).
This is my Router Guard:
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/register",
name: "Register",
component: Register,
},
{
path: "/login",
name: "Login",
component: Login,
},
{
path: "/dashboard",
name: "Dashboard",
component: Dashboard,
meta: {
requiresAuth: true,
},
},
];
router.beforeEach((to) => {
//If route requires authentication
if (to.matched.some((rec) => rec.meta.requiresAuth)) {
//Check firebase user
auth.onAuthStateChanged((user) => {
console.log(user);
//If the user object does not exist then redirect to the /Login page
if (!user) {
router.push("/login");
}
});
}
});
If I now try to open localhost:8080/dashboard it shows the dashboard for a split second and then hops to the /login page.
If also tried it with next({name: 'Login'}) but for some reason I keep getting white pages when I use next().
Hope someone can help me.
Thanks :)
The problem is that instead of checking for a logged-in user you are adding an "event listener" auth.onAuthStateChanged.. it fires async when the authentication state changes. However you need a sync check here. The best would be to use vuex and store your user in a global state. Though if you don't use vuex at all and you need your user only here, then probably a "local" user var in the router would also work.. something like this:
let user = null
auth.onAuthStateChanged(u => {
console.log(u)
if (u) {
user = u
} else {
user = null
}
})
router.beforeEach(to => {
if (to.matched.some(rec => rec.meta.requiresAuth)) {
//Check firebase user
if (!user) {
router.push("/login");
}
}
})
It's just a concept, but it should work.. let me know :)
I'm using react-native-contacts inside my react native app to save a contact.
Before saving I request WRITE permission from android.
It works, I open the contact form through my app and save it using the contact form. The contact is saving properly. But, after I have saved the contact, it goes to the home screen, not to my app.
I want to return to my app after the contact is saved.
here is my code,
saveContact = user => {
var newPerson = {
emailAddresses: [
{
label: "work",
email: user.email
}
],
phoneNumbers: [
{
label: "mobile",
number: user.mobileNumber
}
],
displayName: user.firstName + " " + user.lastName
};
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_CONTACTS, {
title: "Contacts",
message: "This app would like to write contacts.",
buttonPositive: "Please accept bare mortal"
}).then(() => {
Contacts.openContactForm(newPerson, (err, contact) => {
if (err) throw err;
// contact has been saved
});
});
};
So I think you are talking about Callback when openContactForm when creation screen is closed
This issue is still OPEN on their github issue page and this feature is still not given by package owner.
For instance, you can see for iOS this thread
I think for now you need to add event listeners for both android and ios separately.
For more information about handling event listeners here
I am using apollo with next and recently I noticed that custom routes breaks SSR. Usually if you navigate through pages apollo caches the query and when you are on the page the next time, it serves everything from cache. However with custom routes, the cache is never used.
I also noticed that when I click on these pages, an error flashes in the console. But it goes away very fast and I wasn't able to copy it here.
Server.js
//
server.get('/about-us', (req, res) => app.render(req, res, '/about'));
server.get('/about', (req, res) => res.redirect(301, '/about-us'));
Menu Click Handler
const navigate = link => () => {
Router.push(link);
};
Menu Items
export const menu = [
{
name: 'Home',
url: '/',
},
{
name: 'Catalogs',
url: '/catalogs',
},
{
name: 'Shop',
url: '/shop',
},
{
name: 'Wholesale',
url: '/wholesale',
},
{
name: 'About Us',
url: '/about-us',
prefetch: true,
},
{
name: 'Contact Us',
url: '/contact-us',
prefetch: true,
},
];
Based on a suggestion from nextjs spectrum I tried prefetching custom pages in the TopNav Component but it didn't work.
const prefetch = url => {
if (process.browser) {
console.log('prefetching these urls', url);
Router.prefetch(url);
}
};
useEffect(() => {
menu.forEach(menuItem => {
if (menuItem.prefetch) {
prefetch(menuItem.url);
}
});
}, []);
I was able to figure out the problem. This is not really well documented but you need to prefetch the component. So for my case instead of prefetching /about-us I should have prefetched /about.
That's why there is as prop in the link component. Nextjs 9 just got released which fixes this issue.
https://nextjs.org/blog/next-9#dynamic-route-segments
For nextjs 9 you can save your file as [pid].js and it will catch all paths in a specific route. i.e for /products/test-product you have to create folder products and inside that add [pid].js.
I needed to query for product based on slug so I added this and voila, I have access to the slug inside my component.
Product.getInitialProps = async ({ query }) => {
return { slug: query.pid };
};
These issues were pretty frustrating before next 9 but it's heavily simplified and it helped me fully remove server.js.