@internetarchive/donation-form 0.5.8-alpha.5 → 0.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/src/braintree-manager/braintree-interfaces.d.ts +6 -0
  2. package/dist/src/braintree-manager/braintree-interfaces.js.map +1 -1
  3. package/dist/src/braintree-manager/braintree-manager.d.ts +4 -1
  4. package/dist/src/braintree-manager/braintree-manager.js +11 -0
  5. package/dist/src/braintree-manager/braintree-manager.js.map +1 -1
  6. package/dist/src/braintree-manager/payment-providers/credit-card/credit-card-interface.d.ts +6 -0
  7. package/dist/src/braintree-manager/payment-providers/credit-card/credit-card-interface.js.map +1 -1
  8. package/dist/src/braintree-manager/payment-providers/credit-card/credit-card.d.ts +10 -2
  9. package/dist/src/braintree-manager/payment-providers/credit-card/credit-card.js +70 -8
  10. package/dist/src/braintree-manager/payment-providers/credit-card/credit-card.js.map +1 -1
  11. package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container.d.ts +10 -5
  12. package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container.js +8 -0
  13. package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container.js.map +1 -1
  14. package/dist/src/braintree-manager/payment-providers-interface.d.ts +4 -1
  15. package/dist/src/braintree-manager/payment-providers-interface.js.map +1 -1
  16. package/dist/src/braintree-manager/payment-providers.d.ts +4 -1
  17. package/dist/src/braintree-manager/payment-providers.js +13 -1
  18. package/dist/src/braintree-manager/payment-providers.js.map +1 -1
  19. package/dist/src/donation-form-controller.js +12 -0
  20. package/dist/src/donation-form-controller.js.map +1 -1
  21. package/dist/src/donation-form-error.d.ts +3 -0
  22. package/dist/src/donation-form-error.js +7 -0
  23. package/dist/src/donation-form-error.js.map +1 -0
  24. package/dist/src/util/promisedSleep.d.ts +1 -0
  25. package/dist/src/util/promisedSleep.js +4 -0
  26. package/dist/src/util/promisedSleep.js.map +1 -0
  27. package/dist/test/mocks/mock-braintree-manager.d.ts +4 -1
  28. package/dist/test/mocks/mock-braintree-manager.js +5 -0
  29. package/dist/test/mocks/mock-braintree-manager.js.map +1 -1
  30. package/dist/test/mocks/mock-hosted-fields-container.d.ts +1 -0
  31. package/dist/test/mocks/mock-hosted-fields-container.js +3 -0
  32. package/dist/test/mocks/mock-hosted-fields-container.js.map +1 -1
  33. package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.d.ts +4 -1
  34. package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.js +5 -0
  35. package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.js.map +1 -1
  36. package/dist/test/mocks/payment-providers/mock-payment-providers.d.ts +4 -1
  37. package/dist/test/mocks/payment-providers/mock-payment-providers.js +5 -0
  38. package/dist/test/mocks/payment-providers/mock-payment-providers.js.map +1 -1
  39. package/dist/test/tests/donation-form-controller.test.js +1 -1
  40. package/dist/test/tests/donation-form-controller.test.js.map +1 -1
  41. package/dist/test/tests/donation-form.test.js +1 -1
  42. package/dist/test/tests/donation-form.test.js.map +1 -1
  43. package/dist/test/tests/form-elements/payment-selector.test.js +1 -1
  44. package/dist/test/tests/form-elements/payment-selector.test.js.map +1 -1
  45. package/dist/test/tests/payment-providers/creditcard.test.js +98 -0
  46. package/dist/test/tests/payment-providers/creditcard.test.js.map +1 -1
  47. package/package.json +3 -2
  48. package/src/braintree-manager/braintree-interfaces.ts +11 -0
  49. package/src/braintree-manager/braintree-manager.ts +19 -0
  50. package/src/braintree-manager/payment-providers/credit-card/credit-card-interface.ts +10 -0
  51. package/src/braintree-manager/payment-providers/credit-card/credit-card.ts +88 -13
  52. package/src/braintree-manager/payment-providers/credit-card/hosted-field-container.ts +21 -8
  53. package/src/braintree-manager/payment-providers-interface.ts +12 -1
  54. package/src/braintree-manager/payment-providers.ts +22 -2
  55. package/src/donation-form-controller.ts +17 -3
  56. package/src/donation-form-error.ts +6 -0
  57. package/src/util/promisedSleep.ts +3 -0
@@ -1,6 +1,11 @@
1
1
  import { DonationRequest, DonationResponse, SuccessResponse, PaymentProvider, DonationPaymentInfo, CustomerInfo, BillingInfo } from '@internetarchive/donation-form-data-models';
2
2
  import { PromisedSingleton } from '@internetarchive/promised-singleton';
3
+ import { Unsubscribe } from 'nanoevents';
3
4
  import { PaymentProvidersInterface } from './payment-providers-interface';
5
+ export interface BraintreeManagerEvents {
6
+ paymentProvidersHostedFieldsRetry: (retryNumber: number) => void;
7
+ paymentProvidersHostedFieldsFailed: (error: unknown) => void;
8
+ }
4
9
  /**
5
10
  * The BraintreeManager is the main entrypoint for much of the common braintree functionality.
6
11
  *
@@ -10,6 +15,7 @@ import { PaymentProvidersInterface } from './payment-providers-interface';
10
15
  * @interface BraintreeManagerInterface
11
16
  */
12
17
  export interface BraintreeManagerInterface {
18
+ on<E extends keyof BraintreeManagerEvents>(event: E, callback: BraintreeManagerEvents[E]): Unsubscribe;
13
19
  /**
14
20
  * The PaymentProviders class contains the IA-specific handlers for each of the
15
21
  * different payment providers.
@@ -1 +1 @@
1
- {"version":3,"file":"braintree-interfaces.js","sourceRoot":"","sources":["../../../src/braintree-manager/braintree-interfaces.ts"],"names":[],"mappings":"AA6JA,MAAM,CAAN,IAAY,kBAGX;AAHD,WAAY,kBAAkB;IAC5B,yCAAmB,CAAA;IACnB,yCAAmB,CAAA;AACrB,CAAC,EAHW,kBAAkB,KAAlB,kBAAkB,QAG7B","sourcesContent":["import {\n DonationRequest,\n DonationResponse,\n SuccessResponse,\n PaymentProvider,\n DonationPaymentInfo,\n CustomerInfo,\n BillingInfo,\n} from '@internetarchive/donation-form-data-models';\nimport { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { PaymentProvidersInterface } from './payment-providers-interface';\n\n/**\n * The BraintreeManager is the main entrypoint for much of the common braintree functionality.\n *\n * A single instance of it gets created and passed down through all of the components.\n *\n * @export\n * @interface BraintreeManagerInterface\n */\nexport interface BraintreeManagerInterface {\n /**\n * The PaymentProviders class contains the IA-specific handlers for each of the\n * different payment providers.\n *\n * They are generally data-focused, as opposed to UI-focused, but there\n * is some cross-polination between PaymentProviders and FlowHandlers.\n *\n * @type {PaymentProvidersInterface}\n * @memberof BraintreeManagerInterface\n */\n paymentProviders: PaymentProvidersInterface;\n\n /**\n * The Braintree Client instance.\n *\n * This gets used to isntantiate clients for all of the payment providers.\n *\n * @type {PromisedSingleton<braintree.Client>}\n * @memberof BraintreeManagerInterface\n */\n instance: PromisedSingleton<braintree.Client>;\n\n /**\n * Set the referrer for later submission\n *\n * @param {string} referrer\n * @memberof BraintreeManagerInterface\n */\n setReferrer(referrer: string): void;\n\n /**\n * Set the origin for later submission\n *\n * @param {string} origin\n * @memberof BraintreeManagerInterface\n */\n setOrigin(origin: string): void;\n\n /**\n * Set the logged-in user for later submission\n *\n * @param {string} loggedInUser\n * @memberof BraintreeManagerInterface\n */\n setLoggedInUser(loggedInUser: string): void;\n\n /**\n * Perform startup tasts like session resuming\n *\n * @memberof BraintreeManagerInterface\n */\n startup(): void;\n\n /**\n * Submit donation to the backend\n *\n * @param {{\n * nonce: string;\n * paymentProvider: PaymentProvider;\n * donationInfo: DonationPaymentInfo;\n * billingInfo: BillingInfo;\n * customerInfo: CustomerInfo;\n * upsellOnetimeTransactionId?: string;\n * customerId?: string;\n * recaptchaToken?: string;\n * bin?: string; // first 6 digits of CC\n * binName?: string; // credit card bank name\n * }} options\n * @returns {Promise<DonationResponse>}\n * @memberof BraintreeManagerInterface\n */\n submitDonation(options: {\n nonce: string;\n paymentProvider: PaymentProvider;\n donationInfo: DonationPaymentInfo;\n billingInfo: BillingInfo;\n customerInfo: CustomerInfo;\n upsellOnetimeTransactionId?: string;\n customerId?: string;\n recaptchaToken?: string;\n bin?: string; // first 6 digits of CC\n binName?: string; // credit card bank name\n }): Promise<DonationResponse>;\n\n /**\n * Submit the upsell donation\n *\n * @param {{\n * oneTimeDonationResponse: SuccessResponse;\n * amount: number;\n * }} options\n * @returns {Promise<DonationResponse>}\n * @memberof BraintreeManagerInterface\n */\n submitUpsellDonation(options: {\n oneTimeDonationResponse: SuccessResponse;\n amount: number;\n }): Promise<DonationResponse>;\n\n /**\n * Finish the donation after a successful completion.\n *\n * @param {{\n * successResponse: SuccessResponse;\n * upsellSuccessResponse?: SuccessResponse;\n * }} options\n * @memberof BraintreeManagerInterface\n */\n donationSuccessful(options: {\n successResponse: SuccessResponse;\n upsellSuccessResponse?: SuccessResponse;\n }): void;\n}\n\nexport interface BraintreeEndpointManagerInterface {\n /**\n * Responsible for submitting a data object to the backend\n * and returning a Promise of the JSON object response.\n *\n * @param {object} data\n * @returns {Promise<object>}\n * @memberof BraintreeEndpointManagerInterface\n */\n submitData(request: DonationRequest): Promise<DonationResponse>;\n\n /**\n * Once the user is finished with the donation flow, either after\n * a monthly donation or an upsell, we notify the endpoint manager\n * so it can redirect the user to the thank you page.\n */\n donationSuccessful(options: {\n successResponse: SuccessResponse;\n upsellSuccessResponse?: SuccessResponse;\n }): void;\n}\n\nexport enum HostingEnvironment {\n Development = 'dev',\n Production = 'prod',\n}\n"]}
1
+ {"version":3,"file":"braintree-interfaces.js","sourceRoot":"","sources":["../../../src/braintree-manager/braintree-interfaces.ts"],"names":[],"mappings":"AAwKA,MAAM,CAAN,IAAY,kBAGX;AAHD,WAAY,kBAAkB;IAC5B,yCAAmB,CAAA;IACnB,yCAAmB,CAAA;AACrB,CAAC,EAHW,kBAAkB,KAAlB,kBAAkB,QAG7B","sourcesContent":["import {\n DonationRequest,\n DonationResponse,\n SuccessResponse,\n PaymentProvider,\n DonationPaymentInfo,\n CustomerInfo,\n BillingInfo,\n} from '@internetarchive/donation-form-data-models';\nimport { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { Unsubscribe } from 'nanoevents';\nimport { PaymentProvidersInterface } from './payment-providers-interface';\n\nexport interface BraintreeManagerEvents {\n paymentProvidersHostedFieldsRetry: (retryNumber: number) => void;\n paymentProvidersHostedFieldsFailed: (error: unknown) => void;\n}\n\n/**\n * The BraintreeManager is the main entrypoint for much of the common braintree functionality.\n *\n * A single instance of it gets created and passed down through all of the components.\n *\n * @export\n * @interface BraintreeManagerInterface\n */\nexport interface BraintreeManagerInterface {\n on<E extends keyof BraintreeManagerEvents>(\n event: E,\n callback: BraintreeManagerEvents[E],\n ): Unsubscribe;\n\n /**\n * The PaymentProviders class contains the IA-specific handlers for each of the\n * different payment providers.\n *\n * They are generally data-focused, as opposed to UI-focused, but there\n * is some cross-polination between PaymentProviders and FlowHandlers.\n *\n * @type {PaymentProvidersInterface}\n * @memberof BraintreeManagerInterface\n */\n paymentProviders: PaymentProvidersInterface;\n\n /**\n * The Braintree Client instance.\n *\n * This gets used to isntantiate clients for all of the payment providers.\n *\n * @type {PromisedSingleton<braintree.Client>}\n * @memberof BraintreeManagerInterface\n */\n instance: PromisedSingleton<braintree.Client>;\n\n /**\n * Set the referrer for later submission\n *\n * @param {string} referrer\n * @memberof BraintreeManagerInterface\n */\n setReferrer(referrer: string): void;\n\n /**\n * Set the origin for later submission\n *\n * @param {string} origin\n * @memberof BraintreeManagerInterface\n */\n setOrigin(origin: string): void;\n\n /**\n * Set the logged-in user for later submission\n *\n * @param {string} loggedInUser\n * @memberof BraintreeManagerInterface\n */\n setLoggedInUser(loggedInUser: string): void;\n\n /**\n * Perform startup tasts like session resuming\n *\n * @memberof BraintreeManagerInterface\n */\n startup(): void;\n\n /**\n * Submit donation to the backend\n *\n * @param {{\n * nonce: string;\n * paymentProvider: PaymentProvider;\n * donationInfo: DonationPaymentInfo;\n * billingInfo: BillingInfo;\n * customerInfo: CustomerInfo;\n * upsellOnetimeTransactionId?: string;\n * customerId?: string;\n * recaptchaToken?: string;\n * bin?: string; // first 6 digits of CC\n * binName?: string; // credit card bank name\n * }} options\n * @returns {Promise<DonationResponse>}\n * @memberof BraintreeManagerInterface\n */\n submitDonation(options: {\n nonce: string;\n paymentProvider: PaymentProvider;\n donationInfo: DonationPaymentInfo;\n billingInfo: BillingInfo;\n customerInfo: CustomerInfo;\n upsellOnetimeTransactionId?: string;\n customerId?: string;\n recaptchaToken?: string;\n bin?: string; // first 6 digits of CC\n binName?: string; // credit card bank name\n }): Promise<DonationResponse>;\n\n /**\n * Submit the upsell donation\n *\n * @param {{\n * oneTimeDonationResponse: SuccessResponse;\n * amount: number;\n * }} options\n * @returns {Promise<DonationResponse>}\n * @memberof BraintreeManagerInterface\n */\n submitUpsellDonation(options: {\n oneTimeDonationResponse: SuccessResponse;\n amount: number;\n }): Promise<DonationResponse>;\n\n /**\n * Finish the donation after a successful completion.\n *\n * @param {{\n * successResponse: SuccessResponse;\n * upsellSuccessResponse?: SuccessResponse;\n * }} options\n * @memberof BraintreeManagerInterface\n */\n donationSuccessful(options: {\n successResponse: SuccessResponse;\n upsellSuccessResponse?: SuccessResponse;\n }): void;\n}\n\nexport interface BraintreeEndpointManagerInterface {\n /**\n * Responsible for submitting a data object to the backend\n * and returning a Promise of the JSON object response.\n *\n * @param {object} data\n * @returns {Promise<object>}\n * @memberof BraintreeEndpointManagerInterface\n */\n submitData(request: DonationRequest): Promise<DonationResponse>;\n\n /**\n * Once the user is finished with the donation flow, either after\n * a monthly donation or an upsell, we notify the endpoint manager\n * so it can redirect the user to the thank you page.\n */\n donationSuccessful(options: {\n successResponse: SuccessResponse;\n upsellSuccessResponse?: SuccessResponse;\n }): void;\n}\n\nexport enum HostingEnvironment {\n Development = 'dev',\n Production = 'prod',\n}\n"]}
@@ -1,9 +1,10 @@
1
1
  import { DonationResponse, CustomerInfo, BillingInfo, DonationPaymentInfo, PaymentProvider, SuccessResponse } from '@internetarchive/donation-form-data-models';
2
2
  import { PaymentClientsInterface } from './payment-clients';
3
- import { BraintreeManagerInterface, BraintreeEndpointManagerInterface, HostingEnvironment } from './braintree-interfaces';
3
+ import { BraintreeManagerInterface, BraintreeEndpointManagerInterface, HostingEnvironment, BraintreeManagerEvents } from './braintree-interfaces';
4
4
  import { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';
5
5
  import { PromisedSingleton } from '@internetarchive/promised-singleton';
6
6
  import { PaymentProvidersInterface } from './payment-providers-interface';
7
+ import { Unsubscribe } from 'nanoevents';
7
8
  /** @inheritdoc */
8
9
  export declare class BraintreeManager implements BraintreeManagerInterface {
9
10
  private referrer?;
@@ -37,6 +38,8 @@ export declare class BraintreeManager implements BraintreeManagerInterface {
37
38
  * @memberof BraintreeManager
38
39
  */
39
40
  private deviceData?;
41
+ private emitter;
42
+ on<E extends keyof BraintreeManagerEvents>(event: E, callback: BraintreeManagerEvents[E]): Unsubscribe;
40
43
  /** @inheritdoc */
41
44
  paymentProviders: PaymentProvidersInterface;
42
45
  /** @inheritdoc */
@@ -3,9 +3,11 @@ import { DonationResponse, DonationRequest, DonationRequestCustomFields, Donatio
3
3
  import { PaymentProviders } from './payment-providers';
4
4
  import { HostingEnvironment, } from './braintree-interfaces';
5
5
  import { PromisedSingleton } from '@internetarchive/promised-singleton';
6
+ import { createNanoEvents } from 'nanoevents';
6
7
  /** @inheritdoc */
7
8
  export class BraintreeManager {
8
9
  constructor(options) {
10
+ this.emitter = createNanoEvents();
9
11
  /** @inheritdoc */
10
12
  this.instance = new PromisedSingleton({
11
13
  generator: () => __awaiter(this, void 0, void 0, function* () {
@@ -30,6 +32,15 @@ export class BraintreeManager {
30
32
  hostingEnvironment: options.hostingEnvironment,
31
33
  hostedFieldConfig: options.hostedFieldConfig,
32
34
  });
35
+ this.paymentProviders.on('hostedFieldsRetry', (retryNumber) => {
36
+ this.emitter.emit('paymentProvidersHostedFieldsRetry', retryNumber);
37
+ });
38
+ this.paymentProviders.on('hostedFieldsFailed', (error) => {
39
+ this.emitter.emit('paymentProvidersHostedFieldsFailed', error);
40
+ });
41
+ }
42
+ on(event, callback) {
43
+ return this.emitter.on(event, callback);
33
44
  }
34
45
  /** @inheritdoc */
35
46
  startup() {
@@ -1 +1 @@
1
- {"version":3,"file":"braintree-manager.js","sourceRoot":"","sources":["../../../src/braintree-manager/braintree-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DonationResponse,\n DonationRequest,\n DonationRequestCustomFields,\n DonationType,\n CustomerInfo,\n BillingInfo,\n DonationPaymentInfo,\n PaymentProvider,\n SuccessResponse,\n} from '@internetarchive/donation-form-data-models';\n\nimport { PaymentProviders } from './payment-providers';\nimport { PaymentClientsInterface } from './payment-clients';\nimport {\n BraintreeManagerInterface,\n BraintreeEndpointManagerInterface,\n HostingEnvironment,\n} from './braintree-interfaces';\nimport { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';\nimport { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { PaymentProvidersInterface } from './payment-providers-interface';\n\n/** @inheritdoc */\nexport class BraintreeManager implements BraintreeManagerInterface {\n private referrer?: string;\n\n /**\n * The origin is made up of campaign / ABTest information that the user originated from.\n *\n * The field is a freeform string so it can be anything, but make sure it's something\n * identifiable so it can be queried in CiviCRM.\n *\n * For instance, we use this format for the Donation Banner:\n * - `{Source}-{Test Name}-{Variant Name}`, eg:\n * - `DonateBanner-Campaign Start 2020-IADefault`\n * - `DonateBanner-Mid Campaign-IAThermometer`\n *\n * For additional specificity, you could add additional info, ie.\n * - `DonateBanner-MidJuly2020 Campaign-VariantA-Button1`\n *\n * @private\n * @type {string}\n * @memberof BraintreeManager\n */\n private origin?: string;\n\n private loggedInUser?: string;\n\n /**\n * The Device Data token generated by the DataCollector.\n *\n * This gets submitted for several of the payment providers as an anti-fraud mechanism.\n *\n * @private\n * @type {string}\n * @memberof BraintreeManager\n */\n private deviceData?: string;\n\n /** @inheritdoc */\n paymentProviders: PaymentProvidersInterface;\n\n /** @inheritdoc */\n async startup(): Promise<void> {\n return this.collectDeviceData();\n }\n\n /** @inheritdoc */\n instance = new PromisedSingleton<braintree.Client>({\n generator: async (): Promise<braintree.Client> => {\n const client = await this.paymentClients.braintreeClient.get();\n return client?.create({ authorization: this.authorizationToken });\n },\n });\n\n /** @inheritdoc */\n async submitDonation(options: {\n nonce: string;\n paymentProvider: PaymentProvider;\n donationInfo: DonationPaymentInfo;\n billingInfo: BillingInfo;\n customerInfo: CustomerInfo;\n upsellOnetimeTransactionId?: string;\n customerId?: string;\n recaptchaToken?: string;\n bin?: string; // first 6 digits of CC\n binName?: string; // credit card bank name\n }): Promise<DonationResponse> {\n const customFields = new DonationRequestCustomFields();\n // eslint-disable-next-line @typescript-eslint/camelcase\n customFields.fee_amount_covered = options.donationInfo.feeAmountCovered;\n // eslint-disable-next-line @typescript-eslint/camelcase\n customFields.logged_in_user = this.loggedInUser;\n customFields.referrer = this.referrer;\n customFields.origin = this.origin;\n\n // This is interesting and applies only to Venmo, but will work for other providers as well.\n // In Safari, `donationInfo` actually comes through as a DonationPaymentInfo object,\n // but in Chrome, it comes through as a plain object so you can't call `.total()` on it to\n // get the total amount and instead have to calculate the total\n const total = DonationPaymentInfo.calculateTotal(\n options.donationInfo.amount,\n options.donationInfo.coverFees,\n );\n\n const donationRequest = new DonationRequest({\n deviceData: this.deviceData,\n paymentProvider: options.paymentProvider,\n paymentMethodNonce: options.nonce,\n amount: total,\n donationType: options.donationInfo.donationType,\n customer: options.customerInfo,\n billing: options.billingInfo,\n customFields: customFields,\n upsellOnetimeTransactionId: options.upsellOnetimeTransactionId,\n customerId: options.customerId,\n recaptchaToken: options.recaptchaToken,\n bin: options.bin,\n binName: options.binName,\n });\n\n const jsonResponse = await this.endpointManager.submitData(donationRequest);\n const modeledResponse = new DonationResponse(jsonResponse);\n return modeledResponse;\n }\n\n /** @inheritdoc */\n async submitUpsellDonation(options: {\n oneTimeDonationResponse: SuccessResponse;\n amount: number;\n }): Promise<DonationResponse> {\n const response = options.oneTimeDonationResponse;\n\n const donationInfo = new DonationPaymentInfo({\n amount: options.amount,\n donationType: DonationType.Upsell,\n coverFees: false,\n });\n\n return this.submitDonation({\n nonce: response.paymentMethodNonce,\n paymentProvider: response.paymentProvider,\n customerId: response.customer_id,\n donationInfo: donationInfo,\n customerInfo: response.customer,\n billingInfo: response.billing,\n upsellOnetimeTransactionId: response.transaction_id,\n });\n }\n\n /** @inheritdoc */\n donationSuccessful(options: {\n successResponse: SuccessResponse;\n upsellSuccessResponse?: SuccessResponse;\n }): void {\n this.endpointManager.donationSuccessful(options);\n }\n\n private deviceDataCollectionStarted = false;\n\n /**\n * Collect Braintree device data. This is used to help fraud detection.\n *\n * @private\n * @returns {Promise<void>}\n * @memberof BraintreeManager\n */\n private async collectDeviceData(): Promise<void> {\n if (this.deviceDataCollectionStarted) {\n return;\n }\n this.deviceDataCollectionStarted = true;\n\n const instance = await this.instance.get();\n if (!instance) {\n return;\n }\n\n return this.paymentClients.dataCollector\n .get()\n .then((collector?: braintree.DataCollector) => {\n return collector?.create({ client: instance, kount: false, paypal: true });\n })\n .then(instance => {\n this.deviceData = instance?.deviceData;\n });\n }\n\n /**\n * Braintree Authorization Token\n *\n * @private\n * @type {string}\n * @memberof BraintreeManager\n */\n private authorizationToken: string;\n\n /**\n * The endpoint manager for network communications\n *\n * @private\n * @type {BraintreeEndpointManagerInterface}\n * @memberof BraintreeManager\n */\n private endpointManager: BraintreeEndpointManagerInterface;\n\n /**\n * The payment clients container containing the braintree, paypal, and google clients\n *\n * @private\n * @type {PaymentClientsInterface}\n * @memberof BraintreeManager\n */\n private paymentClients: PaymentClientsInterface;\n\n private hostingEnvironment: HostingEnvironment = HostingEnvironment.Development;\n\n constructor(options: {\n authorizationToken: string;\n paymentClients: PaymentClientsInterface;\n endpointManager: BraintreeEndpointManagerInterface;\n hostedFieldConfig: HostedFieldConfiguration;\n hostingEnvironment: HostingEnvironment;\n venmoProfileId?: string;\n googlePayMerchantId?: string;\n referrer?: string;\n loggedInUser?: string;\n origin?: string;\n }) {\n this.authorizationToken = options.authorizationToken;\n this.endpointManager = options.endpointManager;\n this.hostingEnvironment = options.hostingEnvironment;\n this.paymentClients = options.paymentClients;\n\n this.referrer = options.referrer;\n this.loggedInUser = options.loggedInUser;\n this.origin = options.origin;\n\n this.paymentProviders = new PaymentProviders({\n braintreeManager: this,\n paymentClients: this.paymentClients,\n venmoProfileId: options.venmoProfileId,\n googlePayMerchantId: options.googlePayMerchantId,\n hostingEnvironment: options.hostingEnvironment,\n hostedFieldConfig: options.hostedFieldConfig,\n });\n }\n\n /** @inheritdoc */\n setReferrer(referrer: string): void {\n this.referrer = referrer;\n }\n\n /** @inheritdoc */\n setLoggedInUser(loggedInUser: string): void {\n this.loggedInUser = loggedInUser;\n }\n\n /** @inheritdoc */\n setOrigin(origin: string): void {\n this.origin = origin;\n }\n}\n"]}
1
+ {"version":3,"file":"braintree-manager.js","sourceRoot":"","sources":["../../../src/braintree-manager/braintree-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DonationResponse,\n DonationRequest,\n DonationRequestCustomFields,\n DonationType,\n CustomerInfo,\n BillingInfo,\n DonationPaymentInfo,\n PaymentProvider,\n SuccessResponse,\n} from '@internetarchive/donation-form-data-models';\n\nimport { PaymentProviders } from './payment-providers';\nimport { PaymentClientsInterface } from './payment-clients';\nimport {\n BraintreeManagerInterface,\n BraintreeEndpointManagerInterface,\n HostingEnvironment,\n BraintreeManagerEvents,\n} from './braintree-interfaces';\nimport { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';\nimport { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { PaymentProvidersInterface } from './payment-providers-interface';\nimport { createNanoEvents, Unsubscribe } from 'nanoevents';\n\n/** @inheritdoc */\nexport class BraintreeManager implements BraintreeManagerInterface {\n private referrer?: string;\n\n /**\n * The origin is made up of campaign / ABTest information that the user originated from.\n *\n * The field is a freeform string so it can be anything, but make sure it's something\n * identifiable so it can be queried in CiviCRM.\n *\n * For instance, we use this format for the Donation Banner:\n * - `{Source}-{Test Name}-{Variant Name}`, eg:\n * - `DonateBanner-Campaign Start 2020-IADefault`\n * - `DonateBanner-Mid Campaign-IAThermometer`\n *\n * For additional specificity, you could add additional info, ie.\n * - `DonateBanner-MidJuly2020 Campaign-VariantA-Button1`\n *\n * @private\n * @type {string}\n * @memberof BraintreeManager\n */\n private origin?: string;\n\n private loggedInUser?: string;\n\n /**\n * The Device Data token generated by the DataCollector.\n *\n * This gets submitted for several of the payment providers as an anti-fraud mechanism.\n *\n * @private\n * @type {string}\n * @memberof BraintreeManager\n */\n private deviceData?: string;\n\n private emitter = createNanoEvents<BraintreeManagerEvents>();\n\n on<E extends keyof BraintreeManagerEvents>(\n event: E,\n callback: BraintreeManagerEvents[E],\n ): Unsubscribe {\n return this.emitter.on(event, callback);\n }\n\n /** @inheritdoc */\n paymentProviders: PaymentProvidersInterface;\n\n /** @inheritdoc */\n async startup(): Promise<void> {\n return this.collectDeviceData();\n }\n\n /** @inheritdoc */\n instance = new PromisedSingleton<braintree.Client>({\n generator: async (): Promise<braintree.Client> => {\n const client = await this.paymentClients.braintreeClient.get();\n return client?.create({ authorization: this.authorizationToken });\n },\n });\n\n /** @inheritdoc */\n async submitDonation(options: {\n nonce: string;\n paymentProvider: PaymentProvider;\n donationInfo: DonationPaymentInfo;\n billingInfo: BillingInfo;\n customerInfo: CustomerInfo;\n upsellOnetimeTransactionId?: string;\n customerId?: string;\n recaptchaToken?: string;\n bin?: string; // first 6 digits of CC\n binName?: string; // credit card bank name\n }): Promise<DonationResponse> {\n const customFields = new DonationRequestCustomFields();\n // eslint-disable-next-line @typescript-eslint/camelcase\n customFields.fee_amount_covered = options.donationInfo.feeAmountCovered;\n // eslint-disable-next-line @typescript-eslint/camelcase\n customFields.logged_in_user = this.loggedInUser;\n customFields.referrer = this.referrer;\n customFields.origin = this.origin;\n\n // This is interesting and applies only to Venmo, but will work for other providers as well.\n // In Safari, `donationInfo` actually comes through as a DonationPaymentInfo object,\n // but in Chrome, it comes through as a plain object so you can't call `.total()` on it to\n // get the total amount and instead have to calculate the total\n const total = DonationPaymentInfo.calculateTotal(\n options.donationInfo.amount,\n options.donationInfo.coverFees,\n );\n\n const donationRequest = new DonationRequest({\n deviceData: this.deviceData,\n paymentProvider: options.paymentProvider,\n paymentMethodNonce: options.nonce,\n amount: total,\n donationType: options.donationInfo.donationType,\n customer: options.customerInfo,\n billing: options.billingInfo,\n customFields: customFields,\n upsellOnetimeTransactionId: options.upsellOnetimeTransactionId,\n customerId: options.customerId,\n recaptchaToken: options.recaptchaToken,\n bin: options.bin,\n binName: options.binName,\n });\n\n const jsonResponse = await this.endpointManager.submitData(donationRequest);\n const modeledResponse = new DonationResponse(jsonResponse);\n return modeledResponse;\n }\n\n /** @inheritdoc */\n async submitUpsellDonation(options: {\n oneTimeDonationResponse: SuccessResponse;\n amount: number;\n }): Promise<DonationResponse> {\n const response = options.oneTimeDonationResponse;\n\n const donationInfo = new DonationPaymentInfo({\n amount: options.amount,\n donationType: DonationType.Upsell,\n coverFees: false,\n });\n\n return this.submitDonation({\n nonce: response.paymentMethodNonce,\n paymentProvider: response.paymentProvider,\n customerId: response.customer_id,\n donationInfo: donationInfo,\n customerInfo: response.customer,\n billingInfo: response.billing,\n upsellOnetimeTransactionId: response.transaction_id,\n });\n }\n\n /** @inheritdoc */\n donationSuccessful(options: {\n successResponse: SuccessResponse;\n upsellSuccessResponse?: SuccessResponse;\n }): void {\n this.endpointManager.donationSuccessful(options);\n }\n\n private deviceDataCollectionStarted = false;\n\n /**\n * Collect Braintree device data. This is used to help fraud detection.\n *\n * @private\n * @returns {Promise<void>}\n * @memberof BraintreeManager\n */\n private async collectDeviceData(): Promise<void> {\n if (this.deviceDataCollectionStarted) {\n return;\n }\n this.deviceDataCollectionStarted = true;\n\n const instance = await this.instance.get();\n if (!instance) {\n return;\n }\n\n return this.paymentClients.dataCollector\n .get()\n .then((collector?: braintree.DataCollector) => {\n return collector?.create({ client: instance, kount: false, paypal: true });\n })\n .then(instance => {\n this.deviceData = instance?.deviceData;\n });\n }\n\n /**\n * Braintree Authorization Token\n *\n * @private\n * @type {string}\n * @memberof BraintreeManager\n */\n private authorizationToken: string;\n\n /**\n * The endpoint manager for network communications\n *\n * @private\n * @type {BraintreeEndpointManagerInterface}\n * @memberof BraintreeManager\n */\n private endpointManager: BraintreeEndpointManagerInterface;\n\n /**\n * The payment clients container containing the braintree, paypal, and google clients\n *\n * @private\n * @type {PaymentClientsInterface}\n * @memberof BraintreeManager\n */\n private paymentClients: PaymentClientsInterface;\n\n private hostingEnvironment: HostingEnvironment = HostingEnvironment.Development;\n\n constructor(options: {\n authorizationToken: string;\n paymentClients: PaymentClientsInterface;\n endpointManager: BraintreeEndpointManagerInterface;\n hostedFieldConfig: HostedFieldConfiguration;\n hostingEnvironment: HostingEnvironment;\n venmoProfileId?: string;\n googlePayMerchantId?: string;\n referrer?: string;\n loggedInUser?: string;\n origin?: string;\n }) {\n this.authorizationToken = options.authorizationToken;\n this.endpointManager = options.endpointManager;\n this.hostingEnvironment = options.hostingEnvironment;\n this.paymentClients = options.paymentClients;\n\n this.referrer = options.referrer;\n this.loggedInUser = options.loggedInUser;\n this.origin = options.origin;\n\n this.paymentProviders = new PaymentProviders({\n braintreeManager: this,\n paymentClients: this.paymentClients,\n venmoProfileId: options.venmoProfileId,\n googlePayMerchantId: options.googlePayMerchantId,\n hostingEnvironment: options.hostingEnvironment,\n hostedFieldConfig: options.hostedFieldConfig,\n });\n\n this.paymentProviders.on('hostedFieldsRetry', (retryNumber: number) => {\n this.emitter.emit('paymentProvidersHostedFieldsRetry', retryNumber);\n });\n\n this.paymentProviders.on('hostedFieldsFailed', (error: unknown) => {\n this.emitter.emit('paymentProvidersHostedFieldsFailed', error);\n });\n }\n\n /** @inheritdoc */\n setReferrer(referrer: string): void {\n this.referrer = referrer;\n }\n\n /** @inheritdoc */\n setLoggedInUser(loggedInUser: string): void {\n this.loggedInUser = loggedInUser;\n }\n\n /** @inheritdoc */\n setOrigin(origin: string): void {\n this.origin = origin;\n }\n}\n"]}
@@ -1,5 +1,10 @@
1
1
  import { PromisedSingleton } from '@internetarchive/promised-singleton';
2
+ import { Unsubscribe } from 'nanoevents';
2
3
  import { HostedFieldName } from './hosted-field-container';
4
+ export interface CreditCardHandlerEvents {
5
+ hostedFieldsRetry: (retryNumber: number) => void;
6
+ hostedFieldsFailed: (error: unknown) => void;
7
+ }
3
8
  export interface CreditCardHandlerInterface {
4
9
  instance: PromisedSingleton<braintree.HostedFields | undefined>;
5
10
  tokenizeHostedFields(): Promise<braintree.HostedFieldsTokenizePayload | undefined>;
@@ -7,4 +12,5 @@ export interface CreditCardHandlerInterface {
7
12
  removeFieldErrors(fields: HostedFieldName[]): void;
8
13
  showErrorMessage(message?: string): void;
9
14
  hideErrorMessage(): void;
15
+ on<E extends keyof CreditCardHandlerEvents>(event: E, callback: CreditCardHandlerEvents[E]): Unsubscribe;
10
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"credit-card-interface.js","sourceRoot":"","sources":["../../../../../src/braintree-manager/payment-providers/credit-card/credit-card-interface.ts"],"names":[],"mappings":"","sourcesContent":["import { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { HostedFieldName } from './hosted-field-container';\n\nexport interface CreditCardHandlerInterface {\n instance: PromisedSingleton<braintree.HostedFields | undefined>;\n tokenizeHostedFields(): Promise<braintree.HostedFieldsTokenizePayload | undefined>;\n markFieldErrors(fields: HostedFieldName[]): void;\n removeFieldErrors(fields: HostedFieldName[]): void;\n showErrorMessage(message?: string): void;\n hideErrorMessage(): void;\n}\n"]}
1
+ {"version":3,"file":"credit-card-interface.js","sourceRoot":"","sources":["../../../../../src/braintree-manager/payment-providers/credit-card/credit-card-interface.ts"],"names":[],"mappings":"","sourcesContent":["import { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { Unsubscribe } from 'nanoevents';\nimport { HostedFieldName } from './hosted-field-container';\n\nexport interface CreditCardHandlerEvents {\n hostedFieldsRetry: (retryNumber: number) => void;\n hostedFieldsFailed: (error: unknown) => void;\n}\n\nexport interface CreditCardHandlerInterface {\n instance: PromisedSingleton<braintree.HostedFields | undefined>;\n tokenizeHostedFields(): Promise<braintree.HostedFieldsTokenizePayload | undefined>;\n markFieldErrors(fields: HostedFieldName[]): void;\n removeFieldErrors(fields: HostedFieldName[]): void;\n showErrorMessage(message?: string): void;\n hideErrorMessage(): void;\n on<E extends keyof CreditCardHandlerEvents>(\n event: E,\n callback: CreditCardHandlerEvents[E],\n ): Unsubscribe;\n}\n"]}
@@ -2,17 +2,25 @@ import { PromisedSingleton } from '@internetarchive/promised-singleton';
2
2
  import { BraintreeManagerInterface } from '../../braintree-interfaces';
3
3
  import { HostedFieldConfiguration } from './hosted-field-configuration';
4
4
  import { HostedFieldName } from './hosted-field-container';
5
- import { CreditCardHandlerInterface } from './credit-card-interface';
5
+ import { CreditCardHandlerEvents, CreditCardHandlerInterface } from './credit-card-interface';
6
+ import { Unsubscribe } from 'nanoevents';
6
7
  export declare class CreditCardHandler implements CreditCardHandlerInterface {
7
- instance: PromisedSingleton<braintree.HostedFields | undefined>;
8
+ on<E extends keyof CreditCardHandlerEvents>(event: E, callback: CreditCardHandlerEvents[E]): Unsubscribe;
9
+ instance: PromisedSingleton<import("../../../@types/braintree-web").HostedFields | undefined>;
10
+ private emitter;
11
+ private maxRetryCount;
12
+ private loadTimeout;
8
13
  constructor(options: {
9
14
  braintreeManager: BraintreeManagerInterface;
10
15
  hostedFieldClient: braintree.HostedFields;
11
16
  hostedFieldConfig: HostedFieldConfiguration;
17
+ maxRetryCount?: number;
18
+ loadTimeout?: number;
12
19
  });
13
20
  private braintreeManager;
14
21
  private hostedFieldClient;
15
22
  private hostedFieldConfig;
23
+ private createHostedFields;
16
24
  tokenizeHostedFields(): Promise<braintree.HostedFieldsTokenizePayload | undefined>;
17
25
  markFieldErrors(fields: HostedFieldName[]): void;
18
26
  removeFieldErrors(fields: HostedFieldName[]): void;
@@ -1,20 +1,82 @@
1
1
  import { __awaiter } from "tslib";
2
2
  import { PromisedSingleton } from '@internetarchive/promised-singleton';
3
+ import { createNanoEvents } from 'nanoevents';
4
+ import { DonationFormError } from '../../../donation-form-error';
3
5
  export class CreditCardHandler {
4
6
  constructor(options) {
5
- this.braintreeManager = options.braintreeManager;
6
- this.hostedFieldClient = options.hostedFieldClient;
7
- this.hostedFieldConfig = options.hostedFieldConfig;
7
+ var _a, _b;
8
8
  this.instance = new PromisedSingleton({
9
9
  generator: () => __awaiter(this, void 0, void 0, function* () {
10
10
  const braintreeClient = yield this.braintreeManager.instance.get();
11
- return this.hostedFieldClient.create({
12
- client: braintreeClient,
13
- styles: this.hostedFieldConfig.hostedFieldStyle,
14
- fields: this.hostedFieldConfig.hostedFieldFieldOptions,
15
- });
11
+ const hostedFields = yield this.createHostedFields(braintreeClient);
12
+ return hostedFields;
16
13
  }),
17
14
  });
15
+ this.emitter = createNanoEvents();
16
+ this.braintreeManager = options.braintreeManager;
17
+ this.hostedFieldClient = options.hostedFieldClient;
18
+ this.hostedFieldConfig = options.hostedFieldConfig;
19
+ this.maxRetryCount = (_a = options.maxRetryCount) !== null && _a !== void 0 ? _a : 2;
20
+ this.loadTimeout = ((_b = options.loadTimeout) !== null && _b !== void 0 ? _b : 6) * 1000;
21
+ }
22
+ on(event, callback) {
23
+ return this.emitter.on(event, callback);
24
+ }
25
+ createHostedFields(braintreeClient, retryCount = 0) {
26
+ return __awaiter(this, void 0, void 0, function* () {
27
+ // we mainly want to do this for retry events, but it doesn't
28
+ // hurt to do it on the first try
29
+ this.hostedFieldConfig.hostedFieldContainer.resetHostedFields();
30
+ try {
31
+ // The hosted fields have a 60 second timeout internally, but braintree
32
+ // support recommended setting a shorter timeout because 99% of users
33
+ // load the hosted fields in under 4 seconds and 99.9% with 18 seconds.
34
+ // What we're doing here is creating a "timeout" promise
35
+ // and a "create hosted fields" promise and doing a `Promise.race()` to
36
+ // resolve when the first one finishes. If the timeout finishes first,
37
+ // we throw an error to trigger the retry logic. If the hosted fields
38
+ // finishes first, we cancel the timeout promise since we're done.
39
+ let timeout;
40
+ const timeoutPromise = new Promise((resolve, reject) => {
41
+ timeout = window.setTimeout(() => {
42
+ const error = new DonationFormError('Timeout loading Hosted Fields');
43
+ reject(error);
44
+ }, this.loadTimeout);
45
+ });
46
+ const hostedFieldsPromise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
47
+ try {
48
+ const fields = yield this.hostedFieldClient.create({
49
+ client: braintreeClient,
50
+ styles: this.hostedFieldConfig.hostedFieldStyle,
51
+ fields: this.hostedFieldConfig.hostedFieldFieldOptions,
52
+ });
53
+ // clear the timeout when this finishes so we don't also get the timeout rejection
54
+ window.clearTimeout(timeout);
55
+ resolve(fields);
56
+ }
57
+ catch (error) {
58
+ if (error instanceof Error && error.message.includes('Hosted Fields timed out')) {
59
+ // this is the timeout error, so we don't need to do anything
60
+ }
61
+ else {
62
+ // this is some other error. reject so it bubbles up to Sentry
63
+ reject(error);
64
+ }
65
+ }
66
+ }));
67
+ const result = yield Promise.race([timeoutPromise, hostedFieldsPromise]);
68
+ return result;
69
+ }
70
+ catch (error) {
71
+ if (retryCount >= this.maxRetryCount) {
72
+ this.emitter.emit('hostedFieldsFailed', error);
73
+ throw error;
74
+ }
75
+ const newRetryCount = retryCount + 1;
76
+ this.emitter.emit('hostedFieldsRetry', newRetryCount);
77
+ return this.createHostedFields(braintreeClient, newRetryCount);
78
+ }
79
+ });
18
80
  }
19
81
  tokenizeHostedFields() {
20
82
  return __awaiter(this, void 0, void 0, function* () {
@@ -1 +1 @@
1
- {"version":3,"file":"credit-card.js","sourceRoot":"","sources":["../../../../../src/braintree-manager/payment-providers/credit-card/credit-card.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAMxE,MAAM,OAAO,iBAAiB;IAG5B,YAAY,OAIX;QACC,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;QACjD,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACnD,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QAEnD,IAAI,CAAC,QAAQ,GAAG,IAAI,iBAAiB,CAAqC;YACxE,SAAS,EAAE,GAAsD,EAAE;gBACjE,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBACnE,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;oBACnC,MAAM,EAAE,eAAe;oBACvB,MAAM,EAAE,IAAI,CAAC,iBAAiB,CAAC,gBAAgB;oBAC/C,MAAM,EAAE,IAAI,CAAC,iBAAiB,CAAC,uBAAuB;iBACvD,CAAC,CAAC;YACL,CAAC,CAAA;SACF,CAAC,CAAC;IACL,CAAC;IAMK,oBAAoB;;YACxB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;YAC/C,OAAO,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,QAAQ,GAAG;QAClC,CAAC;KAAA;IAED,eAAe,CAAC,MAAyB;QACvC,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IACtE,CAAC;IAED,iBAAiB,CAAC,MAAyB;QACzC,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxE,CAAC;IAED,gBAAgB,CAAC,OAAgB;QAC/B,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACxE,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,gBAAgB,EAAE,CAAC;IACjE,CAAC;CACF","sourcesContent":["import { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { BraintreeManagerInterface } from '../../braintree-interfaces';\nimport { HostedFieldConfiguration } from './hosted-field-configuration';\nimport { HostedFieldName } from './hosted-field-container';\nimport { CreditCardHandlerInterface } from './credit-card-interface';\n\nexport class CreditCardHandler implements CreditCardHandlerInterface {\n instance: PromisedSingleton<braintree.HostedFields | undefined>;\n\n constructor(options: {\n braintreeManager: BraintreeManagerInterface;\n hostedFieldClient: braintree.HostedFields;\n hostedFieldConfig: HostedFieldConfiguration;\n }) {\n this.braintreeManager = options.braintreeManager;\n this.hostedFieldClient = options.hostedFieldClient;\n this.hostedFieldConfig = options.hostedFieldConfig;\n\n this.instance = new PromisedSingleton<braintree.HostedFields | undefined>({\n generator: async (): Promise<braintree.HostedFields | undefined> => {\n const braintreeClient = await this.braintreeManager.instance.get();\n return this.hostedFieldClient.create({\n client: braintreeClient,\n styles: this.hostedFieldConfig.hostedFieldStyle,\n fields: this.hostedFieldConfig.hostedFieldFieldOptions,\n });\n },\n });\n }\n\n private braintreeManager: BraintreeManagerInterface;\n private hostedFieldClient: braintree.HostedFields;\n private hostedFieldConfig: HostedFieldConfiguration;\n\n async tokenizeHostedFields(): Promise<braintree.HostedFieldsTokenizePayload | undefined> {\n const hostedFields = await this.instance.get();\n return hostedFields?.tokenize();\n }\n\n markFieldErrors(fields: HostedFieldName[]): void {\n this.hostedFieldConfig.hostedFieldContainer.markFieldErrors(fields);\n }\n\n removeFieldErrors(fields: HostedFieldName[]): void {\n this.hostedFieldConfig.hostedFieldContainer.removeFieldErrors(fields);\n }\n\n showErrorMessage(message?: string): void {\n this.hostedFieldConfig.hostedFieldContainer.showErrorMessage(message);\n }\n\n hideErrorMessage(): void {\n this.hostedFieldConfig.hostedFieldContainer.hideErrorMessage();\n }\n}\n"]}
1
+ {"version":3,"file":"credit-card.js","sourceRoot":"","sources":["../../../../../src/braintree-manager/payment-providers/credit-card/credit-card.ts"],"names":[],"mappings":"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","sourcesContent":["import { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { BraintreeManagerInterface } from '../../braintree-interfaces';\nimport { HostedFieldConfiguration } from './hosted-field-configuration';\nimport { HostedFieldName } from './hosted-field-container';\nimport { CreditCardHandlerEvents, CreditCardHandlerInterface } from './credit-card-interface';\nimport { createNanoEvents, Unsubscribe } from 'nanoevents';\nimport { DonationFormError } from '../../../donation-form-error';\n\nexport class CreditCardHandler implements CreditCardHandlerInterface {\n on<E extends keyof CreditCardHandlerEvents>(\n event: E,\n callback: CreditCardHandlerEvents[E],\n ): Unsubscribe {\n return this.emitter.on(event, callback);\n }\n\n instance = new PromisedSingleton<braintree.HostedFields | undefined>({\n generator: async (): Promise<braintree.HostedFields | undefined> => {\n const braintreeClient = await this.braintreeManager.instance.get();\n const hostedFields = await this.createHostedFields(braintreeClient);\n return hostedFields;\n },\n });\n\n private emitter = createNanoEvents<CreditCardHandlerEvents>();\n\n private maxRetryCount: number;\n\n private loadTimeout: number;\n\n constructor(options: {\n braintreeManager: BraintreeManagerInterface;\n hostedFieldClient: braintree.HostedFields;\n hostedFieldConfig: HostedFieldConfiguration;\n maxRetryCount?: number;\n loadTimeout?: number;\n }) {\n this.braintreeManager = options.braintreeManager;\n this.hostedFieldClient = options.hostedFieldClient;\n this.hostedFieldConfig = options.hostedFieldConfig;\n this.maxRetryCount = options.maxRetryCount ?? 2;\n this.loadTimeout = (options.loadTimeout ?? 6) * 1000;\n }\n\n private braintreeManager: BraintreeManagerInterface;\n private hostedFieldClient: braintree.HostedFields;\n private hostedFieldConfig: HostedFieldConfiguration;\n\n private async createHostedFields(\n braintreeClient: braintree.Client,\n retryCount = 0,\n ): Promise<braintree.HostedFields | undefined> {\n // we mainly want to do this for retry events, but it doesn't\n // hurt to do it on the first try\n this.hostedFieldConfig.hostedFieldContainer.resetHostedFields();\n try {\n // The hosted fields have a 60 second timeout internally, but braintree\n // support recommended setting a shorter timeout because 99% of users\n // load the hosted fields in under 4 seconds and 99.9% with 18 seconds.\n // What we're doing here is creating a \"timeout\" promise\n // and a \"create hosted fields\" promise and doing a `Promise.race()` to\n // resolve when the first one finishes. If the timeout finishes first,\n // we throw an error to trigger the retry logic. If the hosted fields\n // finishes first, we cancel the timeout promise since we're done.\n let timeout: number;\n\n const timeoutPromise = new Promise<void>((resolve, reject) => {\n timeout = window.setTimeout(() => {\n const error = new DonationFormError('Timeout loading Hosted Fields');\n reject(error);\n }, this.loadTimeout);\n });\n\n const hostedFieldsPromise = new Promise<braintree.HostedFields | undefined>(\n async (resolve, reject) => {\n try {\n const fields = await this.hostedFieldClient.create({\n client: braintreeClient,\n styles: this.hostedFieldConfig.hostedFieldStyle,\n fields: this.hostedFieldConfig.hostedFieldFieldOptions,\n });\n // clear the timeout when this finishes so we don't also get the timeout rejection\n window.clearTimeout(timeout);\n resolve(fields);\n } catch (error) {\n if (error instanceof Error && error.message.includes('Hosted Fields timed out')) {\n // this is the timeout error, so we don't need to do anything\n } else {\n // this is some other error. reject so it bubbles up to Sentry\n reject(error);\n }\n }\n },\n );\n\n const result = await Promise.race([timeoutPromise, hostedFieldsPromise]);\n\n return result as braintree.HostedFields;\n } catch (error) {\n if (retryCount >= this.maxRetryCount) {\n this.emitter.emit('hostedFieldsFailed', error);\n throw error;\n }\n const newRetryCount = retryCount + 1;\n this.emitter.emit('hostedFieldsRetry', newRetryCount);\n return this.createHostedFields(braintreeClient, newRetryCount);\n }\n }\n\n async tokenizeHostedFields(): Promise<braintree.HostedFieldsTokenizePayload | undefined> {\n const hostedFields = await this.instance.get();\n return hostedFields?.tokenize();\n }\n\n markFieldErrors(fields: HostedFieldName[]): void {\n this.hostedFieldConfig.hostedFieldContainer.markFieldErrors(fields);\n }\n\n removeFieldErrors(fields: HostedFieldName[]): void {\n this.hostedFieldConfig.hostedFieldContainer.removeFieldErrors(fields);\n }\n\n showErrorMessage(message?: string): void {\n this.hostedFieldConfig.hostedFieldContainer.showErrorMessage(message);\n }\n\n hideErrorMessage(): void {\n this.hostedFieldConfig.hostedFieldContainer.hideErrorMessage();\n }\n}\n"]}
@@ -4,26 +4,31 @@ export declare enum HostedFieldName {
4
4
  ExpirationDate = "expirationDate"
5
5
  }
6
6
  export interface HostedFieldContainerInterface {
7
- fieldFor(field: HostedFieldName): HTMLInputElement;
7
+ fieldFor(field: HostedFieldName): HTMLDivElement;
8
8
  markFieldErrors(fields: HostedFieldName[]): void;
9
9
  removeFieldErrors(fields: HostedFieldName[]): void;
10
10
  showErrorMessage(message?: string): void;
11
11
  hideErrorMessage(): void;
12
+ /**
13
+ * Reset the hosted fields to retry in case of timeout
14
+ */
15
+ resetHostedFields(): void;
12
16
  }
13
17
  export declare class HostedFieldContainer implements HostedFieldContainerInterface {
14
18
  private number;
15
19
  private cvv;
16
20
  private expirationDate;
17
21
  private errorContainer;
18
- fieldFor(field: HostedFieldName): HTMLInputElement;
22
+ fieldFor(field: HostedFieldName): HTMLDivElement;
19
23
  markFieldErrors(fields: HostedFieldName[]): void;
20
24
  removeFieldErrors(fields: HostedFieldName[]): void;
21
25
  showErrorMessage(message?: string): void;
22
26
  hideErrorMessage(): void;
27
+ resetHostedFields(): void;
23
28
  constructor(options: {
24
- number: HTMLInputElement;
25
- cvv: HTMLInputElement;
26
- expirationDate: HTMLInputElement;
29
+ number: HTMLDivElement;
30
+ cvv: HTMLDivElement;
31
+ expirationDate: HTMLDivElement;
27
32
  errorContainer: HTMLDivElement;
28
33
  });
29
34
  }
@@ -41,5 +41,13 @@ export class HostedFieldContainer {
41
41
  hideErrorMessage() {
42
42
  this.errorContainer.style.display = 'none';
43
43
  }
44
+ resetHostedFields() {
45
+ const elements = [this.number, this.cvv, this.expirationDate];
46
+ elements.forEach(element => {
47
+ while (element.firstChild) {
48
+ element.firstChild.remove();
49
+ }
50
+ });
51
+ }
44
52
  }
45
53
  //# sourceMappingURL=hosted-field-container.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hosted-field-container.js","sourceRoot":"","sources":["../../../../../src/braintree-manager/payment-providers/credit-card/hosted-field-container.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,oCAAiB,CAAA;IACjB,8BAAW,CAAA;IACX,oDAAiC,CAAA;AACnC,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B;AAUD,MAAM,OAAO,oBAAoB;IA4C/B,YAAY,OAKX;QACC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC/C,CAAC;IA7CD,QAAQ,CAAC,KAAsB;QAC7B,QAAQ,KAAK,EAAE;YACb,KAAK,eAAe,CAAC,MAAM;gBACzB,OAAO,IAAI,CAAC,MAAM,CAAC;YACrB,KAAK,eAAe,CAAC,GAAG;gBACtB,OAAO,IAAI,CAAC,GAAG,CAAC;YAClB,KAAK,eAAe,CAAC,cAAc;gBACjC,OAAO,IAAI,CAAC,cAAc,CAAC;SAC9B;IACH,CAAC;IAED,eAAe,CAAC,MAAyB;QACvC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClC,KAAK,CAAC,aAA6B,CAAC,KAAK,GAAG,IAAI,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,iBAAiB,CAAC,MAAyB;QACzC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClC,KAAK,CAAC,aAA6B,CAAC,KAAK,GAAG,KAAK,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB,CAAC,OAAgB;QAC/B,MAAM,KAAK,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,yDAAyD,CAAC;QACnF,IAAI,CAAC,cAAc,CAAC,SAAS,GAAG,KAAK,CAAC;QACtC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IAC9C,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IAC7C,CAAC;CAaF","sourcesContent":["import { BadgedInput } from '../../../form-elements/badged-input';\n\nexport enum HostedFieldName {\n Number = 'number',\n CVV = 'cvv',\n ExpirationDate = 'expirationDate',\n}\n\nexport interface HostedFieldContainerInterface {\n fieldFor(field: HostedFieldName): HTMLInputElement;\n markFieldErrors(fields: HostedFieldName[]): void;\n removeFieldErrors(fields: HostedFieldName[]): void;\n showErrorMessage(message?: string): void;\n hideErrorMessage(): void;\n}\n\nexport class HostedFieldContainer implements HostedFieldContainerInterface {\n private number: HTMLInputElement;\n\n private cvv: HTMLInputElement;\n\n private expirationDate: HTMLInputElement;\n\n private errorContainer: HTMLDivElement;\n\n fieldFor(field: HostedFieldName): HTMLInputElement {\n switch (field) {\n case HostedFieldName.Number:\n return this.number;\n case HostedFieldName.CVV:\n return this.cvv;\n case HostedFieldName.ExpirationDate:\n return this.expirationDate;\n }\n }\n\n markFieldErrors(fields: HostedFieldName[]): void {\n fields.forEach(field => {\n const input = this.fieldFor(field);\n (input.parentElement as BadgedInput).error = true;\n });\n }\n\n removeFieldErrors(fields: HostedFieldName[]): void {\n fields.forEach(field => {\n const input = this.fieldFor(field);\n (input.parentElement as BadgedInput).error = false;\n });\n }\n\n showErrorMessage(message?: string): void {\n const error = message ?? 'Some payment information below is missing or incorrect.';\n this.errorContainer.innerHTML = error;\n this.errorContainer.style.display = 'block';\n }\n\n hideErrorMessage(): void {\n this.errorContainer.style.display = 'none';\n }\n\n constructor(options: {\n number: HTMLInputElement;\n cvv: HTMLInputElement;\n expirationDate: HTMLInputElement;\n errorContainer: HTMLDivElement;\n }) {\n this.number = options.number;\n this.cvv = options.cvv;\n this.expirationDate = options.expirationDate;\n this.errorContainer = options.errorContainer;\n }\n}\n"]}
1
+ {"version":3,"file":"hosted-field-container.js","sourceRoot":"","sources":["../../../../../src/braintree-manager/payment-providers/credit-card/hosted-field-container.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,oCAAiB,CAAA;IACjB,8BAAW,CAAA;IACX,oDAAiC,CAAA;AACnC,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B;AAcD,MAAM,OAAO,oBAAoB;IAqD/B,YAAY,OAKX;QACC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC/C,CAAC;IAtDD,QAAQ,CAAC,KAAsB;QAC7B,QAAQ,KAAK,EAAE;YACb,KAAK,eAAe,CAAC,MAAM;gBACzB,OAAO,IAAI,CAAC,MAAM,CAAC;YACrB,KAAK,eAAe,CAAC,GAAG;gBACtB,OAAO,IAAI,CAAC,GAAG,CAAC;YAClB,KAAK,eAAe,CAAC,cAAc;gBACjC,OAAO,IAAI,CAAC,cAAc,CAAC;SAC9B;IACH,CAAC;IAED,eAAe,CAAC,MAAyB;QACvC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClC,KAAK,CAAC,aAA6B,CAAC,KAAK,GAAG,IAAI,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,iBAAiB,CAAC,MAAyB;QACzC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClC,KAAK,CAAC,aAA6B,CAAC,KAAK,GAAG,KAAK,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB,CAAC,OAAgB;QAC/B,MAAM,KAAK,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,yDAAyD,CAAC;QACnF,IAAI,CAAC,cAAc,CAAC,SAAS,GAAG,KAAK,CAAC;QACtC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IAC9C,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IAC7C,CAAC;IAED,iBAAiB;QACf,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9D,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;YACzB,OAAO,OAAO,CAAC,UAAU,EAAE;gBACzB,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;aAC7B;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CAaF","sourcesContent":["import { BadgedInput } from '../../../form-elements/badged-input';\n\nexport enum HostedFieldName {\n Number = 'number',\n CVV = 'cvv',\n ExpirationDate = 'expirationDate',\n}\n\nexport interface HostedFieldContainerInterface {\n fieldFor(field: HostedFieldName): HTMLDivElement;\n markFieldErrors(fields: HostedFieldName[]): void;\n removeFieldErrors(fields: HostedFieldName[]): void;\n showErrorMessage(message?: string): void;\n hideErrorMessage(): void;\n /**\n * Reset the hosted fields to retry in case of timeout\n */\n resetHostedFields(): void;\n}\n\nexport class HostedFieldContainer implements HostedFieldContainerInterface {\n private number: HTMLDivElement;\n\n private cvv: HTMLDivElement;\n\n private expirationDate: HTMLDivElement;\n\n private errorContainer: HTMLDivElement;\n\n fieldFor(field: HostedFieldName): HTMLDivElement {\n switch (field) {\n case HostedFieldName.Number:\n return this.number;\n case HostedFieldName.CVV:\n return this.cvv;\n case HostedFieldName.ExpirationDate:\n return this.expirationDate;\n }\n }\n\n markFieldErrors(fields: HostedFieldName[]): void {\n fields.forEach(field => {\n const input = this.fieldFor(field);\n (input.parentElement as BadgedInput).error = true;\n });\n }\n\n removeFieldErrors(fields: HostedFieldName[]): void {\n fields.forEach(field => {\n const input = this.fieldFor(field);\n (input.parentElement as BadgedInput).error = false;\n });\n }\n\n showErrorMessage(message?: string): void {\n const error = message ?? 'Some payment information below is missing or incorrect.';\n this.errorContainer.innerHTML = error;\n this.errorContainer.style.display = 'block';\n }\n\n hideErrorMessage(): void {\n this.errorContainer.style.display = 'none';\n }\n\n resetHostedFields(): void {\n const elements = [this.number, this.cvv, this.expirationDate];\n elements.forEach(element => {\n while (element.firstChild) {\n element.firstChild.remove();\n }\n });\n }\n\n constructor(options: {\n number: HTMLDivElement;\n cvv: HTMLDivElement;\n expirationDate: HTMLDivElement;\n errorContainer: HTMLDivElement;\n }) {\n this.number = options.number;\n this.cvv = options.cvv;\n this.expirationDate = options.expirationDate;\n this.errorContainer = options.errorContainer;\n }\n}\n"]}
@@ -1,10 +1,13 @@
1
1
  import { PromisedSingleton } from '@internetarchive/promised-singleton';
2
2
  import { ApplePayHandlerInterface } from './payment-providers/apple-pay/apple-pay-interface';
3
- import { CreditCardHandlerInterface } from './payment-providers/credit-card/credit-card-interface';
3
+ import { CreditCardHandlerEvents, CreditCardHandlerInterface } from './payment-providers/credit-card/credit-card-interface';
4
4
  import { VenmoHandlerInterface } from './payment-providers/venmo-interface';
5
5
  import { PayPalHandlerInterface } from './payment-providers/paypal/paypal-interface';
6
6
  import { GooglePayHandlerInterface } from './payment-providers/google-pay-interface';
7
+ import { Unsubscribe } from 'nanoevents';
8
+ export declare type PaymentProvidersEvents = CreditCardHandlerEvents;
7
9
  export interface PaymentProvidersInterface {
10
+ on<E extends keyof PaymentProvidersEvents>(event: E, callback: PaymentProvidersEvents[E]): Unsubscribe;
8
11
  creditCardHandler: PromisedSingleton<CreditCardHandlerInterface>;
9
12
  applePayHandler: PromisedSingleton<ApplePayHandlerInterface>;
10
13
  venmoHandler: PromisedSingleton<VenmoHandlerInterface | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"payment-providers-interface.js","sourceRoot":"","sources":["../../../src/braintree-manager/payment-providers-interface.ts"],"names":[],"mappings":"","sourcesContent":["import { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { ApplePayHandlerInterface } from './payment-providers/apple-pay/apple-pay-interface';\nimport { CreditCardHandlerInterface } from './payment-providers/credit-card/credit-card-interface';\nimport { VenmoHandlerInterface } from './payment-providers/venmo-interface';\nimport { PayPalHandlerInterface } from './payment-providers/paypal/paypal-interface';\nimport { GooglePayHandlerInterface } from './payment-providers/google-pay-interface';\n\nexport interface PaymentProvidersInterface {\n creditCardHandler: PromisedSingleton<CreditCardHandlerInterface>;\n applePayHandler: PromisedSingleton<ApplePayHandlerInterface>;\n venmoHandler: PromisedSingleton<VenmoHandlerInterface | undefined>;\n paypalHandler: PromisedSingleton<PayPalHandlerInterface>;\n googlePayHandler: PromisedSingleton<GooglePayHandlerInterface>;\n}\n"]}
1
+ {"version":3,"file":"payment-providers-interface.js","sourceRoot":"","sources":["../../../src/braintree-manager/payment-providers-interface.ts"],"names":[],"mappings":"","sourcesContent":["import { PromisedSingleton } from '@internetarchive/promised-singleton';\nimport { ApplePayHandlerInterface } from './payment-providers/apple-pay/apple-pay-interface';\nimport {\n CreditCardHandlerEvents,\n CreditCardHandlerInterface,\n} from './payment-providers/credit-card/credit-card-interface';\nimport { VenmoHandlerInterface } from './payment-providers/venmo-interface';\nimport { PayPalHandlerInterface } from './payment-providers/paypal/paypal-interface';\nimport { GooglePayHandlerInterface } from './payment-providers/google-pay-interface';\nimport { Unsubscribe } from 'nanoevents';\n\n// this will bubble up child events\nexport type PaymentProvidersEvents = CreditCardHandlerEvents;\n\nexport interface PaymentProvidersInterface {\n on<E extends keyof PaymentProvidersEvents>(\n event: E,\n callback: PaymentProvidersEvents[E],\n ): Unsubscribe;\n creditCardHandler: PromisedSingleton<CreditCardHandlerInterface>;\n applePayHandler: PromisedSingleton<ApplePayHandlerInterface>;\n venmoHandler: PromisedSingleton<VenmoHandlerInterface | undefined>;\n paypalHandler: PromisedSingleton<PayPalHandlerInterface>;\n googlePayHandler: PromisedSingleton<GooglePayHandlerInterface>;\n}\n"]}
@@ -2,12 +2,13 @@ import { PromisedSingleton } from '@internetarchive/promised-singleton';
2
2
  import { PaymentClientsInterface } from './payment-clients';
3
3
  import { BraintreeManagerInterface, HostingEnvironment } from './braintree-interfaces';
4
4
  import { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';
5
- import { PaymentProvidersInterface } from './payment-providers-interface';
5
+ import { PaymentProvidersEvents, PaymentProvidersInterface } from './payment-providers-interface';
6
6
  import { ApplePayHandlerInterface } from './payment-providers/apple-pay/apple-pay-interface';
7
7
  import { CreditCardHandlerInterface } from './payment-providers/credit-card/credit-card-interface';
8
8
  import { VenmoHandlerInterface } from './payment-providers/venmo-interface';
9
9
  import { PayPalHandlerInterface } from './payment-providers/paypal/paypal-interface';
10
10
  import { GooglePayHandlerInterface } from './payment-providers/google-pay-interface';
11
+ import { Unsubscribe } from 'nanoevents';
11
12
  /**
12
13
  * The PaymentProviders class contains the IA-specific handlers for each of the
13
14
  * different payment providers.
@@ -20,6 +21,7 @@ import { GooglePayHandlerInterface } from './payment-providers/google-pay-interf
20
21
  * @implements {PaymentProvidersInterface}
21
22
  */
22
23
  export declare class PaymentProviders implements PaymentProvidersInterface {
24
+ on<E extends keyof PaymentProvidersEvents>(event: E, callback: PaymentProvidersEvents[E]): Unsubscribe;
23
25
  creditCardHandler: PromisedSingleton<CreditCardHandlerInterface>;
24
26
  applePayHandler: PromisedSingleton<ApplePayHandlerInterface>;
25
27
  venmoHandler: PromisedSingleton<VenmoHandlerInterface | undefined>;
@@ -31,6 +33,7 @@ export declare class PaymentProviders implements PaymentProvidersInterface {
31
33
  private hostedFieldConfig;
32
34
  private hostingEnvironment;
33
35
  private paymentClients;
36
+ private emitter;
34
37
  constructor(options: {
35
38
  braintreeManager: BraintreeManagerInterface;
36
39
  paymentClients: PaymentClientsInterface;
@@ -7,6 +7,7 @@ import { PayPalHandler } from './payment-providers/paypal/paypal';
7
7
  import { ApplePaySessionManager } from './payment-providers/apple-pay/apple-pay-session-manager';
8
8
  import { GooglePayHandler } from './payment-providers/google-pay';
9
9
  import { HostingEnvironment } from './braintree-interfaces';
10
+ import { createNanoEvents } from 'nanoevents';
10
11
  /**
11
12
  * The PaymentProviders class contains the IA-specific handlers for each of the
12
13
  * different payment providers.
@@ -23,11 +24,18 @@ export class PaymentProviders {
23
24
  this.creditCardHandler = new PromisedSingleton({
24
25
  generator: () => __awaiter(this, void 0, void 0, function* () {
25
26
  const client = yield this.paymentClients.hostedFields.get();
26
- return new CreditCardHandler({
27
+ const handler = new CreditCardHandler({
27
28
  braintreeManager: this.braintreeManager,
28
29
  hostedFieldClient: client,
29
30
  hostedFieldConfig: this.hostedFieldConfig,
30
31
  });
32
+ handler.on('hostedFieldsRetry', (retryNumber) => {
33
+ this.emitter.emit('hostedFieldsRetry', retryNumber);
34
+ });
35
+ handler.on('hostedFieldsFailed', (error) => {
36
+ this.emitter.emit('hostedFieldsFailed', error);
37
+ });
38
+ return handler;
31
39
  }),
32
40
  });
33
41
  this.applePayHandler = new PromisedSingleton({
@@ -83,6 +91,7 @@ export class PaymentProviders {
83
91
  }),
84
92
  });
85
93
  this.hostingEnvironment = HostingEnvironment.Development;
94
+ this.emitter = createNanoEvents();
86
95
  this.braintreeManager = options.braintreeManager;
87
96
  this.venmoProfileId = options.venmoProfileId;
88
97
  this.googlePayMerchantId = options.googlePayMerchantId;
@@ -90,5 +99,8 @@ export class PaymentProviders {
90
99
  this.hostingEnvironment = options.hostingEnvironment;
91
100
  this.hostedFieldConfig = options.hostedFieldConfig;
92
101
  }
102
+ on(event, callback) {
103
+ return this.emitter.on(event, callback);
104
+ }
93
105
  }
94
106
  //# sourceMappingURL=payment-providers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"payment-providers.js","sourceRoot":"","sources":["../../../src/braintree-manager/payment-providers.ts"],"names":[],"mappings":"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","sourcesContent":["import { PromisedSingleton } from '@internetarchive/promised-singleton';\n\nimport { CreditCardHandler } from './payment-providers/credit-card/credit-card';\nimport { ApplePayHandler } from './payment-providers/apple-pay/apple-pay';\nimport { VenmoHandler } from './payment-providers/venmo';\nimport { PayPalHandler } from './payment-providers/paypal/paypal';\nimport { ApplePaySessionManager } from './payment-providers/apple-pay/apple-pay-session-manager';\nimport { PaymentClientsInterface } from './payment-clients';\nimport { GooglePayHandler } from './payment-providers/google-pay';\nimport { BraintreeManagerInterface, HostingEnvironment } from './braintree-interfaces';\nimport { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';\nimport { PaymentProvidersInterface } from './payment-providers-interface';\nimport { ApplePayHandlerInterface } from './payment-providers/apple-pay/apple-pay-interface';\nimport { CreditCardHandlerInterface } from './payment-providers/credit-card/credit-card-interface';\nimport { VenmoHandlerInterface } from './payment-providers/venmo-interface';\nimport { PayPalHandlerInterface } from './payment-providers/paypal/paypal-interface';\nimport { GooglePayHandlerInterface } from './payment-providers/google-pay-interface';\n\n/**\n * The PaymentProviders class contains the IA-specific handlers for each of the\n * different payment providers.\n *\n * They are generally data-focused, as opposed to UI-focused, but there\n * is some cross-polination between PaymentProviders and FlowHandlers.\n *\n * @export\n * @class PaymentProviders\n * @implements {PaymentProvidersInterface}\n */\nexport class PaymentProviders implements PaymentProvidersInterface {\n creditCardHandler = new PromisedSingleton<CreditCardHandlerInterface>({\n generator: async (): Promise<CreditCardHandlerInterface> => {\n const client = await this.paymentClients.hostedFields.get();\n return new CreditCardHandler({\n braintreeManager: this.braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: this.hostedFieldConfig,\n });\n },\n });\n\n applePayHandler = new PromisedSingleton<ApplePayHandlerInterface>({\n generator: async (): Promise<ApplePayHandlerInterface> => {\n const client = await this.paymentClients.applePay.get();\n const applePaySessionManager = new ApplePaySessionManager();\n return new ApplePayHandler({\n braintreeManager: this.braintreeManager,\n applePayClient: client,\n applePaySessionManager: applePaySessionManager,\n });\n },\n });\n\n venmoHandler = new PromisedSingleton<VenmoHandlerInterface | undefined>({\n generator: async (): Promise<VenmoHandlerInterface | undefined> => {\n const client = await this.paymentClients.venmo.get();\n if (!this.venmoProfileId) {\n return undefined;\n }\n return new VenmoHandler({\n braintreeManager: this.braintreeManager,\n venmoClient: client,\n venmoProfileId: this.venmoProfileId,\n });\n },\n });\n\n paypalHandler = new PromisedSingleton<PayPalHandlerInterface>({\n generator: async (): Promise<PayPalHandlerInterface> => {\n const paypalLibrary = this.paymentClients.paypalLibrary.get();\n const client = this.paymentClients.payPal.get();\n\n const values = await Promise.all([client, paypalLibrary]);\n const handler = new PayPalHandler({\n braintreeManager: this.braintreeManager,\n paypalClient: values[0],\n paypalButton: values[1].Button,\n hostingEnvironment: this.hostingEnvironment,\n });\n return handler;\n },\n });\n\n googlePayHandler = new PromisedSingleton<GooglePayHandlerInterface>({\n generator: async (): Promise<GooglePayHandlerInterface> => {\n const googlePaymentsClient = this.paymentClients.googlePaymentsClient.get();\n const braintreeClient = this.paymentClients.googlePayBraintreeClient.get();\n\n const values = await Promise.all([braintreeClient, googlePaymentsClient]);\n const handler = new GooglePayHandler({\n braintreeManager: this.braintreeManager,\n googlePayMerchantId: this.googlePayMerchantId,\n googlePayBraintreeClient: values[0],\n googlePaymentsClient: values[1],\n });\n return handler;\n },\n });\n\n private braintreeManager: BraintreeManagerInterface;\n\n private venmoProfileId?: string;\n\n private googlePayMerchantId?: string;\n\n private hostedFieldConfig: HostedFieldConfiguration;\n\n private hostingEnvironment: HostingEnvironment = HostingEnvironment.Development;\n\n private paymentClients: PaymentClientsInterface;\n\n constructor(options: {\n braintreeManager: BraintreeManagerInterface;\n paymentClients: PaymentClientsInterface;\n venmoProfileId?: string;\n googlePayMerchantId?: string;\n hostingEnvironment: HostingEnvironment;\n hostedFieldConfig: HostedFieldConfiguration;\n }) {\n this.braintreeManager = options.braintreeManager;\n this.venmoProfileId = options.venmoProfileId;\n this.googlePayMerchantId = options.googlePayMerchantId;\n this.paymentClients = options.paymentClients;\n this.hostingEnvironment = options.hostingEnvironment;\n this.hostedFieldConfig = options.hostedFieldConfig;\n }\n}\n"]}
1
+ {"version":3,"file":"payment-providers.js","sourceRoot":"","sources":["../../../src/braintree-manager/payment-providers.ts"],"names":[],"mappings":"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","sourcesContent":["import { PromisedSingleton } from '@internetarchive/promised-singleton';\n\nimport { CreditCardHandler } from './payment-providers/credit-card/credit-card';\nimport { ApplePayHandler } from './payment-providers/apple-pay/apple-pay';\nimport { VenmoHandler } from './payment-providers/venmo';\nimport { PayPalHandler } from './payment-providers/paypal/paypal';\nimport { ApplePaySessionManager } from './payment-providers/apple-pay/apple-pay-session-manager';\nimport { PaymentClientsInterface } from './payment-clients';\nimport { GooglePayHandler } from './payment-providers/google-pay';\nimport { BraintreeManagerInterface, HostingEnvironment } from './braintree-interfaces';\nimport { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';\nimport { PaymentProvidersEvents, PaymentProvidersInterface } from './payment-providers-interface';\nimport { ApplePayHandlerInterface } from './payment-providers/apple-pay/apple-pay-interface';\nimport { CreditCardHandlerInterface } from './payment-providers/credit-card/credit-card-interface';\nimport { VenmoHandlerInterface } from './payment-providers/venmo-interface';\nimport { PayPalHandlerInterface } from './payment-providers/paypal/paypal-interface';\nimport { GooglePayHandlerInterface } from './payment-providers/google-pay-interface';\nimport { createNanoEvents, Unsubscribe } from 'nanoevents';\n\n/**\n * The PaymentProviders class contains the IA-specific handlers for each of the\n * different payment providers.\n *\n * They are generally data-focused, as opposed to UI-focused, but there\n * is some cross-polination between PaymentProviders and FlowHandlers.\n *\n * @export\n * @class PaymentProviders\n * @implements {PaymentProvidersInterface}\n */\nexport class PaymentProviders implements PaymentProvidersInterface {\n on<E extends keyof PaymentProvidersEvents>(\n event: E,\n callback: PaymentProvidersEvents[E],\n ): Unsubscribe {\n return this.emitter.on(event, callback);\n }\n\n creditCardHandler = new PromisedSingleton<CreditCardHandlerInterface>({\n generator: async (): Promise<CreditCardHandlerInterface> => {\n const client = await this.paymentClients.hostedFields.get();\n const handler = new CreditCardHandler({\n braintreeManager: this.braintreeManager,\n hostedFieldClient: client,\n hostedFieldConfig: this.hostedFieldConfig,\n });\n\n handler.on('hostedFieldsRetry', (retryNumber: number) => {\n this.emitter.emit('hostedFieldsRetry', retryNumber);\n });\n\n handler.on('hostedFieldsFailed', (error: unknown) => {\n this.emitter.emit('hostedFieldsFailed', error);\n });\n\n return handler;\n },\n });\n\n applePayHandler = new PromisedSingleton<ApplePayHandlerInterface>({\n generator: async (): Promise<ApplePayHandlerInterface> => {\n const client = await this.paymentClients.applePay.get();\n const applePaySessionManager = new ApplePaySessionManager();\n return new ApplePayHandler({\n braintreeManager: this.braintreeManager,\n applePayClient: client,\n applePaySessionManager: applePaySessionManager,\n });\n },\n });\n\n venmoHandler = new PromisedSingleton<VenmoHandlerInterface | undefined>({\n generator: async (): Promise<VenmoHandlerInterface | undefined> => {\n const client = await this.paymentClients.venmo.get();\n if (!this.venmoProfileId) {\n return undefined;\n }\n return new VenmoHandler({\n braintreeManager: this.braintreeManager,\n venmoClient: client,\n venmoProfileId: this.venmoProfileId,\n });\n },\n });\n\n paypalHandler = new PromisedSingleton<PayPalHandlerInterface>({\n generator: async (): Promise<PayPalHandlerInterface> => {\n const paypalLibrary = this.paymentClients.paypalLibrary.get();\n const client = this.paymentClients.payPal.get();\n\n const values = await Promise.all([client, paypalLibrary]);\n const handler = new PayPalHandler({\n braintreeManager: this.braintreeManager,\n paypalClient: values[0],\n paypalButton: values[1].Button,\n hostingEnvironment: this.hostingEnvironment,\n });\n return handler;\n },\n });\n\n googlePayHandler = new PromisedSingleton<GooglePayHandlerInterface>({\n generator: async (): Promise<GooglePayHandlerInterface> => {\n const googlePaymentsClient = this.paymentClients.googlePaymentsClient.get();\n const braintreeClient = this.paymentClients.googlePayBraintreeClient.get();\n\n const values = await Promise.all([braintreeClient, googlePaymentsClient]);\n const handler = new GooglePayHandler({\n braintreeManager: this.braintreeManager,\n googlePayMerchantId: this.googlePayMerchantId,\n googlePayBraintreeClient: values[0],\n googlePaymentsClient: values[1],\n });\n return handler;\n },\n });\n\n private braintreeManager: BraintreeManagerInterface;\n\n private venmoProfileId?: string;\n\n private googlePayMerchantId?: string;\n\n private hostedFieldConfig: HostedFieldConfiguration;\n\n private hostingEnvironment: HostingEnvironment = HostingEnvironment.Development;\n\n private paymentClients: PaymentClientsInterface;\n\n private emitter = createNanoEvents<PaymentProvidersEvents>();\n\n constructor(options: {\n braintreeManager: BraintreeManagerInterface;\n paymentClients: PaymentClientsInterface;\n venmoProfileId?: string;\n googlePayMerchantId?: string;\n hostingEnvironment: HostingEnvironment;\n hostedFieldConfig: HostedFieldConfiguration;\n }) {\n this.braintreeManager = options.braintreeManager;\n this.venmoProfileId = options.venmoProfileId;\n this.googlePayMerchantId = options.googlePayMerchantId;\n this.paymentClients = options.paymentClients;\n this.hostingEnvironment = options.hostingEnvironment;\n this.hostedFieldConfig = options.hostedFieldConfig;\n }\n}\n"]}
@@ -91,6 +91,18 @@ let DonationFormController = class DonationFormController extends LitElement {
91
91
  loggedInUser: this.loggedInUser,
92
92
  origin: this.origin,
93
93
  });
94
+ this.braintreeManager.on('paymentProvidersHostedFieldsRetry', (retryNumber) => {
95
+ const event = new CustomEvent('paymentProvidersHostedFieldsRetry', {
96
+ detail: { retryNumber },
97
+ });
98
+ this.dispatchEvent(event);
99
+ });
100
+ this.braintreeManager.on('paymentProvidersHostedFieldsFailed', (error) => {
101
+ const event = new CustomEvent('paymentProvidersHostedFieldsFailed', {
102
+ detail: { error },
103
+ });
104
+ this.dispatchEvent(event);
105
+ });
94
106
  }
95
107
  }
96
108
  setupRecaptchaManager() {