2018-03-17 05:04:01 +08:00
import { Injectable } from '@angular/core' ;
import { Observable } from 'rxjs/Observable' ;
import {
Plugin ,
Cordova ,
IonicNativePlugin
} from '@ionic-native/core' ;
2017-12-02 12:03:40 +08:00
2018-03-17 05:04:01 +08:00
export type IMakePayments = 'This device can make payments and has a supported card' | 'This device cannot make payments.' | 'This device can make payments but has no supported cards' ;
2017-12-02 12:03:40 +08:00
export type IShippingType = 'shipping' | 'delivery' | 'store' | 'service' ;
2018-03-17 05:04:01 +08:00
export type IBillingRequirement = 'none' | 'all' | 'postcode' | 'name' | 'email' | 'phone' ;
export type ITransactionStatus = 'success' | 'failure' | 'invalid-billing-address' | 'invalid-shipping-address' | 'invalid-shipping-contact' | 'require-pin' | 'incorrect-pin' | 'locked-pin' ;
2017-12-09 03:56:53 +08:00
export type ICompleteTransaction = 'Payment status applied.' ;
2018-03-17 05:04:01 +08:00
export type IUpdateItemsAndShippingStatus = 'Updated List Info' | 'Did you make a payment request?' ;
2017-12-02 12:03:40 +08:00
export interface IPaymentResponse {
billingNameFirst? : string ;
2017-12-09 03:56:53 +08:00
billingNameMiddle? : string ;
2017-12-02 12:03:40 +08:00
billingNameLast? : string ;
2017-12-09 03:56:53 +08:00
billingEmailAddress? : string ;
2017-12-02 12:03:40 +08:00
billingSupplementarySubLocality? : string ;
2017-12-09 03:56:53 +08:00
billingAddressStreet? : string ;
billingAddressCity? : string ;
billingAddressState? : string ;
billingPostalCode? : string ;
2017-12-02 12:03:40 +08:00
billingCountry? : string ;
2017-12-09 03:56:53 +08:00
billingISOCountryCode? : string ;
shippingNameFirst? : string ;
shippingNameMiddle? : string ;
shippingNameLast? : string ;
shippingEmailAddress? : string ;
shippingPhoneNumber? : string ;
2017-12-02 12:03:40 +08:00
shippingSupplementarySubLocality? : string ;
2017-12-09 03:56:53 +08:00
shippingAddressStreet? : string ;
shippingAddressCity? : string ;
shippingAddressState? : string ;
shippingPostalCode? : string ;
shippingCountry? : string ;
shippingISOCountryCode? : string ;
paymentData : string ;
2017-12-02 12:03:40 +08:00
transactionIdentifier : string ;
paymentMethodDisplayName? : string ;
paymentMethodNetwork? : string ;
paymentMethodTypeCard? : string ;
}
export interface IOrderItem {
label : string ;
amount : number ;
}
2018-03-17 05:04:01 +08:00
export interface IShippingMethod {
2017-12-02 12:03:40 +08:00
identifier : string ;
label : string ;
detail : string ;
amount : number ;
}
2017-12-09 03:56:53 +08:00
export interface IOrderItemsAndShippingMethods {
2017-12-02 12:03:40 +08:00
items : IOrderItem [ ] ;
shippingMethods? : IShippingMethod [ ] ;
2017-12-09 03:56:53 +08:00
}
export interface IOrder extends IOrderItemsAndShippingMethods {
2017-12-02 12:03:40 +08:00
merchantIdentifier : string ;
currencyCode : string ;
countryCode : string ;
2017-12-09 03:56:53 +08:00
billingAddressRequirement? : IBillingRequirement | IBillingRequirement [ ] ;
shippingAddressRequirement? : IBillingRequirement | IBillingRequirement [ ] ;
shippingType? : IShippingType ;
2017-12-02 12:03:40 +08:00
}
2017-12-09 03:56:53 +08:00
export interface ISelectedShippingContact {
shippingAddressCity : string ;
shippingAddressState : string ;
shippingPostalCode : string ;
shippingISOCountryCode : string ;
}
2017-12-02 12:03:40 +08:00
/ * *
* @name Apple Pay
* @description
* A dependency free Cordova plugin to provide Apple Pay functionality .
*
* @usage
* ` ` ` typescript
* import { ApplePay } from '@ionic-native/apple-pay' ;
*
*
* constructor ( private applePay : ApplePay ) { }
*
* . . .
2017-12-09 03:56:53 +08:00
* async applePay() {
* // This block is optional -- only if you need to update order items/shipping
* // methods in response to shipping method selections
* this . applePay . startListeningForShippingContactSelection ( )
* . subscribe ( async selection = > {
* try {
* await this . applePay . updateItemsAndShippingMethods ( {
* items : getFromSelection ( selection ) ,
* shippingMethods : getFromSelection ( selection ) ,
* } ) ;
* }
* catch {
* // handle update items error
* }
* } ) ;
2017-12-02 12:03:40 +08:00
*
2017-12-09 03:56:53 +08:00
* try {
* const applePayTransaction = await this . applePay . makePaymentRequest ( {
* items ,
* shippingMethods ,
* merchantIdentifier ,
* currencyCode ,
* countryCode ,
* billingAddressRequirement : [ 'name' , 'email' , 'phone' ] ,
* shippingAddressRequirement : 'none' ,
* shippingType : 'shipping'
* } ) ;
2017-12-02 12:03:40 +08:00
*
2017-12-09 03:56:53 +08:00
* const transactionStatus = await completeTransactionWithMerchant ( applePayTransaction ) ;
* await this . applePay . completeLastTransaction ( transactionStatus ) ;
* } catch {
* // handle payment request error
* // Can also handle stop complete transaction but these should normally not occur
* }
2017-12-02 12:03:40 +08:00
*
2017-12-09 03:56:53 +08:00
* // only if you started listening before
* await this . applePay . stopListeningForShippingContactSelection ( ) ;
* }
2017-12-02 12:03:40 +08:00
* ` ` `
* /
@Plugin ( {
pluginName : 'ApplePay' ,
plugin : 'cordova-plugin-applepay' ,
pluginRef : 'ApplePay' ,
2017-12-09 03:56:53 +08:00
repo : 'https://github.com/samkelleher/cordova-plugin-applepay' ,
2018-03-17 05:04:01 +08:00
platforms : [ 'iOS' ] ,
2017-12-02 12:03:40 +08:00
} )
@Injectable ( )
export class ApplePay extends IonicNativePlugin {
2018-03-17 05:04:01 +08:00
2017-12-02 12:03:40 +08:00
/ * *
* Detects if the current device supports Apple Pay and has any capable cards registered .
* @return { Promise < IMakePayments > } Returns a promise
*
* @usage
2017-12-09 03:56:53 +08:00
* try {
* const message = await this . applePay . canMakePayments ( ) ;
* // Apple Pay is enabled and a supported card is setup. Expect:
* // 'This device can make payments and has a supported card'
* } catch ( message ) {
* // There is an issue, examine the message to see the details, will be:
* // 'This device cannot make payments.''
* // 'This device can make payments but has no supported cards'
* }
2017-12-02 12:03:40 +08:00
* /
@Cordova ( {
otherPromise : true
} )
canMakePayments ( ) : Promise < IMakePayments > {
return ;
}
2017-12-09 03:56:53 +08:00
/ * *
* Starts listening for shipping contact selection changes
* Any time the user selects shipping contact , this callback will fire .
* You * must * call ` updateItemsAndShippingMethods ` in response or else the
* user will not be able to process payment .
* @return { Observable < ISelectedShippingContact > } emits with shipping contact information on
* shipping contact selection changes
* /
@Cordova ( {
observable : true ,
clearFunction : 'stopListeningForShippingContactSelection'
} )
2018-03-17 05:04:01 +08:00
startListeningForShippingContactSelection ( ) : Observable < ISelectedShippingContact > {
2017-12-09 03:56:53 +08:00
return ;
}
/ * *
* Stops listening for shipping contact selection changes
* @return { Promise } whether stop listening was successful . This should
* really only fail if this is called without starting listening
* /
@Cordova ( {
otherPromise : true
} )
stopListeningForShippingContactSelection ( ) : Promise < boolean > {
return ;
}
/ * *
* Update the list of pay sheet items and shipping methods in response to
* a shipping contact selection event . This * must * be called in response to
* any shipping contact selection event or else the user will not be able
* to complete a transaction on the pay sheet . Do not call without
* subscribing to shipping contact selection events first
* @returns { Promise }
*
* @param { Object } including ` items ` and ` shippingMethods ` properties .
*
* @usage
* this . applePay . startListeningForShippingContactSelection ( ) . pluck ( 'shippingAddressState' ) . subscribe ( shippingAddressState = > {
* let shippingMethods ;
* if ( 'AK' === shippingAddressState ) {
* shippingMethods = [ {
* identifier : 'Alaska' ,
* label : 'Alaska' ,
* detail : 'For shipping to Alaska' ,
* amount : 9.99
* } , ] ;
* } else {
* shippingMethods = [ {
* identifier : 'Continental' ,
* label : 'Continental' ,
* detail : 'For shipping Continentally' ,
* amount : 5.99
* } ] ;
* }
* this . paySheetItems . shippingCost = {
* label : 'Shipping Cost' ,
* amount : shippingMethod [ 0 ] . amount
* } ;
* this . applePay . updateItemsAndShippingMethods ( this . paySheetItems , shippingMethods ) ;
* } ) ;
* /
@Cordova ( {
otherPromise : true
} )
2018-03-17 05:04:01 +08:00
updateItemsAndShippingMethods ( list : IOrderItemsAndShippingMethods ) : Promise < IUpdateItemsAndShippingStatus > {
2017-12-09 03:56:53 +08:00
return ;
}
2017-12-02 12:03:40 +08:00
/ * *
* Request a payment with Apple Pay
* @return { Promise < IPaymentResponse > } Returns a promise that resolves when something happens
*
* @param order { IOrder }
*
* @usage
2017-12-09 03:56:53 +08:00
* try {
* const paymentResponse = this . applePay . makePaymentRequest ( {
* items : [
* {
* label : '3 x Basket Items' ,
* amount : 49.99
* } ,
* {
* label : 'Next Day Delivery' ,
* amount : 3.99
* } ,
* {
* label : 'My Fashion Company' ,
* amount : 53.98
* }
* ] ,
* shippingMethods : [
* {
* identifier : 'NextDay' ,
* label : 'NextDay' ,
* detail : 'Arrives tomorrow by 5pm.' ,
* amount : 3.99
* } ,
* {
* identifier : 'Standard' ,
* label : 'Standard' ,
* detail : 'Arrive by Friday.' ,
* amount : 4.99
* } ,
* {
* identifier : 'SaturdayDelivery' ,
* label : 'Saturday' ,
* detail : 'Arrive by 5pm this Saturday.' ,
* amount : 6.99
* }
* ] ,
* merchantIdentifier : 'merchant.apple.test' ,
* currencyCode : 'GBP' ,
* countryCode : 'GB' ,
* billingAddressRequirement : 'none' ,
* shippingAddressRequirement : 'none' ,
* shippingType : 'shipping' ,
* } ) ;
*
* // The user has authorized the payment.
*
* // Handle the token, asynchronously, i.e. pass to your merchant bank to
* // action the payment, then once finished, depending on the outcome:
*
* // Here is an example implementation:
*
* const captureStatus = await MyPaymentProvider . authorizeApplePayToken ( paymentResponse . paymentData ) ;
* await this . applePay . completeLastTransaction ( 'success' ) ;
* }
* catch ( err ) {
* if ( isPaymentAuthError ( err ) ) {
* this . completeLastTransaction ( 'failure' ) ;
* }
* else {
* // Failed to open pay sheet or user canceled payment
* }
* }
2017-12-02 12:03:40 +08:00
* /
@Cordova ( {
otherPromise : true
} )
makePaymentRequest ( order : IOrder ) : Promise < IPaymentResponse > {
return ;
}
/ * *
* Once the makePaymentRequest has been resolved successfully , the device will be waiting for a completion event .
* This means , that the application must proceed with the token authorisation and return a success , failure ,
* or other validation error . Once this has been passed back , the Apple Pay sheet will be dismissed via an animation .
2017-12-09 03:56:53 +08:00
* @return { Promise < ICompleteTransaction > } Returns a promise that resolves after confirmation of payment authorization completion
2017-12-02 12:03:40 +08:00
*
* @param complete { ITransactionStatus }
*
* /
2017-12-09 03:56:53 +08:00
@Cordova ( {
otherPromise : true
} )
2018-03-17 05:04:01 +08:00
completeLastTransaction ( complete : ITransactionStatus ) : Promise < ICompleteTransaction > {
2017-12-09 03:56:53 +08:00
return ;
2017-12-02 12:03:40 +08:00
}
}