Skip to content

Commit

Permalink
PPCP Wallet pay button implementation (#10)
Browse files Browse the repository at this point in the history
* ppcp wallet pay button implementation

---------

Co-authored-by: shagufa-ali <80478231+shagufa-ali@users.noreply.github.com>
  • Loading branch information
Shagufa92 and shagufa-ali authored Nov 29, 2023
1 parent e9b6703 commit 665f4bc
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 362 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"typescript-transform-paths": "^3.3.1"
},
"peerDependencies": {
"@boldcommerce/checkout-frontend-library": "0.52.2"
"@boldcommerce/checkout-frontend-library": "0.53.0"
},
"files": [
"lib/**/*"
Expand All @@ -52,7 +52,7 @@
"*.{js,jsx,ts,tsx}": "eslint --fix --max-warnings 0"
},
"dependencies": {
"@boldcommerce/checkout-frontend-library": "0.52.2",
"@boldcommerce/checkout-frontend-library": "0.53.0",
"@paypal/paypal-js": "^7.0.1",
"@types/applepayjs": "^3.0.4",
"@types/googlepay": "^0.6.4"
Expand Down
112 changes: 43 additions & 69 deletions src/paypal/ppcp_buttons/ppcpOnApprove.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,51 @@
import {OnApproveActions, OnApproveData} from '@paypal/paypal-js/types/components/buttons';
import {OrderResponseBody, ShippingInfo} from '@paypal/paypal-js/types/apis/orders';
import {getFirstAndLastName, getPhoneNumber, getTotals,} from 'src/utils';
import {formatPaypalToApiAddress} from 'src/paypal/formatPaypalToApiAddress';
import {addPayment, apiTypeKeys, batchRequest, getCurrency, IAddPaymentRequest, IBatchableRequest, buildAddressBatchRequest, buildCustomerBatchRequest} from '@boldcommerce/checkout-frontend-library';
import {OnApproveData} from '@paypal/paypal-js/types/components/buttons';
import {getTotals,} from 'src/utils';
import {
addPayment,
getCurrency,
IAddPaymentRequest,
IWalletPayOnApproveRequest, walletPayOnApprove
} from '@boldcommerce/checkout-frontend-library';
import {API_RETRY} from 'src/types';
import {getPaypalGatewayPublicId} from 'src/paypal/managePaypalState';
import {orderProcessing, displayError} from 'src/actions';

export async function ppcpOnApprove(data: OnApproveData, actions: OnApproveActions): Promise<void> {
export async function ppcpOnApprove(data: OnApproveData): Promise<void> {
const {iso_code: currencyCode} = getCurrency();
return actions.order?.get().then(async ({ payer, purchase_units, payment_source}: OrderResponseBody) => {

// Build Batch Requests
const requests: Array<IBatchableRequest> = [];

// extract all shipping info
const { name, address: shippingAddress } = purchase_units[0].shipping as ShippingInfo;
const shippingNames = getFirstAndLastName(name?.full_name);

// extract all billing info
const {name: payerName, address: billingAddress} = payer;
const billingNames = {firstName: payerName?.given_name || '', lastName: payerName?.surname || ''};
const phone = getPhoneNumber(payer.phone?.phone_number.national_number);
const email = payer.email_address || '';
const isBillingAddressFilled = (
!!billingAddress?.address_line_1
&& !!billingAddress.admin_area_1
&& !!billingAddress.admin_area_2
&& !!billingAddress.country_code
&& !!billingAddress.postal_code
);

const formattedShippingAddress = formatPaypalToApiAddress(shippingAddress, shippingNames.firstName, shippingNames.lastName, phone);
const formattedBillingAddress = formatPaypalToApiAddress(isBillingAddressFilled ? billingAddress : shippingAddress, billingNames.firstName, billingNames.lastName, phone);

const shippingAddressRequest = buildAddressBatchRequest(formattedShippingAddress, 'shipping');
const billingAddressRequest = buildAddressBatchRequest(formattedBillingAddress, 'billing');

const customerRequest = buildCustomerBatchRequest(billingNames.firstName, billingNames.lastName, email);

customerRequest && requests.push(customerRequest);
shippingAddressRequest && requests.push(shippingAddressRequest);
billingAddressRequest && requests.push(billingAddressRequest);
requests.push({apiType: apiTypeKeys.setTaxes, payload: {}});

const batchResponse = await batchRequest(requests, API_RETRY);

if (batchResponse.success) {
// add payment
const totals = getTotals();
const payment: IAddPaymentRequest = {
token: data.orderID,
gateway_public_id: getPaypalGatewayPublicId(),
currency: currencyCode,
amount: totals.totalAmountDue,
wallet_pay_type: 'paypal',
extra_payment_data: {
orderId: data.orderID,
facilitatorAccessToken: data.facilitatorAccessToken,
payerId: data.payerID,
paymentSource: payment_source,
}
} as IAddPaymentRequest;
const paymentResult = await addPayment(payment, API_RETRY);
if (!paymentResult.success) {
displayError('There was an unknown error while processing your payment.', 'payment_gateway', 'unknown_error');
return;
}
// finalize order
orderProcessing();
} else {
displayError('There was an unknown error while processing your payment.', 'payment_gateway', 'unknown_error');
return;
const body: IWalletPayOnApproveRequest = {
gateway_type: 'paypal',
payment_data: {
locale: navigator.language,
paypal_order_id: data.orderID
}
};

const res = await walletPayOnApprove(body, API_RETRY);

if (!res.success) {
displayError('There was an unknown error while processing your payment.', 'payment_gateway', 'unknown_error');
return;
}

const totals = getTotals();
const payment: IAddPaymentRequest = {
token: data.orderID,
gateway_public_id: getPaypalGatewayPublicId(),
currency: currencyCode,
amount: totals.totalAmountDue,
extra_payment_data: {
orderId: data.orderID,
facilitatorAccessToken: data.facilitatorAccessToken,
payerId: data.payerID,
}
});
} as IAddPaymentRequest;
const paymentResult = await addPayment(payment, API_RETRY);
if (!paymentResult.success) {
displayError('There was an unknown error while processing your payment.', 'payment_gateway', 'unknown_error');
return;
}

// finalize order
orderProcessing();
}
22 changes: 3 additions & 19 deletions src/paypal/ppcp_buttons/ppcpOnLoad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import {
enableDisableSection,
getPaypalNameSpace,
paypalOnClick,
paypalOnShippingChange,
ppcpOnApprove,
showPaymentMethodTypes
} from 'src';
import {OnShippingChangeActions, OnShippingChangeData} from '@paypal/paypal-js/types/components/buttons';
import {ppcpOrderCreate} from 'src/paypal/ppcp_buttons/ppcpOrderCreate';
import {ppcpOnShippingChange} from 'src/paypal/ppcp_buttons/ppcpOnShippingChange';

export async function ppcpOnLoad(payment: IExpressPayPaypalCommercePlatformButton): Promise<void> {

Expand All @@ -29,7 +28,7 @@ export async function ppcpOnLoad(payment: IExpressPayPaypalCommercePlatformButto
fundingSource: 'paypal',
createOrder: ppcpOrderCreate,
onClick: paypalOnClick,
onShippingChange: paypalOnShippingChange as (data: OnShippingChangeData, actions: OnShippingChangeActions) => Promise<void>,
onShippingChange: ppcpOnShippingChange,
onApprove: ppcpOnApprove,
style: {
...payment.style,
Expand All @@ -40,24 +39,13 @@ export async function ppcpOnLoad(payment: IExpressPayPaypalCommercePlatformButto
fundingSource: 'paylater',
createOrder: ppcpOrderCreate,
onClick: paypalOnClick,
onShippingChange: paypalOnShippingChange as (data: OnShippingChangeData, actions: OnShippingChangeActions) => Promise<void>,
onShippingChange: ppcpOnShippingChange,
onApprove: ppcpOnApprove,
style: {
...payment.style,
},
});

const venmoButton = paypal.Buttons({
fundingSource: 'venmo',
createOrder: ppcpOrderCreate,
onClick: paypalOnClick,
onApprove: ppcpOnApprove,
style: {
...payment.style,
color: 'blue', // paypal bug. venmo doesnt work with any other color
},
});

if(container) {
if (paypalButton.isEligible()) {
await paypalButton.render(`#${paypalDivId}`);
Expand All @@ -69,10 +57,6 @@ export async function ppcpOnLoad(payment: IExpressPayPaypalCommercePlatformButto
enableSection = true;
}

if (venmoButton.isEligible()) {
await venmoButton.render(`#${paypalDivId}`);
enableSection = true;
}
}

if(enableSection) {
Expand Down
27 changes: 27 additions & 0 deletions src/paypal/ppcp_buttons/ppcpOnShippingChange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {OnShippingChangeActions, OnShippingChangeData} from '@paypal/paypal-js/types/components/buttons';
import {
IWalletPayOnShippingRequest,
walletPayOnShipping
} from '@boldcommerce/checkout-frontend-library';
import {API_RETRY, displayError,} from 'src';


export async function ppcpOnShippingChange(data: OnShippingChangeData, actions: OnShippingChangeActions): Promise<void> {

const body: IWalletPayOnShippingRequest = {
gateway_type: 'paypal',
payment_data: {
locale: navigator.language,
paypal_order_id: data.orderID,
shipping_address: data.shipping_address,
shipping_options: data.selected_shipping_option,
}
};

const res = await walletPayOnShipping(body, API_RETRY);
if (!res.success) {
displayError('There was an unknown error while getting the shipping details.', 'payment_gateway', 'unknown_error');
return actions.reject();
}

}
12 changes: 6 additions & 6 deletions src/paypal/ppcp_buttons/ppcpOrderCreate.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import {
createPaymentGatewayOrder,
IApiSuccessResponse,
ICreatePaymentGatewayOrderRequest,
ICreatePaymentGatewayOrderResponse
IWalletPayCreateOrderRequest,
IWalletPayCreateOrderResponse,
walletPayCreateOrder
} from '@boldcommerce/checkout-frontend-library';
import {API_RETRY} from 'src/types';
import {displayError} from 'src/actions';

export async function ppcpOrderCreate(): Promise<string> {
const payment: ICreatePaymentGatewayOrderRequest = {
const payment: IWalletPayCreateOrderRequest = {
gateway_type: 'paypal',
payment_data: {
locale: navigator.language,
payment_type: 'paypal',
}
};

const paymentResult = await createPaymentGatewayOrder(payment, API_RETRY);
const paymentResult = await walletPayCreateOrder(payment, API_RETRY);
if(paymentResult.success) {
const {data} = paymentResult.response as IApiSuccessResponse;
const {payment_data} = data as ICreatePaymentGatewayOrderResponse;
const {payment_data} = data as IWalletPayCreateOrderResponse;
const orderId = payment_data.id as string;
return orderId;
} else {
Expand Down
Loading

0 comments on commit 665f4bc

Please sign in to comment.