Skip to content

Commit

Permalink
using onAuthorized on gpay,applepay,paypal
Browse files Browse the repository at this point in the history
  • Loading branch information
ribeiroguilherme committed Dec 18, 2023
1 parent 324a3ae commit 0c7c16d
Show file tree
Hide file tree
Showing 18 changed files with 226 additions and 220 deletions.
31 changes: 30 additions & 1 deletion packages/lib/src/components/ApplePay/ApplePay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ApplePayElement extends UIElement<ApplePayConfiguration> {
this.submit = this.submit.bind(this);
this.validateMerchant = this.validateMerchant.bind(this);
this.collectOrderTrackingDetailsIfNeeded = this.collectOrderTrackingDetailsIfNeeded.bind(this);
this.handleAuthorization = this.handleAuthorization.bind(this);
}

/**
Expand Down Expand Up @@ -110,7 +111,8 @@ class ApplePayElement extends UIElement<ApplePayConfiguration> {
...(deliveryAddress && { deliveryAddress })
});

this.makePaymentsCall()
this.handleAuthorization()
.then(this.makePaymentsCall)
.then(this.sanitizeResponse)
.then(this.verifyPaymentDidNotFail)
.then(this.collectOrderTrackingDetailsIfNeeded)
Expand All @@ -125,6 +127,8 @@ class ApplePayElement extends UIElement<ApplePayConfiguration> {
this.handleResponse(paymentResponse);
})
.catch((error: onSubmitReject) => {
console.error(error);

this.setElementStatus('ready');
const errors = error?.error?.applePayError;

Expand All @@ -145,6 +149,31 @@ class ApplePayElement extends UIElement<ApplePayConfiguration> {
}));
}

/**
* Call the 'onAuthorized' callback if available.
* Must be resolved/reject for the payment flow to continue
*
* @private
*/
private async handleAuthorization(): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (!this.props.onAuthorized) {
resolve();
}

const { authorizedEvent, billingAddress, deliveryAddress } = this.state;

this.props.onAuthorized(
{
authorizedEvent,
...(billingAddress && { billingAddress }),
...(deliveryAddress && { deliveryAddress })
},
{ resolve, reject }
);
});
}

/**
* Verify if the 'onOrderTrackingRequest' is provided. If so, triggers the callback expecting an
* Apple Pay order details back
Expand Down
1 change: 0 additions & 1 deletion packages/lib/src/components/ApplePay/defaultProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ const defaultProps = {

// Events
onClick: resolve => resolve(),
onAuthorized: resolve => resolve(),
onPaymentMethodSelected: null,
onShippingContactSelected: null,
onShippingMethodSelected: null,
Expand Down
18 changes: 17 additions & 1 deletion packages/lib/src/components/ApplePay/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,29 @@ export interface ApplePayConfiguration extends UIElementProps {

onClick?: (resolve, reject) => void;

/**
* Callback called when ApplePay authorize the payment.
* Must be resolved/rejected with the action object.
*
* @param paymentData
* @returns
*/
onAuthorized?: (
data: {
authorizedEvent: ApplePayJS.ApplePayPaymentAuthorizedEvent;
billingAddress?: Partial<AddressData>;
deliveryAddress?: Partial<AddressData>;
},
actions: { resolve: () => void; reject: () => void }
) => void;

/**
* Collect the order tracking details if available.
* This callback is invoked when a successfull payment is resolved
*
* {@link https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentorderdetails}
* @param resolve - Must be called with the orderDetails fields
* @param reject - Must be called if something failed during the order creation
* @param reject - Must be called if something failed during the order creation. Calling 'reject' won't cancel the payment flow
*/
onOrderTrackingRequest?: (resolve: (orderDetails: ApplePayPaymentOrderDetails) => void, reject: () => void) => void;

Expand Down
4 changes: 0 additions & 4 deletions packages/lib/src/components/Dropin/Dropin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ class DropinElement extends UIElement<DropinConfiguration> {
};
}

public override get authorizedEvent(): any {
return this.dropinRef?.state?.activePaymentMethod?.authorizedEvent;
}

get isValid() {
return (
!!this.dropinRef &&
Expand Down
33 changes: 27 additions & 6 deletions packages/lib/src/components/GooglePay/GooglePay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class GooglePay extends UIElement<GooglePayConfiguration> {

constructor(props) {
super(props);
this.handleAuthorization = this.handleAuthorization.bind(this);

this.googlePay = new GooglePayService({
...this.props,
Expand All @@ -30,10 +31,6 @@ class GooglePay extends UIElement<GooglePayConfiguration> {
});
}

/**
* Formats the component data input
* For legacy support - maps configuration.merchantIdentifier to configuration.merchantId
*/
formatProps(props): GooglePayConfiguration {
// const allowedCardNetworks = props.brands?.length ? mapBrands(props.brands) : props.allowedCardNetworks;
const buttonSizeMode = props.buttonSizeMode ?? (props.isDropin ? 'fill' : 'static');
Expand Down Expand Up @@ -109,7 +106,8 @@ class GooglePay extends UIElement<GooglePayConfiguration> {
});

return new Promise<google.payments.api.PaymentAuthorizationResult>(resolve => {
this.makePaymentsCall()
this.handleAuthorization()
.then(this.makePaymentsCall)
.then(this.sanitizeResponse)
.then(this.verifyPaymentDidNotFail)
.then((paymentResponse: PaymentResponseData) => {
Expand All @@ -126,14 +124,37 @@ class GooglePay extends UIElement<GooglePayConfiguration> {
transactionState: 'ERROR',
error: {
intent: error?.error?.googlePayError?.intent || 'PAYMENT_AUTHORIZATION',
message: error?.error?.googlePayError?.message || 'Something went wrong',
message: error?.error?.googlePayError?.message || 'Payment failed',
reason: error?.error?.googlePayError?.reason || 'OTHER_ERROR'
}
});
});
});
};

/**
* Call the 'onAuthorized' callback if available.
* Must be resolved/reject for the payment flow to continue
*/
private async handleAuthorization(): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (!this.props.onAuthorized) {
resolve();
}

const { authorizedEvent, billingAddress, deliveryAddress } = this.state;

this.props.onAuthorized(
{
authorizedEvent,
...(billingAddress && { billingAddress }),
...(deliveryAddress && { deliveryAddress })
},
{ resolve, reject }
);
});
}

/**
* Validation
*/
Expand Down
1 change: 0 additions & 1 deletion packages/lib/src/components/GooglePay/defaultProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export default {
totalPriceStatus: 'FINAL' as google.payments.api.TotalPriceStatus,

// Callbacks
onAuthorized: params => params,
onClick: resolve => resolve(),

// CardParameters
Expand Down
18 changes: 17 additions & 1 deletion packages/lib/src/components/GooglePay/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AddressData } from '../../types';
import { UIElementProps } from '../internal/UIElement/types';

export interface GooglePayPropsConfiguration {
Expand Down Expand Up @@ -149,7 +150,22 @@ export interface GooglePayConfiguration extends UIElementProps {

// Events
onClick?: (resolve, reject) => void;
onAuthorized?: (paymentData: google.payments.api.PaymentData) => void;

/**
* Callback called when GooglePay authorize the payment.
* Must be resolved/rejected with the action object.
*
* @param paymentData
* @returns
*/
onAuthorized?: (
data: {
authorizedEvent: google.payments.api.PaymentData;
billingAddress?: Partial<AddressData>;
deliveryAddress?: Partial<AddressData>;
},
actions: { resolve: () => void; reject: () => void }
) => void;
}

// Used to add undocumented google payment options
Expand Down
44 changes: 32 additions & 12 deletions packages/lib/src/components/PayPal/Paypal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import './Paypal.scss';
import CoreProvider from '../../core/Context/CoreProvider';
import AdyenCheckoutError from '../../core/Errors/AdyenCheckoutError';
import { ERRORS } from './constants';
import { createShopperDetails } from './utils/create-shopper-details';
import { TxVariants } from '../tx-variants';
import { formatPaypalOrderContatcToAdyenFormat } from './utils/format-paypal-order-contact-to-adyen-format';

class PaypalElement extends UIElement<PayPalConfiguration> {
public static type = TxVariants.paypal;
Expand Down Expand Up @@ -90,27 +90,47 @@ class PaypalElement extends UIElement<PayPalConfiguration> {
return true;
}

private handleCancel = () => {
this.handleError(new AdyenCheckoutError('CANCEL'));
};

private handleOnApprove = (data: any, actions: any): Promise<void> | void => {
const { onShopperDetails } = this.props;
const { onAuthorized } = this.props;
const state = { data: { details: data, paymentData: this.paymentData } };

if (!onShopperDetails) {
if (!onAuthorized) {
this.handleAdditionalDetails(state);
return;
}

return actions.order
.get()
.then(paypalOrder => {
const shopperDetails = createShopperDetails(paypalOrder);
return new Promise<void>((resolve, reject) => onShopperDetails(shopperDetails, paypalOrder, { resolve, reject }));
.then((paypalOrder: any) => {
const billingAddress = formatPaypalOrderContatcToAdyenFormat(paypalOrder?.payer);
const deliveryAddress = formatPaypalOrderContatcToAdyenFormat(
paypalOrder?.purchase_units?.[0].shipping,
true
);

this.setState({
authorizedEvent: paypalOrder,
...(billingAddress && { billingAddress }),
...(deliveryAddress && { deliveryAddress })
});

return new Promise<void>((resolve, reject) =>
onAuthorized(
{
authorizedEvent: paypalOrder,
...(billingAddress && { billingAddress }),
...(deliveryAddress && { deliveryAddress })
},
{ resolve, reject }
)
);
})
.then(() => this.handleAdditionalDetails(state))
.catch(error => this.handleError(new AdyenCheckoutError('ERROR', 'Something went wrong while parsing PayPal Order', { cause: error })));
.catch(error =>
this.handleError(
new AdyenCheckoutError('ERROR', 'Something went wrong while parsing PayPal Order', { cause: error })
)
);
};

handleResolve(token: string) {
Expand Down Expand Up @@ -142,7 +162,7 @@ class PaypalElement extends UIElement<PayPalConfiguration> {
this.componentRef = ref;
}}
{...this.props}
onCancel={this.handleCancel}
onCancel={() => this.handleError(new AdyenCheckoutError('CANCEL'))}
onChange={this.setState}
onApprove={this.handleOnApprove}
onError={error => {
Expand Down
1 change: 0 additions & 1 deletion packages/lib/src/components/PayPal/defaultProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ const defaultProps: Partial<PayPalConfiguration> = {
// Events
onInit: () => {},
onClick: () => {},
onCancel: () => {},
onError: () => {},
onShippingChange: () => {}
};
Expand Down
18 changes: 10 additions & 8 deletions packages/lib/src/components/PayPal/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { PaymentAmount, PaymentMethod, ShopperDetails } from '../../types/global-types';
import UIElement from '../internal/UIElement/UIElement';
import { AddressData, PaymentAmount, PaymentMethod } from '../../types/global-types';
import { SUPPORTED_LOCALES } from './config';
import { UIElementProps } from '../internal/UIElement/types';

Expand Down Expand Up @@ -169,12 +168,15 @@ export interface PayPalConfig {
}

export interface PayPalConfiguration extends PayPalCommonProps, UIElementProps {
onSubmit?: (state: any, element: UIElement) => void;
onComplete?: (state, element?: UIElement) => void;
onAdditionalDetails?: (state: any, element: UIElement) => void;
onCancel?: (state: any, element: UIElement) => void;
onError?: (state: any, element?: UIElement) => void;
onShopperDetails?(shopperDetails: ShopperDetails, rawData: any, actions: { resolve: () => void; reject: () => void }): void;
/**
* Callback called when PayPal authorizes the payment.
* Must be resolved/rejected with the action object. If resolved, the additional details will be invoked. Otherwise it will be skipped
*/
onAuthorized?: (
data: { authorizedEvent: any; billingAddress?: Partial<AddressData>; deliveryAddress?: Partial<AddressData> },
actions: { resolve: () => void; reject: () => void }
) => void;

paymentMethods?: PaymentMethod[];
showPayButton?: boolean;
}
Expand Down
Loading

0 comments on commit 0c7c16d

Please sign in to comment.