export let PaymentRequest ; if ( ( < any > window ) . ApplePaySession && ! ApplePaySession . supportsVersion ( 3 ) ) { const APPLE_PAY_JS_IDENTIFIER = 'https://apple.com/apple-pay' ; PaymentRequest = class { private paymentRequest : ApplePayJS . ApplePayPaymentRequest ; private preservedDetails : PaymentDetailsUpdate ; private preservedDisplayItems : PaymentItem [ ] ; public paymentRequestID : string = '' ; public shippingAddress : PaymentAddress = null ; public shippingOption : string = '' ; public shippingType : string = 'shipping' ; private session : ApplePaySession ; private paymentResolver = null ; private paymentRejector = null ; public onshippingaddresschange = null ; public onshippingoptionchange = null ; public onpaymentmethodselected = null ; private merchantIdentifier : string = '' ; param { PaymentMethodData [ ] } methodData param { PaymentDetailsInit } details param { PaymentOptions } options constructor ( methodData , details , options ) { let methodSpecified = false ; this . paymentRequest = { countryCode : '' , currencyCode : '' , lineItems : [ ] , merchantCapabilities : null , supportedNetworks : [ ] , total : null , billingContact : null , requiredBillingContactFields : [ ] , requiredShippingContactFields : [ ] , shippingContact : null , shippingMethods : < ApplePayJS . ApplePayShippingMethod [ ] > [ ] , shippingType : 'shipping' , } ; for ( let method of methodData ) { if ( method . supportedMethods . indexOf ( APPLE_PAY_JS_IDENTIFIER ) > - 1 || method . supportedMethods === APPLE_PAY_JS_IDENTIFIER ) { this . paymentRequest . supportedNetworks = method . data . supportedNetworks ; this . paymentRequest . countryCode = method . data . countryCode ; if ( method . data . version !== 3 ) { throw 'Apple Pay needs to be version 3.' ; } if ( method . data . billingContact ) { this . paymentRequest . billingContact = method . data . billingContact ; } else { delete this . paymentRequest . billingContact ; } if ( method . data . shippingContact ) { this . paymentRequest . shippingContact = method . data . shippingContact ; } else { delete this . paymentRequest . shippingContact ; } if ( method . data . merchantCapabilities ) { this . paymentRequest . merchantCapabilities = method . data . merchantCapabilities ; } this . merchantIdentifier = method . data . merchantIdentifier ; methodSpecified = true ; break ; } } if ( ! methodSpecified ) { throw 'Payment method not specified for Apple Pay.' ; } if ( details ) { this . updatePaymentDetails ( details ) ; } if ( options ) { if ( options . requestShipping ) { this . paymentRequest . requiredBillingContactFields . push ( 'postalAddress' ) ; this . paymentRequest . requiredShippingContactFields . push ( 'postalAddress' ) ; } if ( options . requestPayerName ) { this . paymentRequest . requiredShippingContactFields . push ( 'name' ) ; } if ( options . requestPayerEmail ) { this . paymentRequest . requiredShippingContactFields . push ( 'email' ) ; } if ( options . requestPayerPhone ) { this . paymentRequest . requiredShippingContactFields . push ( 'phone' ) ; } if ( options . shippingType === 'pickup' ) { this . paymentRequest . shippingType = 'servicePickup' ; } else { this . paymentRequest . shippingType = options . shippingType || 'shipping' ; } } this . session = new ApplePaySession ( 1 , this . paymentRequest ) ; this . session . addEventListener ( 'validatemerchant' , this . onMerchantValidation . bind ( this ) ) ; this . session . addEventListener ( 'paymentauthorized' , this . onPaymentAuthorized . bind ( this ) ) ; this . session . addEventListener ( 'paymentmethodselected' , this . onPaymentMethodSelected . bind ( this ) ) ; this . session . addEventListener ( 'shippingcontactselected' , this . onShippingAddressChange . bind ( this ) ) ; this . session . addEventListener ( 'shippingmethodselected' , this . onShippingOptionChange . bind ( this ) ) ; this . session . addEventListener ( 'cancel' , this . onPaymentCanceled . bind ( this ) ) ; } param { PaymentDetailsUpdate } details param { string } selectedMethod returns private updatePaymentDetails ( details , selectedMethod ? , selectedType ? ) { if ( selectedMethod ) { const newDisplayItems = [ ] ; for ( let item of details . displayItems ) { let included = false ; for ( let _item of this . preservedDisplayItems ) { if ( _item . label === item . label ) included = true ; } if ( ! included ) newDisplayItems . push ( item ) ; } details . displayItems = newDisplayItems ; this . preservedDisplayItems = [ ] ; for ( let modifier of details . modifiers ) { if ( modifier . supportedMethods !== selectedMethod ) continue ; if ( selectedMethod == 'basic-card' && modifier . data && modifier . data . supportedTypes ) { if ( ! selectedType || modifier . data . supportedTypes . indexOf ( selectedType ) === - 1 ) continue ; } if ( modifier . additionalDisplayItems ) { details . displayItems = [ ... details . displayItems , ... modifier . additionalDisplayItems ] ; this . preservedDisplayItems = modifier . additionalDisplayItems ; } if ( modifier . total ) { details . total = modifier . total ; } break ; } } if ( details . displayItems ) { this . paymentRequest . lineItems = < ApplePayJS . ApplePayLineItem [ ] > [ ] ; for ( let item of details . displayItems ) { let lineItem = { type : item . pending === true ? 'pending' : 'final' , label : item . label , amount : item . amount . value } ; this . paymentRequest . lineItems . push ( lineItem ) ; } } if ( details . shippingOptions ) { this . paymentRequest . shippingMethods = < ApplePayJS . ApplePayShippingMethod [ ] > [ ] ; for ( let option of details . shippingOptions ) { let shippingMethod = { label : option . label , detail : option . label , amount : option . amount . value , identifier : option . id } ; this . paymentRequest . shippingMethods . push ( shippingMethod ) ; } } if ( details . total ) { this . paymentRequest . currencyCode = details . total . amount . currency ; this . paymentRequest . total = { type : details . total . pending === true ? 'pending' : 'final' , label : details . total . label , amount : details . total . amount . value } ; } else { throw '`total` is required parameter for `PaymentDetailsUpdate`.' ; } this . preservedDetails = details ; } param { ApplePayJS . ApplePayPaymentMethod } paymentMethod private updatePaymentMethod ( paymentMethod ) { } param { ApplePayJS . ApplePayPaymentContact } contact returns private convertPaymentAddress ( contact ) { let address = { country : contact . countryCode || '' , addressLine : contact . addressLines || [ ] , region : contact . administrativeArea || '' , city : contact . locality || '' , dependentLocality : '' , postalCode : contact . postalCode || '' , sortingCode : contact . country || '' , languageCode : '' , organization : '' , recipient : `${ contact . givenName } ${ contact . familyName }` , phone : contact . phoneNumber || '' } ; return < PaymentAddress > address ; } param { ApplePayJS . ApplePayShippingMethod } shippingMethod private convertShippingMethod ( shippingMethod ) { for ( let method of this . paymentRequest . shippingMethods ) { if ( shippingMethod . identifier === method . identifier ) { return method . identifier ; } } return '' ; } param { ApplePayJS . ApplePayPayment } payment returns { any } private convertPaymentResponse ( payment ) { let shippingAddress = this . convertPaymentAddress ( payment . shippingContact ) ; let billingAddress = this . convertPaymentAddress ( payment . billingContact ) ; let response = { details : { billingAddress : billingAddress } , methodName : APPLE_PAY_JS_IDENTIFIER , payerEmail : payment . shippingContact . emailAddress , payerName : `${ payment . billingContact . givenName } ${ payment . billingContact . familyName }` , payerPhone : payment . shippingContact . phoneNumber , shippingAddress : shippingAddress , shippingOption : '' , applePayRaw : payment , complete : this . onPaymentComplete . bind ( this ) } ; return response ; } returns public show ( ) { this . session . begin ( ) ; return new Promise ( ( resolve , reject ) => { this . paymentResolver = ( response ) => { resolve ( < any > response ) ; } ; this . paymentRejector = ( error ) => { reject ( error ) ; } ; } ) ; } returns public abort ( ) { this . session . abort ( ) ; } returns public canMakePayment ( ) { if ( this . merchantIdentifier ) { return ApplePaySession . canMakePaymentsWithActiveCard ( this . merchantIdentifier ) ; } else { throw '`merchantIdentifier` is not specified.' ; } } param { string } type param { ( e : Event ) => any } callback returns public addEventListener ( type , callback ) { if ( type === 'shippingaddresschange' || type === 'shippingoptionchange' || type === 'merchantvalidation' ) { this [ `on${ type }` ] = callback ; } else { throw `Unknown event type "${ type }" for \`addEventListener\`.` ; } } param { ApplePayJS . ApplePayValidMerchantEvent } e returns private onMerchantValidation ( e ) { if ( ! this [ 'onmerchantvalidation' ] ) return ; e . stopPropagation ( ) ; this [ 'onmerchantvalidation' ] ( { validationURL : e . validationURL , complete : p => { p . then ( ( merchantSession ) => { this . session . completeMerchantValidation ( merchantSession ) ; } ) ; } } ) ; } param { ApplePayJS . ApplePayPaymentMethodSelectedEvent } e returns private onPaymentMethodSelected ( e ) { e . stopPropagation ( ) ; this . updatePaymentDetails ( this . preservedDetails , 'https://apple.com/apple-pay' ) ; let newTotal = this . paymentRequest . total ; let newLineItems = this . paymentRequest . lineItems ; this . session . completePaymentMethodSelection ( newTotal , newLineItems ) ; } param { ApplePayJS . ApplePayShippingContactSelectedEvent } e returns private onShippingAddressChange ( e ) { if ( ! this [ 'onshippingaddresschange' ] ) return ; e . stopPropagation ( ) ; let shippingContact = e . shippingContact ; this . shippingAddress = this . convertPaymentAddress ( shippingContact ) ; this [ 'onshippingaddresschange' ] ( { updateWith : p => { p . then ( ( details ) => { this . updatePaymentDetails ( details ) ; this . session . completeShippingContactSelection ( ApplePaySession . STATUS_SUCCESS , this . paymentRequest . shippingMethods , this . paymentRequest . total , this . paymentRequest . lineItems ) ; } , ( details ) => { this . updatePaymentDetails ( details ) ; this . session . completeShippingContactSelection ( ApplePaySession . STATUS_FAILURE , this . paymentRequest . shippingMethods , this . paymentRequest . total , this . paymentRequest . lineItems ) ; } ) ; } } ) ; } param { ApplePayJS . ApplePayShippingMethodSelectedEvent } e returns private onShippingOptionChange ( e ) { if ( ! this [ 'onshippingoptionchange' ] ) return ; e . stopPropagation ( ) ; let shippingMethod = e . shippingMethod ; this . shippingOption = this . convertShippingMethod ( shippingMethod ) ; this [ 'onshippingoptionchange' ] ( { updateWith : p => { p . then ( ( details ) => { this . updatePaymentDetails ( details ) ; this . session . completeShippingMethodSelection ( ApplePaySession . STATUS_SUCCESS , this . paymentRequest . total , this . paymentRequest . lineItems ) ; } , ( details ) => { this . updatePaymentDetails ( details ) ; this . session . completeShippingMethodSelection ( ApplePaySession . STATUS_FAILURE , null , null ) ; } ) ; } } ) ; } param { ApplePayJS . ApplePayPaymentAuthorizedEvent } e returns private onPaymentAuthorized ( e ) { if ( this . paymentResolver ) { let response = this . convertPaymentResponse ( e . payment ) ; this . paymentResolver ( response ) ; this . paymentResolver = null ; this . paymentRejector = null ; } } returns private onPaymentCanceled ( ) { if ( this . paymentRejector ) { this . paymentRejector ( ) ; this . paymentResolver = null ; this . paymentRejector = null ; } } param { 'success' | 'fail' | 'unknown' } result returns private onPaymentComplete ( result ) { if ( result === 'success' || result === 'fail' || result === 'unknown' || result === '' ) { let status ; switch ( result ) { case 'success' : status = ApplePaySession . STATUS_SUCCESS ; break ; case 'fail' : status = ApplePaySession . STATUS_FAILURE ; break ; case 'unknown' : status = ApplePaySession . STATUS_SUCCESS ; break ; default : status = ApplePaySession . STATUS_SUCCESS ; break ; } this . session . completePayment ( status ) ; } else { throw 'Unknown status code for complete().' ; } } } ; }