@internetarchive/donation-form 1.0.2 → 1.0.3-alpha-webdev7960.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 (210) 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.js +157 -157
  38. package/dist/src/form-elements/contact-form/contact-form.js.map +1 -1
  39. package/dist/src/form-elements/contact-form/countries.js.map +1 -1
  40. package/dist/src/form-elements/header/donation-form-header.js +14 -14
  41. package/dist/src/form-elements/header/donation-form-header.js.map +1 -1
  42. package/dist/src/form-elements/header/donation-summary.js +15 -15
  43. package/dist/src/form-elements/header/donation-summary.js.map +1 -1
  44. package/dist/src/form-elements/payment-selector.js +164 -164
  45. package/dist/src/form-elements/payment-selector.js.map +1 -1
  46. package/dist/src/form-elements/total-amount.js +16 -16
  47. package/dist/src/form-elements/total-amount.js.map +1 -1
  48. package/dist/src/modals/confirm-donation-modal-content.js +51 -51
  49. package/dist/src/modals/confirm-donation-modal-content.js.map +1 -1
  50. package/dist/src/modals/error-modal-content.js +22 -22
  51. package/dist/src/modals/error-modal-content.js.map +1 -1
  52. package/dist/src/modals/upsell-modal-content.js +182 -182
  53. package/dist/src/modals/upsell-modal-content.js.map +1 -1
  54. package/dist/src/payment-flow-handlers/donation-flow-modal-manager.js +20 -20
  55. package/dist/src/payment-flow-handlers/donation-flow-modal-manager.js.map +1 -1
  56. package/dist/src/payment-flow-handlers/handlers/applepay-flow-handler.js.map +1 -1
  57. package/dist/src/payment-flow-handlers/handlers/creditcard-flow-handler.js.map +1 -1
  58. package/dist/src/payment-flow-handlers/handlers/googlepay-flow-handler.js.map +1 -1
  59. package/dist/src/payment-flow-handlers/handlers/paypal-flow-handler.js.map +1 -1
  60. package/dist/src/payment-flow-handlers/handlers/venmo-flow-handler.js.map +1 -1
  61. package/dist/src/payment-flow-handlers/handlers/venmo-restoration-state-handler.js.map +1 -1
  62. package/dist/src/payment-flow-handlers/payment-flow-handlers.js.map +1 -1
  63. package/dist/src/recaptcha-manager/recaptcha-manager.js.map +1 -1
  64. package/dist/src/util/promisedSleep.js.map +1 -1
  65. package/dist/test/helpers/fillInContactForm.js.map +1 -1
  66. package/dist/test/mocks/flow-handlers/individual-handlers/mock-applepay-flow-handler.js.map +1 -1
  67. package/dist/test/mocks/flow-handlers/individual-handlers/mock-creditcard-flow-handler.js.map +1 -1
  68. package/dist/test/mocks/flow-handlers/individual-handlers/mock-googlepay-flow-handler.js.map +1 -1
  69. package/dist/test/mocks/flow-handlers/individual-handlers/mock-paypal-flow-handler.js.map +1 -1
  70. package/dist/test/mocks/flow-handlers/individual-handlers/mock-venmo-flow-handler.js.map +1 -1
  71. package/dist/test/mocks/flow-handlers/mock-payment-flow-handlers.js.map +1 -1
  72. package/dist/test/mocks/mock-braintree-manager.js.map +1 -1
  73. package/dist/test/mocks/mock-donation-info.js.map +1 -1
  74. package/dist/test/mocks/mock-endpoint-manager.js.map +1 -1
  75. package/dist/test/mocks/mock-hosted-fields-config.js.map +1 -1
  76. package/dist/test/mocks/mock-hosted-fields-container.js.map +1 -1
  77. package/dist/test/mocks/mock-lazy-loader.js.map +1 -1
  78. package/dist/test/mocks/mock-modal-manager.js.map +1 -1
  79. package/dist/test/mocks/mock-payment-clients.js.map +1 -1
  80. package/dist/test/mocks/mock-paypal-button-renderer.js.map +1 -1
  81. package/dist/test/mocks/mock-recaptcha-manager.js.map +1 -1
  82. package/dist/test/mocks/models/mock-billing-info.js.map +1 -1
  83. package/dist/test/mocks/models/mock-custom-fields.js.map +1 -1
  84. package/dist/test/mocks/models/mock-customer-info.js.map +1 -1
  85. package/dist/test/mocks/models/mock-donation-request.js.map +1 -1
  86. package/dist/test/mocks/models/mock-success-response.js.map +1 -1
  87. package/dist/test/mocks/payment-clients/mock-applepay-client.js.map +1 -1
  88. package/dist/test/mocks/payment-clients/mock-applepay-payment.js.map +1 -1
  89. package/dist/test/mocks/payment-clients/mock-applepay-paymentauthorizedevent.js.map +1 -1
  90. package/dist/test/mocks/payment-clients/mock-applepay-session.js.map +1 -1
  91. package/dist/test/mocks/payment-clients/mock-applepay-sessionmanager.js.map +1 -1
  92. package/dist/test/mocks/payment-clients/mock-applepay-validatemerchantevent.js.map +1 -1
  93. package/dist/test/mocks/payment-clients/mock-braintree-client.js.map +1 -1
  94. package/dist/test/mocks/payment-clients/mock-data-collector.js.map +1 -1
  95. package/dist/test/mocks/payment-clients/mock-googlepay-client.js.map +1 -1
  96. package/dist/test/mocks/payment-clients/mock-googlepay-library.js.map +1 -1
  97. package/dist/test/mocks/payment-clients/mock-grecaptcha.js.map +1 -1
  98. package/dist/test/mocks/payment-clients/mock-hostedfields-client.js.map +1 -1
  99. package/dist/test/mocks/payment-clients/mock-hostedfieldstateobject-generator.js.map +1 -1
  100. package/dist/test/mocks/payment-clients/mock-hostedfieldtokenizepayload.js.map +1 -1
  101. package/dist/test/mocks/payment-clients/mock-paypal-client.js.map +1 -1
  102. package/dist/test/mocks/payment-clients/mock-paypal-library.js.map +1 -1
  103. package/dist/test/mocks/payment-clients/mock-venmo-client.js.map +1 -1
  104. package/dist/test/mocks/payment-providers/individual-providers/mock-applepay-datasource-delegate.js.map +1 -1
  105. package/dist/test/mocks/payment-providers/individual-providers/mock-applepay-handler.js.map +1 -1
  106. package/dist/test/mocks/payment-providers/individual-providers/mock-creditcard-handler.js.map +1 -1
  107. package/dist/test/mocks/payment-providers/individual-providers/mock-googlepay-handler.js.map +1 -1
  108. package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-button-datasource-delegate.js.map +1 -1
  109. package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-button-datasource.js.map +1 -1
  110. package/dist/test/mocks/payment-providers/individual-providers/mock-paypal-handler.js.map +1 -1
  111. package/dist/test/mocks/payment-providers/individual-providers/mock-venmo-handler.js.map +1 -1
  112. package/dist/test/mocks/payment-providers/mock-payment-providers.js.map +1 -1
  113. package/dist/test/tests/braintree-manager.test.js.map +1 -1
  114. package/dist/test/tests/donation-form-controller.test.js +39 -39
  115. package/dist/test/tests/donation-form-controller.test.js.map +1 -1
  116. package/dist/test/tests/donation-form.test.js +4 -4
  117. package/dist/test/tests/donation-form.test.js.map +1 -1
  118. package/dist/test/tests/flow-handlers/donation-flow-modal-manager.test.js +14 -14
  119. package/dist/test/tests/flow-handlers/donation-flow-modal-manager.test.js.map +1 -1
  120. package/dist/test/tests/form-elements/donation-summary.test.js.map +1 -1
  121. package/dist/test/tests/form-elements/payment-selector.test.js.map +1 -1
  122. package/dist/test/tests/modals/error-modal-content.test.js +2 -2
  123. package/dist/test/tests/modals/error-modal-content.test.js.map +1 -1
  124. package/dist/test/tests/modals/upsell-modal-content.test.js +31 -31
  125. package/dist/test/tests/modals/upsell-modal-content.test.js.map +1 -1
  126. package/dist/test/tests/models/donation-payment-info.test.js.map +1 -1
  127. package/dist/test/tests/payment-clients.test.js.map +1 -1
  128. package/dist/test/tests/payment-providers/applepay-sessiondatasource.test.js.map +1 -1
  129. package/dist/test/tests/payment-providers/applepay-sessionmanager.test.js.map +1 -1
  130. package/dist/test/tests/payment-providers/applepay.test.js.map +1 -1
  131. package/dist/test/tests/payment-providers/creditcard.test.js.map +1 -1
  132. package/dist/test/tests/payment-providers/googlepay.test.js.map +1 -1
  133. package/dist/test/tests/payment-providers/payment-providers.test.js.map +1 -1
  134. package/dist/test/tests/payment-providers/paypal-button-datasource.test.js.map +1 -1
  135. package/dist/test/tests/payment-providers/paypal.test.js.map +1 -1
  136. package/dist/test/tests/payment-providers/venmo.test.js.map +1 -1
  137. package/dist/test/tests/recaptcha-manager.test.js.map +1 -1
  138. package/package.json +107 -107
  139. package/src/@types/analytics-handler/index.d.ts +8 -8
  140. package/src/@types/braintree-web/LICENSE +21 -21
  141. package/src/@types/braintree-web/index.d.ts +93 -93
  142. package/src/@types/braintree-web/modules/american-express.d.ts +50 -50
  143. package/src/@types/braintree-web/modules/apple-pay.d.ts +213 -213
  144. package/src/@types/braintree-web/modules/client.d.ts +103 -103
  145. package/src/@types/braintree-web/modules/core.d.ts +34 -34
  146. package/src/@types/braintree-web/modules/data-collector.d.ts +13 -13
  147. package/src/@types/braintree-web/modules/google-payment.d.ts +269 -269
  148. package/src/@types/braintree-web/modules/hosted-fields.d.ts +366 -366
  149. package/src/@types/braintree-web/modules/paypal-checkout.d.ts +262 -262
  150. package/src/@types/braintree-web/modules/paypal.d.ts +177 -177
  151. package/src/@types/braintree-web/modules/three-d-secure.d.ts +141 -141
  152. package/src/@types/braintree-web/modules/unionpay.d.ts +224 -224
  153. package/src/@types/braintree-web/modules/us-bank-account.d.ts +81 -81
  154. package/src/@types/braintree-web/modules/venmo.d.ts +110 -110
  155. package/src/@types/braintree-web/package.json +64 -64
  156. package/src/@types/paypal-checkout-components/LICENSE +21 -21
  157. package/src/@types/paypal-checkout-components/index.d.ts +67 -67
  158. package/src/@types/paypal-checkout-components/modules/button.d.ts +50 -50
  159. package/src/@types/paypal-checkout-components/modules/callback-data.d.ts +244 -244
  160. package/src/@types/paypal-checkout-components/modules/configuration.d.ts +114 -114
  161. package/src/@types/paypal-checkout-components/package.json +58 -58
  162. package/src/braintree-manager/braintree-interfaces.ts +172 -172
  163. package/src/braintree-manager/braintree-manager.ts +281 -281
  164. package/src/braintree-manager/payment-clients.ts +146 -146
  165. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-interface.ts +13 -13
  166. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-delegate.ts +8 -8
  167. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-interface.ts +10 -10
  168. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource.ts +119 -119
  169. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-manager.ts +21 -21
  170. package/src/braintree-manager/payment-providers/apple-pay/apple-pay.ts +97 -97
  171. package/src/braintree-manager/payment-providers/credit-card/credit-card-interface.ts +21 -21
  172. package/src/braintree-manager/payment-providers/credit-card/credit-card.ts +130 -130
  173. package/src/braintree-manager/payment-providers/credit-card/hosted-field-configuration.ts +19 -19
  174. package/src/braintree-manager/payment-providers/credit-card/hosted-field-container.ts +85 -85
  175. package/src/braintree-manager/payment-providers/google-pay-interface.ts +8 -8
  176. package/src/braintree-manager/payment-providers/google-pay.ts +59 -59
  177. package/src/braintree-manager/payment-providers/paypal/paypal-button-datasource.ts +218 -218
  178. package/src/braintree-manager/payment-providers/paypal/paypal-interface.ts +13 -13
  179. package/src/braintree-manager/payment-providers/paypal/paypal.ts +78 -78
  180. package/src/braintree-manager/payment-providers/venmo-interface.ts +8 -8
  181. package/src/braintree-manager/payment-providers/venmo.ts +67 -67
  182. package/src/braintree-manager/payment-providers-interface.ts +25 -25
  183. package/src/braintree-manager/payment-providers.ts +147 -147
  184. package/src/donation-form-controller.ts +623 -623
  185. package/src/donation-form-error.ts +6 -6
  186. package/src/donation-form.ts +576 -576
  187. package/src/form-elements/badged-input.ts +109 -109
  188. package/src/form-elements/contact-form/autocomplete-field-options.ts +63 -63
  189. package/src/form-elements/contact-form/contact-form.ts +434 -434
  190. package/src/form-elements/contact-form/countries.ts +252 -252
  191. package/src/form-elements/header/donation-form-header.ts +98 -98
  192. package/src/form-elements/header/donation-summary.ts +61 -61
  193. package/src/form-elements/payment-selector.ts +365 -365
  194. package/src/form-elements/total-amount.ts +46 -46
  195. package/src/modals/confirm-donation-modal-content.ts +168 -168
  196. package/src/modals/error-modal-content.ts +48 -48
  197. package/src/modals/upsell-modal-content.ts +284 -284
  198. package/src/payment-flow-handlers/donation-flow-modal-manager.ts +439 -439
  199. package/src/payment-flow-handlers/handlers/applepay-flow-handler.ts +109 -109
  200. package/src/payment-flow-handlers/handlers/creditcard-flow-handler.ts +232 -232
  201. package/src/payment-flow-handlers/handlers/googlepay-flow-handler.ts +111 -111
  202. package/src/payment-flow-handlers/handlers/paypal-flow-handler.ts +331 -331
  203. package/src/payment-flow-handlers/handlers/venmo-flow-handler.ts +119 -119
  204. package/src/payment-flow-handlers/handlers/venmo-restoration-state-handler.ts +127 -127
  205. package/src/payment-flow-handlers/payment-flow-handlers.ts +218 -218
  206. package/src/recaptcha-manager/recaptcha-manager.ts +123 -123
  207. package/src/util/promisedSleep.ts +3 -3
  208. package/dist/demo/app-root.d.ts +0 -0
  209. package/dist/demo/app-root.js +0 -2
  210. package/dist/demo/app-root.js.map +0 -1
@@ -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
+ }