@internetarchive/donation-form 1.0.3-alpha-webdev7960.1 → 1.0.3-webdev-8114.0

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 (211) hide show
  1. package/LICENSE +661 -661
  2. package/README.md +115 -115
  3. package/dist/demo/braintree-endpoint-manager.js.map +1 -1
  4. package/dist/demo/demo-analytics-handler.js.map +1 -1
  5. package/dist/demo/submit-form-with.js.map +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/src/braintree-manager/braintree-interfaces.js.map +1 -1
  8. package/dist/src/braintree-manager/braintree-manager.js.map +1 -1
  9. package/dist/src/braintree-manager/payment-clients.js.map +1 -1
  10. package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-interface.js.map +1 -1
  11. package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-delegate.js.map +1 -1
  12. package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-interface.js.map +1 -1
  13. package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource.js.map +1 -1
  14. package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-manager.js.map +1 -1
  15. package/dist/src/braintree-manager/payment-providers/apple-pay/apple-pay.js.map +1 -1
  16. package/dist/src/braintree-manager/payment-providers/credit-card/credit-card-interface.js.map +1 -1
  17. package/dist/src/braintree-manager/payment-providers/credit-card/credit-card.js.map +1 -1
  18. package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-configuration.js.map +1 -1
  19. package/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container.js.map +1 -1
  20. package/dist/src/braintree-manager/payment-providers/google-pay-interface.js.map +1 -1
  21. package/dist/src/braintree-manager/payment-providers/google-pay.js.map +1 -1
  22. package/dist/src/braintree-manager/payment-providers/paypal/paypal-button-datasource.js.map +1 -1
  23. package/dist/src/braintree-manager/payment-providers/paypal/paypal-interface.js.map +1 -1
  24. package/dist/src/braintree-manager/payment-providers/paypal/paypal.js.map +1 -1
  25. package/dist/src/braintree-manager/payment-providers/venmo-interface.js.map +1 -1
  26. package/dist/src/braintree-manager/payment-providers/venmo.js.map +1 -1
  27. package/dist/src/braintree-manager/payment-providers-interface.js.map +1 -1
  28. package/dist/src/braintree-manager/payment-providers.js.map +1 -1
  29. package/dist/src/donation-form-controller.js +123 -123
  30. package/dist/src/donation-form-controller.js.map +1 -1
  31. package/dist/src/donation-form-error.js.map +1 -1
  32. package/dist/src/donation-form.js +107 -107
  33. package/dist/src/donation-form.js.map +1 -1
  34. package/dist/src/form-elements/badged-input.js +47 -47
  35. package/dist/src/form-elements/badged-input.js.map +1 -1
  36. package/dist/src/form-elements/contact-form/autocomplete-field-options.js.map +1 -1
  37. package/dist/src/form-elements/contact-form/contact-form.d.ts +1 -1
  38. package/dist/src/form-elements/contact-form/contact-form.js +174 -179
  39. package/dist/src/form-elements/contact-form/contact-form.js.map +1 -1
  40. package/dist/src/form-elements/contact-form/countries.js.map +1 -1
  41. package/dist/src/form-elements/header/donation-form-header.js +14 -14
  42. package/dist/src/form-elements/header/donation-form-header.js.map +1 -1
  43. package/dist/src/form-elements/header/donation-summary.js +15 -15
  44. package/dist/src/form-elements/header/donation-summary.js.map +1 -1
  45. package/dist/src/form-elements/payment-selector.js +164 -164
  46. package/dist/src/form-elements/payment-selector.js.map +1 -1
  47. package/dist/src/form-elements/total-amount.js +16 -16
  48. package/dist/src/form-elements/total-amount.js.map +1 -1
  49. package/dist/src/modals/confirm-donation-modal-content.js +51 -51
  50. package/dist/src/modals/confirm-donation-modal-content.js.map +1 -1
  51. package/dist/src/modals/error-modal-content.js +22 -22
  52. package/dist/src/modals/error-modal-content.js.map +1 -1
  53. package/dist/src/modals/upsell-modal-content.js +182 -182
  54. package/dist/src/modals/upsell-modal-content.js.map +1 -1
  55. package/dist/src/payment-flow-handlers/donation-flow-modal-manager.js +20 -20
  56. package/dist/src/payment-flow-handlers/donation-flow-modal-manager.js.map +1 -1
  57. package/dist/src/payment-flow-handlers/handlers/applepay-flow-handler.js.map +1 -1
  58. package/dist/src/payment-flow-handlers/handlers/creditcard-flow-handler.js.map +1 -1
  59. package/dist/src/payment-flow-handlers/handlers/googlepay-flow-handler.js.map +1 -1
  60. package/dist/src/payment-flow-handlers/handlers/paypal-flow-handler.js.map +1 -1
  61. package/dist/src/payment-flow-handlers/handlers/venmo-flow-handler.js.map +1 -1
  62. package/dist/src/payment-flow-handlers/handlers/venmo-restoration-state-handler.js.map +1 -1
  63. package/dist/src/payment-flow-handlers/payment-flow-handlers.js.map +1 -1
  64. package/dist/src/recaptcha-manager/recaptcha-manager.js.map +1 -1
  65. package/dist/src/util/promisedSleep.js.map +1 -1
  66. package/dist/test/helpers/fillInContactForm.js.map +1 -1
  67. package/dist/test/mocks/flow-handlers/individual-handlers/mock-applepay-flow-handler.js.map +1 -1
  68. package/dist/test/mocks/flow-handlers/individual-handlers/mock-creditcard-flow-handler.js.map +1 -1
  69. package/dist/test/mocks/flow-handlers/individual-handlers/mock-googlepay-flow-handler.js.map +1 -1
  70. package/dist/test/mocks/flow-handlers/individual-handlers/mock-paypal-flow-handler.js.map +1 -1
  71. package/dist/test/mocks/flow-handlers/individual-handlers/mock-venmo-flow-handler.js.map +1 -1
  72. package/dist/test/mocks/flow-handlers/mock-payment-flow-handlers.js.map +1 -1
  73. package/dist/test/mocks/mock-braintree-manager.js.map +1 -1
  74. package/dist/test/mocks/mock-donation-info.js.map +1 -1
  75. package/dist/test/mocks/mock-endpoint-manager.js.map +1 -1
  76. package/dist/test/mocks/mock-hosted-fields-config.js.map +1 -1
  77. package/dist/test/mocks/mock-hosted-fields-container.js.map +1 -1
  78. package/dist/test/mocks/mock-lazy-loader.js.map +1 -1
  79. package/dist/test/mocks/mock-modal-manager.js.map +1 -1
  80. package/dist/test/mocks/mock-payment-clients.js.map +1 -1
  81. package/dist/test/mocks/mock-paypal-button-renderer.js.map +1 -1
  82. package/dist/test/mocks/mock-recaptcha-manager.js.map +1 -1
  83. package/dist/test/mocks/models/mock-billing-info.js.map +1 -1
  84. package/dist/test/mocks/models/mock-custom-fields.js.map +1 -1
  85. package/dist/test/mocks/models/mock-customer-info.js.map +1 -1
  86. package/dist/test/mocks/models/mock-donation-request.js.map +1 -1
  87. package/dist/test/mocks/models/mock-success-response.js.map +1 -1
  88. package/dist/test/mocks/payment-clients/mock-applepay-client.js.map +1 -1
  89. package/dist/test/mocks/payment-clients/mock-applepay-payment.js.map +1 -1
  90. package/dist/test/mocks/payment-clients/mock-applepay-paymentauthorizedevent.js.map +1 -1
  91. package/dist/test/mocks/payment-clients/mock-applepay-session.js.map +1 -1
  92. package/dist/test/mocks/payment-clients/mock-applepay-sessionmanager.js.map +1 -1
  93. package/dist/test/mocks/payment-clients/mock-applepay-validatemerchantevent.js.map +1 -1
  94. package/dist/test/mocks/payment-clients/mock-braintree-client.js.map +1 -1
  95. package/dist/test/mocks/payment-clients/mock-data-collector.js.map +1 -1
  96. package/dist/test/mocks/payment-clients/mock-googlepay-client.js.map +1 -1
  97. package/dist/test/mocks/payment-clients/mock-googlepay-library.js.map +1 -1
  98. package/dist/test/mocks/payment-clients/mock-grecaptcha.js.map +1 -1
  99. package/dist/test/mocks/payment-clients/mock-hostedfields-client.js.map +1 -1
  100. package/dist/test/mocks/payment-clients/mock-hostedfieldstateobject-generator.js.map +1 -1
  101. package/dist/test/mocks/payment-clients/mock-hostedfieldtokenizepayload.js.map +1 -1
  102. package/dist/test/mocks/payment-clients/mock-paypal-client.js.map +1 -1
  103. package/dist/test/mocks/payment-clients/mock-paypal-library.js.map +1 -1
  104. package/dist/test/mocks/payment-clients/mock-venmo-client.js.map +1 -1
  105. package/dist/test/mocks/payment-providers/individual-providers/mock-applepay-datasource-delegate.js.map +1 -1
  106. package/dist/test/mocks/payment-providers/individual-providers/mock-applepay-handler.js.map +1 -1
  107. package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.js.map +1 -1
  108. package/dist/test/mocks/payment-providers/individual-providers/mock-googlepay-handler.js.map +1 -1
  109. package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-button-datasource-delegate.js.map +1 -1
  110. package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-button-datasource.js.map +1 -1
  111. package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-handler.js.map +1 -1
  112. package/dist/test/mocks/payment-providers/individual-providers/mock-venmo-handler.js.map +1 -1
  113. package/dist/test/mocks/payment-providers/mock-payment-providers.js.map +1 -1
  114. package/dist/test/tests/braintree-manager.test.js.map +1 -1
  115. package/dist/test/tests/donation-form-controller.test.js +39 -39
  116. package/dist/test/tests/donation-form-controller.test.js.map +1 -1
  117. package/dist/test/tests/donation-form.test.js +4 -4
  118. package/dist/test/tests/donation-form.test.js.map +1 -1
  119. package/dist/test/tests/flow-handlers/donation-flow-modal-manager.test.js +14 -14
  120. package/dist/test/tests/flow-handlers/donation-flow-modal-manager.test.js.map +1 -1
  121. package/dist/test/tests/form-elements/contact-form.test.d.ts +1 -0
  122. package/dist/test/tests/form-elements/contact-form.test.js +132 -0
  123. package/dist/test/tests/form-elements/contact-form.test.js.map +1 -0
  124. package/dist/test/tests/form-elements/donation-summary.test.js.map +1 -1
  125. package/dist/test/tests/form-elements/payment-selector.test.js.map +1 -1
  126. package/dist/test/tests/modals/error-modal-content.test.js +2 -2
  127. package/dist/test/tests/modals/error-modal-content.test.js.map +1 -1
  128. package/dist/test/tests/modals/upsell-modal-content.test.js +31 -31
  129. package/dist/test/tests/modals/upsell-modal-content.test.js.map +1 -1
  130. package/dist/test/tests/models/donation-payment-info.test.js.map +1 -1
  131. package/dist/test/tests/payment-clients.test.js.map +1 -1
  132. package/dist/test/tests/payment-providers/applepay-sessiondatasource.test.js.map +1 -1
  133. package/dist/test/tests/payment-providers/applepay-sessionmanager.test.js.map +1 -1
  134. package/dist/test/tests/payment-providers/applepay.test.js.map +1 -1
  135. package/dist/test/tests/payment-providers/creditcard.test.js.map +1 -1
  136. package/dist/test/tests/payment-providers/googlepay.test.js.map +1 -1
  137. package/dist/test/tests/payment-providers/payment-providers.test.js.map +1 -1
  138. package/dist/test/tests/payment-providers/paypal-button-datasource.test.js.map +1 -1
  139. package/dist/test/tests/payment-providers/paypal.test.js.map +1 -1
  140. package/dist/test/tests/payment-providers/venmo.test.js.map +1 -1
  141. package/dist/test/tests/recaptcha-manager.test.js.map +1 -1
  142. package/package.json +107 -107
  143. package/src/@types/analytics-handler/index.d.ts +8 -8
  144. package/src/@types/braintree-web/LICENSE +21 -21
  145. package/src/@types/braintree-web/index.d.ts +93 -93
  146. package/src/@types/braintree-web/modules/american-express.d.ts +50 -50
  147. package/src/@types/braintree-web/modules/apple-pay.d.ts +213 -213
  148. package/src/@types/braintree-web/modules/client.d.ts +103 -103
  149. package/src/@types/braintree-web/modules/core.d.ts +34 -34
  150. package/src/@types/braintree-web/modules/data-collector.d.ts +13 -13
  151. package/src/@types/braintree-web/modules/google-payment.d.ts +269 -269
  152. package/src/@types/braintree-web/modules/hosted-fields.d.ts +366 -366
  153. package/src/@types/braintree-web/modules/paypal-checkout.d.ts +262 -262
  154. package/src/@types/braintree-web/modules/paypal.d.ts +177 -177
  155. package/src/@types/braintree-web/modules/three-d-secure.d.ts +141 -141
  156. package/src/@types/braintree-web/modules/unionpay.d.ts +224 -224
  157. package/src/@types/braintree-web/modules/us-bank-account.d.ts +81 -81
  158. package/src/@types/braintree-web/modules/venmo.d.ts +110 -110
  159. package/src/@types/braintree-web/package.json +64 -64
  160. package/src/@types/paypal-checkout-components/LICENSE +21 -21
  161. package/src/@types/paypal-checkout-components/index.d.ts +67 -67
  162. package/src/@types/paypal-checkout-components/modules/button.d.ts +50 -50
  163. package/src/@types/paypal-checkout-components/modules/callback-data.d.ts +244 -244
  164. package/src/@types/paypal-checkout-components/modules/configuration.d.ts +114 -114
  165. package/src/@types/paypal-checkout-components/package.json +58 -58
  166. package/src/braintree-manager/braintree-interfaces.ts +172 -172
  167. package/src/braintree-manager/braintree-manager.ts +281 -281
  168. package/src/braintree-manager/payment-clients.ts +146 -146
  169. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-interface.ts +13 -13
  170. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-delegate.ts +8 -8
  171. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-interface.ts +10 -10
  172. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource.ts +119 -119
  173. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-manager.ts +21 -21
  174. package/src/braintree-manager/payment-providers/apple-pay/apple-pay.ts +97 -97
  175. package/src/braintree-manager/payment-providers/credit-card/credit-card-interface.ts +21 -21
  176. package/src/braintree-manager/payment-providers/credit-card/credit-card.ts +130 -130
  177. package/src/braintree-manager/payment-providers/credit-card/hosted-field-configuration.ts +19 -19
  178. package/src/braintree-manager/payment-providers/credit-card/hosted-field-container.ts +85 -85
  179. package/src/braintree-manager/payment-providers/google-pay-interface.ts +8 -8
  180. package/src/braintree-manager/payment-providers/google-pay.ts +59 -59
  181. package/src/braintree-manager/payment-providers/paypal/paypal-button-datasource.ts +218 -218
  182. package/src/braintree-manager/payment-providers/paypal/paypal-interface.ts +13 -13
  183. package/src/braintree-manager/payment-providers/paypal/paypal.ts +78 -78
  184. package/src/braintree-manager/payment-providers/venmo-interface.ts +8 -8
  185. package/src/braintree-manager/payment-providers/venmo.ts +67 -67
  186. package/src/braintree-manager/payment-providers-interface.ts +25 -25
  187. package/src/braintree-manager/payment-providers.ts +147 -147
  188. package/src/donation-form-controller.ts +623 -623
  189. package/src/donation-form-error.ts +6 -6
  190. package/src/donation-form.ts +576 -576
  191. package/src/form-elements/badged-input.ts +109 -109
  192. package/src/form-elements/contact-form/autocomplete-field-options.ts +63 -63
  193. package/src/form-elements/contact-form/contact-form.ts +432 -434
  194. package/src/form-elements/contact-form/countries.ts +252 -252
  195. package/src/form-elements/header/donation-form-header.ts +98 -98
  196. package/src/form-elements/header/donation-summary.ts +61 -61
  197. package/src/form-elements/payment-selector.ts +365 -365
  198. package/src/form-elements/total-amount.ts +46 -46
  199. package/src/modals/confirm-donation-modal-content.ts +168 -168
  200. package/src/modals/error-modal-content.ts +48 -48
  201. package/src/modals/upsell-modal-content.ts +284 -284
  202. package/src/payment-flow-handlers/donation-flow-modal-manager.ts +439 -439
  203. package/src/payment-flow-handlers/handlers/applepay-flow-handler.ts +109 -109
  204. package/src/payment-flow-handlers/handlers/creditcard-flow-handler.ts +232 -232
  205. package/src/payment-flow-handlers/handlers/googlepay-flow-handler.ts +111 -111
  206. package/src/payment-flow-handlers/handlers/paypal-flow-handler.ts +331 -331
  207. package/src/payment-flow-handlers/handlers/venmo-flow-handler.ts +119 -119
  208. package/src/payment-flow-handlers/handlers/venmo-restoration-state-handler.ts +127 -127
  209. package/src/payment-flow-handlers/payment-flow-handlers.ts +218 -218
  210. package/src/recaptcha-manager/recaptcha-manager.ts +123 -123
  211. package/src/util/promisedSleep.ts +3 -3
@@ -1,281 +1,281 @@
1
- import {
2
- DonationResponse,
3
- DonationRequest,
4
- DonationRequestCustomFields,
5
- DonationType,
6
- CustomerInfo,
7
- BillingInfo,
8
- DonationPaymentInfo,
9
- PaymentProvider,
10
- SuccessResponse,
11
- } from '@internetarchive/donation-form-data-models';
12
-
13
- import { PaymentProviders } from './payment-providers';
14
- import { PaymentClientsInterface } from './payment-clients';
15
- import {
16
- BraintreeManagerInterface,
17
- BraintreeEndpointManagerInterface,
18
- HostingEnvironment,
19
- BraintreeManagerEvents,
20
- } from './braintree-interfaces';
21
- import { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';
22
- import { PromisedSingleton } from '@internetarchive/promised-singleton';
23
- import { PaymentProvidersInterface } from './payment-providers-interface';
24
- import { createNanoEvents, Unsubscribe } from 'nanoevents';
25
-
26
- /** @inheritdoc */
27
- export class BraintreeManager implements BraintreeManagerInterface {
28
- private referrer?: string;
29
-
30
- /**
31
- * The origin is made up of campaign / ABTest information that the user originated from.
32
- *
33
- * The field is a freeform string so it can be anything, but make sure it's something
34
- * identifiable so it can be queried in CiviCRM.
35
- *
36
- * For instance, we use this format for the Donation Banner:
37
- * - `{Source}-{Test Name}-{Variant Name}`, eg:
38
- * - `DonateBanner-Campaign Start 2020-IADefault`
39
- * - `DonateBanner-Mid Campaign-IAThermometer`
40
- *
41
- * For additional specificity, you could add additional info, ie.
42
- * - `DonateBanner-MidJuly2020 Campaign-VariantA-Button1`
43
- *
44
- * @private
45
- * @type {string}
46
- * @memberof BraintreeManager
47
- */
48
- private origin?: string;
49
-
50
- private loggedInUser?: string;
51
-
52
- /**
53
- * The Device Data token generated by the DataCollector.
54
- *
55
- * This gets submitted for several of the payment providers as an anti-fraud mechanism.
56
- *
57
- * @private
58
- * @type {string}
59
- * @memberof BraintreeManager
60
- */
61
- private deviceData?: string;
62
-
63
- private emitter = createNanoEvents<BraintreeManagerEvents>();
64
-
65
- on<E extends keyof BraintreeManagerEvents>(
66
- event: E,
67
- callback: BraintreeManagerEvents[E],
68
- ): Unsubscribe {
69
- return this.emitter.on(event, callback);
70
- }
71
-
72
- /** @inheritdoc */
73
- paymentProviders: PaymentProvidersInterface;
74
-
75
- /** @inheritdoc */
76
- async startup(): Promise<void> {
77
- return this.collectDeviceData();
78
- }
79
-
80
- /** @inheritdoc */
81
- instance = new PromisedSingleton<braintree.Client>({
82
- generator: async (): Promise<braintree.Client> => {
83
- const client = await this.paymentClients.braintreeClient.get();
84
- return client?.create({ authorization: this.authorizationToken });
85
- },
86
- });
87
-
88
- /** @inheritdoc */
89
- async submitDonation(options: {
90
- nonce: string;
91
- paymentProvider: PaymentProvider;
92
- donationInfo: DonationPaymentInfo;
93
- billingInfo: BillingInfo;
94
- customerInfo: CustomerInfo;
95
- upsellOnetimeTransactionId?: string;
96
- customerId?: string;
97
- recaptchaToken?: string;
98
- bin?: string; // first 6 digits of CC
99
- binName?: string; // credit card bank name
100
- }): Promise<DonationResponse> {
101
- const customFields = new DonationRequestCustomFields();
102
- customFields.fee_amount_covered = options.donationInfo.feeAmountCovered;
103
- customFields.logged_in_user = this.loggedInUser;
104
- customFields.referrer = this.referrer;
105
- customFields.origin = this.origin;
106
-
107
- // This is interesting and applies only to Venmo, but will work for other providers as well.
108
- // In Safari, `donationInfo` actually comes through as a DonationPaymentInfo object,
109
- // but in Chrome, it comes through as a plain object so you can't call `.total()` on it to
110
- // get the total amount and instead have to calculate the total
111
- const total = DonationPaymentInfo.calculateTotal(
112
- options.donationInfo.amount,
113
- options.donationInfo.coverFees,
114
- );
115
-
116
- const donationRequest = new DonationRequest({
117
- deviceData: this.deviceData,
118
- paymentProvider: options.paymentProvider,
119
- paymentMethodNonce: options.nonce,
120
- amount: total,
121
- donationType: options.donationInfo.donationType,
122
- customer: options.customerInfo,
123
- billing: options.billingInfo,
124
- customFields: customFields,
125
- upsellOnetimeTransactionId: options.upsellOnetimeTransactionId,
126
- customerId: options.customerId,
127
- recaptchaToken: options.recaptchaToken,
128
- bin: options.bin,
129
- binName: options.binName,
130
- });
131
-
132
- const jsonResponse = await this.endpointManager.submitData(donationRequest);
133
- const modeledResponse = new DonationResponse(jsonResponse);
134
- return modeledResponse;
135
- }
136
-
137
- /** @inheritdoc */
138
- async submitUpsellDonation(options: {
139
- oneTimeDonationResponse: SuccessResponse;
140
- amount: number;
141
- }): Promise<DonationResponse> {
142
- const response = options.oneTimeDonationResponse;
143
-
144
- const donationInfo = new DonationPaymentInfo({
145
- amount: options.amount,
146
- donationType: DonationType.Upsell,
147
- coverFees: false,
148
- });
149
-
150
- return this.submitDonation({
151
- nonce: response.paymentMethodNonce,
152
- paymentProvider: response.paymentProvider,
153
- customerId: response.customer_id,
154
- donationInfo: donationInfo,
155
- customerInfo: response.customer,
156
- billingInfo: response.billing,
157
- upsellOnetimeTransactionId: response.transaction_id,
158
- });
159
- }
160
-
161
- /** @inheritdoc */
162
- donationSuccessful(options: {
163
- successResponse: SuccessResponse;
164
- upsellSuccessResponse?: SuccessResponse;
165
- }): void {
166
- this.endpointManager.donationSuccessful(options);
167
- }
168
-
169
- private deviceDataCollectionStarted = false;
170
-
171
- /**
172
- * Collect Braintree device data. This is used to help fraud detection.
173
- *
174
- * @private
175
- * @returns {Promise<void>}
176
- * @memberof BraintreeManager
177
- */
178
- private async collectDeviceData(): Promise<void> {
179
- if (this.deviceDataCollectionStarted) {
180
- return;
181
- }
182
- this.deviceDataCollectionStarted = true;
183
-
184
- const instance = await this.instance.get();
185
- if (!instance) {
186
- return;
187
- }
188
-
189
- return this.paymentClients.dataCollector
190
- .get()
191
- .then((collector?: braintree.DataCollector) => {
192
- return collector?.create({ client: instance, kount: false, paypal: true });
193
- })
194
- .then(instance => {
195
- this.deviceData = instance?.deviceData;
196
- });
197
- }
198
-
199
- /**
200
- * Braintree Authorization Token
201
- *
202
- * @private
203
- * @type {string}
204
- * @memberof BraintreeManager
205
- */
206
- private authorizationToken: string;
207
-
208
- /**
209
- * The endpoint manager for network communications
210
- *
211
- * @private
212
- * @type {BraintreeEndpointManagerInterface}
213
- * @memberof BraintreeManager
214
- */
215
- private endpointManager: BraintreeEndpointManagerInterface;
216
-
217
- /**
218
- * The payment clients container containing the braintree, paypal, and google clients
219
- *
220
- * @private
221
- * @type {PaymentClientsInterface}
222
- * @memberof BraintreeManager
223
- */
224
- private paymentClients: PaymentClientsInterface;
225
-
226
- private hostingEnvironment: HostingEnvironment = HostingEnvironment.Development;
227
-
228
- constructor(options: {
229
- authorizationToken: string;
230
- paymentClients: PaymentClientsInterface;
231
- endpointManager: BraintreeEndpointManagerInterface;
232
- hostedFieldConfig: HostedFieldConfiguration;
233
- hostingEnvironment: HostingEnvironment;
234
- venmoProfileId?: string;
235
- googlePayMerchantId?: string;
236
- referrer?: string;
237
- loggedInUser?: string;
238
- origin?: string;
239
- }) {
240
- this.authorizationToken = options.authorizationToken;
241
- this.endpointManager = options.endpointManager;
242
- this.hostingEnvironment = options.hostingEnvironment;
243
- this.paymentClients = options.paymentClients;
244
-
245
- this.referrer = options.referrer;
246
- this.loggedInUser = options.loggedInUser;
247
- this.origin = options.origin;
248
-
249
- this.paymentProviders = new PaymentProviders({
250
- braintreeManager: this,
251
- paymentClients: this.paymentClients,
252
- venmoProfileId: options.venmoProfileId,
253
- googlePayMerchantId: options.googlePayMerchantId,
254
- hostingEnvironment: options.hostingEnvironment,
255
- hostedFieldConfig: options.hostedFieldConfig,
256
- });
257
-
258
- this.paymentProviders.on('hostedFieldsRetry', (retryNumber: number) => {
259
- this.emitter.emit('paymentProvidersHostedFieldsRetry', retryNumber);
260
- });
261
-
262
- this.paymentProviders.on('hostedFieldsFailed', (error: unknown) => {
263
- this.emitter.emit('paymentProvidersHostedFieldsFailed', error);
264
- });
265
- }
266
-
267
- /** @inheritdoc */
268
- setReferrer(referrer: string): void {
269
- this.referrer = referrer;
270
- }
271
-
272
- /** @inheritdoc */
273
- setLoggedInUser(loggedInUser: string): void {
274
- this.loggedInUser = loggedInUser;
275
- }
276
-
277
- /** @inheritdoc */
278
- setOrigin(origin: string): void {
279
- this.origin = origin;
280
- }
281
- }
1
+ import {
2
+ DonationResponse,
3
+ DonationRequest,
4
+ DonationRequestCustomFields,
5
+ DonationType,
6
+ CustomerInfo,
7
+ BillingInfo,
8
+ DonationPaymentInfo,
9
+ PaymentProvider,
10
+ SuccessResponse,
11
+ } from '@internetarchive/donation-form-data-models';
12
+
13
+ import { PaymentProviders } from './payment-providers';
14
+ import { PaymentClientsInterface } from './payment-clients';
15
+ import {
16
+ BraintreeManagerInterface,
17
+ BraintreeEndpointManagerInterface,
18
+ HostingEnvironment,
19
+ BraintreeManagerEvents,
20
+ } from './braintree-interfaces';
21
+ import { HostedFieldConfiguration } from './payment-providers/credit-card/hosted-field-configuration';
22
+ import { PromisedSingleton } from '@internetarchive/promised-singleton';
23
+ import { PaymentProvidersInterface } from './payment-providers-interface';
24
+ import { createNanoEvents, Unsubscribe } from 'nanoevents';
25
+
26
+ /** @inheritdoc */
27
+ export class BraintreeManager implements BraintreeManagerInterface {
28
+ private referrer?: string;
29
+
30
+ /**
31
+ * The origin is made up of campaign / ABTest information that the user originated from.
32
+ *
33
+ * The field is a freeform string so it can be anything, but make sure it's something
34
+ * identifiable so it can be queried in CiviCRM.
35
+ *
36
+ * For instance, we use this format for the Donation Banner:
37
+ * - `{Source}-{Test Name}-{Variant Name}`, eg:
38
+ * - `DonateBanner-Campaign Start 2020-IADefault`
39
+ * - `DonateBanner-Mid Campaign-IAThermometer`
40
+ *
41
+ * For additional specificity, you could add additional info, ie.
42
+ * - `DonateBanner-MidJuly2020 Campaign-VariantA-Button1`
43
+ *
44
+ * @private
45
+ * @type {string}
46
+ * @memberof BraintreeManager
47
+ */
48
+ private origin?: string;
49
+
50
+ private loggedInUser?: string;
51
+
52
+ /**
53
+ * The Device Data token generated by the DataCollector.
54
+ *
55
+ * This gets submitted for several of the payment providers as an anti-fraud mechanism.
56
+ *
57
+ * @private
58
+ * @type {string}
59
+ * @memberof BraintreeManager
60
+ */
61
+ private deviceData?: string;
62
+
63
+ private emitter = createNanoEvents<BraintreeManagerEvents>();
64
+
65
+ on<E extends keyof BraintreeManagerEvents>(
66
+ event: E,
67
+ callback: BraintreeManagerEvents[E],
68
+ ): Unsubscribe {
69
+ return this.emitter.on(event, callback);
70
+ }
71
+
72
+ /** @inheritdoc */
73
+ paymentProviders: PaymentProvidersInterface;
74
+
75
+ /** @inheritdoc */
76
+ async startup(): Promise<void> {
77
+ return this.collectDeviceData();
78
+ }
79
+
80
+ /** @inheritdoc */
81
+ instance = new PromisedSingleton<braintree.Client>({
82
+ generator: async (): Promise<braintree.Client> => {
83
+ const client = await this.paymentClients.braintreeClient.get();
84
+ return client?.create({ authorization: this.authorizationToken });
85
+ },
86
+ });
87
+
88
+ /** @inheritdoc */
89
+ async submitDonation(options: {
90
+ nonce: string;
91
+ paymentProvider: PaymentProvider;
92
+ donationInfo: DonationPaymentInfo;
93
+ billingInfo: BillingInfo;
94
+ customerInfo: CustomerInfo;
95
+ upsellOnetimeTransactionId?: string;
96
+ customerId?: string;
97
+ recaptchaToken?: string;
98
+ bin?: string; // first 6 digits of CC
99
+ binName?: string; // credit card bank name
100
+ }): Promise<DonationResponse> {
101
+ const customFields = new DonationRequestCustomFields();
102
+ customFields.fee_amount_covered = options.donationInfo.feeAmountCovered;
103
+ customFields.logged_in_user = this.loggedInUser;
104
+ customFields.referrer = this.referrer;
105
+ customFields.origin = this.origin;
106
+
107
+ // This is interesting and applies only to Venmo, but will work for other providers as well.
108
+ // In Safari, `donationInfo` actually comes through as a DonationPaymentInfo object,
109
+ // but in Chrome, it comes through as a plain object so you can't call `.total()` on it to
110
+ // get the total amount and instead have to calculate the total
111
+ const total = DonationPaymentInfo.calculateTotal(
112
+ options.donationInfo.amount,
113
+ options.donationInfo.coverFees,
114
+ );
115
+
116
+ const donationRequest = new DonationRequest({
117
+ deviceData: this.deviceData,
118
+ paymentProvider: options.paymentProvider,
119
+ paymentMethodNonce: options.nonce,
120
+ amount: total,
121
+ donationType: options.donationInfo.donationType,
122
+ customer: options.customerInfo,
123
+ billing: options.billingInfo,
124
+ customFields: customFields,
125
+ upsellOnetimeTransactionId: options.upsellOnetimeTransactionId,
126
+ customerId: options.customerId,
127
+ recaptchaToken: options.recaptchaToken,
128
+ bin: options.bin,
129
+ binName: options.binName,
130
+ });
131
+
132
+ const jsonResponse = await this.endpointManager.submitData(donationRequest);
133
+ const modeledResponse = new DonationResponse(jsonResponse);
134
+ return modeledResponse;
135
+ }
136
+
137
+ /** @inheritdoc */
138
+ async submitUpsellDonation(options: {
139
+ oneTimeDonationResponse: SuccessResponse;
140
+ amount: number;
141
+ }): Promise<DonationResponse> {
142
+ const response = options.oneTimeDonationResponse;
143
+
144
+ const donationInfo = new DonationPaymentInfo({
145
+ amount: options.amount,
146
+ donationType: DonationType.Upsell,
147
+ coverFees: false,
148
+ });
149
+
150
+ return this.submitDonation({
151
+ nonce: response.paymentMethodNonce,
152
+ paymentProvider: response.paymentProvider,
153
+ customerId: response.customer_id,
154
+ donationInfo: donationInfo,
155
+ customerInfo: response.customer,
156
+ billingInfo: response.billing,
157
+ upsellOnetimeTransactionId: response.transaction_id,
158
+ });
159
+ }
160
+
161
+ /** @inheritdoc */
162
+ donationSuccessful(options: {
163
+ successResponse: SuccessResponse;
164
+ upsellSuccessResponse?: SuccessResponse;
165
+ }): void {
166
+ this.endpointManager.donationSuccessful(options);
167
+ }
168
+
169
+ private deviceDataCollectionStarted = false;
170
+
171
+ /**
172
+ * Collect Braintree device data. This is used to help fraud detection.
173
+ *
174
+ * @private
175
+ * @returns {Promise<void>}
176
+ * @memberof BraintreeManager
177
+ */
178
+ private async collectDeviceData(): Promise<void> {
179
+ if (this.deviceDataCollectionStarted) {
180
+ return;
181
+ }
182
+ this.deviceDataCollectionStarted = true;
183
+
184
+ const instance = await this.instance.get();
185
+ if (!instance) {
186
+ return;
187
+ }
188
+
189
+ return this.paymentClients.dataCollector
190
+ .get()
191
+ .then((collector?: braintree.DataCollector) => {
192
+ return collector?.create({ client: instance, kount: false, paypal: true });
193
+ })
194
+ .then(instance => {
195
+ this.deviceData = instance?.deviceData;
196
+ });
197
+ }
198
+
199
+ /**
200
+ * Braintree Authorization Token
201
+ *
202
+ * @private
203
+ * @type {string}
204
+ * @memberof BraintreeManager
205
+ */
206
+ private authorizationToken: string;
207
+
208
+ /**
209
+ * The endpoint manager for network communications
210
+ *
211
+ * @private
212
+ * @type {BraintreeEndpointManagerInterface}
213
+ * @memberof BraintreeManager
214
+ */
215
+ private endpointManager: BraintreeEndpointManagerInterface;
216
+
217
+ /**
218
+ * The payment clients container containing the braintree, paypal, and google clients
219
+ *
220
+ * @private
221
+ * @type {PaymentClientsInterface}
222
+ * @memberof BraintreeManager
223
+ */
224
+ private paymentClients: PaymentClientsInterface;
225
+
226
+ private hostingEnvironment: HostingEnvironment = HostingEnvironment.Development;
227
+
228
+ constructor(options: {
229
+ authorizationToken: string;
230
+ paymentClients: PaymentClientsInterface;
231
+ endpointManager: BraintreeEndpointManagerInterface;
232
+ hostedFieldConfig: HostedFieldConfiguration;
233
+ hostingEnvironment: HostingEnvironment;
234
+ venmoProfileId?: string;
235
+ googlePayMerchantId?: string;
236
+ referrer?: string;
237
+ loggedInUser?: string;
238
+ origin?: string;
239
+ }) {
240
+ this.authorizationToken = options.authorizationToken;
241
+ this.endpointManager = options.endpointManager;
242
+ this.hostingEnvironment = options.hostingEnvironment;
243
+ this.paymentClients = options.paymentClients;
244
+
245
+ this.referrer = options.referrer;
246
+ this.loggedInUser = options.loggedInUser;
247
+ this.origin = options.origin;
248
+
249
+ this.paymentProviders = new PaymentProviders({
250
+ braintreeManager: this,
251
+ paymentClients: this.paymentClients,
252
+ venmoProfileId: options.venmoProfileId,
253
+ googlePayMerchantId: options.googlePayMerchantId,
254
+ hostingEnvironment: options.hostingEnvironment,
255
+ hostedFieldConfig: options.hostedFieldConfig,
256
+ });
257
+
258
+ this.paymentProviders.on('hostedFieldsRetry', (retryNumber: number) => {
259
+ this.emitter.emit('paymentProvidersHostedFieldsRetry', retryNumber);
260
+ });
261
+
262
+ this.paymentProviders.on('hostedFieldsFailed', (error: unknown) => {
263
+ this.emitter.emit('paymentProvidersHostedFieldsFailed', error);
264
+ });
265
+ }
266
+
267
+ /** @inheritdoc */
268
+ setReferrer(referrer: string): void {
269
+ this.referrer = referrer;
270
+ }
271
+
272
+ /** @inheritdoc */
273
+ setLoggedInUser(loggedInUser: string): void {
274
+ this.loggedInUser = loggedInUser;
275
+ }
276
+
277
+ /** @inheritdoc */
278
+ setOrigin(origin: string): void {
279
+ this.origin = origin;
280
+ }
281
+ }