@internetarchive/donation-monthly-portal 7.7.0 → 7.7.2
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.
- package/dist/src/edit-plan-form.d.ts +2 -0
- package/dist/src/edit-plan-form.js +4 -0
- package/dist/src/edit-plan-form.js.map +1 -1
- package/dist/src/form-sections/parts/braintree-manager.d.ts +6 -0
- package/dist/src/form-sections/parts/braintree-manager.js +218 -1
- package/dist/src/form-sections/parts/braintree-manager.js.map +1 -1
- package/dist/src/form-sections/payment-method.d.ts +11 -0
- package/dist/src/form-sections/payment-method.js +190 -45
- package/dist/src/form-sections/payment-method.js.map +1 -1
- package/dist/src/models/plan.d.ts +1 -1
- package/dist/src/models/plan.js +58 -36
- package/dist/src/models/plan.js.map +1 -1
- package/dist/src/monthly-giving-circle.d.ts +2 -0
- package/dist/src/monthly-giving-circle.js +6 -0
- package/dist/src/monthly-giving-circle.js.map +1 -1
- package/dist/src/plans.js +13 -14
- package/dist/src/plans.js.map +1 -1
- package/dist/src/utils/venmo-pending-storage.d.ts +23 -0
- package/dist/src/utils/venmo-pending-storage.js +74 -0
- package/dist/src/utils/venmo-pending-storage.js.map +1 -0
- package/dist/test/edit-plan-flow-payment-method.test.js +776 -3
- package/dist/test/edit-plan-flow-payment-method.test.js.map +1 -1
- package/dist/test/form-sections/braintree-manager.test.d.ts +1 -0
- package/dist/test/form-sections/braintree-manager.test.js +642 -0
- package/dist/test/form-sections/braintree-manager.test.js.map +1 -0
- package/dist/test/helpers/mock-storage.d.ts +9 -0
- package/dist/test/helpers/mock-storage.js +26 -0
- package/dist/test/helpers/mock-storage.js.map +1 -0
- package/dist/test/models/plan.test.js +94 -1
- package/dist/test/models/plan.test.js.map +1 -1
- package/dist/test/plans-payment-method-display.test.d.ts +1 -0
- package/dist/test/plans-payment-method-display.test.js +126 -0
- package/dist/test/plans-payment-method-display.test.js.map +1 -0
- package/dist/test/utils/venmo-pending-storage.test.d.ts +1 -0
- package/dist/test/utils/venmo-pending-storage.test.js +121 -0
- package/dist/test/utils/venmo-pending-storage.test.js.map +1 -0
- package/package.json +6 -1
- package/src/edit-plan-form.ts +4 -0
- package/src/form-sections/parts/braintree-manager.ts +252 -0
- package/src/form-sections/payment-method.ts +209 -50
- package/src/models/plan.ts +56 -35
- package/src/monthly-giving-circle.ts +5 -0
- package/src/plans.ts +6 -9
- package/src/utils/venmo-pending-storage.ts +80 -0
|
@@ -2,6 +2,7 @@ import { LitElement } from 'lit';
|
|
|
2
2
|
import '@internetarchive/donation-form/dist/src/form-elements/badged-input';
|
|
3
3
|
import type { PaymentConfig } from './form-sections/parts/braintree-manager';
|
|
4
4
|
import type { MonthlyPlan } from './models/plan';
|
|
5
|
+
import type { VenmoPendingStorage } from './utils/venmo-pending-storage';
|
|
5
6
|
import './form-sections/amount';
|
|
6
7
|
import './form-sections/date';
|
|
7
8
|
import './form-sections/cancel';
|
|
@@ -16,6 +17,7 @@ export declare class IauxEditPlanForm extends LitElement {
|
|
|
16
17
|
coverFees: boolean;
|
|
17
18
|
feeCovered: number;
|
|
18
19
|
}) => void;
|
|
20
|
+
venmoPendingStorage?: VenmoPendingStorage;
|
|
19
21
|
paymentConfig: PaymentConfig;
|
|
20
22
|
braintreeNumberInput: HTMLDivElement;
|
|
21
23
|
braintreeExpirationDateInput: HTMLDivElement;
|
|
@@ -63,6 +63,7 @@ let IauxEditPlanForm = class IauxEditPlanForm extends LitElement {
|
|
|
63
63
|
.plan=${this.plan}
|
|
64
64
|
.patronEmail=${this.patronEmail}
|
|
65
65
|
.paymentConfig=${this.paymentConfig}
|
|
66
|
+
.venmoPendingStorage=${this.venmoPendingStorage}
|
|
66
67
|
@UpdatePaymentMethod=${(e) => {
|
|
67
68
|
const { newPaymentMethodRequest } = e.detail;
|
|
68
69
|
if (this.plan) {
|
|
@@ -118,6 +119,9 @@ __decorate([
|
|
|
118
119
|
__decorate([
|
|
119
120
|
property({ type: Object })
|
|
120
121
|
], IauxEditPlanForm.prototype, "updateAmountHandler", void 0);
|
|
122
|
+
__decorate([
|
|
123
|
+
property({ type: Object })
|
|
124
|
+
], IauxEditPlanForm.prototype, "venmoPendingStorage", void 0);
|
|
121
125
|
__decorate([
|
|
122
126
|
property({ type: Object })
|
|
123
127
|
], IauxEditPlanForm.prototype, "paymentConfig", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit-plan-form.js","sourceRoot":"","sources":["../../src/edit-plan-form.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,oEAAoE,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"edit-plan-form.js","sourceRoot":"","sources":["../../src/edit-plan-form.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html } from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\n\nimport '@internetarchive/donation-form/dist/src/form-elements/badged-input';\n\nimport { HostingEnvironment } from '@internetarchive/donation-form';\nimport type { PaymentConfig } from './form-sections/parts/braintree-manager';\nimport type { MonthlyPlan } from './models/plan';\nimport type { VenmoPendingStorage } from './utils/venmo-pending-storage';\nimport './form-sections/amount';\nimport './form-sections/date';\nimport './form-sections/cancel';\nimport './form-sections/payment-method';\nimport type { MGCEditPlanAmount } from './form-sections/amount';\nimport type { MGCEditPlanDate } from './form-sections/date';\nimport type { MGCEditPaymentMethod } from './form-sections/payment-method';\n\n@customElement('ia-mgc-edit-plan')\nexport class IauxEditPlanForm extends LitElement {\n @property({ type: Object }) plan?: MonthlyPlan;\n\n @property({ type: String }) patronEmail: string = '';\n\n @property({ type: Boolean }) canEditPaymentMethod: boolean = false;\n\n @property({ type: Object }) updateAmountHandler?: (\n plan: MonthlyPlan,\n amountUpdates: {\n amount: number;\n baseAmount: number;\n coverFees: boolean;\n feeCovered: number;\n },\n ) => void;\n\n @property({ type: Object }) venmoPendingStorage?: VenmoPendingStorage;\n\n @property({ type: Object }) paymentConfig: PaymentConfig = {\n referrer: '',\n origin: '',\n braintreeAuthToken: '',\n venmoProfileId: '',\n googlePayMerchantId: '',\n environment: HostingEnvironment.Development,\n paymentClients: undefined,\n endpointManager: undefined,\n };\n\n @query('#braintree-creditcard') braintreeNumberInput!: HTMLDivElement;\n\n @query('#braintree-expiration') braintreeExpirationDateInput!: HTMLDivElement;\n\n @query('#braintree-cvv') braintreeCVVInput!: HTMLDivElement;\n\n @query('#braintree-error-message') braintreeErrorMessage!: HTMLDivElement;\n\n createRenderRoot() {\n return this;\n }\n\n paymentMethodUpdates(status: 'success' | 'fail') {\n const paymentMethodForm = this.querySelector(\n 'ia-mgc-edit-payment-method',\n ) as MGCEditPaymentMethod;\n paymentMethodForm!.paymentMethodUpdated(status);\n }\n\n amountUpdates(status: 'success' | 'fail') {\n const amountForm = this.querySelector(\n 'ia-mgc-edit-plan-amount',\n ) as MGCEditPlanAmount;\n amountForm!.amountUpdated(status);\n }\n\n dateUpdates(status: 'success' | 'fail') {\n const dateForm = this.querySelector('ia-mgc-edit-date') as MGCEditPlanDate;\n dateForm!.dateUpdated(status);\n }\n\n render() {\n return html`\n <section class=\"mgc-edit-plan\">\n <ia-mgc-edit-plan-amount\n .plan=${this.plan}\n @updateAmount=${(e: CustomEvent) => {\n const { amount, baseAmount, coverFees, feeCovered } = e.detail;\n if (this.plan) {\n this.updateAmountHandler?.(this.plan, {\n amount,\n baseAmount,\n coverFees,\n feeCovered,\n });\n }\n }}\n ></ia-mgc-edit-plan-amount>\n ${this.canEditPaymentMethod\n ? html`\n <hr />\n <ia-mgc-edit-payment-method\n .plan=${this.plan}\n .patronEmail=${this.patronEmail}\n .paymentConfig=${this.paymentConfig}\n .venmoPendingStorage=${this.venmoPendingStorage}\n @UpdatePaymentMethod=${(e: CustomEvent) => {\n const { newPaymentMethodRequest } = e.detail;\n if (this.plan) {\n this.dispatchEvent(\n new CustomEvent('UpdatePaymentMethod', {\n detail: { plan: this.plan, newPaymentMethodRequest },\n }),\n );\n }\n }}\n >\n </ia-mgc-edit-payment-method>\n `\n : ''}\n <hr />\n <ia-mgc-edit-date\n @updateDate=${(e: CustomEvent) => {\n const { newDate } = e.detail;\n if (this.plan) {\n this.dispatchEvent(\n new CustomEvent('updateDate', {\n detail: { plan: this.plan, newDate },\n }),\n );\n }\n }}\n .plan=${this.plan}\n ></ia-mgc-edit-date>\n <hr />\n <ia-mgc-cancel-plan\n .plan=${this.plan}\n @cancelPlan=${() => {\n this.dispatchEvent(new Event('cancelPlan'));\n }}\n ></ia-mgc-cancel-plan>\n <hr />\n <p class=\"email-edit-plan\">\n Need to update your plan further? Please email us at\n <a href=${this.mailToText()}>donations@archive.org</a>.\n </p>\n </section>\n `;\n }\n\n mailToText(): string {\n return `mailto:donations@archive.org?subject=I'd like to update my monthly donation`;\n }\n}\n"]}
|
|
@@ -2,6 +2,7 @@ import { LitElement, CSSResult, PropertyValueMap } from 'lit';
|
|
|
2
2
|
import { BraintreeManagerInterface, HostingEnvironment } from '@internetarchive/donation-form';
|
|
3
3
|
import type { BraintreeEndpointManagerInterface } from '@internetarchive/donation-form/dist/src/braintree-manager/braintree-interfaces.js';
|
|
4
4
|
import type { PaymentClientsInterface } from '@internetarchive/donation-form/dist/src/braintree-manager/payment-clients.js';
|
|
5
|
+
import { VenmoPendingStorage } from '../../utils/venmo-pending-storage';
|
|
5
6
|
import type { MonthlyPlan } from '../../models/plan';
|
|
6
7
|
export type PaymentConfig = {
|
|
7
8
|
braintreeAuthToken?: string;
|
|
@@ -20,6 +21,7 @@ export declare class MGCBraintreeManager extends LitElement {
|
|
|
20
21
|
paymentConfig?: PaymentConfig;
|
|
21
22
|
braintreeManager?: BraintreeManagerInterface;
|
|
22
23
|
private elementConnected;
|
|
24
|
+
venmoPendingStorage?: VenmoPendingStorage;
|
|
23
25
|
get braintreeInputs(): {
|
|
24
26
|
errorMessage: HTMLDivElement | null;
|
|
25
27
|
number: HTMLDivElement | null;
|
|
@@ -37,6 +39,10 @@ export declare class MGCBraintreeManager extends LitElement {
|
|
|
37
39
|
get creditCardTemplate(): import("lit").TemplateResult<1>;
|
|
38
40
|
renderPayPalVaultButton(): Promise<void>;
|
|
39
41
|
private handlePayPalAuthorized;
|
|
42
|
+
startVenmoPayment(): Promise<void>;
|
|
43
|
+
startGooglePayPayment(): Promise<void>;
|
|
44
|
+
startApplePayPayment(originalEvent: Event): Promise<void>;
|
|
45
|
+
private checkVenmoRestoration;
|
|
40
46
|
private setupBraintreeManager;
|
|
41
47
|
get contactForm(): HTMLFormElement | null;
|
|
42
48
|
}
|
|
@@ -233,8 +233,207 @@ let MGCBraintreeManager = class MGCBraintreeManager extends LitElement {
|
|
|
233
233
|
},
|
|
234
234
|
}));
|
|
235
235
|
}
|
|
236
|
+
async startVenmoPayment() {
|
|
237
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
238
|
+
const handler = await ((_a = this.braintreeManager) === null || _a === void 0 ? void 0 : _a.paymentProviders.venmoHandler.get());
|
|
239
|
+
if (!handler)
|
|
240
|
+
return;
|
|
241
|
+
if ((_b = this.plan) === null || _b === void 0 ? void 0 : _b.id)
|
|
242
|
+
(_c = this.venmoPendingStorage) === null || _c === void 0 ? void 0 : _c.setPending(this.plan.id);
|
|
243
|
+
try {
|
|
244
|
+
const payload = await handler.startPayment();
|
|
245
|
+
if ((_d = this.plan) === null || _d === void 0 ? void 0 : _d.id)
|
|
246
|
+
(_e = this.venmoPendingStorage) === null || _e === void 0 ? void 0 : _e.clearPending(this.plan.id);
|
|
247
|
+
this.dispatchEvent(new CustomEvent('VenmoAuthorized', {
|
|
248
|
+
detail: {
|
|
249
|
+
paymentMethodInfo: {
|
|
250
|
+
description: `Venmo - ${payload.details.username}`,
|
|
251
|
+
nonce: payload.nonce,
|
|
252
|
+
type: payload.type,
|
|
253
|
+
details: { username: payload.details.username },
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
catch (e) {
|
|
259
|
+
if ((_f = this.plan) === null || _f === void 0 ? void 0 : _f.id)
|
|
260
|
+
(_g = this.venmoPendingStorage) === null || _g === void 0 ? void 0 : _g.clearPending(this.plan.id);
|
|
261
|
+
const code = e === null || e === void 0 ? void 0 : e.code;
|
|
262
|
+
if (code === 'VENMO_APP_CANCELED' || code === 'VENMO_CANCELED') {
|
|
263
|
+
console.log('Venmo payment cancelled');
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
console.error('Venmo payment error:', e);
|
|
267
|
+
this.dispatchEvent(new CustomEvent('VenmoError', { detail: { error: e } }));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async startGooglePayPayment() {
|
|
272
|
+
var _a, _b, _c;
|
|
273
|
+
const handler = await ((_a = this.braintreeManager) === null || _a === void 0 ? void 0 : _a.paymentProviders.googlePayHandler.get());
|
|
274
|
+
if (!handler)
|
|
275
|
+
return;
|
|
276
|
+
try {
|
|
277
|
+
const instance = await handler.instance.get();
|
|
278
|
+
if (!instance)
|
|
279
|
+
return;
|
|
280
|
+
const paymentDataRequest = await instance.createPaymentDataRequest({
|
|
281
|
+
emailRequired: true,
|
|
282
|
+
transactionInfo: {
|
|
283
|
+
currencyCode: 'USD',
|
|
284
|
+
totalPriceStatus: 'FINAL',
|
|
285
|
+
totalPrice: `${(_c = (_b = this.plan) === null || _b === void 0 ? void 0 : _b.amount) !== null && _c !== void 0 ? _c : 0}`,
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
const paymentData = await handler.paymentsClient.loadPaymentData(paymentDataRequest);
|
|
289
|
+
const payload = await instance.parseResponse(paymentData);
|
|
290
|
+
this.dispatchEvent(new CustomEvent('GooglePayVaultAuthorized', {
|
|
291
|
+
detail: {
|
|
292
|
+
paymentMethodInfo: {
|
|
293
|
+
description: `Google Pay - ${payload.details.cardType} - ${payload.details.lastFour}`,
|
|
294
|
+
nonce: payload.nonce,
|
|
295
|
+
type: payload.type,
|
|
296
|
+
details: {
|
|
297
|
+
cardType: payload.details.cardType,
|
|
298
|
+
lastFour: payload.details.lastFour,
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
catch (e) {
|
|
305
|
+
const statusCode = e === null || e === void 0 ? void 0 : e.statusCode;
|
|
306
|
+
if (statusCode === 'CANCELED') {
|
|
307
|
+
console.log('Google Pay payment cancelled');
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
console.error('Google Pay payment error:', e);
|
|
311
|
+
this.dispatchEvent(new CustomEvent('GooglePayError', { detail: { error: e } }));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// In order to trigger the Apple Pay flow, you HAVE to call this from
|
|
316
|
+
// directly within the user-gesture handler that produced `originalEvent`
|
|
317
|
+
// (Safari requires this). Notice we're not actually using the event itself.
|
|
318
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
319
|
+
async startApplePayPayment(originalEvent) {
|
|
320
|
+
var _a, _b, _c;
|
|
321
|
+
const handler = await ((_a = this.braintreeManager) === null || _a === void 0 ? void 0 : _a.paymentProviders.applePayHandler.get());
|
|
322
|
+
if (!handler)
|
|
323
|
+
return;
|
|
324
|
+
try {
|
|
325
|
+
const applePayInstance = await handler.instance.get();
|
|
326
|
+
if (!applePayInstance)
|
|
327
|
+
return;
|
|
328
|
+
const paymentRequest = applePayInstance.createPaymentRequest({
|
|
329
|
+
total: {
|
|
330
|
+
label: 'Internet Archive Monthly',
|
|
331
|
+
amount: `${(_c = (_b = this.plan) === null || _b === void 0 ? void 0 : _b.amount) !== null && _c !== void 0 ? _c : 0}`,
|
|
332
|
+
},
|
|
333
|
+
requiredBillingContactFields: ['postalAddress'],
|
|
334
|
+
});
|
|
335
|
+
const session = new ApplePaySession(3, paymentRequest);
|
|
336
|
+
session.onvalidatemerchant = (event) => {
|
|
337
|
+
applePayInstance.performValidation({
|
|
338
|
+
validationURL: event.validationURL,
|
|
339
|
+
displayName: 'Internet Archive',
|
|
340
|
+
}, (validationErr, validationData) => {
|
|
341
|
+
if (validationErr) {
|
|
342
|
+
console.error('Apple Pay merchant validation error:', validationErr);
|
|
343
|
+
session.abort();
|
|
344
|
+
this.dispatchEvent(new CustomEvent('ApplePayError', {
|
|
345
|
+
detail: { error: validationErr },
|
|
346
|
+
}));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
session.completeMerchantValidation(validationData);
|
|
350
|
+
});
|
|
351
|
+
};
|
|
352
|
+
session.onpaymentauthorized = async (event) => {
|
|
353
|
+
try {
|
|
354
|
+
const payload = await applePayInstance.tokenize({
|
|
355
|
+
token: event.payment.token,
|
|
356
|
+
});
|
|
357
|
+
session.completePayment(ApplePaySession.STATUS_SUCCESS);
|
|
358
|
+
this.dispatchEvent(new CustomEvent('ApplePayVaultAuthorized', {
|
|
359
|
+
detail: {
|
|
360
|
+
paymentMethodInfo: {
|
|
361
|
+
description: `Apple Pay - ${payload.details.cardType} - ${payload.details.dpanLastTwo}`,
|
|
362
|
+
nonce: payload.nonce,
|
|
363
|
+
type: payload.type,
|
|
364
|
+
details: {
|
|
365
|
+
cardType: payload.details.cardType,
|
|
366
|
+
lastTwo: payload.details.dpanLastTwo,
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
}));
|
|
371
|
+
}
|
|
372
|
+
catch (e) {
|
|
373
|
+
session.completePayment(ApplePaySession.STATUS_FAILURE);
|
|
374
|
+
console.error('Apple Pay tokenization error:', e);
|
|
375
|
+
this.dispatchEvent(new CustomEvent('ApplePayError', { detail: { error: e } }));
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
session.oncancel = () => {
|
|
379
|
+
console.log('Apple Pay payment cancelled');
|
|
380
|
+
};
|
|
381
|
+
session.begin();
|
|
382
|
+
}
|
|
383
|
+
catch (e) {
|
|
384
|
+
console.error('Apple Pay error:', e);
|
|
385
|
+
this.dispatchEvent(new CustomEvent('ApplePayError', { detail: { error: e } }));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
async checkVenmoRestoration() {
|
|
389
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
390
|
+
const planId = (_a = this.plan) === null || _a === void 0 ? void 0 : _a.id;
|
|
391
|
+
if (!planId)
|
|
392
|
+
return;
|
|
393
|
+
const pending = (_b = this.venmoPendingStorage) === null || _b === void 0 ? void 0 : _b.getPending(planId);
|
|
394
|
+
if (!pending)
|
|
395
|
+
return;
|
|
396
|
+
try {
|
|
397
|
+
const handler = await ((_c = this.braintreeManager) === null || _c === void 0 ? void 0 : _c.paymentProviders.venmoHandler.get());
|
|
398
|
+
if (!handler) {
|
|
399
|
+
(_d = this.venmoPendingStorage) === null || _d === void 0 ? void 0 : _d.clearPending(planId);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const instance = await handler.instance.get();
|
|
403
|
+
if (!instance) {
|
|
404
|
+
(_e = this.venmoPendingStorage) === null || _e === void 0 ? void 0 : _e.clearPending(planId);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
// Clear before tokenizing to prevent retry loops on failure
|
|
408
|
+
(_f = this.venmoPendingStorage) === null || _f === void 0 ? void 0 : _f.clearPending(planId);
|
|
409
|
+
if (!instance.hasTokenizationResult())
|
|
410
|
+
return;
|
|
411
|
+
// startPayment() re-checks hasTokenizationResult() internally and
|
|
412
|
+
// calls instance.tokenize() on the cached result — it does NOT launch
|
|
413
|
+
// a new Venmo redirect when a tokenization result is already present.
|
|
414
|
+
const payload = await handler.startPayment();
|
|
415
|
+
this.dispatchEvent(new CustomEvent('VenmoAuthorized', {
|
|
416
|
+
detail: {
|
|
417
|
+
paymentMethodInfo: {
|
|
418
|
+
description: `Venmo - ${payload.details.username}`,
|
|
419
|
+
nonce: payload.nonce,
|
|
420
|
+
type: payload.type,
|
|
421
|
+
details: { username: payload.details.username },
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
}));
|
|
425
|
+
}
|
|
426
|
+
catch (e) {
|
|
427
|
+
(_g = this.venmoPendingStorage) === null || _g === void 0 ? void 0 : _g.clearPending(planId);
|
|
428
|
+
const code = e === null || e === void 0 ? void 0 : e.code;
|
|
429
|
+
if (code !== 'VENMO_APP_CANCELED' && code !== 'VENMO_CANCELED') {
|
|
430
|
+
console.error('Venmo restoration error:', e);
|
|
431
|
+
this.dispatchEvent(new CustomEvent('VenmoError', { detail: { error: e } }));
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
236
435
|
async setupBraintreeManager() {
|
|
237
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
436
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
238
437
|
this.braintreeManager = new BraintreeManager({
|
|
239
438
|
paymentClients: (_b = (_a = this.paymentConfig) === null || _a === void 0 ? void 0 : _a.paymentClients) !== null && _b !== void 0 ? _b : {},
|
|
240
439
|
endpointManager: (_c = this.paymentConfig) === null || _c === void 0 ? void 0 : _c.endpointManager,
|
|
@@ -281,6 +480,21 @@ let MGCBraintreeManager = class MGCBraintreeManager extends LitElement {
|
|
|
281
480
|
});
|
|
282
481
|
this.dispatchEvent(event);
|
|
283
482
|
});
|
|
483
|
+
// BraintreeManager (@internetarchive/donation-form) has no config option to
|
|
484
|
+
// suppress Google Pay, so we replace the handler directly. The upstream path
|
|
485
|
+
// is `BraintreeManager.paymentProviders.googlePayHandler` — if that changes
|
|
486
|
+
// this cast will silently stop working and the button may reappear.
|
|
487
|
+
if (!((_j = this.paymentConfig) === null || _j === void 0 ? void 0 : _j.googlePayMerchantId) && this.braintreeManager) {
|
|
488
|
+
// BraintreeManager has no config option to suppress Google Pay, so we
|
|
489
|
+
// replace the handler directly. Casting only paymentProviders (not the
|
|
490
|
+
// whole manager) keeps the access chain type-checked — if upstream
|
|
491
|
+
// renames paymentProviders or googlePayHandler, TypeScript will catch it.
|
|
492
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
493
|
+
this.braintreeManager.paymentProviders.googlePayHandler = {
|
|
494
|
+
get: async () => null,
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
await this.checkVenmoRestoration();
|
|
284
498
|
this.dispatchEvent(new Event('BraintreeManagerSetupComplete'));
|
|
285
499
|
}
|
|
286
500
|
get contactForm() {
|
|
@@ -305,6 +519,9 @@ __decorate([
|
|
|
305
519
|
__decorate([
|
|
306
520
|
state()
|
|
307
521
|
], MGCBraintreeManager.prototype, "elementConnected", void 0);
|
|
522
|
+
__decorate([
|
|
523
|
+
property({ type: Object })
|
|
524
|
+
], MGCBraintreeManager.prototype, "venmoPendingStorage", void 0);
|
|
308
525
|
MGCBraintreeManager = __decorate([
|
|
309
526
|
customElement('ia-mgc-braintree-manager')
|
|
310
527
|
], MGCBraintreeManager);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"braintree-manager.js","sourceRoot":"","sources":["../../../../src/form-sections/parts/braintree-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport { LitElement, html, css, CSSResult, PropertyValueMap } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport {\n HostedFieldContainer,\n HostedFieldName,\n} from '@internetarchive/donation-form/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container';\nimport {\n BraintreeManager,\n BraintreeManagerInterface,\n HostingEnvironment,\n} from '@internetarchive/donation-form';\nimport {\n DonationPaymentInfo,\n DonationType,\n} from '@internetarchive/donation-form-data-models';\nimport type { BraintreeEndpointManagerInterface } from '@internetarchive/donation-form/dist/src/braintree-manager/braintree-interfaces.js';\nimport type { PaymentClientsInterface } from '@internetarchive/donation-form/dist/src/braintree-manager/payment-clients.js';\n\nimport creditCardImg from '@internetarchive/icon-credit-card/index.js';\nimport calendarImg from '@internetarchive/icon-calendar/index.js';\nimport lockImg from '@internetarchive/icon-lock/index.js';\n\nimport type { MonthlyPlan } from '../../models/plan';\n\nexport type PaymentConfig = {\n braintreeAuthToken?: string;\n endpointManager?: BraintreeEndpointManagerInterface;\n paymentClients?: PaymentClientsInterface;\n environment?: HostingEnvironment;\n venmoProfileId?: string;\n googlePayMerchantId?: string;\n referrer: string;\n origin: string;\n};\n\n@customElement('ia-mgc-braintree-manager')\nexport class MGCBraintreeManager extends LitElement {\n @property({ type: Object }) plan?: MonthlyPlan;\n\n @property({ type: Boolean, reflect: true }) displayCreditCard: boolean =\n false;\n\n @property({ type: String }) patronEmail: string = '';\n\n @property({ type: Object }) paymentConfig?: PaymentConfig;\n\n @property({ type: Object }) braintreeManager?: BraintreeManagerInterface;\n\n @state() private elementConnected: boolean = false;\n\n get braintreeInputs(): {\n errorMessage: HTMLDivElement | null;\n number: HTMLDivElement | null;\n cvv: HTMLDivElement | null;\n expirationDate: HTMLDivElement | null;\n } {\n return {\n errorMessage: this.querySelector(\n '#braintree-error-message',\n ) as HTMLDivElement | null,\n number: this.querySelector(\n '#braintree-creditcard',\n ) as HTMLDivElement | null,\n cvv: this.querySelector('#braintree-cvv') as HTMLDivElement | null,\n expirationDate: this.querySelector(\n '#braintree-expiration',\n ) as HTMLDivElement | null,\n };\n }\n\n createRenderRoot() {\n return this;\n }\n\n disconnectedCallback(): void {\n this.elementConnected = false;\n }\n\n connectedCallback(): void {\n // eslint-disable-next-line wc/guard-super-call\n super.connectedCallback();\n\n console.log('connectedCallback', { paymentConfig: this.paymentConfig });\n\n this.elementConnected = true;\n }\n\n protected updated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>,\n ): void {\n const elementHasConnectedToDOM =\n changed.has('elementConnected') && this.elementConnected;\n if (elementHasConnectedToDOM) {\n if (this.paymentConfig) {\n const {\n braintreeAuthToken,\n endpointManager,\n paymentClients,\n environment,\n } = this.paymentConfig || {};\n\n const needsBraintreeManager =\n !this.braintreeManager &&\n braintreeAuthToken &&\n endpointManager &&\n paymentClients &&\n environment;\n if (needsBraintreeManager) {\n this.setupBraintreeManager();\n }\n }\n }\n\n if (\n this.braintreeManager &&\n changed.has('displayCreditCard') &&\n this.displayCreditCard\n ) {\n this.setupCreditCardHandler();\n }\n }\n\n async validateCreditCardFields() {\n const handler =\n await this.braintreeManager?.paymentProviders.creditCardHandler.get();\n let tokenized = false;\n let hostedFieldsResponse = null;\n try {\n hostedFieldsResponse = await handler?.tokenizeHostedFields();\n tokenized = true;\n } catch (e) {\n const error = e as unknown as any;\n\n handler?.showErrorMessage();\n\n // todo: move these codes to an enum/type\n switch (error.code) {\n case 'HOSTED_FIELDS_FIELDS_EMPTY':\n // occurs when none of the fields are filled in\n handler?.markFieldErrors([\n HostedFieldName.Number,\n HostedFieldName.CVV,\n HostedFieldName.ExpirationDate,\n ]);\n break;\n case 'HOSTED_FIELDS_FIELDS_INVALID':\n // occurs when certain fields do not pass client side validationto\n // Object.keys(.details.invalidFields).forEach(key => {\n // handler?.markFieldErrors([key as HostedFieldName]);\n // });\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE':\n // occurs when:\n // * the client token used for client authorization was generated\n // with a customer ID and the fail on duplicate payment method\n // option is set to true\n // * the card being tokenized has previously been vaulted (with any customer)\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED':\n // occurs when:\n // * the client token used for client authorization was generated\n // with a customer ID and the verify card option is set to true\n // and you have credit card verification turned on in the Braintree\n // control panel\n // * the cvv does not pass verfication\n handler?.markFieldErrors([HostedFieldName.CVV]);\n break;\n case 'HOSTED_FIELDS_FAILED_TOKENIZATION':\n // occurs for any other tokenization error on the server\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR':\n // occurs when the Braintree gateway cannot be contacted\n break;\n default:\n // something else happened\n break;\n }\n }\n\n if (!tokenized) {\n return false;\n }\n\n return hostedFieldsResponse;\n }\n\n async setupCreditCardHandler() {\n // braintree turn on hosted fields\n const handler =\n await this.braintreeManager?.paymentProviders.creditCardHandler.get();\n try {\n await handler?.tokenizeHostedFields();\n } catch (e) {\n // todo: show error message only about fields not loading\n }\n\n handler?.removeFieldErrors([\n HostedFieldName.Number,\n HostedFieldName.CVV,\n HostedFieldName.ExpirationDate,\n ]);\n }\n\n render() {\n return html` <div>${this.creditCardTemplate}</div> `;\n }\n\n lightDomCSS(): CSSResult {\n return css`\n contact-form form badged-input {\n width: 100%;\n }\n\n #ia-mgc-cc-area .braintree-input {\n width: 100%;\n display: block;\n height: stretch;\n height: -webkit-fill-available;\n }\n `;\n }\n\n get creditCardTemplate() {\n return html`\n <div id=\"ia-mgc-cc-area\" style=\"border: 1px sold red;\">\n <style>\n ${this.lightDomCSS()}\n </style>\n <div id=\"braintree-error-message\"></div>\n <div class=\"braintree-row\">\n <badged-input\n .icon=${creditCardImg}\n ?required=${true}\n class=\"creditcard\"\n >\n <div class=\"braintree-input\" id=\"braintree-creditcard\"></div>\n </badged-input>\n </div>\n <div class=\"braintree-row\">\n <badged-input\n .icon=${calendarImg}\n ?required=${true}\n class=\"expiration\"\n >\n <div class=\"braintree-input\" id=\"braintree-expiration\"></div>\n </badged-input>\n <badged-input .icon=${lockImg} ?required=${true} class=\"cvv\">\n <div class=\"braintree-input\" id=\"braintree-cvv\"></div>\n </badged-input>\n </div>\n </div>\n `;\n }\n\n async renderPayPalVaultButton(): Promise<void> {\n console.log('[PayPal] renderPayPalVaultButton called');\n\n const handler =\n await this.braintreeManager?.paymentProviders.paypalHandler.get();\n console.log('[PayPal] handler:', handler);\n if (!handler) return;\n\n const container = document.querySelector('#ia-mgc-paypal-button');\n console.log('[PayPal] container element:', container);\n\n const donationInfo = new DonationPaymentInfo({\n donationType: DonationType.Monthly,\n amount: this.plan?.amount ?? 0,\n coverFees: false,\n });\n\n const dataSource = await handler.renderPayPalButton({\n selector: '#ia-mgc-paypal-button',\n style: { color: 'blue', shape: 'rect', size: 'medium' },\n donationInfo,\n });\n console.log('[PayPal] dataSource:', dataSource);\n\n if (!dataSource) return;\n\n dataSource.delegate = {\n payPalPaymentStarted: async () => {\n console.log('PayPal payment started');\n },\n payPalPaymentAuthorized: async (_ds: any, payload: any) => {\n this.handlePayPalAuthorized(payload);\n },\n payPalPaymentConfirmed: async (_ds: any, payload: any) => {\n this.handlePayPalAuthorized(payload);\n },\n payPalPaymentCancelled: async () => {\n console.log('PayPal payment cancelled');\n },\n payPalPaymentError: async (_ds: any, error: unknown) => {\n console.error('PayPal vault error:', error);\n this.dispatchEvent(\n new CustomEvent('PayPalVaultError', { detail: { error } }),\n );\n },\n };\n }\n\n private handlePayPalAuthorized(payload: {\n nonce: string;\n type: string;\n details: { email: string };\n }): void {\n this.dispatchEvent(\n new CustomEvent('PayPalVaultAuthorized', {\n detail: {\n paymentMethodInfo: {\n description: `PayPal - ${payload.details.email}`,\n nonce: payload.nonce,\n type: payload.type,\n details: { email: payload.details.email },\n },\n },\n }),\n );\n }\n\n private async setupBraintreeManager(): Promise<void> {\n this.braintreeManager = new BraintreeManager({\n paymentClients:\n this.paymentConfig?.paymentClients ?? ({} as PaymentClientsInterface),\n endpointManager: this.paymentConfig\n ?.endpointManager as BraintreeEndpointManagerInterface,\n authorizationToken: this.paymentConfig?.braintreeAuthToken ?? '',\n venmoProfileId: this.paymentConfig?.venmoProfileId,\n googlePayMerchantId: this.paymentConfig?.googlePayMerchantId,\n hostedFieldConfig: {\n hostedFieldStyle: {}, // Provide your custom style object here\n hostedFieldFieldOptions: {\n number: {\n selector: '#braintree-creditcard',\n placeholder: 'Card number',\n },\n cvv: {\n selector: '#braintree-cvv',\n placeholder: 'CVC',\n },\n expirationDate: {\n selector: '#braintree-expiration',\n placeholder: 'MM / YY',\n },\n }, // Provide your custom field options here\n hostedFieldContainer: new HostedFieldContainer({\n number: this.braintreeInputs.number as HTMLDivElement,\n cvv: this.braintreeInputs.cvv as HTMLDivElement,\n expirationDate: this.braintreeInputs.expirationDate as HTMLDivElement,\n errorContainer: this.braintreeInputs.errorMessage as HTMLDivElement,\n }),\n },\n hostingEnvironment: this.paymentConfig?.environment as HostingEnvironment,\n referrer: window.location.href,\n loggedInUser: this.patronEmail,\n origin: window.location.origin,\n });\n\n this.braintreeManager.on(\n 'paymentProvidersHostedFieldsRetry',\n (retryNumber: number) => {\n const event = new CustomEvent('paymentProvidersHostedFieldsRetry', {\n detail: { retryNumber },\n });\n this.dispatchEvent(event);\n },\n );\n\n this.braintreeManager.on(\n 'paymentProvidersHostedFieldsFailed',\n (error: unknown) => {\n const event = new CustomEvent('paymentProvidersHostedFieldsFailed', {\n detail: { error },\n });\n this.dispatchEvent(event);\n },\n );\n\n this.dispatchEvent(new Event('BraintreeManagerSetupComplete'));\n }\n\n get contactForm(): HTMLFormElement | null {\n return this.querySelector('form[name=\"contact-form\"]');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"braintree-manager.js","sourceRoot":"","sources":["../../../../src/form-sections/parts/braintree-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport { LitElement, html, css, CSSResult, PropertyValueMap } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport {\n HostedFieldContainer,\n HostedFieldName,\n} from '@internetarchive/donation-form/dist/src/braintree-manager/payment-providers/credit-card/hosted-field-container';\nimport {\n BraintreeManager,\n BraintreeManagerInterface,\n HostingEnvironment,\n} from '@internetarchive/donation-form';\nimport {\n DonationPaymentInfo,\n DonationType,\n} from '@internetarchive/donation-form-data-models';\nimport type { BraintreeEndpointManagerInterface } from '@internetarchive/donation-form/dist/src/braintree-manager/braintree-interfaces.js';\nimport type { PaymentClientsInterface } from '@internetarchive/donation-form/dist/src/braintree-manager/payment-clients.js';\n\nimport creditCardImg from '@internetarchive/icon-credit-card/index.js';\nimport calendarImg from '@internetarchive/icon-calendar/index.js';\nimport lockImg from '@internetarchive/icon-lock/index.js';\nimport { VenmoPendingStorage } from '../../utils/venmo-pending-storage';\n\nimport type { MonthlyPlan } from '../../models/plan';\n\nexport type PaymentConfig = {\n braintreeAuthToken?: string;\n endpointManager?: BraintreeEndpointManagerInterface;\n paymentClients?: PaymentClientsInterface;\n environment?: HostingEnvironment;\n venmoProfileId?: string;\n googlePayMerchantId?: string;\n referrer: string;\n origin: string;\n};\n\n@customElement('ia-mgc-braintree-manager')\nexport class MGCBraintreeManager extends LitElement {\n @property({ type: Object }) plan?: MonthlyPlan;\n\n @property({ type: Boolean, reflect: true }) displayCreditCard: boolean =\n false;\n\n @property({ type: String }) patronEmail: string = '';\n\n @property({ type: Object }) paymentConfig?: PaymentConfig;\n\n @property({ type: Object }) braintreeManager?: BraintreeManagerInterface;\n\n @state() private elementConnected: boolean = false;\n\n @property({ type: Object }) venmoPendingStorage?: VenmoPendingStorage;\n\n get braintreeInputs(): {\n errorMessage: HTMLDivElement | null;\n number: HTMLDivElement | null;\n cvv: HTMLDivElement | null;\n expirationDate: HTMLDivElement | null;\n } {\n return {\n errorMessage: this.querySelector(\n '#braintree-error-message',\n ) as HTMLDivElement | null,\n number: this.querySelector(\n '#braintree-creditcard',\n ) as HTMLDivElement | null,\n cvv: this.querySelector('#braintree-cvv') as HTMLDivElement | null,\n expirationDate: this.querySelector(\n '#braintree-expiration',\n ) as HTMLDivElement | null,\n };\n }\n\n createRenderRoot() {\n return this;\n }\n\n disconnectedCallback(): void {\n this.elementConnected = false;\n }\n\n connectedCallback(): void {\n // eslint-disable-next-line wc/guard-super-call\n super.connectedCallback();\n\n console.log('connectedCallback', { paymentConfig: this.paymentConfig });\n\n this.elementConnected = true;\n }\n\n protected updated(\n changed: PropertyValueMap<any> | Map<PropertyKey, unknown>,\n ): void {\n const elementHasConnectedToDOM =\n changed.has('elementConnected') && this.elementConnected;\n if (elementHasConnectedToDOM) {\n if (this.paymentConfig) {\n const {\n braintreeAuthToken,\n endpointManager,\n paymentClients,\n environment,\n } = this.paymentConfig || {};\n\n const needsBraintreeManager =\n !this.braintreeManager &&\n braintreeAuthToken &&\n endpointManager &&\n paymentClients &&\n environment;\n if (needsBraintreeManager) {\n this.setupBraintreeManager();\n }\n }\n }\n\n if (\n this.braintreeManager &&\n changed.has('displayCreditCard') &&\n this.displayCreditCard\n ) {\n this.setupCreditCardHandler();\n }\n }\n\n async validateCreditCardFields() {\n const handler =\n await this.braintreeManager?.paymentProviders.creditCardHandler.get();\n let tokenized = false;\n let hostedFieldsResponse = null;\n try {\n hostedFieldsResponse = await handler?.tokenizeHostedFields();\n tokenized = true;\n } catch (e) {\n const error = e as unknown as any;\n\n handler?.showErrorMessage();\n\n // todo: move these codes to an enum/type\n switch (error.code) {\n case 'HOSTED_FIELDS_FIELDS_EMPTY':\n // occurs when none of the fields are filled in\n handler?.markFieldErrors([\n HostedFieldName.Number,\n HostedFieldName.CVV,\n HostedFieldName.ExpirationDate,\n ]);\n break;\n case 'HOSTED_FIELDS_FIELDS_INVALID':\n // occurs when certain fields do not pass client side validationto\n // Object.keys(.details.invalidFields).forEach(key => {\n // handler?.markFieldErrors([key as HostedFieldName]);\n // });\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE':\n // occurs when:\n // * the client token used for client authorization was generated\n // with a customer ID and the fail on duplicate payment method\n // option is set to true\n // * the card being tokenized has previously been vaulted (with any customer)\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED':\n // occurs when:\n // * the client token used for client authorization was generated\n // with a customer ID and the verify card option is set to true\n // and you have credit card verification turned on in the Braintree\n // control panel\n // * the cvv does not pass verfication\n handler?.markFieldErrors([HostedFieldName.CVV]);\n break;\n case 'HOSTED_FIELDS_FAILED_TOKENIZATION':\n // occurs for any other tokenization error on the server\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR':\n // occurs when the Braintree gateway cannot be contacted\n break;\n default:\n // something else happened\n break;\n }\n }\n\n if (!tokenized) {\n return false;\n }\n\n return hostedFieldsResponse;\n }\n\n async setupCreditCardHandler() {\n // braintree turn on hosted fields\n const handler =\n await this.braintreeManager?.paymentProviders.creditCardHandler.get();\n try {\n await handler?.tokenizeHostedFields();\n } catch (e) {\n // todo: show error message only about fields not loading\n }\n\n handler?.removeFieldErrors([\n HostedFieldName.Number,\n HostedFieldName.CVV,\n HostedFieldName.ExpirationDate,\n ]);\n }\n\n render() {\n return html` <div>${this.creditCardTemplate}</div> `;\n }\n\n lightDomCSS(): CSSResult {\n return css`\n contact-form form badged-input {\n width: 100%;\n }\n\n #ia-mgc-cc-area .braintree-input {\n width: 100%;\n display: block;\n height: stretch;\n height: -webkit-fill-available;\n }\n `;\n }\n\n get creditCardTemplate() {\n return html`\n <div id=\"ia-mgc-cc-area\" style=\"border: 1px sold red;\">\n <style>\n ${this.lightDomCSS()}\n </style>\n <div id=\"braintree-error-message\"></div>\n <div class=\"braintree-row\">\n <badged-input\n .icon=${creditCardImg}\n ?required=${true}\n class=\"creditcard\"\n >\n <div class=\"braintree-input\" id=\"braintree-creditcard\"></div>\n </badged-input>\n </div>\n <div class=\"braintree-row\">\n <badged-input\n .icon=${calendarImg}\n ?required=${true}\n class=\"expiration\"\n >\n <div class=\"braintree-input\" id=\"braintree-expiration\"></div>\n </badged-input>\n <badged-input .icon=${lockImg} ?required=${true} class=\"cvv\">\n <div class=\"braintree-input\" id=\"braintree-cvv\"></div>\n </badged-input>\n </div>\n </div>\n `;\n }\n\n async renderPayPalVaultButton(): Promise<void> {\n console.log('[PayPal] renderPayPalVaultButton called');\n\n const handler =\n await this.braintreeManager?.paymentProviders.paypalHandler.get();\n console.log('[PayPal] handler:', handler);\n if (!handler) return;\n\n const container = document.querySelector('#ia-mgc-paypal-button');\n console.log('[PayPal] container element:', container);\n\n const donationInfo = new DonationPaymentInfo({\n donationType: DonationType.Monthly,\n amount: this.plan?.amount ?? 0,\n coverFees: false,\n });\n\n const dataSource = await handler.renderPayPalButton({\n selector: '#ia-mgc-paypal-button',\n style: { color: 'blue', shape: 'rect', size: 'medium' },\n donationInfo,\n });\n console.log('[PayPal] dataSource:', dataSource);\n\n if (!dataSource) return;\n\n dataSource.delegate = {\n payPalPaymentStarted: async () => {\n console.log('PayPal payment started');\n },\n payPalPaymentAuthorized: async (_ds: any, payload: any) => {\n this.handlePayPalAuthorized(payload);\n },\n payPalPaymentConfirmed: async (_ds: any, payload: any) => {\n this.handlePayPalAuthorized(payload);\n },\n payPalPaymentCancelled: async () => {\n console.log('PayPal payment cancelled');\n },\n payPalPaymentError: async (_ds: any, error: unknown) => {\n console.error('PayPal vault error:', error);\n this.dispatchEvent(\n new CustomEvent('PayPalVaultError', { detail: { error } }),\n );\n },\n };\n }\n\n private handlePayPalAuthorized(payload: {\n nonce: string;\n type: string;\n details: { email: string };\n }): void {\n this.dispatchEvent(\n new CustomEvent('PayPalVaultAuthorized', {\n detail: {\n paymentMethodInfo: {\n description: `PayPal - ${payload.details.email}`,\n nonce: payload.nonce,\n type: payload.type,\n details: { email: payload.details.email },\n },\n },\n }),\n );\n }\n\n async startVenmoPayment(): Promise<void> {\n const handler =\n await this.braintreeManager?.paymentProviders.venmoHandler.get();\n if (!handler) return;\n\n if (this.plan?.id) this.venmoPendingStorage?.setPending(this.plan.id);\n\n try {\n const payload = await handler.startPayment();\n if (this.plan?.id) this.venmoPendingStorage?.clearPending(this.plan.id);\n this.dispatchEvent(\n new CustomEvent('VenmoAuthorized', {\n detail: {\n paymentMethodInfo: {\n description: `Venmo - ${payload.details.username}`,\n nonce: payload.nonce,\n type: payload.type,\n details: { username: payload.details.username },\n },\n },\n }),\n );\n } catch (e: unknown) {\n if (this.plan?.id) this.venmoPendingStorage?.clearPending(this.plan.id);\n const code = (e as { code?: string })?.code;\n if (code === 'VENMO_APP_CANCELED' || code === 'VENMO_CANCELED') {\n console.log('Venmo payment cancelled');\n } else {\n console.error('Venmo payment error:', e);\n this.dispatchEvent(\n new CustomEvent('VenmoError', { detail: { error: e } }),\n );\n }\n }\n }\n\n async startGooglePayPayment(): Promise<void> {\n const handler =\n await this.braintreeManager?.paymentProviders.googlePayHandler.get();\n if (!handler) return;\n\n try {\n const instance = await handler.instance.get();\n if (!instance) return;\n\n const paymentDataRequest = await instance.createPaymentDataRequest({\n emailRequired: true,\n transactionInfo: {\n currencyCode: 'USD',\n totalPriceStatus: 'FINAL',\n totalPrice: `${this.plan?.amount ?? 0}`,\n },\n });\n\n const paymentData =\n await handler.paymentsClient.loadPaymentData(paymentDataRequest);\n const payload = await instance.parseResponse(paymentData);\n this.dispatchEvent(\n new CustomEvent('GooglePayVaultAuthorized', {\n detail: {\n paymentMethodInfo: {\n description: `Google Pay - ${payload.details.cardType} - ${payload.details.lastFour}`,\n nonce: payload.nonce,\n type: payload.type,\n details: {\n cardType: payload.details.cardType,\n lastFour: payload.details.lastFour,\n },\n },\n },\n }),\n );\n } catch (e: unknown) {\n const statusCode = (e as { statusCode?: string })?.statusCode;\n if (statusCode === 'CANCELED') {\n console.log('Google Pay payment cancelled');\n } else {\n console.error('Google Pay payment error:', e);\n this.dispatchEvent(\n new CustomEvent('GooglePayError', { detail: { error: e } }),\n );\n }\n }\n }\n\n // In order to trigger the Apple Pay flow, you HAVE to call this from\n // directly within the user-gesture handler that produced `originalEvent`\n // (Safari requires this). Notice we're not actually using the event itself.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async startApplePayPayment(originalEvent: Event): Promise<void> {\n const handler =\n await this.braintreeManager?.paymentProviders.applePayHandler.get();\n if (!handler) return;\n\n try {\n const applePayInstance = await handler.instance.get();\n if (!applePayInstance) return;\n\n const paymentRequest = applePayInstance.createPaymentRequest({\n total: {\n label: 'Internet Archive Monthly',\n amount: `${this.plan?.amount ?? 0}`,\n },\n requiredBillingContactFields: ['postalAddress'],\n });\n\n const session = new ApplePaySession(3, paymentRequest);\n\n session.onvalidatemerchant = (\n event: ApplePayJS.ApplePayValidateMerchantEvent,\n ) => {\n applePayInstance.performValidation(\n {\n validationURL: event.validationURL,\n displayName: 'Internet Archive',\n },\n (validationErr: unknown, validationData: unknown) => {\n if (validationErr) {\n console.error(\n 'Apple Pay merchant validation error:',\n validationErr,\n );\n session.abort();\n this.dispatchEvent(\n new CustomEvent('ApplePayError', {\n detail: { error: validationErr },\n }),\n );\n return;\n }\n session.completeMerchantValidation(validationData);\n },\n );\n };\n\n session.onpaymentauthorized = async (\n event: ApplePayJS.ApplePayPaymentAuthorizedEvent,\n ) => {\n try {\n const payload = await applePayInstance.tokenize({\n token: event.payment.token,\n });\n session.completePayment(ApplePaySession.STATUS_SUCCESS);\n this.dispatchEvent(\n new CustomEvent('ApplePayVaultAuthorized', {\n detail: {\n paymentMethodInfo: {\n description: `Apple Pay - ${payload.details.cardType} - ${payload.details.dpanLastTwo}`,\n nonce: payload.nonce,\n type: payload.type,\n details: {\n cardType: payload.details.cardType,\n lastTwo: payload.details.dpanLastTwo,\n },\n },\n },\n }),\n );\n } catch (e: unknown) {\n session.completePayment(ApplePaySession.STATUS_FAILURE);\n console.error('Apple Pay tokenization error:', e);\n this.dispatchEvent(\n new CustomEvent('ApplePayError', { detail: { error: e } }),\n );\n }\n };\n\n session.oncancel = () => {\n console.log('Apple Pay payment cancelled');\n };\n\n session.begin();\n } catch (e: unknown) {\n console.error('Apple Pay error:', e);\n this.dispatchEvent(\n new CustomEvent('ApplePayError', { detail: { error: e } }),\n );\n }\n }\n\n private async checkVenmoRestoration(): Promise<void> {\n const planId = this.plan?.id;\n if (!planId) return;\n const pending = this.venmoPendingStorage?.getPending(planId);\n if (!pending) return;\n\n try {\n const handler =\n await this.braintreeManager?.paymentProviders.venmoHandler.get();\n if (!handler) {\n this.venmoPendingStorage?.clearPending(planId);\n return;\n }\n\n const instance = await handler.instance.get();\n if (!instance) {\n this.venmoPendingStorage?.clearPending(planId);\n return;\n }\n\n // Clear before tokenizing to prevent retry loops on failure\n this.venmoPendingStorage?.clearPending(planId);\n\n if (!instance.hasTokenizationResult()) return;\n\n // startPayment() re-checks hasTokenizationResult() internally and\n // calls instance.tokenize() on the cached result — it does NOT launch\n // a new Venmo redirect when a tokenization result is already present.\n const payload = await handler.startPayment();\n this.dispatchEvent(\n new CustomEvent('VenmoAuthorized', {\n detail: {\n paymentMethodInfo: {\n description: `Venmo - ${payload.details.username}`,\n nonce: payload.nonce,\n type: payload.type,\n details: { username: payload.details.username },\n },\n },\n }),\n );\n } catch (e: unknown) {\n this.venmoPendingStorage?.clearPending(planId);\n const code = (e as { code?: string })?.code;\n if (code !== 'VENMO_APP_CANCELED' && code !== 'VENMO_CANCELED') {\n console.error('Venmo restoration error:', e);\n this.dispatchEvent(\n new CustomEvent('VenmoError', { detail: { error: e } }),\n );\n }\n }\n }\n\n private async setupBraintreeManager(): Promise<void> {\n this.braintreeManager = new BraintreeManager({\n paymentClients:\n this.paymentConfig?.paymentClients ?? ({} as PaymentClientsInterface),\n endpointManager: this.paymentConfig\n ?.endpointManager as BraintreeEndpointManagerInterface,\n authorizationToken: this.paymentConfig?.braintreeAuthToken ?? '',\n venmoProfileId: this.paymentConfig?.venmoProfileId,\n googlePayMerchantId: this.paymentConfig?.googlePayMerchantId,\n hostedFieldConfig: {\n hostedFieldStyle: {}, // Provide your custom style object here\n hostedFieldFieldOptions: {\n number: {\n selector: '#braintree-creditcard',\n placeholder: 'Card number',\n },\n cvv: {\n selector: '#braintree-cvv',\n placeholder: 'CVC',\n },\n expirationDate: {\n selector: '#braintree-expiration',\n placeholder: 'MM / YY',\n },\n }, // Provide your custom field options here\n hostedFieldContainer: new HostedFieldContainer({\n number: this.braintreeInputs.number as HTMLDivElement,\n cvv: this.braintreeInputs.cvv as HTMLDivElement,\n expirationDate: this.braintreeInputs.expirationDate as HTMLDivElement,\n errorContainer: this.braintreeInputs.errorMessage as HTMLDivElement,\n }),\n },\n hostingEnvironment: this.paymentConfig?.environment as HostingEnvironment,\n referrer: window.location.href,\n loggedInUser: this.patronEmail,\n origin: window.location.origin,\n });\n\n this.braintreeManager.on(\n 'paymentProvidersHostedFieldsRetry',\n (retryNumber: number) => {\n const event = new CustomEvent('paymentProvidersHostedFieldsRetry', {\n detail: { retryNumber },\n });\n this.dispatchEvent(event);\n },\n );\n\n this.braintreeManager.on(\n 'paymentProvidersHostedFieldsFailed',\n (error: unknown) => {\n const event = new CustomEvent('paymentProvidersHostedFieldsFailed', {\n detail: { error },\n });\n this.dispatchEvent(event);\n },\n );\n\n // BraintreeManager (@internetarchive/donation-form) has no config option to\n // suppress Google Pay, so we replace the handler directly. The upstream path\n // is `BraintreeManager.paymentProviders.googlePayHandler` — if that changes\n // this cast will silently stop working and the button may reappear.\n if (!this.paymentConfig?.googlePayMerchantId && this.braintreeManager) {\n // BraintreeManager has no config option to suppress Google Pay, so we\n // replace the handler directly. Casting only paymentProviders (not the\n // whole manager) keeps the access chain type-checked — if upstream\n // renames paymentProviders or googlePayHandler, TypeScript will catch it.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this.braintreeManager.paymentProviders as any).googlePayHandler = {\n get: async () => null,\n };\n }\n\n await this.checkVenmoRestoration();\n this.dispatchEvent(new Event('BraintreeManagerSetupComplete'));\n }\n\n get contactForm(): HTMLFormElement | null {\n return this.querySelector('form[name=\"contact-form\"]');\n }\n}\n"]}
|
|
@@ -11,6 +11,7 @@ import '../presentational/mgc-button';
|
|
|
11
11
|
import type { MGCButton } from '../presentational/mgc-button';
|
|
12
12
|
import '../presentational/mgc-update-status';
|
|
13
13
|
import type { MGCBraintreeManager, PaymentConfig } from '../form-sections/parts/braintree-manager';
|
|
14
|
+
import { VenmoPendingStorage } from '../utils/venmo-pending-storage';
|
|
14
15
|
/**
|
|
15
16
|
* <ia-mgc-edit-payment-method>
|
|
16
17
|
* - collecting the data to send to the service
|
|
@@ -32,8 +33,13 @@ export declare class MGCEditPaymentMethod extends LitElement {
|
|
|
32
33
|
paymentSelectorFirstUpdated: boolean;
|
|
33
34
|
updateMessage: string;
|
|
34
35
|
updateStatus: 'success' | 'fail' | '';
|
|
36
|
+
venmoPendingStorage?: VenmoPendingStorage;
|
|
37
|
+
private authorizedPaymentMethodRequest?;
|
|
35
38
|
createRenderRoot(): this;
|
|
39
|
+
firstUpdated(): void;
|
|
40
|
+
private checkAndRestoreVenmoState;
|
|
36
41
|
submitPaymentMethodChange(e: Event): void;
|
|
42
|
+
private selectProvider;
|
|
37
43
|
clearStatusMessaging(): void;
|
|
38
44
|
paymentMethodUpdated(status: 'success' | 'fail'): Promise<void>;
|
|
39
45
|
get updateRequestButton(): MGCButton;
|
|
@@ -42,7 +48,12 @@ export declare class MGCEditPaymentMethod extends LitElement {
|
|
|
42
48
|
get paymentFormSection(): TemplateResult | typeof nothing;
|
|
43
49
|
get creditCardElement(): ContactForm | null;
|
|
44
50
|
get braintreeManagerElement(): MGCBraintreeManager | null;
|
|
51
|
+
get paymentMethodDetail(): string;
|
|
45
52
|
render(): TemplateResult<1>;
|
|
53
|
+
showVenmoError(message?: string): void;
|
|
54
|
+
private handleVenmoAuthorized;
|
|
55
|
+
private handleGooglePayVaultAuthorized;
|
|
56
|
+
private handleApplePayVaultAuthorized;
|
|
46
57
|
private handlePayPalVaultAuthorized;
|
|
47
58
|
get styles(): import("lit").CSSResult;
|
|
48
59
|
}
|