[Ionic Tutorial] Processing Payments with Firebase's FireStore

in utopian-io •  4 months ago

ionic.jpg
image source

Repository: Ionic Github Repository

Software Requirements:
Visual Studio Code(Or any preferred code editor),
A Stripe account

What you will learn:
In this tutorial you would learning about payment processing using stripe. I would be covering these major concepts

  • How to add your secret key to your application
  • How to use your stripe token to process a stripe payment
  • How to use firestore to carry out this processes

Difficulty: Intermediate

Tutorial

In the last tutorial we learnt how to generate tokens from stripe with two methods. This tutorial would be explaining how we could actually process the payments with the generated tokens we got from the first tutorial. Note that this can only be done on a secure back-end which firebase makes easy for us.
To do this we would be using functions that we would create and upload to our backend to carry out these processes for us.

To get started, we would need to initialize our application as a firebase app. To do this run this command in your terminal while in your project directory

firebase init

This would initialize this project as a firebase project and add all the files we would need to deploy our functions.
In your projects directory you should have a folder called functions. Navigate into this folder and run this command to install stripe to the firebase project

npm install stripe --save

This should include it in your package.json which should now look like this

{
"name": "functions",
"description": "cloud functions for firebase",
"dependencies": {
    "firebase-admin": "4.1.2",
    "firebase-functions":"0.5",
    "stripe": "^4.23.1"//This signifies that firebase has been added
},
"private": true
}

How to add your secret key

To get your secret key, you must have a stripe account which was required in the part one of this tutorial. If you dont know how to find it click Here and login to see your own personal stripe secret key. Every transaction made with your stripe account would require the key and so it is advisable that you keep your key a secret.

When you go to the link above and get your secret key, you would need to add it as a setting. This can be done in two ways but the better way is to use this command

firebase:config:set stripe.testkey = "Your secret key goes here"

And the alternative method would be used in the next step below

Using firestore to process payments

We would be using firestore to process payments whenever a new token is loaded on our firestore database. This means that our function would be triggered whenever a new token is written on our database and this payment would be processed. Firebase has a way of doing this and the code is stated and explained below

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp(functions.config().firebase);

const stripe = require('stripe')('Your test key');

exports.stripeCharge = functions.firestore
  .document('/payments/{userId}/mypayments/{paymentId}')
  .onCreate((snap,event) => {
    const payment = snap.data()
    const userId = event.params.userId
    const paymentId = event.params.paymentId
    console.log(payment);

    // checks if payment exists or if it has already been charged
    if (!payment || payment.charge) return null;

    return admin.firestore()
      .doc(`/users/${userId}`)
      .get()
      .then(snapshot => {
        return snapshot
      })
      .then(customer => {
        const amount = payment.amount // amount must be in cents
        const idempotency_key = paymentId  // prevent duplicate charges
        const source = payment.token.source.id;
        const currency = 'usd'
        const charge = {amount, currency, source}
        console.log(charge);

        return stripe.charges.create(charge, { idempotency_key })
     })
     .then((charge) => {
       admin.firestore()
        .collection('/payments').doc(userId).collection('mypayments').doc(paymentId)
        .set({
          charge: charge
        }, { merge: true })
        .catch(er=>{
            console.log(er);
            return er
        }
        )
        if(charge.status === 'succeeded'){
          if(payment.amount === 3000){
          const validTill = Date.now() +  12 * 30 * 24 * 60 * 60;
          admin.firestore()
            .collection('store'+userId).doc('subscriptionValidtill')
            .set({
              validTill
            })
            .catch(er=>{
              console.log(er);
              return er;
            })
        }
       
          
        }
     })

The first thing i did was import the firebase functionalities which we would be using like this

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

After this i initialized the app and added the test key which is the alternative method to the method stated above

admin.initializeApp(functions.config().firebase);

const stripe = require('stripe')('sk_test_4ZvAeCMGrH85ySuFNZRDxvg9');

I then started building the function which was going to be used on the server. To do this, i stated it as an export and made it to be triggered whenever a new token is written under payments in the firestore database.
I then made collected the payment details from the data that was written

exports.stripeCharge = functions.firestore
  .document('/payments/{userId}/mypayments/{paymentId}')
  .onCreate((snap,event) => {
    const payment = snap.data()
    const userId = event.params.userId
    const paymentId = event.params.paymentId
    console.log(payment);

    // checks if payment exists or if it has already been charged
    if (!payment || payment.charge) return null;

    return admin.firestore()
      .doc(`/users/${userId}`)
      .get()
      .then(snapshot => {
        return snapshot
      })
      .then(customer => {
        const amount = payment.amount // amount must be in cents
        const idempotency_key = paymentId  // prevent duplicate charges
        const source = payment.token.source.id;
        const currency = 'usd'
        const charge = {amount, currency, source}
        console.log(charge);

And then used the data i got to process the payment

   return stripe.charges.create(charge, { idempotency_key })

Note: The idempotency key is to prevent duplicate charges
If this payment was successful, i then wrote this payment under the users database for future reference

  if(charge.status === 'succeeded'){
          if(payment.amount === 3000){
          const validTill = Date.now() +  12 * 30 * 24 * 60 * 60;
          admin.firestore()
            .collection('store'+userId).doc('subscriptionValidtill')
            .set({
              validTill
            })
            .catch(er=>{
              console.log(er);
              return er;
            })
        }

Now that you have the function in place, you would need to deploy it. To do this run this command

firebase deploy --only functions//Specify functions so it would only deploy functions

You can then run the process from the first tutorial and this process would also be run.
Note: You should use your stripe test keys for development purposes and not use the live keys unless the application is ready for production.

You can find the code for this tutorial in my github repo
Here

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Thank you for your contribution @yalzeee.
After reviewing your tutorial we suggest the following points listed below:

  • We suggest you put some images on your developed work. Images with the results of what you are developing helps users a lot to understand what they are explaining.

  • In your code place more comments. The comments in the code are very important for users to better understand what you are developing.

  • In your tutorial you have some writing errors, be careful in doing a review of your tutorial to correct errors that may escape.

Your tutorial is interesting, thanks for your work on doing this tutorial. We are waiting for more of your tutorials.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

·

Thank you for your review, @portugalcoin! Keep up the good work!

Hello! I find your post valuable for the wafrica community! Thanks for the great post! We encourage and support quality contents and projects from the West African region.
Do you have a suggestion, concern or want to appear as a guest author on WAfrica, join our discord server and discuss with a member of our curation team.
Don't forget to join us every Sunday by 20:30GMT for our Sunday WAFRO party on our discord channel. Thank you.

Hey, @yalzeee!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!