# TEConnect Payment Request (Angular)
[](https://www.npmjs.com/package/@magensa/te-connect-ng "@magensa/te-connect-ng npm.js")
Angular components for use with Apple Pay and Google Pay via Token Exchange Connect.
TypeScript Type Defs are exposed, and can be imported from this module as well.
# Payment Request Platforms
TEConnect currently offers two payment request platforms to create payment tokens: [Apple Pay](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md), and [Google Pay](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md). The payment tokens are processed via [Magensa's Payment Protection Gateway](https://svc1.magensa.net/MPPGv4/MPPGv4Service.svc) (MPPG). To that end - there are many configurable options exposed when using [Apple Pay](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md), and [Google Pay](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md) via TEConnect. This document will focus on a very simple implementation using both platforms. If you are interested in a more customized experience for your users, using [Apple Pay](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md), and/or [Google Pay](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md) - check out the [TecApplePayREADME.md](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md), and/or [TecGooglePayREADME](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md) which will cover more specific configuration for each - as well as links to Apple/Google's documentation, respectively.
# Getting Started
```
npm install @magensa/te-connect @magensa/te-connect-ng
```
or
```
yarn add @magensa/te-connnect @magensa/te-connect-ng
```
If you would prefer to let the code speak, below we have an [example implementation](#Example-Implementation) for both platforms - along with a [Google Pay complex example](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md#Google-Pay-Example-Implementation) and an [Apple Pay complex example](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#Apple-Pay-Example-Implementation)
# Step-by-step
1. The first step is to create a TEConnect instance, and feed that instance into the TEConnectModuleNg where you are importing it:
- The first parameter is your public key for [TEConnect manual entry](https://github.com/Magensa/te-connect-ng) (```CardEntry``` component).
- The second parameter is the [```options``` object](https://github.com/Magensa/te-connect-ng#teconnect-options)
- For the ```tecPaymentRequest``` options:
- supply your ```appleMerchantId``` to enable Apple Pay.
- ```appleMerchantId``` is obtained after the on-boarding process with Magensa™ is completed. [Please reach out to Magensa™ support team for more info](https://www.magensa.net/support.html)
- supply your ```googleMerchantId``` to enable Google Pay.
- ```googleMerchantId``` is obtained after the [on-boarding process with Google](https://pay.google.com/business/console) is completed.
- For Google Pay capabilities - ```googleMerchantId```, ```googleMerchantName```, and ```gatewayId``` are needed.
- ```gatewayId``` is obtained after the on-boarding process with Magensa™ is completed. [Please reach out to Magensa™ support team for more info](https://www.magensa.net/support.html)
- ```googleMerchantId``` and ```googleMerchantName``` are obtained using [Google Pay and Wallet Console](https://pay.google.com/business/console). [More info on ```MerchantInfo``` here](https://developers.google.com/pay/api/web/reference/request-objects#MerchantInfo). Be aware that the name and id are fed to TEConnect seperately - which differs from the direct integration [Google Pay documentation](https://developers.google.com/pay/api/web/reference/request-objects#MerchantInfo).
```typescript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { TeConnectNgModule, TEConnect } from '@magensa/te-connect-ng';
import { createTEConnect } from '@magensa/te-connect'
import { AppComponent } from './app.component';
const TE_CONNECT: TEConnect = createTEConnect("__publicKeyGoesHere__", {
tecPaymentRequest: {
appleMerchantId: "__tecAppleMerchantId__"
googleMerchantId: "__googleMerchantId__",
}
});
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
TeConnectNgModule.forRoot(TE_CONNECT)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
```
2. In your component, there are three variables that must be declared to utilize the Payment Request workflow. Those variables are:
- ```(canMakePaymentsResult)```:
- This event will emit a [```CanMakePaymentsResult```](#CanMakePaymentsResult) when the component mounts the DOM. Attach a listener function to capture this event.
- ```[paymentRequestObject]```
- Build a [```paymentRequestObject```](#Payment-Request-Object) to define the Payment Request Form(s).
- [Apple's Payment Request Object Structure](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#Payment-Request-Object), [Google's Payment Request Object Structure](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md#Payment-Request-Object).
- Note that if you are using multiple platforms (i.e. both Apple and Google) you must seperate the payment request objects by platform (i.e. ```{ googlePay: {...}, applePay: {...}}```).
- ```[confirmToken]```:
- When a user submits the payment request form - an event is emitted. Listen to the [```confirmToken```](#confirmToken-Event) event to inspect the result (as demonstrated below).
- The ```completePayment``` function is a property of the ```confirmToken``` event _for Apple Pay only_. This function must be called within 30 seconds of the event firing - otherwise the Apple Pay form will timeout. For Google Pay - visible authorization (on the Google Pay form) is optional.
```typescript
import { Component } from '@angular/core';
import {
TecPaymentRequestObject,
CanMakePaymentsResult,
ConfirmTokenEvent
} from 'te-connect-ng';
import { exampleApplePaymentRequestObject, exampleGooglePaymentRequestObject } from '../consts';
@Component({
selector: 'app-root',
templateUrl: `
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent {
prObject: TecPaymentRequestObject = {
applePay: exampleApplePaymentRequestObject,
googlePay: exampleGooglePaymentRequestObject
};
handleCanMakePaymentsResult = (availablePrMethods: CanMakePaymentsResult) => {
if (availablePrMethods) {
//const { applePay, googlePay } = availablePrMethods;
}
}
confirmPaymentToken = (tokenResp: ConfirmTokenEvent) => {
const { tokenDetails, completePayment, error } = tokenResp;
if (error) {
//Unsuccessful - check message.
if (typeof(completePayment) === 'function')
completePayment('failure');
}
else {
//Successful
//Pass `tokenDetails.token` directly to MPPG for processing.
//if Apple Pay - close user's payment request form with payment success notification.
if (typeof(completePayment) === 'function')
completePayment('success');
}
}
}
```
The above is a minimally viable solution to get you started. There are three more code examples - a [minimally viable example](#example-implementation) using both Apple Pay and Google Pay, as well as two more complex examples to leverage more of the features available, for each respective platform ([Apple Pay Complex Example here](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#Apple-Pay-Example-Implementation), [Google Pay Complex Example here](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md#Google-Pay-Example-Implementation)). Read on for further features and details availble to the Payment Request Utility.
# Payment Request Object
The Payment Request Object is required, in order to use the ```lib-tec-payment-request```. This object describes the form(s) that the end-user will interact with.
Each platform will have a different payment request object with different properties. If your application has opted-in for more than one platform (i.e. both Google and Apple Pay) - be sure to seperate the payment request objects by platform:
```javascript
const applePaymentRequestObject = {
storeDisplayName: "TEConnect Example Store",
currencyCode: "USD",
countryCode: "US",
supportedNetworks: ['visa', 'masterCard', 'amex', 'discover', 'jcb'],
merchantCapabilities: ['supports3DS'],
total: {
label: "Test Transaction",
amount: "1.00",
type: "final"
}
};
const googlePaymentRequestObject = {
allowedCardNetworks: ["AMEX", "DISCOVER", "JCB", "MASTERCARD", "MIR", "VISA"],
merchantName: "TEConnect Example Merchant",
gatewayId: "_gateway_id_provided_by_Magensa_",
transactionInfo: {
totalPriceStatus: 'FINAL',
totalPrice: '1.23',
currencyCode: 'USD',
countryCode: 'US'
}
};
const teConnectPaymentRequestObject = {
applePay: applePaymentRequestObject,
googlePay: googlePaymentRequestObject
};
```
### Apple Pay Payment Request Object
[More information and helpful links about Apple's Payment Request Object can be found here](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#Apple-Pay-Payment-Request-Object)
### Google Pay Payment Request Object
[More information and helpful links about Google's Payment Request Object can be found here](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md#Google-Pay-Payment-Request-Object)
# Token Exchange Connect Payment Request Features
The Token Exchange Connect Payment Request Component is the interface needed to interact, and respond to user's interactions on the Payment Request Form.
## ```[paymentRequestObject]```
Define your [payment request object](#Payment-Request-Object) with this variable. This object is required.
## ```(canMakePaymentsResult)```
This event will emit a [```CanMakePaymentsResult```](#CanMakePaymentsResult). Define a listener function to listen to this event. This event fires under two circumstances:
- Once the component is mounted.
- If the [```paymentRequestObject```](#Payment-Request-Object) is updated.
#### ```CanMakePaymentsResult```
```typescript
type CanMakePaymentsResult = {
applePay?: boolean,
googlePay?: boolean
} | null;
```
## ```[confirmToken]```
Define your listener function for the [```confirmToken```](#confirmToken-Event) event with this variable. This function is required.
## Update Payment Request Object
Once you have supplied a [payment request object](#Payment-Request-Object) as the component's ```[paymentRequestObject]``` - this object will be watched, and can be updated as needed. Be aware of a few things about updating your ```[paymentRequestObject]```:
- Updates to the payment request object are only useful __before__ the Apple Pay Button is displayed.
- Once the user has the ability to hit the button - the payment request object is defined for that session.
- When the object is updated - this is a __full update__, so the object will completely replace the previous payment request object supplied.
- It's not necessary to update your object inside of [payment request listeners](#Payment-Request-Event-Handlers). Any response in your completion functions will update the form dynamically.
## ```[tecPaymentRequestOptions]```
Use this variable to define your custom [Payment Request Button Options](#Payment-Request-Button-Options). This value is optional.
## ```[shippingContactUpdate]``` __(Apple Pay Only)__
Use this variable to define your [Shipping Contact](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#shippingContactUpdate-Event) event listener function. This value is optional.
## ```[paymentMethodSelection]``` __(Apple Pay Only)__
Use this variable to define your [Payment Method](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#paymentMethodSelection-Event) event listener function. This value is optional.
## ```[shippingMethodUpdate]``` __(Apple Pay Only)__
Use this variable to define your [Shipping Method](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#shippingMethodUpdate-Event) event listener function. This value is optional.
## ```[cancelTransaction]``` __(Apple Pay Only)__
Use this variable to define your [Cancel Transaction](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#cancelTransaction-Event) event listener function. This value is optional.
# Payment Request Event Handlers
Listening to the ```confirm-token``` event is required to complete the workflow for all payment platforms.
Apple Pay uses an event handler driven workflow. When users interact with the payment request form - there are several events that are fired.
[More details about Apple Pay listeners here](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#Apple-Pay-Listeners)
### ```confirmToken``` Event
This is the only event listener that is required to complete both workflows. This is the only event that can optionally contain an ```error``` property (in the case the payment was submitted, but was unsuccessful). Be sure to check for that property first, if it exists.
When listening to the ```confirmToken``` event - there will be up to two special properties to the event:
- ```tokenDetails```
- ```type``` specifies the payment request platform in which the token was created.
- ```applePay``` or ```googlePay```.
- ```token``` will be the object needed to process transactions, using the payment token created during the current session.
- Pass the ```token``` to the appropriate MPPG operation, unaltered, for processing.
- ```error``` is an optional property in the case the token creation was unsuccessful.
- ```completePayment```
- This function will only exist for Apple Pay tokens. It is used to close the Apple Pay form with a status message.
- [More information about ```completePayment``` can be found here](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#Apple-Pay-Listeners)
- This property will not exist for Google Pay tokens. This is one of the many ways to differentiate between which platform the user is using to complete the transaction.
```confirmToken``` example:
```typescript
import { Component } from '@angular/core';
import {
TecPaymentRequestObject
CanMakePaymentsResult,
ConfirmTokenEvent
} from 'te-connect-ng';
import { exampleApplePaymentRequestObject, exampleGooglePaymentRequestObject } from '../consts';
@Component({
selector: 'app-root',
templateUrl: `
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent {
isAppleUser: boolean = false;
prObject: TecPaymentRequestObject = {
applePay: exampleApplePaymentRequestObject,
googlePay: exampleGooglePaymentRequestObject
};
handleCanMakePaymentsResult = (availablePrMethods: CanMakePaymentsResult) => {
if (availablePrMethods && availablePrMethods.applePay === true) {
this.isAppleUser = true;
}
}
confirmPaymentToken = (tokenResp: ConfirmTokenEvent) => {
const { tokenDetails, completePayment, error } = tokenResponse;
if (error) {
//You can complete with string value, as below.
//completePayment("failure");
//Optionally - you can provide more concise error messages
if (this.isAppleUser === true) {
completePayment({
status: window['ApplePaySession'].STATUS_FAILURE,
errors: [
new window['ApplePayError']("shippingContactInvalid", "postalCode", "ZIP Code is invalid"),
new window['ApplePayError']("addressUnserviceable", "addressLines", "Cannot deliver to P.O. Box")
]
})
}
}
else {
if (typeof( completePayment ) === 'function') {
//tokenDetails.type === 'applePay'
completePayment('success');
//pass `tokenDetails.token` to MPPG to process payment
}
else {
//tokenDetails.type === 'googlePay'
//pass `tokenDetails.token` to MPPG to process payment
}
}
}
}
```
# Payment Request Button Options
The ```TecPaymentRequestButtons``` component accepts an optional prop named ```tecPrOptions```. Here you can define your custom options for the payment request buttons. You may define custom values for the Apple Pay Button, using the property ```applePayOptions```, and Google Pay Button with ```googlePayOptions``` (You can see the [default values](#Default-Payment-Request-Button-Options-Values), for an example on how to structure the object, below).
## Apple Pay Button Options
[More details about Apple Pay Button Options can be found here](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#Apple-Pay-Button-Options)
## Google Pay Button Options
[More details about Google Pay Button Options can be found here](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md#Google-Pay-Button-Options)
#### Default Payment Request Button Options Values:
```typescript
const defaultButtonOptions: TecPaymentRequestOptions = {
applePayOptions: {
buttonLanguage: 'en',
buttonType: 'plain',
buttonStyle: 'black'
},
googlePayOptions: {
preClick: undefined, //Only calls if is of type 'function'
buttonColor: undefined, //Currently defaults to 'black' but default is not static, and is determined by Google
buttonType: undefined,
buttonLocale: undefined, //If not supplied - defaults to browser or OS language settings
buttonSizeMode: 'static'
}
};
```
# Example Implementation
Below you will find a minimally viable implementation.
```app.module.ts```
```typescript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { TeConnectNgModule, TEConnect } from '@magensa/te-connect-ng';
import { createTEConnect } from '@magensa/te-connect';
import { AppComponent } from './app.component';
const TE_CONNECT: TEConnect = createTEConnect("__publicKeyGoesHere__", {
tecPaymentRequest: {
appleMerchantId: "__tecAppleMerchantId__",
googleMerchantId: "__googleMerchantId__"
}
});
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
TeConnectNgModule.forRoot(TE_CONNECT)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
```
```app.component.ts```
```typescript
import { Component } from '@angular/core';
import {
CanMakePaymentsResult,
TecPaymentRequestObject,
ConfirmTokenListener,
ConfirmTokenEvent,
CompletePaymentResult
} from 'te-connect-ng';
import { exampleApplePaymentRequestObject, exampleGooglePaymentRequestObject } from '../consts';
@Component({
selector: 'app-root',
templateUrl: `
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent {
isAppleUser: boolean = false;
prObject: TecPaymentRequestObject = {
applePay: exampleApplePaymentRequestObject,
googlePay: exampleGooglePaymentRequestObject
};
handleCanMakePaymentsResult = (availablePrMethods: CanMakePaymentsResult) => {
if (availablePrMethods && availablePrMethods.applePay) {
this.isAppleUser = true;
}
}
confirmPaymentToken: ConfirmTokenListener = (tokenResponse: ConfirmTokenEvent) => {
const { tokenDetails, completePayment, error } = tokenResponse;
if (error) {
//You can complete with string value, as below.
//completePayment("failure");
//Optionally - you can provide more concise error messages
if (this.isAppleUser === true) {
completePayment({
status: window['ApplePaySession'].STATUS_FAILURE,
errors: [
new window['ApplePayError']("shippingContactInvalid", "postalCode", "ZIP Code is invalid"),
new window['ApplePayError']("addressUnserviceable", "addressLines", "Cannot deliver to P.O. Box")
]
})
}
}
else {
if (typeof( completePayment ) === 'function') {
//tokenDetails.type === 'applePay'
completePayment('success');
//pass `tokenDetails.token` to MPPG to process payment
}
else {
//tokenDetails.type === 'googlePay'
//pass `tokenDetails.token` to MPPG to process payment
}
}
}
}
```
# Payment Request Error Handling
All Apple Pay callbacks accept an ```errors[]``` array. [More information here](https://github.com/Magensa/te-connect-ng/blob/master/TecApplePayREADME.md#Apple-Pay-Error-Handling)
Google Pay Errors are handled within the optional callbacks. [More information on that here](https://github.com/Magensa/te-connect-ng/blob/master/TecGooglePayREADME.md#Google-Pay-Error-Handling)