@internetarchive/donation-form 1.0.1 → 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 (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.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 +5 -5
  127. package/dist/test/tests/models/donation-payment-info.test.js.map +1 -1
  128. package/dist/test/tests/payment-clients.test.js.map +1 -1
  129. package/dist/test/tests/payment-providers/applepay-sessiondatasource.test.js.map +1 -1
  130. package/dist/test/tests/payment-providers/applepay-sessionmanager.test.js.map +1 -1
  131. package/dist/test/tests/payment-providers/applepay.test.js.map +1 -1
  132. package/dist/test/tests/payment-providers/creditcard.test.js.map +1 -1
  133. package/dist/test/tests/payment-providers/googlepay.test.js.map +1 -1
  134. package/dist/test/tests/payment-providers/payment-providers.test.js.map +1 -1
  135. package/dist/test/tests/payment-providers/paypal-button-datasource.test.js.map +1 -1
  136. package/dist/test/tests/payment-providers/paypal.test.js.map +1 -1
  137. package/dist/test/tests/payment-providers/venmo.test.js.map +1 -1
  138. package/dist/test/tests/recaptcha-manager.test.js.map +1 -1
  139. package/package.json +107 -107
  140. package/src/@types/analytics-handler/index.d.ts +8 -8
  141. package/src/@types/braintree-web/LICENSE +21 -21
  142. package/src/@types/braintree-web/index.d.ts +93 -93
  143. package/src/@types/braintree-web/modules/american-express.d.ts +50 -50
  144. package/src/@types/braintree-web/modules/apple-pay.d.ts +213 -213
  145. package/src/@types/braintree-web/modules/client.d.ts +103 -103
  146. package/src/@types/braintree-web/modules/core.d.ts +34 -34
  147. package/src/@types/braintree-web/modules/data-collector.d.ts +13 -13
  148. package/src/@types/braintree-web/modules/google-payment.d.ts +269 -269
  149. package/src/@types/braintree-web/modules/hosted-fields.d.ts +366 -366
  150. package/src/@types/braintree-web/modules/paypal-checkout.d.ts +262 -262
  151. package/src/@types/braintree-web/modules/paypal.d.ts +177 -177
  152. package/src/@types/braintree-web/modules/three-d-secure.d.ts +141 -141
  153. package/src/@types/braintree-web/modules/unionpay.d.ts +224 -224
  154. package/src/@types/braintree-web/modules/us-bank-account.d.ts +81 -81
  155. package/src/@types/braintree-web/modules/venmo.d.ts +110 -110
  156. package/src/@types/braintree-web/package.json +64 -64
  157. package/src/@types/paypal-checkout-components/LICENSE +21 -21
  158. package/src/@types/paypal-checkout-components/index.d.ts +67 -67
  159. package/src/@types/paypal-checkout-components/modules/button.d.ts +50 -50
  160. package/src/@types/paypal-checkout-components/modules/callback-data.d.ts +244 -244
  161. package/src/@types/paypal-checkout-components/modules/configuration.d.ts +114 -114
  162. package/src/@types/paypal-checkout-components/package.json +58 -58
  163. package/src/braintree-manager/braintree-interfaces.ts +172 -172
  164. package/src/braintree-manager/braintree-manager.ts +281 -281
  165. package/src/braintree-manager/payment-clients.ts +146 -146
  166. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-interface.ts +13 -13
  167. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-delegate.ts +8 -8
  168. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource-interface.ts +10 -10
  169. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-datasource.ts +119 -119
  170. package/src/braintree-manager/payment-providers/apple-pay/apple-pay-session-manager.ts +21 -21
  171. package/src/braintree-manager/payment-providers/apple-pay/apple-pay.ts +97 -97
  172. package/src/braintree-manager/payment-providers/credit-card/credit-card-interface.ts +21 -21
  173. package/src/braintree-manager/payment-providers/credit-card/credit-card.ts +130 -130
  174. package/src/braintree-manager/payment-providers/credit-card/hosted-field-configuration.ts +19 -19
  175. package/src/braintree-manager/payment-providers/credit-card/hosted-field-container.ts +85 -85
  176. package/src/braintree-manager/payment-providers/google-pay-interface.ts +8 -8
  177. package/src/braintree-manager/payment-providers/google-pay.ts +59 -59
  178. package/src/braintree-manager/payment-providers/paypal/paypal-button-datasource.ts +218 -218
  179. package/src/braintree-manager/payment-providers/paypal/paypal-interface.ts +13 -13
  180. package/src/braintree-manager/payment-providers/paypal/paypal.ts +78 -78
  181. package/src/braintree-manager/payment-providers/venmo-interface.ts +8 -8
  182. package/src/braintree-manager/payment-providers/venmo.ts +67 -67
  183. package/src/braintree-manager/payment-providers-interface.ts +25 -25
  184. package/src/braintree-manager/payment-providers.ts +147 -147
  185. package/src/donation-form-controller.ts +623 -623
  186. package/src/donation-form-error.ts +6 -6
  187. package/src/donation-form.ts +576 -576
  188. package/src/form-elements/badged-input.ts +109 -109
  189. package/src/form-elements/contact-form/autocomplete-field-options.ts +63 -63
  190. package/src/form-elements/contact-form/contact-form.ts +434 -434
  191. package/src/form-elements/contact-form/countries.ts +252 -252
  192. package/src/form-elements/header/donation-form-header.ts +98 -98
  193. package/src/form-elements/header/donation-summary.ts +61 -61
  194. package/src/form-elements/payment-selector.ts +365 -365
  195. package/src/form-elements/total-amount.ts +46 -46
  196. package/src/modals/confirm-donation-modal-content.ts +168 -168
  197. package/src/modals/error-modal-content.ts +48 -48
  198. package/src/modals/upsell-modal-content.ts +284 -284
  199. package/src/payment-flow-handlers/donation-flow-modal-manager.ts +439 -439
  200. package/src/payment-flow-handlers/handlers/applepay-flow-handler.ts +109 -109
  201. package/src/payment-flow-handlers/handlers/creditcard-flow-handler.ts +232 -232
  202. package/src/payment-flow-handlers/handlers/googlepay-flow-handler.ts +111 -111
  203. package/src/payment-flow-handlers/handlers/paypal-flow-handler.ts +331 -331
  204. package/src/payment-flow-handlers/handlers/venmo-flow-handler.ts +119 -119
  205. package/src/payment-flow-handlers/handlers/venmo-restoration-state-handler.ts +127 -127
  206. package/src/payment-flow-handlers/payment-flow-handlers.ts +218 -218
  207. package/src/recaptcha-manager/recaptcha-manager.ts +123 -123
  208. package/src/util/promisedSleep.ts +3 -3
  209. package/dist/demo/app-root.d.ts +0 -0
  210. package/dist/demo/app-root.js +0 -2
  211. 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
+ }