Ionic Card IO – prikupljanje podataka s bankovne kartice

U ovom ću blog postu pokazati kako napraviti jednostavnu Ionic aplikaciju koja će imati mogućnost prikupljanja podataka s bankovne kartice kako bi se moglo provesti plaćanje.

Važna napomena! Ovdje navedeni primjer tiče se samo klijentske strane i plaćanje neće biti provedeno. Za to je potreban i backend koji je moguće napraviti u npr. NodeJS-u.

Što je Card IO?

https://www.card.io/ omogućava skeniranje bankovne kartice kako bi se olakšalo i ubrzalo plaćanje.

Više o funkcionalnostima moguće je pronaći na poveznici https://github.com/card-io/card.io-Cordova-Plugin ili unutar dokumentacije Ionic Native 3.x Card IO plugina

Nekoliko je opcionalnih parametara koji se mogu koristiti prilikom skeniranja bankovne kartice unutar CardIOOptions objekta:

– requireExpiry (boolean) – Set to true to require expiry date
– requireCVV (boolean) – The user will be prompted for the card CVV
– requirePostalCode (boolean) – The user will be prompted for the card billing postal code.
– suppressManual (boolean) – Removes the keyboard button from the scan screen.
– restrictPostalCodeToNumericOnly (boolean) – The postal code will only collect numeric input. Set this if you know the expected country’s postal code has only numeric postal codes.
– keepApplicationTheme (boolean) – The theme for the card.io Activity’s will be set to the theme of the application.
– requireCardholderName (boolean) – The user will be prompted for the cardholder name
– scanInstructions (string) – Used to display instructions to the user while they are scanning their card.
– noCamera (boolean) – If set, the card will not be scanned with the camera.
– scanExpiry (boolean) – If scanExpiry is true, an attempt to extract the expiry from the card image will be made.
– languageOrLocale (string) – The preferred language for all strings appearing in the user interface. If not set, or if set to null, defaults to the device’s current language setting.
– guideColor (string | number) – Changes the color of the guide overlay on the camera. The color is provided in hexadecimal format (e.g. #FFFFFF)
– supressConfirmation (boolean) – The user will not be prompted to confirm their card number after processing.
– hideCardIOLogo (boolean) – The card.io logo will not be shown overlaid on the camera.
– useCardIOLogo (boolean) – The card.io logo will be shown instead of the PayPal logo.
– supressScan (boolean) – Once a card image has been captured but before it has been processed, this value will determine whether to continue processing as usual.

S druge strane, tu je i CardIOResponse objekt unutar kojega je moguće odrediti koje informacije želimo dobiti nakon što se uspješno obavi skeniranje bankovne kartice.

- cardType (string) - Card type
- redactedCardNumber (string) - Masked card number, showing only last 4 digits
- cardNumber (string) - Full card number
- expiryMonth (number) - Expiry month
- expiryYear (number) - Expiry year
- cvv (string) - CVV
- postalCode (string) - Postal code
- cardholderName (string) - Cardholder name

Kreiranje aplikacije

Kreiram novi Ionic projekt i odmah dodajem Android platformu.

$ ionic start IonicCardIO blank
$ cd IonicCardIO
$ ionic cordova platform add android

Card IO implementacija

Za početak, instaliram Ionic Native 3.x plugin Card IO.

$ ionic cordova plugin add card.io.cordova.mobilesdk
$ npm install --save @ionic-native/card-io

Nakon toga ovaj plugin deklariram unutar app.module.ts datoteke.

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { CardIO } from '@ionic-native/card-io';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    CardIO,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Sadržaj ekrana neće sadržavati ništa posebno. Glavna funkcionalnost krije se iza gumba tj. funkcije scanCard().

Ipak, kako bi se kartica mogla uslikati potrebno je dati odobrenje koje će biti automatski zatraženo prilikom prvog pokretanja aplikacije.

Ionic Card IO - početni ekran

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      Ionic CardIO
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-fab bottom right>
        <button ion-fab (click)="scanCard()">
          <ion-icon name="card"></ion-icon>
        </button>
  </ion-fab>
</ion-content>

Funkcionalnost se nalazi unutar home.ts datoteke tj. unutar HomePage klase.

import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';

import { CardIO, CardIOOptions, CardIOResponse } from '@ionic-native/card-io';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  results: CardIOResponse;

  constructor(public navCtrl: NavController,
              private _platform: Platform,
              private _cardIO: CardIO) {
  }

  async scanCard(){
    try {
      await this._platform.ready();
      const canScan = await this._cardIO.canScan();
      if(canScan){
         const options: CardIOOptions = {
          scanInstructions: "Skenirajte bankovnu karticu!",
         };
         this.results = await this._cardIO.scan(options);
         console.log(this.results);
      }
    }
    catch (e) {
      console.error(e);
    }
  }

}

Vezano uz ranije navedeni CardIOOptions objekt, ako ga postavim na sljedeći način

const options: CardIOOptions = {
          requireExpiry: true,
          requireCVV: true,
          requirePostalCode: true,
          suppressManual: false,
          restrictPostalCodeToNumericOnly: false,
          keepApplicationTheme: true,
          requireCardholderName: true,
          scanInstructions: "Skenirajte bankovnu karticu!",
          noCamera: false,
          scanExpiry: true,
          languageOrLocale: "HR",
          guideColor: "#488aff",
          supressConfirmation: false,
          hideCardIOLogo: false,
          useCardIOLogo: true,
          supressScan: false
};

Ekran za skeniranje tj. za ručni unos podataka s bankovne kartice izgleda ovako:

Ionic Card IO

Međutim, ako to malo drugačije posložim

const options: CardIOOptions = {
          requireExpiry: true,
          requireCVV: true,
          requirePostalCode: false,
          suppressManual: false,
          restrictPostalCodeToNumericOnly: false,
          keepApplicationTheme: true,
          requireCardholderName: true,
          scanInstructions: "Skenirajte bankovnu karticu!",
          noCamera: false,
          scanExpiry: true,
          languageOrLocale: "HR",
          guideColor: "#488aff",
          supressConfirmation: false,
          hideCardIOLogo: false,
          useCardIOLogo: false,
          supressScan: false
};

i ekrani će izgledati drugačije

Ionic Card IO

S obzirom da u ovom primjeru ne želim koristiti svoju karticu iskoristit ću dostupne demo podatke sa adrese https://www.datatrans.ch/showcase/test-cc-numbers

Test card numbers

Prikupit ću podatke s dvije kartice.

Ionic Card IO

Što unutar Chrome Developer konzole izgleda ovako:

Ionic Card IO

Zaključak

Struktura aplikacije prema package.json

{
  "name": "IonicCardIO",
  "version": "0.0.1",
  "author": "Tomislav Stanković",
  "homepage": "https://www.tomislavstankovic.com/",
  "private": true,
  "scripts": {
    "start": "ionic-app-scripts serve",
    "clean": "ionic-app-scripts clean",
    "build": "ionic-app-scripts build",
    "lint": "ionic-app-scripts lint"
  },
  "dependencies": {
    "@angular/animations": "5.2.11",
    "@angular/common": "5.2.11",
    "@angular/compiler": "5.2.11",
    "@angular/compiler-cli": "5.2.11",
    "@angular/core": "5.2.11",
    "@angular/forms": "5.2.11",
    "@angular/http": "5.2.11",
    "@angular/platform-browser": "5.2.11",
    "@angular/platform-browser-dynamic": "5.2.11",
    "@ionic-native/card-io": "^4.19.0",
    "@ionic-native/core": "~4.18.0",
    "@ionic-native/splash-screen": "~4.18.0",
    "@ionic-native/status-bar": "~4.18.0",
    "@ionic/storage": "2.2.0",
    "card.io.cordova.mobilesdk": "2.1.0",
    "cordova-android": "7.1.4",
    "cordova-plugin-device": "^2.0.2",
    "cordova-plugin-ionic-keyboard": "^2.1.3",
    "cordova-plugin-ionic-webview": "^2.3.2",
    "cordova-plugin-splashscreen": "^5.0.2",
    "cordova-plugin-statusbar": "^2.4.2",
    "cordova-plugin-whitelist": "^1.3.3",
    "ionic-angular": "3.9.2",
    "ionicons": "3.0.0",
    "rxjs": "5.5.11",
    "sw-toolbox": "3.6.0",
    "zone.js": "0.8.26"
  },
  "devDependencies": {
    "@ionic/app-scripts": "3.2.1",
    "typescript": "~2.6.2"
  },
  "description": "An Ionic project",
  "cordova": {
    "plugins": {
      "card.io.cordova.mobilesdk": {},
      "cordova-plugin-whitelist": {},
      "cordova-plugin-statusbar": {},
      "cordova-plugin-device": {},
      "cordova-plugin-splashscreen": {},
      "cordova-plugin-ionic-webview": {
        "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
      },
      "cordova-plugin-ionic-keyboard": {}
    },
    "platforms": [
      "android"
    ]
  }
}

Ionic 3 – uspostavljanje telefonskog poziva

Iako se poziv može uspostaviti i korištenjem

<a href="tel:0101010101">Zovi</a> 

ipak je korisno imati više mogućnosti koje pruža Call Number plugin.

Kreiranje aplikacije

Kreiram novi Ionic projekt i odmah dodajem Android platformu.

$ ionic start IonicCallNumber --blank
$ cd IonicCallNumber
$ ionic cordova platform add android

Call Number

Plugin Call Number dodajem sljedećim naredbama:

$ ionic cordova plugin add call-number
$ npm install --save @ionic-native/call-number

Naravno, nakon toga ovaj plugin deklariram unutar app.module.ts datoteke.

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { CallNumber } from '@ionic-native/call-number';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    CallNumber,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Ekran za uspostavljanje poziva sadržavati će samo jedan gumb.

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Call Number
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <button ion-button (click)="call()">Zovi</button>
</ion-content>

Funkcionalnost se sastoji od pozivanja call() funkcije.

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import { CallNumber } from '@ionic-native/call-number';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public _navCtrl: NavController,
              private _callNumber: CallNumber) {
  }

  async call(){
     try {
       await this._callNumber.callNumber('0101010101', false);
       console.log("Pozivam broj.");
     }
     catch(e){
      console.error(e);
     }
  }

}

Kao što se može vidjeti u dokumentaciji https://ionicframework.com/docs/native/call-number/ dva su parametra koja mogu koristiti prilikom uspostavljanja poziva.

Param Type Details
numberToCall string The phone number to call as a string
bypassAppChooser boolean Set to true to bypass the app chooser and go directly to dialer

U mojem primjeru koristio sam false zato što želim da me aplikacija puta putem koje aplikacije želim uspostaviti poziv.

Nakon klik na gumb za uspostavu poziva napuštam Ionic aplikaciju.

Ionic 3 – uspostavljanje telefonskog poziva

U tom trenutku prvo što se događa je to da Ionic aplikacija traži dozvolu za korištenje te funkcionalnosti. Nakon što se dobije dozvola biti će mi ponuđene sve aplikacije koje imam instalirane na mobilnom uređaju, a koje imaju mogućnost uspostavljanja poziva. Da sam u gornjem primjeru koristio true umjesto false u tom mi se slučaju ne bi prikazao taj popis aplikacija nego bi se poziv uspostavio odmah.

Ionic 3 – uspostavljanje telefonskog poziva

Zaključak

Struktura aplikacije prema package.json

{
  "name": "IonicCallNumber",
  "version": "0.0.1",
  "author": "Tomislav Stanković",
  "homepage": "https://www.tomislavstankovic.com/",
  "private": true,
  "scripts": {
    "start": "ionic-app-scripts serve",
    "clean": "ionic-app-scripts clean",
    "build": "ionic-app-scripts build",
    "lint": "ionic-app-scripts lint"
  },
  "dependencies": {
    "@angular/animations": "5.2.11",
    "@angular/common": "5.2.11",
    "@angular/compiler": "5.2.11",
    "@angular/compiler-cli": "5.2.11",
    "@angular/core": "5.2.11",
    "@angular/forms": "5.2.11",
    "@angular/http": "5.2.11",
    "@angular/platform-browser": "5.2.11",
    "@angular/platform-browser-dynamic": "5.2.11",
    "@ionic-native/call-number": "^4.18.0",
    "@ionic-native/core": "~4.18.0",
    "@ionic-native/splash-screen": "~4.18.0",
    "@ionic-native/status-bar": "~4.18.0",
    "@ionic/storage": "2.2.0",
    "call-number": "^1.0.1",
    "cordova-android": "7.0.0",
    "cordova-plugin-device": "^2.0.2",
    "cordova-plugin-ionic-keyboard": "^2.1.3",
    "cordova-plugin-ionic-webview": "^2.3.1",
    "cordova-plugin-splashscreen": "^5.0.2",
    "cordova-plugin-statusbar": "^2.4.2",
    "cordova-plugin-whitelist": "^1.3.3",
    "ionic-angular": "3.9.2",
    "ionicons": "3.0.0",
    "mx.ferreyra.callnumber": "~0.0.2",
    "rxjs": "5.5.11",
    "sw-toolbox": "3.6.0",
    "zone.js": "0.8.26"
  },
  "devDependencies": {
    "@ionic/app-scripts": "3.2.1",
    "typescript": "~2.6.2"
  },
  "description": "An Ionic Call Number project",
  "cordova": {
    "plugins": {
      "mx.ferreyra.callnumber": {},
      "cordova-plugin-whitelist": {},
      "cordova-plugin-statusbar": {},
      "cordova-plugin-device": {},
      "cordova-plugin-splashscreen": {},
      "cordova-plugin-ionic-webview": {
        "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
      },
      "cordova-plugin-ionic-keyboard": {}
    },
    "platforms": [
      "android"
    ]
  }
}

Ionic geolociranje – dohvaćanje i prikaz lokacije korisnika

Ranije sam već objavio jedan blog post na temu prikaza Google karte međutim ondje kao početnu lokaciju koristim zadane koordinate Vinkovaca.

loadMap(){
  let latLng = new google.maps.LatLng('45.287906','18.805678');
  let mapOptions = {
     center:latLng,
     zoom:11,
     mapTypeId: google.maps.MapTypeId.ROADMAP
}

I to je u redu opcija ako će korisnici aplikacije biti iz Vinkovaca, ali ako se korisnik nalazi u bilo kojem drugom mjestu neće baš imati koristi od aplikacije koja mu kao zadanu lokaciju prikazuje mjesto gdje on nije.

Zato moram pronaći način kako dinamički dohvatiti lokaciju korisnika u trenutku kada on pokreće mobilnu aplikaciju ili u trenutku kada on unutar mobilne aplikacije ode na dio koji mu prikazuje Google kartu.

Kako dohvatiti lokaciju korisnika?

U ovom slučaju mogu koristiti Ionic Native Geolocation plugin koji će mi omogućiti dohvaćanje lokacije korisnika (koordinate).

This plugin provides information about the device’s location, such as latitude and longitude. Common sources of location information include Global Positioning System (GPS) and location inferred from network signals such as IP address, RFID, WiFi and Bluetooth MAC addresses, and GSM/CDMA cell IDs.

Plugin instaliram sljedećim naredbama:

$ ionic cordova plugin add cordova-plugin-geolocation --variable GEOLOCATION_USAGE_DESCRIPTION="To locate you"
$ npm install --save @ionic-native/geolocation

Odmah nakon instalacije plugin deklariram unutar app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { Geolocation } from '@ionic-native/geolocation';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    Geolocation,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Sada sam spreman za praktičan prikaz dohvaćanja lokacije korisnika. To radim pozivanjem funkcije mojaLokacija().

Korisnik mora odobriti Ionic aplikaciji dohvaćanje lokacije.

Ionic geolociranje – dinamičko dohvaćanje lokacije korisnika

U ovom slučaju tek nakon što sam dobio koordinate korisnika pozivam funkciju this.loadMap(resp.coords.latitude, resp.coords.longitude); koja će prikazati Google kartu na ekranu, a korisnikova lokacija biti će na sredini ekrana.

 mojaLokacija(){
    let options = {
      enableHighAccuracy: true
    };
    this._geolocation.getCurrentPosition(options).then((resp) => {
      console.log(resp);
      if(resp.coords.latitude && resp.coords.longitude){
         this.loadMap(resp.coords.latitude, resp.coords.longitude);
      }
     }).catch((error) => {
      console.log('Error getting location', error);
     });
  }

Ionic geolociranje – dinamičko dohvaćanje lokacije korisnika

Međutim, ovdje postoji jedan problem. Da bi ovo iznad bilo moguće na mobilnom uređaju u postavkama mora biti omogućeno dohvaćanje lokacije.

Android postavke uređaja

Komponenta na kraju sa svim funkcionalnostima izgleda ovako:

import { Component, ViewChild, ElementRef } from '@angular/core';
import { NavController } from 'ionic-angular';

import { Geolocation } from '@ionic-native/geolocation';

declare var google;

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  @ViewChild('map') mapElmt: ElementRef;
  map: any;

  constructor(public _navCtrl: NavController,
              private _geolocation: Geolocation) {
  }

  ionViewDidEnter(){
    this.mojaLokacija();
  }

  mojaLokacija(){
    let options = {
      enableHighAccuracy: true
    };
    this._geolocation.getCurrentPosition(options).then((resp) => {
      console.log(resp);
      if(resp.coords.latitude && resp.coords.longitude){
         this.loadMap(resp.coords.latitude, resp.coords.longitude);
      }
     }).catch((error) => {
      console.log('Error getting location', error);
     });
  }

  loadMap(latitude, longitude){
    let latLng = new google.maps.LatLng(latitude,longitude);
    let mapOptions = {
      center:latLng,
      zoom:13,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    this.map = new google.maps.Map(this.mapElmt.nativeElement, mapOptions);
  }

}

Ako to nije uključeno unutar Ionic aplikacije neće se prikazati ništa tj. ekran će biti prazan jer se funkcija za prikaz Google karte neće niti učitati jer nema koordinara. U slučaju da su varijable s koordinatama prazne prikazat će se zadana lokacija negdje u Africi na moru.

Ionic geolociranje – dinamičko dohvaćanje lokacije korisnika

Naravno da ovo ne želim dopustiti i da korisnik Ionic aplikacije treba biti obaviješten o čemu se radi tj. ako želi koristiti određenu funkcionalnost mobilne aplikacije treba dati lokaciju uređaja. Korisnik čak ne mora niti znati da mu su mu postavke lokacije isključene i zato moram pronaći način kako da to saznam i omogućim mu da to uključi.

Android – upravljanje postavkama lokacije

Pomoću plugina Ionic Native Diagnostic mogu saznati je li dohvaćanje lokacije omogućeno na tom konkretnom Android uređaju. U slučaju kada nije imam mogućnost obavijestiti korisnika i omogućiti mu da uključi lociranje.

Checks whether device hardware features are enabled or available to the app, e.g. camera, GPS, wifi

Plugin instaliram sljedećim naredbama:

$ ionic cordova plugin add cordova.plugins.diagnostic
$ npm install --save @ionic-native/diagnostic

Odmah nakon instalacije plugin deklariram unutar app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { Geolocation } from '@ionic-native/geolocation';
import { Diagnostic } from '@ionic-native/diagnostic';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    Geolocation,
    Diagnostic,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Sada mogu testirati ovu opciju.

Ako sada pokrenem aplikaciju dobijem sljedeće

Ionic geolociranje – dinamičko dohvaćanje lokacije korisnika

Klikom na “UKLJUČI” otvaraju se postavke u kojima je moguće uključiti geolociranje.

Postavke lokacije - Android

Sva se funkcionalnost nalazi unutar funkcije provjeraLokacije().

provjeraLokacije(){
    this._diagnostic.isLocationEnabled()
    .then((state) => {
      console.log(state);
      if (state == true){
        this.mojaLokacija();
      } else {
        let alert = this._alertCtrl.create({
          title: 'Želite li uključiti geolociranje?',
          message: 'Geolociranje koristimo kako bismo Vam omogućili prikaz objekata u Vašoj blizini.',
          buttons: [
            {
              text: 'Odustani',
              role: 'cancel',
              handler: () => {
                //
              }
            },
            {
              text: 'Uključi',
              handler: () => {
                this._diagnostic.switchToLocationSettings();
              }
            }
          ]
        });
        alert.present();
      } 
    }).catch(e => console.error(e));
  }

Komponenta na kraju sa svim funkcionalnostima izgleda ovako:

import { Component, ViewChild, ElementRef } from '@angular/core';
import { NavController, AlertController } from 'ionic-angular';

import { Geolocation } from '@ionic-native/geolocation';
import { Diagnostic } from '@ionic-native/diagnostic';

declare var google;

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  @ViewChild('map') mapElmt: ElementRef;
  map: any;

  constructor(public _navCtrl: NavController,
              private _geolocation: Geolocation,
              private _diagnostic: Diagnostic,
              public _alertCtrl: AlertController) {
  }

  ionViewDidEnter(){
    this.provjeraLokacije();
  }

  mojaLokacija(){
    let options = {
      enableHighAccuracy: true
    };
    this._geolocation.getCurrentPosition(options).then((resp) => {
      console.log(resp);
      if(resp.coords.latitude && resp.coords.longitude){
         this.loadMap(resp.coords.latitude, resp.coords.longitude);
      }
     }).catch((error) => {
      console.log('Error getting location', error);
     });
  }

  provjeraLokacije(){
    this._diagnostic.isLocationEnabled()
    .then((state) => {
      console.log(state);
      if (state == true){
        this.mojaLokacija();
      } else {
        let alert = this._alertCtrl.create({
          title: 'Želite li uključiti geolociranje?',
          message: 'Geolociranje koristimo kako bismo Vam omogućili prikaz objekata u Vašoj blizini.',
          buttons: [
            {
              text: 'Odustani',
              role: 'cancel',
              handler: () => {
                //
              }
            },
            {
              text: 'Uključi',
              handler: () => {
                this._diagnostic.switchToLocationSettings();
              }
            }
          ]
        });
        alert.present();
      } 
    }).catch(e => console.error(e));
  }

  loadMap(latitude, longitude){
    let latLng = new google.maps.LatLng(latitude,longitude);
    let mapOptions = {
      center:latLng,
      zoom:13,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    this.map = new google.maps.Map(this.mapElmt.nativeElement, mapOptions);
  }

}

Zaključak

Struktura projekta prema package.json

{
  "name": "IonicGeolocation",
  "version": "0.0.1",
  "author": "Tomislav Stanković",
  "homepage": "https://www.tomislavstankovic.com/",
  "private": true,
  "scripts": {
    "start": "ionic-app-scripts serve",
    "clean": "ionic-app-scripts clean",
    "build": "ionic-app-scripts build",
    "lint": "ionic-app-scripts lint"
  },
  "dependencies": {
    "@angular/animations": "5.2.11",
    "@angular/common": "5.2.11",
    "@angular/compiler": "5.2.11",
    "@angular/compiler-cli": "5.2.11",
    "@angular/core": "5.2.11",
    "@angular/forms": "5.2.11",
    "@angular/http": "5.2.11",
    "@angular/platform-browser": "5.2.11",
    "@angular/platform-browser-dynamic": "5.2.11",
    "@ionic-native/core": "~4.17.0",
    "@ionic-native/diagnostic": "^4.18.0",
    "@ionic-native/geolocation": "^4.18.0",
    "@ionic-native/splash-screen": "~4.17.0",
    "@ionic-native/status-bar": "~4.17.0",
    "@ionic/storage": "2.2.0",
    "cordova-android": "7.0.0",
    "cordova-plugin-device": "^2.0.2",
    "cordova-plugin-geolocation": "^4.0.1",
    "cordova-plugin-ionic-keyboard": "^2.1.3",
    "cordova-plugin-ionic-webview": "^2.2.5",
    "cordova-plugin-splashscreen": "^5.0.2",
    "cordova-plugin-statusbar": "^2.4.2",
    "cordova-plugin-whitelist": "^1.3.3",
    "cordova.plugins.diagnostic": "^4.0.10",
    "ionic-angular": "3.9.2",
    "ionicons": "3.0.0",
    "rxjs": "5.5.11",
    "sw-toolbox": "3.6.0",
    "zone.js": "0.8.26"
  },
  "devDependencies": {
    "@ionic/app-scripts": "3.2.1",
    "typescript": "~2.6.2"
  },
  "description": "An Ionic Geolocation project",
  "cordova": {
    "plugins": {
      "cordova-plugin-whitelist": {},
      "cordova-plugin-statusbar": {},
      "cordova-plugin-device": {},
      "cordova-plugin-splashscreen": {},
      "cordova-plugin-ionic-webview": {
        "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
      },
      "cordova-plugin-ionic-keyboard": {},
      "cordova-plugin-geolocation": {
        "GEOLOCATION_USAGE_DESCRIPTION": "To locate you"
      },
      "cordova.plugins.diagnostic": {}
    },
    "platforms": [
      "android"
    ]
  }
}

Ionic 3 Market

U ovom ću blog postu pokazati kako unutar Ionic aplikacije direktno pristupiti nekoj drugoj aplikaciji koja se nalazi na Google Play Store ili Apple Store koristeći Ionic Native Market plugin.

Kreiranje aplikacije

Za početak kreiram novu Ionic aplikaciju.

$ ionic start IonicMarket blank
$ cd IonicMarket
$ ionic cordova platform add android

Pristup trgovini aplikacija

Prema službenoj dokumentaciji, Market plugin instaliram sljedećim naredbama:

$ ionic cordova plugin add cordova-plugin-market
$ npm install --save @ionic-native/market

Navodim ga unutar app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { Market } from '@ionic-native/market';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    Market,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Sada ću na početnoj stranici home.ts kreirati funkciju pokaziAplikaciju() koja će biti aktivirana prilikom klika na gumb. Toj funkciji proslijedim jedan parametar, a to je ID aplikacije.

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import { Market } from '@ionic-native/market';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController,
              private _market: Market) {
  }

  pokaziAplikaciju(){
    this._market.open('com.roadhousegames.lotb');
  }

}

Na ekranu će se nalaziti samo jedan gumb.

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic 3 Market App
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <button (click)="pokaziAplikaciju()" ion-button full>Pokazi aplikaciju</button>
</ion-content>

Konačan rezultat vidi se na sljedećoj slici:

Ionic 3 Market

Zaključak

Ovaj plugin na vrlo jednostavan način rješava potrebu otvaranja Google Play Store tj. Apple Store trgovine unutar Ionic aplikacije.

Struktura aplikacije prema package.json

{
  "name": "IonicMarket",
  "version": "0.0.1",
  "author": "Tomislav Stanković",
  "homepage": "https://www.tomislavstankovic.com/",
  "private": true,
  "scripts": {
    "start": "ionic-app-scripts serve",
    "clean": "ionic-app-scripts clean",
    "build": "ionic-app-scripts build",
    "lint": "ionic-app-scripts lint"
  },
  "dependencies": {
    "@angular/animations": "5.2.11",
    "@angular/common": "5.2.11",
    "@angular/compiler": "5.2.11",
    "@angular/compiler-cli": "5.2.11",
    "@angular/core": "5.2.11",
    "@angular/forms": "5.2.11",
    "@angular/http": "5.2.11",
    "@angular/platform-browser": "5.2.11",
    "@angular/platform-browser-dynamic": "5.2.11",
    "@ionic-native/core": "~4.10.0",
    "@ionic-native/market": "^4.10.0",
    "@ionic-native/splash-screen": "~4.10.0",
    "@ionic-native/status-bar": "~4.10.0",
    "@ionic/storage": "2.1.3",
    "cordova-android": "7.0.0",
    "cordova-plugin-device": "^2.0.2",
    "cordova-plugin-ionic-keyboard": "^2.0.5",
    "cordova-plugin-ionic-webview": "^1.1.19",
    "cordova-plugin-market": "^1.2.0",
    "cordova-plugin-splashscreen": "^5.0.2",
    "cordova-plugin-whitelist": "^1.3.3",
    "ionic-angular": "3.9.2",
    "ionicons": "3.0.0",
    "rxjs": "5.5.11",
    "sw-toolbox": "3.6.0",
    "zone.js": "0.8.26"
  },
  "devDependencies": {
    "@ionic/app-scripts": "3.1.11",
    "typescript": "~2.6.2"
  },
  "description": "Ionic Market App",
  "cordova": {
    "plugins": {
      "cordova-plugin-market": {},
      "cordova-plugin-whitelist": {},
      "cordova-plugin-device": {},
      "cordova-plugin-splashscreen": {},
      "cordova-plugin-ionic-webview": {},
      "cordova-plugin-ionic-keyboard": {}
    },
    "platforms": [
      "android"
    ]
  }
}