Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(payment): PAYPAL-3520 Max capture amount failure #2485

Merged
merged 3 commits into from
Jun 4, 2024

Conversation

bc-nick
Copy link
Contributor

@bc-nick bc-nick commented Apr 26, 2024

What?

Handling an specific error related to max capture failure

Why?

To show the error message with an appropriate information for users

Testing / Proof

Manual testing

Tested with mock data

PSD2_braintree.mov

@bigcommerce/team-checkout @bigcommerce/team-payments

if (isPaypalCommerceProviderError(error)) {
const paypalProviderError = error?.errors?.filter((e: any) => e.provider_error) || [];

return paypalProviderError[0].provider_error?.code === '2046';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be better to create a separate constant for '2046' error? How do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late response. I think it is not necessary, we use this code only here and nowhere else

@bc-nick bc-nick force-pushed the PAYPAL-3520 branch 3 times, most recently from e336fc6 to ad8f56a Compare May 31, 2024 13:51
@@ -9,7 +9,8 @@ import {
PaymentStrategyFactory,
toResolvableModule,
} from '@bigcommerce/checkout-sdk/payment-integration-api';
import { Overlay } from '@bigcommerce/checkout-sdk/ui';
import { LOADING_INDICATOR_STYLES } from '@bigcommerce/checkout-sdk/paypal-commerce-utils';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not use PayPal Commerce specific code in Braintree integration. We have 2 ways to solve this issue:

  1. move LOADING_INDICATOR_STYLES into ui package and use it from there (but leave ppcp refactoring for another PR);
  2. make a copy of LOADING_INDICATOR_STYLES and paste it somewhere in braintree related package;

@@ -316,4 +484,35 @@ export default class BraintreePaypalPaymentStrategy implements PaymentStrategy {

throw new PaymentMethodFailedError(error.message);
}

private isProviderError(error: unknown): boolean {
if (isPaypalCommerceProviderError(error)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not use paypal commerce related code inside brainteree strategy. Please create another typeguard for that.

}
}

private renderPayPalMessages(initializationData?: any) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any type is forbidden for any new code in checkout sdk

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made decision to not pass this parameter, moved it to higher level

onError(new Error('INSTRUMENT_DECLINED'));
}

reject();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to reject promise in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to do this to avoid the execution code freeze. Code will not execute correctly without reject calling

Comment on lines 188 to 191
return Promise.resolve({
...payment,
paymentData: this.formattedPayload(token),
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not necessary to make Promise.resolve here

Suggested change
return Promise.resolve({
...payment,
paymentData: this.formattedPayload(token),
});
return {
...payment,
paymentData: this.formattedPayload(token),
};

}
}

private async tokenizePayment(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private async tokenizePayment(
private async tokenizePaymentOrThrow(

this.renderPayPalMessages(braintreeOptions?.bannerContainerId);
(braintreePaypalCheckout) => {
this.renderPayPalMessages(initializationData);
this.renderPayPalButton(braintreePaypalCheckout);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks a bit complicated.. because when you read the code you can see that loadPaypalCheckoutInstance method might be called up to 3 times, and it is not quite clear to me because we don't really render PayPal message or Button in all cases.

We can put it on hold and refactor in the future, just want to let you know that here is a place, where the code should be updated.

Copy link
Contributor

@serhii-tkachenko serhii-tkachenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Comment on lines +125 to +131
await new Promise((_resolve, reject) => {
if (onError && typeof onError === 'function') {
onError(new Error('INSTRUMENT_DECLINED'));
}

reject();
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see why do we need this promise.. To avoid code freeze we can simply remove the promise, since there is no reason to wait for something.

Suggested change
await new Promise((_resolve, reject) => {
if (onError && typeof onError === 'function') {
onError(new Error('INSTRUMENT_DECLINED'));
}
reject();
});
if (onError && typeof onError === 'function') {
onError(new Error('INSTRUMENT_DECLINED'));
}

@@ -5,7 +5,7 @@ module.exports = {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
diagnostics: false,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not necessary to do this change in current PR

@bc-nick bc-nick merged commit 968015a into bigcommerce:master Jun 4, 2024
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants