Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Apple Pay): allow for customization of event updates #808

Merged
merged 2 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
chore(apple pay): add types for callbacks
  • Loading branch information
cbarton committed Apr 6, 2023
commit 466aaf1897a159215978e7ba0852074fcf013c2e
16 changes: 15 additions & 1 deletion test/types/apple-pay.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import { ApplePayPaymentRequest, ApplePayLineItem } from 'lib/apple-pay/native';
import {
ApplePayPaymentRequest,
ApplePayLineItem,
ApplePayPaymentContact,
ApplePaySelectionUpdate,
} from 'lib/apple-pay/native';

function getTaxes(billingContact: ApplePayPaymentContact | undefined): ApplePaySelectionUpdate | void {
if (billingContact?.postalCode === '12345') {
return { newLineItems: [{ label: 'Tax', amount: '1.00' }] };
}
}

export default function applePay() {
const applePaySimple = recurly.ApplePay({
Expand Down Expand Up @@ -45,6 +56,9 @@ export default function applePay() {
const applePay = recurly.ApplePay({
country: 'US',
currency: 'USD',
callbacks: {
onPaymentMethodSelected: ({ paymentMethod: { billingContact } }) => getTaxes(billingContact),
},
paymentRequest,
});

Expand Down
32 changes: 28 additions & 4 deletions types/lib/apple-pay/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { Emitter } from '../emitter';
import { CheckoutPricingInstance, CheckoutPricingPromise } from '../pricing/checkout';
import { ApplePayPaymentRequest } from './native';
import { TokenPayload } from '../token';
import {
ApplePayPaymentRequest,
ApplePayContactField,
ApplePaySelectionUpdate,
ApplePayErrorUpdate,
ApplePayPaymentSelectedEvent,
ApplePayShippingContactSelectedEvent,
ApplePayShippingMethodSelectedEvent,
ApplePayPaymentAuthorizedEvent,
} from './native';

export type I18n = {
/**
Expand Down Expand Up @@ -29,6 +39,11 @@ export type I18n = {
giftCardLineItemLabel: string;
};

export type PaymentAuthorizedEvent = {
gatewayToken?: string;
recurlyToken: TokenPayload;
} | ApplePayPaymentAuthorizedEvent;

export type ApplePayConfig = {
/**
* Your ISO 3166 country code (ex: ‘US’). This is your country code as the merchant. Required if not
Expand Down Expand Up @@ -62,6 +77,16 @@ export type ApplePayConfig = {
*/
i18n?: I18n;

/**
* Callbacks for the events emitted by the payment session when a user selects options in the payment sheet.
*/
callbacks?: {
onPaymentMethodSelected?: (event: ApplePayPaymentSelectedEvent) => Promise<ApplePaySelectionUpdate> | ApplePaySelectionUpdate | void,
onShippingContactSelected?: (event: ApplePayShippingContactSelectedEvent) => Promise<ApplePaySelectionUpdate> | ApplePaySelectionUpdate | void,
onShippingMethodSelected?: (event: ApplePayShippingMethodSelectedEvent) => Promise<ApplePaySelectionUpdate> | ApplePaySelectionUpdate | void,
onPaymentAuthorized?: (event: PaymentAuthorizedEvent) => Promise<ApplePayErrorUpdate> | ApplePayErrorUpdate | void,
};

/**
* If provided, will override `options.total` and provide the current total price on the CheckoutPricing instance
* when the Apple Pay flow is initiated.
Expand All @@ -85,10 +110,9 @@ export type ApplePayConfig = {
/**
* If set, the apple flow will require the user to provide these attributes.
* See docs here: https://recurly.com/developers/reference/recurly-js/#apple-pay
* @deprecated use paymentRequest.requiredShippingContactFields field instead
*/
requiredShippingContactFields?: Array<
'postalAddress' | 'name' | 'phoneticName' | 'phone' | 'email'
>;
requiredShippingContactFields?: ApplePayContactField[];

/**
* If provided, will use Braintree to process the ApplePay transaction.
Expand Down
184 changes: 184 additions & 0 deletions types/lib/apple-pay/native.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,48 @@ export type ApplePayContactField =
| 'postalAddress'
| 'phoneticName';

/**
* The error code that indicates whether an error on the payment sheet is for shipping or billing information, or for another kind of error.
*/
export type ApplePayErrorCode =
/**
* Indicates that the shipping address or contact information is invalid or missing.
* Use with contactField
*/
| "shippingContactInvalid"
/**
* Indicates that the billing address information is invalid or missing.
* Use with contactField
*/
| "billingContactInvalid"
/**
* Indicates that the merchant can’t provide service to the shipping address (for example, can’t deliver to a P.O. Box).
*/
| "addressUnserviceable"
/**
* Indicates an unknown but nonfatal error occurred during payment processing. The user can attempt authorization again.
*/
| "unknown";

/**
* Names of the fields in the shipping or billing contact information, used to locate errors in the payment sheet.
* @see {@link https://developer.apple.com/documentation/apple_pay_on_the_web/applepayerrorcontactfield} for when to use the fields.
*/
export type ApplePayErrorContactField =
| 'phoneNumber'
| 'emailAddress'
| 'name'
| 'phoneticName'
| 'postalAddress'
| 'addressLines'
| 'locality'
| 'subLocality'
| 'postalCode'
| 'administrativeArea'
| 'subAdministrativeArea'
| 'country'
| 'countryCode';

/**
* Contact information fields to use for billing and shipping contact information.
*/
Expand Down Expand Up @@ -172,3 +214,145 @@ export type ApplePayPaymentRequest = {
*/
recurringPaymentRequest?: ApplePayRecurringPaymentRequest;
};

export class ApplePayError {
/**
* A customizable error type that you create to indicate problems with the address or contact information on an Apple Pay sheet.
* @param errorCode The error code for this instance.
* @param contactField The field name that contains the error on the payment sheet.
* @param message A localized, user-facing string that describes the error.
*/
constructor(errorCode: ApplePayErrorCode, contactField?: ApplePayErrorContactField, message?: string);

/**
* The error code for this instance.
*/
code: ApplePayErrorCode;

/**
* The field name that contains the error on the payment sheet.
*/
contactField?: ApplePayErrorContactField;

/**
* A localized, user-facing string that describes the error.
*/
message: string;
}

export type ApplePayErrorUpdate = {
/**
* A list of customized errors you provide that results from the user's selection.
*/
errors?: ApplePayError[];
};

/**
* Updated transaction details to provide after the user's selection.
*/
export type ApplePaySelectionUpdate = {
/**
* The new total that results from the user's selection.
*/
newTotal?: ApplePayLineItem;

/**
* Updated line items for the payment request that results from the user’s selection.
*/
newLineItems?: ApplePayLineItem[];

/**
* The updated list of available shipping methods that results from the user's selection;
*/
newRecurringPaymentRequest?: ApplePayRecurringPaymentRequest;
} | ApplePayErrorUpdate;

/**
* Describes an Apple Pay payment method
*/
export type ApplePayPaymentMethod = {
/**
* A string, suitable for display, that describes the card.
*/
displayName?: string;

/**
* A string, suitable for display, that is the name of the payment network backing the card.
*/
network?: string;

/**
* A string value representing the card's type of payment.
*/
type?: (
| 'credit'
| 'debit'
);

/**
* The billing contact associated with the card.
*/
billingContact?: ApplePayPaymentContact;
};

/**
* An event object that contains the payment method.
*/
export type ApplePayPaymentSelectedEvent = {
/**
* The card used to complete a payment.
*/
paymentMethod: ApplePayPaymentMethod;
};

/**
* An event object that contains the shipping address the user selects.
*/
export type ApplePayShippingContactSelectedEvent = {
/**
* The shipping address selected by the user.
*/
shippingContact: ApplePayPaymentContact;
};

/**
* An event object that contains the shipping method.
*/
export type ApplePayShippingMethodSelectedEvent = {
/**
* The shipping method selected by the user.
*/
shippingMethod: any;
};

/**
* The result of authorizing a payment request that contains payment information.
*/
export type ApplePayPayment = {
token: {
/**
* Information about the card used in the transaction.
*/
paymentMethod: ApplePayPaymentMethod,
};

/**
* The billing contact selected by the user for this transaction.
*/
billingContact: ApplePayPaymentContact;

/**
* The shipping contact selected by the user for this transaction.
*/
shippingContact: ApplePayPaymentContact;
};

/**
* An event object that contains the token used to authorize a payment.
*/
export type ApplePayPaymentAuthorizedEvent = {
/**
* The authorized payment information for this transaction.
*/
payment: ApplePayPayment;
};