Ionic 4 Stripe payment integration with Firebase — for Apps and PWA
Tags: ionic, stripe, payment, firebase
Published: 2019-09-19 18:07:26

<main role="main"><article class=" u-minHeight100vhOffset65 u-overflowHidden postArticle postArticle--full" ><div class="postArticle-content js-postField js-notesSource editable" id="editor_94" g_editable="true" role="textbox" contenteditable="true" data-default-value="Title
Tell your story…" spellcheck="false"><section name="55c7" class="section section--body section--first section--last"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><p name="0800" class="graf graf--p graf-after--figure">Stripe is one of the most widely used and fastest growing payment gateway you can integrate in your website or app. It supports a wide variety of payment options, and is quickly spreading across the globe. Stripe can take care of almost all your payment requirements in apps and website. Stripe’s ease of integration has made it a popular developer choice over PayPal and other payment gateways. A good comparison between Stripe and PayPal can be studied <a href="https://www.cloudways.com/blog/stripe-vs-paypal/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">here</a> (spoiler&#8202;—&#8202;Stripe wins)</p><h3 name="2ac0" class="graf graf--h3 graf-after--p">What is Ionic&nbsp;4?</h3><p name="eaae" class="graf graf--p graf-after--h3">You probably already know about Ionic, but I’m putting it here just for the sake of beginners. <strong class="markup--strong markup--p-strong">Ionic</strong> is a complete open-source SDK for hybrid mobile app development created by Max Lynch, Ben Sperry and Adam Bradley of Drifty Co. in 2013. Ionic provides tools and services for developing hybrid mobile apps using Web technologies like CSS, HTML5, and Sass. Apps can be built with these Web technologies and then distributed through native app stores to be installed on devices by leveraging Cordova.</p><p name="de54" class="graf graf--p graf-after--p">So, in other words&#8202;—&#8202;If you create Native apps in Android, you code in Java. If you create Native apps in iOS, you code in Obj-C or Swift. Both of these are powerful but complex languages. With Cordova (and Ionic) you can write a single piece of code for your app that can run on both iOS and Android (and windows!), that too with the simplicity of HTML, CSS, and JS.</p><h3 name="f8fe" class="graf graf--h3 graf-after--p">Ionic 4 and Payment&nbsp;Gateways</h3><p name="b85f" class="graf graf--p graf-after--h3 is-selected">Ionic 4 can create a wide variety of apps, and hence a wide variety of payment gateways can be implemented in Ionic 4 apps. The popular ones are PayPal, Stripe, Braintree, in-app purchase etc. For more details on payment gateways, you can read my blog on <a href="https://medium.com/enappd/payment-solutions-in-ionic-8c4bb28ce5cc"  class="markup--anchor markup--p-anchor"    target="_blank">Payment Gateway Solutions in Ionic 4.</a></p><p name="7a41" class="graf graf--p graf-after--p">Stripe can be integrated in websites as well as mobile apps. There are different ways of integration of Stripe SDK. In this blog we’ll learn <strong class="markup--strong markup--p-strong">how to integrate Stripe payment gateway in Ionic 4 apps and Ionic 4 PWA.</strong></p><figure tabindex="0" contenteditable="false" name="a791" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 280px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 40%;"></div><img class="graf-image" data-image-id="1*-1a8E2v5HsoRyQZNoO0RQw.jpeg" data-width="800" data-height="320" src="https://cdn-images-1.medium.com/max/800/1*-1a8E2v5HsoRyQZNoO0RQw.jpeg"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Ionic 4 and Stripe make a great&nbsp;team</figcaption></figure><h4 name="cdce" class="graf graf--h4 graf-after--figure">There are two main ways of integrating Stripe into an Ionic application</h4><p name="8949" class="graf graf--p graf-after--h4">You can either go with the <a href="https://ionicframework.com/docs/native/stripe/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Ionic Native</a> implementation, which is a wrapper around the Stripe native SDKs for iOS and Android. This is powered by <a href="https://github.com/zyra/cordova-plugin-stripe"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">cordova-plugin-stripe</a>. This has the limitation of only facilitating the creation of tokens for <strong class="markup--strong markup--p-strong">once off payments</strong>. This works for both mobile app and PWA.</p><p name="70ae" class="graf graf--p graf-after--p">The alternative approach is to use <a href="https://stripe.com/docs/stripe-js/reference"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Stripe.js</a> which is Stripe’s JavaScript implementation of their functionality. This is easy to use and quick to implement as this is implemented in JavaScript. The functionality is delivered dynamically into the page and supports both <strong class="markup--strong markup--p-strong">single and recurring payments. </strong>Again, you can use it both in mobile and Web, but here we’ll see a web implementation only.</p><p name="1b8f" class="graf graf--p graf-after--p">In this post, we will learn how to implement both these methods for Stripe payments in an Ionic 4 app and PWA. To simplify the understanding, let us understand the complete flow pictorially</p></div><div class="section-inner sectionLayout--outsetColumn"><figure tabindex="0" contenteditable="false" name="2697" class="graf graf--figure graf--layoutOutsetCenter graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 1032px; max-height: 387px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 37.5%;"></div><img class="graf-image" data-image-id="1*T2zDo6nvDhko2_iwnTNYyA.jpeg" data-width="1200" data-height="450" src="https://cdn-images-1.medium.com/max/1200/1*T2zDo6nvDhko2_iwnTNYyA.jpeg"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Stripe Ionic 4 integration flow</figcaption></figure></div><div class="section-inner sectionLayout--insetColumn"><p name="9f9e" class="graf graf--p graf-after--figure">Prerequisites</p><ul class="postList"><li name="7a7d" class="graf graf--li graf-after--p">Create an Ionic 4 app for Stripe integration</li><li name="7ca8" class="graf graf--li graf-after--li">Stripe Developer account for API keys</li></ul><p name="5dc9" class="graf graf--p graf-after--li">Steps</p><ul class="postList"><li name="8f76" class="graf graf--li graf-after--p"><strong class="markup--strong markup--li-strong">Step 1</strong>&#8202;—&#8202;Integrate Stripe Native plugin (SDK) for token generation at app level</li><li name="4fd6" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Step 2</strong>&#8202;—&#8202;Integrate Stripe JS in your PWA / website for token generation at website level</li><li name="1b06" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Step 3&#8202;</strong>—&#8202;Create Firebase function (or any back-end function to accept API calls) to accept tokens from app, and make payment requests to Stripe server</li><li name="2ac3" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Step 4</strong>&#8202;—&#8202;Connect app / PWA to our Firebase server. Complete Stripe payment requests from Firebase server.</li></ul><p name="e128" class="graf graf--p graf-after--li">Let’s start step-by-step</p><blockquote name="48b3" class="graf graf--blockquote graf-after--p">Complete source code of this tutorial is available in the <a href="https://github.com/enappd/ionic4-stripe"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank">Ionic4-stripe Github repository.</a></blockquote><h3 name="9226" class="graf graf--h3 graf-after--blockquote">Prerequisites</h3><h4 name="47e1" class="graf graf--h4 graf-after--h3">Create a basic Ionic 4&nbsp;app</h4><p name="2497" class="graf graf--p graf-after--h4">Creating a basic Ionic 4 app is very easy. Assuming you have all basic requirements installed in your system, run</p><pre name="edac" class="graf graf--pre graf-after--p">$ ionic start MyApp sidemenu</pre><p name="2fb6" class="graf graf--p graf-after--pre">This creates your app with title<code class="markup--code markup--p-code">MyApp</code> and sidemenu template.</p><blockquote name="166d" class="graf graf--blockquote graf-after--p">For more details on how to create a basic Ionic 4 app, refer to my blog <a href="https://medium.com/enappd/how-to-create-an-ionic-4-app-for-beginners-e181e116190a"  class="markup--anchor markup--blockquote-anchor"    target="_blank">How to create an Ionic 4 app</a></blockquote><p name="5853" class="graf graf--p graf-after--blockquote">With minor modifications, my homepage looks like this.</p><figure tabindex="0" contenteditable="false" name="832a" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 383px; max-height: 675px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 176.2%;"></div><img class="graf-image" data-image-id="1*lqxHGxefMwFd9kY9iCX2pQ.png" data-width="383" data-height="675" src="https://cdn-images-1.medium.com/max/800/1*lqxHGxefMwFd9kY9iCX2pQ.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Stripe payment home&nbsp;page</figcaption></figure><p name="cf5c" class="graf graf--p graf-after--figure">The file structure looks something like this, just for an idea</p><figure tabindex="0" contenteditable="false" name="f04e" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 282px; max-height: 548px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 194.3%;"></div><img class="graf-image" data-image-id="1*4R2ubV8xvuu7FXw57iOUlg.png" data-width="282" data-height="548" src="https://cdn-images-1.medium.com/max/800/1*4R2ubV8xvuu7FXw57iOUlg.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">File structure for Stripe Ionic 4 sample&nbsp;app</figcaption></figure><p name="cf0e" class="graf graf--p graf-after--figure">The main functional part of this HTML is nothing but the payment button you see above, which invokes <code class="markup--code markup--p-code">payWithStripe()</code> function</p><pre name="99f7" class="graf graf--pre graf-after--p">&lt;ion-button expand="full" color="success" (click)="payWithStripe()"&gt;Pay with Stripe&lt;/ion-button&gt;</pre><h4 name="8c20" class="graf graf--h4 graf-after--pre">Stripe Developer Account</h4><p name="286d" class="graf graf--p graf-after--h4">Visit <a href="http://stripe.com"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Stripe.com</a> and create an account. Stripe payment services are currently available in limited countries as <a href="https://stripe.com/global"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">shown on this page</a>.</p><p name="dd88" class="graf graf--p graf-after--p">Once you are inside Stripe Dashboard, look for the <strong class="markup--strong markup--p-strong">Developer</strong> Tab -&gt; API keys.</p><figure tabindex="0" contenteditable="false" name="68a0" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 297px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 42.4%;"></div><img class="graf-image" data-image-id="1*K1Qdrnt3GoLaqVoYa3pTqw.png" data-width="1387" data-height="588" src="https://cdn-images-1.medium.com/max/800/1*K1Qdrnt3GoLaqVoYa3pTqw.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Stripe Developer account&#8202;—&#8202;API&nbsp;keys</figcaption></figure><p name="9cad" class="graf graf--p graf-after--figure"><strong class="markup--strong markup--p-strong">Publishable key </strong>is what you use for connecting the Strive Native SDK or Stripe.js in front-end. <strong class="markup--strong markup--p-strong">Secret key</strong> is used in the back-end, where your server connects with Stripe’s server for actual payment.</p><p name="2be9" class="graf graf--p graf-after--p">That’s all you need from Stripe account, for now. You can toggle the <strong class="markup--strong markup--p-strong">Live keys </strong>and use them instead once you have tested the process.</p><p name="af20" class="graf graf--p graf-after--p">Let’s look into the Ionic 4 integration of Stripe now.</p><h3 name="a88d" class="graf graf--h3 graf-after--p">Step 1&#8202;—&#8202;Integrate Stripe Native&nbsp;plugin</h3><blockquote name="3094" class="graf graf--blockquote graf-after--h3"><strong class="markup--strong markup--blockquote-strong">Please note that both Step 1 and Step 2 mentioned above only help you create a payment token from Stripe server. It DOES NOT complete a payment. To complete the payment, you can use the generate token, send it to your server, and complete the payment request via your server (Step 4 below)</strong></blockquote><p name="d03e" class="graf graf--p graf-after--blockquote">To include Stripe functionality in your Ionic 4 app, you need to install Stripe native plugin. Install the plugin with following commands</p><pre name="f768" class="graf graf--pre graf-after--p">$ ionic cordova plugin add cordova-plugin-stripe</pre><pre name="3b8d" class="graf graf--pre graf-after--pre">$ npm install @ionic-native/stripe</pre><p name="13ee" class="graf graf--p graf-after--pre">After installation completes, import Stripe module in your <code class="markup--code markup--p-code">app.module.ts</code></p><figure tabindex="0" contenteditable="false" name="df6f" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 404px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 57.699999999999996%;"></div><img class="graf-image" data-image-id="1*xDfojoxG-ElTaT-o6hC_3A.png" data-width="1031" data-height="595" src="https://cdn-images-1.medium.com/max/800/1*xDfojoxG-ElTaT-o6hC_3A.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">import Stripe in app.module.ts</figcaption></figure><p name="1172" class="graf graf--p graf-after--figure">and also import Stripe in your <code class="markup--code markup--p-code">stripe.page.ts</code> page file, like so</p><figure tabindex="0" contenteditable="false" name="a15d" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 243px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 34.699999999999996%;"></div><img class="graf-image" data-image-id="1*B3B4vz9qiRr0zljrESHdWw.png" data-width="960" data-height="333" src="https://cdn-images-1.medium.com/max/800/1*B3B4vz9qiRr0zljrESHdWw.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Import Stripe in your&nbsp;page</figcaption></figure><p name="5755" class="graf graf--p graf-after--figure">Now, with native SDK, we can only generate a payment token for <strong class="markup--strong markup--p-strong">one-off payments</strong> via Stripe SDK. The payment function looks like the following</p><figure tabindex="0" contenteditable="false" name="2108" class="graf graf--figure graf--iframe is-defaultValue graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/2ee829b7e61d72b3006fe1ad14ac43d5.js %}</div></div></figure><p name="5736" class="graf graf--p graf-after--figure"><code class="markup--code markup--p-code">setPublishableKey</code> connects Stripe SDK using your publishable key.</p><p name="26bc" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">createCardToken</code> along with card details, create a card in Stripe. You can apply front-end checks on card details, otherwise Stripe server will send a relevant error message.</p><p name="6179" class="graf graf--p graf-after--p">Note that the card details used here are Stripe’s default test card details. You can find more test cards <a href="https://stripe.com/docs/testing#cards"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">in Stripe’s docs</a></p><p name="3d3d" class="graf graf--p graf-after--p">In successful response to <code class="markup--code markup--p-code">createCardToken</code> function, Stripe server will send back a payment token, which will have information similar to following</p><figure tabindex="0" contenteditable="false" name="2d54" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 246px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.199999999999996%;"></div><img class="graf-image" data-image-id="1*bxy4zSSxuxZtRMbSEAy8ew.png" data-width="847" data-height="298" src="https://cdn-images-1.medium.com/max/800/1*bxy4zSSxuxZtRMbSEAy8ew.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Successful tokenization response from Stripe&nbsp;server</figcaption></figure><p name="9ca6" class="graf graf--p graf-after--figure">This is the extent of functionality of Stripe’s Ionic Native plugin for now. We’ll see in Step 3 &amp; 4 how to use this token to complete a payment request.</p><h4 name="02c7" class="graf graf--h4 graf-after--p">Note:</h4><p name="f661" class="graf graf--p graf-after--h4">Stripe Native plugin works for both mobile app and PWA. For testing PWA implementation, create a browser platform for the app</p><pre name="4355" class="graf graf--pre graf-after--p">$ ionic cordova platform add browser</pre><p name="458e" class="graf graf--p graf-after--pre">Once the platform is added, run</p><pre name="b13e" class="graf graf--pre graf-after--p">$ ionic cordova run browser</pre><p name="8543" class="graf graf--p graf-after--pre">and you can test the implementation of Stripe Native plugin in PWA.</p><h3 name="0da6" class="graf graf--h3 graf-after--p">Step 2&#8202;—&#8202;Integrate Stripe.js in your PWA /&nbsp;website</h3><p name="8ae7" class="graf graf--p graf-after--h3">In this part, we’ll integrate Stripe in a PWA / website environment, since native plugin will not work here. Our PWA/website page in the sample repo looks like following</p><figure tabindex="0" contenteditable="false" name="14c7" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 387px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 55.300000000000004%;"></div><img class="graf-image" data-image-id="1*lC_KZFQfptCwLmqhG6eJuA.png" data-width="1386" data-height="766" src="https://cdn-images-1.medium.com/max/800/1*lC_KZFQfptCwLmqhG6eJuA.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Stripe elements can be used to create automated payment&nbsp;forms</figcaption></figure><p name="935b" class="graf graf--p graf-after--figure">First of all, add <code class="markup--code markup--p-code">stripe.js</code> in your <code class="markup--code markup--p-code">index.html</code> file. This is valid for both, if you are creating an Ionic 4 PWA, or a standalone website.</p><pre name="f5a0" class="graf graf--pre graf-after--p">&lt;script src="https://js.stripe.com/v3/" async&gt;&lt;/script&gt;</pre></div><div class="section-inner sectionLayout--outsetColumn"><figure tabindex="0" contenteditable="false" name="714e" class="graf graf--figure graf--layoutOutsetCenter graf-after--pre"><div class="aspectRatioPlaceholder is-locked" style="max-width: 1032px; max-height: 380px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 36.8%;"></div><img class="graf-image" data-image-id="1*Q7iSjm4C40A0sSWkIkIfZA.png" data-width="1344" data-height="495" src="https://cdn-images-1.medium.com/max/1200/1*Q7iSjm4C40A0sSWkIkIfZA.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Add stripe.js in your index.html file</figcaption></figure></div><div class="section-inner sectionLayout--insetColumn"><p name="f174" class="graf graf--p graf-after--figure">With <code class="markup--code markup--p-code">stripe.js</code> we use what is called <a href="https://stripe.com/elements"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--p-strong">Stripe Elements</strong></a><strong class="markup--strong markup--p-strong">, </strong>which is similar to PayPal’s Payment Button. With Stripe Elements, you get a ready-made payment form, with proper validations, localizations, and in-browser payment support.</p><p name="0207" class="graf graf--p graf-after--p">We will implement the <code class="markup--code markup--p-code">stripe.js</code> elements in a separate page in our Ionic 4 app&#8202;—&#8202;<strong class="markup--strong markup--p-strong">Stripe-web.</strong></p><p name="060a" class="graf graf--p graf-after--p">In the HTML page, instead of a normal button, we create a form which integrates Stripe elements.</p><figure tabindex="0" contenteditable="false" name="0a9b" class="graf graf--figure graf--iframe is-defaultValue graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/f0ce455bdfcefd81c6adda801b8fac79.js %}</div></div></figure><p name="97e1" class="graf graf--p graf-after--figure">Notice the <code class="markup--code markup--p-code">payment-form</code>&nbsp;, <code class="markup--code markup--p-code">card-element</code> and <code class="markup--code markup--p-code">card-errors</code> ID elements, which will be used by Stripe elements.</p><p name="bae5" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">payment-form</code> will contain the form, listeners for inputs and submit button, <code class="markup--code markup--p-code">card-element</code> will contain the card-input form and <code class="markup--code markup--p-code">card-errors</code> will show any validation errors. The styling for these divs can be controlled easily.</p><p name="8852" class="graf graf--p graf-after--p">Now the JS implementation. The logic part of Stripe element will look like the following.</p><figure tabindex="0" contenteditable="false" name="5692" class="graf graf--figure graf--iframe is-defaultValue graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/824a2ef3d3720787ebd6cf9681b5e28d.js %}</div></div></figure><p name="cb95" class="graf graf--p graf-after--figure">Let’s walk through it one step at a time</p><p name="3ca7" class="graf graf--p graf-after--p">We import Stripe in the page with</p><pre name="c9e2" class="graf graf--pre graf-after--p">declare var Stripe;</pre><p name="44ce" class="graf graf--p graf-after--pre">and then creating <code class="markup--code markup--p-code">stripe</code> variable</p><pre name="31b8" class="graf graf--pre graf-after--p">stripe = Stripe('YOUR_PUBLISHABLE_KEY');</pre><p name="ac16" class="graf graf--p graf-after--pre">This is the initialization step of Stripe elements in your page. Now, since we need the HTML divs to create Stripe elements, we’ll call the relevant functions in <code class="markup--code markup--p-code">ngOnInit</code> so all HTML elements are loaded beforehand.</p><pre name="189c" class="graf graf--pre graf-after--p">ngOnInit() {<br>   this.setupStripe();<br>}</pre><p name="0505" class="graf graf--p graf-after--pre">Now, the <code class="markup--code markup--p-code">setupStripe</code> function contains all the implementation parts of Stripe.js functionality. First of all, we create <code class="markup--code markup--p-code">card</code> in the HTML div with the ID<code class="markup--code markup--p-code">card-element</code></p><pre name="443f" class="graf graf--pre graf-after--p">let elements = this.stripe.elements();<br>var style = {<br> base: {<br>  color: '#32325d',<br>  lineHeight: '24px',<br>  fontFamily: '"Helvetica Neue", Helvetica, sans-serif',<br>  fontSmoothing: 'antialiased',<br>  fontSize: '16px',<br>  '::placeholder': {<br>  color: '#aab7c4'<br> }<br>},<br>invalid: {<br> color: '#fa755a',<br> iconColor: '#fa755a'<br>}<br>};<br>this.card = elements.create('card', { style: style });<br>console.log(this.card);<br>this.card.mount('#card-element');</pre><p name="0db0" class="graf graf--p graf-after--pre">This creates the card input form in HTML which contains four parts</p><ul class="postList"><li name="2d12" class="graf graf--li graf-after--p">Card number</li><li name="59d8" class="graf graf--li graf-after--li">Expiry Date</li><li name="6a4b" class="graf graf--li graf-after--li">CVC, and</li><li name="61b4" class="graf graf--li graf-after--li">ZIP</li></ul><p name="0e3d" class="graf graf--p graf-after--li">All validations are handled automatically, so that’s a 😅</p><p name="ea8c" class="graf graf--p graf-after--p">Next, we attach listeners to form-inputs for displaying validation errors in the HTML div with ID <code class="markup--code markup--p-code">card-errors</code>, if any</p><pre name="13d5" class="graf graf--pre graf-after--p">this.card.addEventListener('change', event =&gt; {<br>var displayError = document.getElementById('card-errors');<br> if (event.error) {<br>  displayError.textContent = event.error.message;<br> } else {<br>  displayError.textContent = '';<br> }<br>});</pre><p name="6121" class="graf graf--p graf-after--pre">Finally, we listen to the <code class="markup--code markup--p-code">submit</code> event of the form, to submit the tokenization request to Stripe server</p><pre name="dad9" class="graf graf--pre graf-after--p">var form = document.getElementById('payment-form');<br>form.addEventListener('submit', event =&gt; {<br> event.preventDefault();</pre><pre name="382d" class="graf graf--pre graf-after--pre">this.stripe.<strong class="markup--strong markup--pre-strong">createSource</strong>(this.card).then(result =&gt; {<br>  if (result.error) {<br>   var errorElement = document.getElementById('card-errors');<br>   errorElement.textContent = result.error.message;<br>  } else {<br>   console.log(result);<br>  }<br> });<br>});</pre><p name="508f" class="graf graf--p graf-after--pre">Notice the <code class="markup--code markup--p-code">createSource</code> function, that creates a payment token. We discussed earlier that the Native SDK can only generate tokens for one-off payments, but here you can generate tokens for cards, from which you can make repeat payments as well. Use <strong class="markup--strong markup--p-strong">createToken()</strong> if you need to make a once off payment or <strong class="markup--strong markup--p-strong">createSource()</strong> to create a card that can be billed multiple times in the future.</p><p name="ff05" class="graf graf--p graf-after--p">The result returns a lot of useful info, that can be stored locally, stored on the server or can be just used once to create payments, using the returned token.</p><figure tabindex="0" contenteditable="false" name="3df4" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 277px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 39.5%;"></div><img class="graf-image" data-image-id="1*NGXMmOkTNOkKtZnPtwS_eQ.png" data-width="984" data-height="389" src="https://cdn-images-1.medium.com/max/800/1*NGXMmOkTNOkKtZnPtwS_eQ.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Card tokenization result with Stripe.js</figcaption></figure><p name="7407" class="graf graf--p graf-after--figure">Notice the <code class="markup--code markup--p-code">usage: reusable</code> denotes multiple transactions can be done on this card i.e. subscription payments etc.</p><p name="6a78" class="graf graf--p graf-after--p">With this, we have successfully created tokens using Stripe elements (stripe.js) in PWA / website environment.</p><h3 name="a3ae" class="graf graf--h3 graf-after--p">Step 3&#8202;—&#8202;Creating Firebase project and functions to execute API calls to Stripe&nbsp;server</h3><p name="4a98" class="graf graf--p graf-after--h3">First two steps of Stripe integration allowed us to generate payment tokens in an app and website environment. But tokens aren’t payments. We want to complete a payment using Stripe. This is where Stripe is a little different from PayPal. PayPal allows you to do complete payment on front-end itself, while Stripe only allows payments from back-end.</p><p name="02f5" class="graf graf--p graf-after--p">For example purpose, we will use Firebase back-end, since it is the easiest to implement with an Ionic 4 app. Once the Firebase project is setup, we’ll make a simple HTTP request to our Firebase server for payment completion.</p><blockquote name="0772" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Assumption</strong>&#8202;—&#8202;You already know how to create a Firebase Project, and deploy Firebase function on it. If not, you can create any other node server and make API calls to it</blockquote><h4 name="50d0" class="graf graf--h4 graf-after--blockquote">Connect Firebase to your&nbsp;project</h4><p name="082c" class="graf graf--p graf-after--h4">In short, you can create a Firebase Project in Firebase console webpage, connect it to Ionic 4 app using <code class="markup--code markup--p-code">firebase init</code>&nbsp;. Also, for this you need to have firebase-tools installed in your system. (Use <code class="markup--code markup--p-code">npm install firebase-tools -g</code>)</p><p name="f853" class="graf graf--p graf-after--p">Once you have your project ready, connect it to your Ionic 4 app using</p><pre name="5263" class="graf graf--pre graf-after--p">$ firebase init</pre><p name="1bea" class="graf graf--p graf-after--pre">then choosing the project, and choosing <code class="markup--code markup--p-code">functions</code> option from the choices.</p><figure tabindex="0" contenteditable="false" name="b505" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 98px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 13.900000000000002%;"></div><img class="graf-image" data-image-id="1*gZrz3bLkZYWOIb57DBIrjA.png" data-width="1040" data-height="145" src="https://cdn-images-1.medium.com/max/800/1*gZrz3bLkZYWOIb57DBIrjA.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Choose Functions options in `Firebase init`</figcaption></figure><p name="6b3d" class="graf graf--p graf-after--figure">With <strong class="markup--strong markup--p-strong">Firebase Functions, </strong>you can essentially right back-end (node.js) functions in same environment, test locally with <code class="markup--code markup--p-code">firebase serve</code> and can then deploy these to your Firebase project, so it can be connected to your app / website.</p><p name="72a6" class="graf graf--p graf-after--p">Once you have Firebase project connected, you will see a <code class="markup--code markup--p-code">functions</code> folder in your project root, as shown below</p><figure tabindex="0" contenteditable="false" name="bdb9" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 295px; max-height: 501px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 169.79999999999998%;"></div><img class="graf-image" data-image-id="1*q-KcVAn51NmNPhtcTRlcpQ.png" data-width="295" data-height="501" src="https://cdn-images-1.medium.com/max/800/1*q-KcVAn51NmNPhtcTRlcpQ.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Firebase functions folder in project&nbsp;root</figcaption></figure><h4 name="7dd6" class="graf graf--h4 graf-after--figure">Create a firebase function to make payment&nbsp;requests</h4><p name="d15c" class="graf graf--p graf-after--h4">After this, you can create your back-end function in <code class="markup--code markup--p-code">functions/index.js</code> file. This function will accept a request object from your app / website, send the payment request to Stripe server, and return the response to your app / website again.</p><figure tabindex="0" contenteditable="false" name="670c" class="graf graf--figure graf--iframe is-defaultValue graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/96ee09f65570936721cc6f3fe6953b1b.js %}</div></div></figure><p name="b539" class="graf graf--p graf-after--figure">Notice that the payment request from your app should contain</p><ul class="postList"><li name="d4c5" class="graf graf--li graf-after--p">amount&#8202;—&#8202;in number (<strong class="markup--strong markup--li-strong">Notice: </strong>this number is in cents when you use “usd”. So use 100 if the payment is for $1. Using less than 50 will give an error.)</li><li name="3bd1" class="graf graf--li graf-after--li">currency&#8202;—&#8202;currency code string e.g. “usd”</li><li name="e8bc" class="graf graf--li graf-after--li">token&#8202;—&#8202;the one we received in Step 1 and Step 2</li></ul><p name="258d" class="graf graf--p graf-after--li">This data should be sent in an object in POST API request, shown in next step.</p><h4 name="2ca3" class="graf graf--h4 graf-after--p">Test Firebase functions locally</h4><p name="3c66" class="graf graf--p graf-after--h4">To test whether your Firebase function is correctly written, run the function locally by running command</p><pre name="adee" class="graf graf--pre graf-after--p">$ firebase serve</pre><p name="ce9c" class="graf graf--p graf-after--pre">This will start your firebase local server, and the url will be displayed in the terminal&nbsp;, something like</p><pre name="2be4" class="graf graf--pre graf-after--p"><a href="http://localhost:5000/shoppr-c97a7/us-central1/payWithStripe"  class="markup--anchor markup--pre-anchor" target="_blank">http://localhost:5000/shoppr-c97a7/us-central1/payWithStripe</a></pre><p name="8c5f" class="graf graf--p graf-after--pre">Now, you can make an API call to this URL using POSTMAN or any other API calling application, or simply a curl request from terminal. Remember, you need to send the amount, currency and token information in this POST API call as well.</p><h4 name="b034" class="graf graf--h4 graf-after--p">Deploy Firebase Function to live&nbsp;site</h4><p name="5b26" class="graf graf--p graf-after--h4">Once your local testing is successful, deploy the firebase functions to live server using</p><pre name="3d8a" class="graf graf--pre graf-after--p">$ firebase deploy --only functions</pre><p name="e2b7" class="graf graf--p graf-after--pre">This will deploy the functions on your live Firebase server, which you can make API calls to. The url of the function will again be shown in the terminal after deployment, something like</p><pre name="3354" class="graf graf--pre graf-after--p"><a href="https://us-central1-shoppr-c97a7.cloudfunctions.net/payWithStripe"  class="markup--anchor markup--pre-anchor" rel="noopener" target="_blank">https://us-central1-shoppr-c97a7.cloudfunctions.net/payWithStripe</a></pre><h3 name="0836" class="graf graf--h3 graf-after--pre">Step 4&#8202;—&#8202;Connect app/PWA to live Firebase server and complete payment&nbsp;requests</h3><p name="5132" class="graf graf--p graf-after--h3">To enable our app to make HTTP requests, we import <code class="markup--code markup--p-code">HttpClient</code> in our <code class="markup--code markup--p-code">app.module.ts</code></p><figure tabindex="0" contenteditable="false" name="1566" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 345px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 49.3%;"></div><img class="graf-image" data-image-id="1*JVCCvddH6hLlGFuBVz5D1Q.png" data-width="958" data-height="472" src="https://cdn-images-1.medium.com/max/800/1*JVCCvddH6hLlGFuBVz5D1Q.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Import HttpCient in app.module.ts</figcaption></figure><p name="0275" class="graf graf--p graf-after--figure">and in our <code class="markup--code markup--p-code">stripe.page.ts</code> page</p><pre name="3036" class="graf graf--pre graf-after--p">import { HttpClient } from "@angular/common/http";</pre><pre name="31d0" class="graf graf--pre graf-after--pre">...</pre><pre name="8da0" class="graf graf--pre graf-after--pre">constructor(private http: HttpClient){}</pre><p name="304d" class="graf graf--p graf-after--pre">Once, we receive the token in response from Stripe server (Step 1 / Step 2), we will call the REST API connecting the app to our Firebase server</p><pre name="0163" class="graf graf--pre graf-after--p">makePayment(token) {<br> this.http<br> .post(<br>'https://us-central1-shoppr-c97a7.cloudfunctions.net/payWithStripe', {<br> amount: 100,<br> currency: "usd",<br> token: token.id<br> })<br> .subscribe(data =&gt; {<br> console.log(data);<br> });<br>}</pre><p name="8813" class="graf graf--p graf-after--pre">A successful response from the server will look like following. It’s a long response, but you get the idea that everything you need is in there, right&nbsp;?</p><figure tabindex="0" contenteditable="false" name="2872" class="graf graf--figure graf--iframe is-defaultValue graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/6ce59b62486a9262ef536c27cfe22734.js %}</div></div></figure><h3 name="e869" class="graf graf--h3 graf-after--figure">Conclusion</h3><p name="0aa2" class="graf graf--p graf-after--h3">I know it is a long post with a lot to understand. Let me repeat the gist of the post&#8202;—&#8202;</p><p name="cc32" class="graf graf--p graf-after--p">Stripe payment consists of two parts&#8202;—&#8202;front-end (tokenization) and back-end (actual payment request). The Stripe payment integration will follow this pictorial flow</p></div><div class="section-inner sectionLayout--outsetColumn"><figure tabindex="0" contenteditable="false" name="985c" class="graf graf--figure graf--layoutOutsetCenter graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 1032px; max-height: 387px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 37.5%;"></div><img class="graf-image" data-image-id="1*T2zDo6nvDhko2_iwnTNYyA.jpeg" data-width="1200" data-height="450" src="https://cdn-images-1.medium.com/max/1200/1*T2zDo6nvDhko2_iwnTNYyA.jpeg"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Stripe Ionic 4 integration flow</figcaption></figure></div><div class="section-inner sectionLayout--insetColumn"><p name="cf38" class="graf graf--p graf-after--figure">Front-end part can be done using</p><ul class="postList"><li name="36b7" class="graf graf--li graf-after--p">Ionic Native Plugin&#8202;—&#8202;<strong class="markup--strong markup--li-strong">Apps</strong> / PWA</li><li name="465b" class="graf graf--li graf-after--li">Stripe.js (Stripe Elements)&#8202;—&#8202;Apps / <strong class="markup--strong markup--li-strong">PWA</strong></li></ul><p name="2eec" class="graf graf--p graf-after--li">Back-end part can be done using any server you have. For example purpose we used a Firebase server.</p><blockquote name="2e66" class="graf graf--blockquote graf-after--p">Complete source code of this tutorial is available in the <a href="https://github.com/enappd/ionic4-stripe"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank">Ionic4-stripe Github repository.</a></blockquote><p name="8331" class="graf graf--p graf-after--blockquote"><strong class="markup--strong markup--p-strong">Stay tuned for more Ionic 4 blogs&nbsp;!</strong></p><h3 name="1681" class="graf graf--h3 graf-after--p">FOUND THIS POST INTERESTING&nbsp;?</h3><p name="178a" class="graf graf--p graf-after--h3">Check out my other post on <a href="https://medium.com/enappd/ionic-4-paypal-payment-integration-for-apps-and-pwa-680b3f7ddb2f"  class="markup--anchor markup--p-anchor"    target="_blank">Ionic 4 PayPal payment integration&#8202;—&#8202;for Apps and PWA</a></p><p name="95a9" class="graf graf--p graf-after--p">Also check out our other blog posts related to <a href="https://medium.com/enappd/how-to-use-firebase-with-ionic-4-complete-guide-for-beginners-1888b1034024"  class="markup--anchor markup--p-anchor"    target="_blank">Firebase in Ionic 4</a>, <a href="https://medium.com/enappd/using-geolocation-and-beacon-plugins-in-ionic-4-754b41304007"  class="markup--anchor markup--p-anchor"    target="_blank">Geolocation</a> in Ionic 4, <a href="https://medium.com/enappd/qr-code-scanning-and-optical-character-recognition-ocr-in-ionic-4-95fd46be91dd"  class="markup--anchor markup--p-anchor"    target="_blank">QR Code and scanners</a> in Ionic 4 and <a href="https://medium.com/enappd/how-to-translate-in-ionic-4-globalization-internationalization-and-localization-31ec5807a8bc"  class="markup--anchor markup--p-anchor"    target="_blank">translations in Ionic 4</a></p><h3 name="362a" class="graf graf--h3 graf-after--p">NEED FREE IONIC 4 STARTERS?</h3><p name="eff2" class="graf graf--p graf-after--h3">You can also find free Ionic 4 starters on our website <a href="http://enappd.com"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">enappd.com</a></p><ul class="postList"><li name="2b12" class="graf graf--li graf-after--p"><a href="https://store.enappd.com/product/free-chat-themes-ionic4/"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">Free Chat Themes Starter for Ionic 4</a></li><li name="a4be" class="graf graf--li graf-after--li"><a href="https://medium.com/enappd/how-to-create-mobile-games-pwa-with-ionic4-and-phaser-7fb1e917678e"  class="markup--anchor markup--li-anchor"    target="_blank">Free Ionic 4&#8202;—&#8202;Phaser game framework integration</a></li></ul><p name="2930" class="graf graf--p graf-after--li">You can also make your next awesome app using <a href="https://store.enappd.com/product/ionic-4-full-app/"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">Ionic 4 Full App</a></p><h3 name="1b1c" class="graf graf--h3 graf-after--p">References</h3><ul class="postList"><li name="bb4a" class="graf graf--li graf-after--h3"><a href="https://ionicframework.com/docs"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">Ionic documentation</a></li></ul><p name="b360" class="graf graf--p graf--empty graf-after--li graf--trailing"><br></p></div></div></section></div></article></main>