diff --git a/src/@ionic-native/plugins/apple-pay/index.ts b/src/@ionic-native/plugins/apple-pay/index.ts index 552d075fa5..1995cb4965 100644 --- a/src/@ionic-native/plugins/apple-pay/index.ts +++ b/src/@ionic-native/plugins/apple-pay/index.ts @@ -1,4 +1,5 @@ import {Injectable} from '@angular/core'; +import {Observable} from 'rxjs/Observable'; import { Plugin, Cordova, @@ -9,27 +10,36 @@ export type IMakePayments = 'This device can make payments and has a supported c export type IShippingType = 'shipping' | 'delivery' | 'store' | 'service'; 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'; +export type ICompleteTransaction = 'Payment status applied.'; +export type IUpdateItemsAndShippingStatus = 'Updated List Info' | 'Did you make a payment request?'; export interface IPaymentResponse { - shippingAddressState?: string; - shippingCountry?: string; - shippingISOCountryCode?: string; - billingAddressCity?: string; - billingISOCountryCode?: string; - shippingNameLast?: string; - paymentData: string; - shippingNameFirst?: string; - billingAddressState?: string; - billingAddressStreet?: string; billingNameFirst?: string; - billingPostalCode?: string; - shippingPostalCode?: string; - shippingAddressStreet?: string; + billingNameMiddle?: string; billingNameLast?: string; + billingEmailAddress?: string; billingSupplementarySubLocality?: string; + billingAddressStreet?: string; + billingAddressCity?: string; + billingAddressState?: string; + billingPostalCode?: string; billingCountry?: string; - shippingAddressCity?: string; + billingISOCountryCode?: string; + + shippingNameFirst?: string; + shippingNameMiddle?: string; + shippingNameLast?: string; + shippingEmailAddress?: string; + shippingPhoneNumber?: string; shippingSupplementarySubLocality?: string; + shippingAddressStreet?: string; + shippingAddressCity?: string; + shippingAddressState?: string; + shippingPostalCode?: string; + shippingCountry?: string; + shippingISOCountryCode?: string; + + paymentData: string; transactionIdentifier: string; paymentMethodDisplayName?: string; paymentMethodNetwork?: string; @@ -46,18 +56,26 @@ export interface IShippingMethod { detail: string; amount: number; } - -export interface IOrder { +export interface IOrderItemsAndShippingMethods { items: IOrderItem[]; shippingMethods?: IShippingMethod[]; +} + +export interface IOrder extends IOrderItemsAndShippingMethods { merchantIdentifier: string; currencyCode: string; countryCode: string; - billingAddressRequirement: IBillingRequirement; - shippingAddressRequirement: IBillingRequirement; - shippingType: IShippingType; + billingAddressRequirement?: IBillingRequirement | IBillingRequirement[]; + shippingAddressRequirement?: IBillingRequirement | IBillingRequirement[]; + shippingType?: IShippingType; } +export interface ISelectedShippingContact { + shippingAddressCity: string; + shippingAddressState: string; + shippingPostalCode: string; + shippingISOCountryCode: string; +} /** * @name Apple Pay @@ -72,82 +90,51 @@ export interface IOrder { * constructor(private applePay: ApplePay) { } * * ... + * 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 + * } + * }); * + * try { + * const applePayTransaction = await this.applePay.makePaymentRequest({ + * items, + * shippingMethods, + * merchantIdentifier, + * currencyCode, + * countryCode, + * billingAddressRequirement: ['name', 'email', 'phone'], + * shippingAddressRequirement: 'none', + * shippingType: 'shipping' + * }); * - * 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' - * }) - * .then((paymentResponse) => { - * // 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: - * - * // MyPaymentProvider.authorizeApplePayToken(token.paymentData) - * // .then((captureStatus) => { - * // // Displays the 'done' green tick and closes the sheet. - * // ApplePay.completeLastTransaction('success'); - * // }) - * // .catch((err) => { - * // // Displays the 'failed' red cross. - * // ApplePay.completeLastTransaction('failure'); - * // }); - * - * - * }) - * .catch((e) => { - * // Failed to open the Apple Pay sheet, or the user cancelled the payment. - * }) + * 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 + * } * + * // only if you started listening before + * await this.applePay.stopListeningForShippingContactSelection(); + * } * ``` */ @Plugin({ pluginName: 'ApplePay', plugin: 'cordova-plugin-applepay', pluginRef: 'ApplePay', - repo: 'https://github.com/trueflywood/cordova-plugin-applepay', + repo: 'https://github.com/samkelleher/cordova-plugin-applepay', platforms: ['iOS'], }) @Injectable() @@ -158,16 +145,15 @@ export class ApplePay extends IonicNativePlugin { * @return {Promise} Returns a promise * * @usage - * ApplePay.canMakePayments() - * .then((message) => { - * // 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' - * }); + * 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' + * } */ @Cordova({ otherPromise: true @@ -176,6 +162,76 @@ export class ApplePay extends IonicNativePlugin { return; } + /** + * 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} emits with shipping contact information on + * shipping contact selection changes + */ + @Cordova({ + observable: true, + clearFunction: 'stopListeningForShippingContactSelection' + }) + startListeningForShippingContactSelection(): Observable { + 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 { + 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 + }) + updateItemsAndShippingMethods(list: IOrderItemsAndShippingMethods): Promise { + return; + } + /** * Request a payment with Apple Pay * @return {Promise} Returns a promise that resolves when something happens @@ -183,13 +239,68 @@ export class ApplePay extends IonicNativePlugin { * @param order {IOrder} * * @usage - * ApplePay.makePaymentRequest(order) - * .then((paymentResponse) => { - * // User approved payment, token generated. - * }) - * .catch((message) => { - * // Error or user cancelled. - * }); + * 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 + * } + * } */ @Cordova({ otherPromise: true @@ -202,11 +313,15 @@ export class ApplePay extends IonicNativePlugin { * 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. + * @return {Promise} Returns a promise that resolves after confirmation of payment authorization completion * * @param complete {ITransactionStatus} * */ - @Cordova() - completeLastTransaction(complete: ITransactionStatus): void { + @Cordova({ + otherPromise: true + }) + completeLastTransaction(complete: ITransactionStatus): Promise { + return; } }