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

CHK-4580 ppcp google pay #41

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/initialize/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
IExpressPayBraintreeApple,
IExpressPayBraintreeGoogle,
IExpressPayPaypal,
IExpressPayPaypalCommercePlatform,

Check warning on line 7 in src/initialize/initialize.ts

View workflow job for this annotation

GitHub Actions / Build

'IExpressPayPaypalCommercePlatform' is defined but never used
IExpressPayStripe,
} from '@boldcommerce/checkout-frontend-library';
import {
Expand All @@ -14,9 +14,10 @@
initStripe,
initPaypal,
setOnAction,
initPPCPApple,

Check warning on line 17 in src/initialize/initialize.ts

View workflow job for this annotation

GitHub Actions / Build

'initPPCPApple' is defined but never used
initPpcp,
} from 'src';
import {initPPCPGoogle} from 'src/paypal/ppcp_google';

Check warning on line 20 in src/initialize/initialize.ts

View workflow job for this annotation

GitHub Actions / Build

'initPPCPGoogle' is defined but never used

export function initialize(props: IInitializeProps): void{
let {alternative_payment_methods} = getOrderInitialData();
Expand All @@ -27,7 +28,8 @@
const loadsPpcp = alternative_payment_methods.some(payment => payment.type === alternatePaymentMethodType.PPCP);
if (loadsPpcp) {
alternative_payment_methods = alternative_payment_methods
.filter(m => m.type !== alternatePaymentMethodType.PPCP_APPLE);
.filter(m => m.type !== alternatePaymentMethodType.PPCP_APPLE
|| m.type !== alternatePaymentMethodType.PPCP_GOOGLE);
}

for (const paymentMethod of alternative_payment_methods) {
Expand All @@ -45,9 +47,6 @@
case alternatePaymentMethodType.BRAINTREE_APPLE:
initBraintreeApple(paymentMethod as IExpressPayBraintreeApple);
break;
case alternatePaymentMethodType.PPCP_APPLE:
initPPCPApple(paymentMethod as IExpressPayPaypalCommercePlatform);
break;
case alternatePaymentMethodType.PPCP:
initPpcp(props.onAction, !!props.fastlane);
break;
Expand Down
1 change: 1 addition & 0 deletions src/paypal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export * from './paypalOnClick';
export * from './paypalOnload';
export * from './paypalOnShippingChange';
export * from './ppcp_apple';
export * from './ppcp_google';
export * from './ppcp_buttons';
6 changes: 6 additions & 0 deletions src/paypal/initPpcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
setOnAction,
showPaymentMethodTypes
} from 'src';
import {initPPCPGoogle} from 'src/paypal/ppcp_google';
import {IExpressPayBraintreeGoogle} from '@boldcommerce/checkout-frontend-library/lib/types/apiInterfaces';

export async function initPpcp(callback?: IOnAction, fastlane = false): Promise<void> {

Expand All @@ -28,6 +30,10 @@ export async function initPpcp(callback?: IOnAction, fastlane = false): Promise<
if(applePayment){
await initPPCPApple(applePayment as IExpressPayPaypalCommercePlatform);
}
const ppcpPayment = payment as IExpressPayBraintreeGoogle;
if(ppcpPayment.google_pay_enabled) {
await initPPCPGoogle(payment as IExpressPayPaypalCommercePlatform);
}
} else {
displayError('There was an unknown error while loading the paypal buttons. Please try again.', 'generic', 'unknown_error');
enableDisableSection( showPaymentMethodTypes.PPCP, true);
Expand Down
68 changes: 65 additions & 3 deletions src/paypal/managePaypalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import {
IPaypalNamespaceApple,
IPPCPAppleConfig,
IPPCPApplePayInstance,
paypalState
paypalState, IPaypalNamespaceGoogle, IPPCPGooglePayInstance, IPPCPGoogleConfig
} from 'src';
import PaymentsClient = google.payments.api.PaymentsClient;

export function setPaypalNameSpace(paypal: PayPalNamespace | IPaypalNamespaceApple | null): void {
export function setPaypalNameSpace(paypal: PayPalNamespace | IPaypalNamespaceApple | IPaypalNamespaceGoogle | null): void {
paypalState.paypal = paypal;
}

Expand All @@ -20,7 +21,7 @@ export function getPaypalNameSpacePromise(): Promise<PayPalNamespace | null> | n
return paypalState.paypalPromise;
}

export function getPaypalNameSpace(): PayPalNamespace | IPaypalNamespaceApple | null {
export function getPaypalNameSpace(): PayPalNamespace | IPaypalNamespaceApple | IPaypalNamespaceGoogle | null {
return paypalState.paypal;
}

Expand All @@ -33,6 +34,11 @@ export function hasPaypalNameSpaceApple(): boolean {
return !!paypal && !!paypal.Applepay;
}

export function hasPaypalNameSpaceGoogle(): boolean {
const paypal = paypalState.paypal as IPaypalNamespaceGoogle;
return !!paypal && !!paypal.Googlepay;
}

export function setPPCPApplePayInstance(ppcpApplePayInstance: IPPCPApplePayInstance | null): void {
paypalState.ppcpApplePayInstance = ppcpApplePayInstance;
}
Expand Down Expand Up @@ -77,6 +83,51 @@ export function getPPCPApplePaySessionChecked(): ApplePaySession {
}
return paypalState.ppcpApplePaySession;
}
export function setPPCPGooglePayInstance(ppcpGooglePayInstance: IPPCPGooglePayInstance | null): void {
paypalState.ppcpGooglePayInstance = ppcpGooglePayInstance;
}

export function getPPCPGooglePayInstance(): IPPCPGooglePayInstance | null {
return paypalState.ppcpGooglePayInstance;
}

export function getPPCPGooglePayInstanceChecked(): IPPCPGooglePayInstance {
if (!paypalState.ppcpGooglePayInstance) {
throw new PaypalNullStateKeyError('Precondition violated: ppcpGooglePayInstance is null');
}
return paypalState.ppcpGooglePayInstance;
}

export function setPPCPGooglePayConfig(ppcpGooglePayConfig: IPPCPGoogleConfig | null): void {
paypalState.ppcpGooglePayConfig = ppcpGooglePayConfig;
}

export function getPPCPGooglePayConfig(): IPPCPGoogleConfig | null {
return paypalState.ppcpGooglePayConfig;
}

export function getPPCPGooglePayConfigChecked(): IPPCPGoogleConfig {
if (!paypalState.ppcpGooglePayConfig) {
throw new PaypalNullStateKeyError('Precondition violated: ppcpGooglePayConfig is null');
}
return paypalState.ppcpGooglePayConfig;
}

export function setPPCPGooglePaySession(ppcpGooglePaySession: PaymentsClient | null): void {
paypalState.ppcpGooglePaySession = ppcpGooglePaySession;
}

export function getPPCPGooglePaySession(): PaymentsClient | null {
return paypalState.ppcpGooglePaySession;
}

export function getPPCPGooglePaySessionChecked(): PaymentsClient {
if (!paypalState.ppcpGooglePaySession) {
throw new PaypalNullStateKeyError('Precondition violated: ppcpGooglePaySession is null');
}
return paypalState.ppcpGooglePaySession;
}


export function setPaypalGatewayPublicId(gatewayPublicId: string): void {
paypalState.gatewayPublicId = gatewayPublicId;
Expand All @@ -96,3 +147,14 @@ export function getPPCPAppleCredentialsChecked(): IExpressPayPaypalCommercePlatf
}
return paypalState.ppcpAppleCredentials;
}

export function setPPCPGoogleCredentials(credentials: IExpressPayPaypalCommercePlatform | null): void {
paypalState.ppcpGoogleCredentials = credentials;
}

export function getPPCPGoogleCredentialsChecked(): IExpressPayPaypalCommercePlatform {
if (!paypalState.ppcpGoogleCredentials) {
throw new PaypalNullStateKeyError('Precondition violated: ppcpGoogleCredentials is null');
}
return paypalState.ppcpGoogleCredentials;
}
2 changes: 1 addition & 1 deletion src/paypal/ppcp_buttons/initPpcpButtons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {loadScript, PayPalNamespace} from '@paypal/paypal-js';
import {getCurrency,getEnvironment,getJwtToken,getPublicOrderId,getShopIdentifier,IExpressPayPaypalCommercePlatformButton} from '@boldcommerce/checkout-frontend-library';

async function initPpcpSdkInternal(payment: IExpressPayPaypalCommercePlatformButton, /* istanbul ignore next */ fastlane = false): Promise<PayPalNamespace | null> {
let components = `buttons,applepay${fastlane ? ',fastlane' : ''}`;
let components = `buttons,applepay,googlepay${fastlane ? ',fastlane' : ''}`;
const {iso_code: currency} = getCurrency();
const merchantCountry = payment.merchant_country;
let buyerCountry = '';
Expand Down
40 changes: 40 additions & 0 deletions src/paypal/ppcp_google/createPPCPGoogle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
enableDisableSection, getPPCPGooglePayConfigChecked,
getPPCPGooglePaySession,
showPaymentMethodTypes,
ppcpOnClickGoogle
} from 'src';

export function createPPCPGoogle(): void {

const isMounted = !!document.getElementById('ppcp-apple-express-payment');
const paymentsClient = getPPCPGooglePaySession();
const {allowedPaymentMethods} = getPPCPGooglePayConfigChecked();

if (!isMounted) {
const ppcpGoogleDiv = document.createElement('div');
ppcpGoogleDiv.id = 'ppcp-google-express-payment';
ppcpGoogleDiv.className = 'ppcp-google-express-payment express-payment';
ppcpGoogleDiv.dataset.testid = 'ppcp-google-express-payment';

const button = paymentsClient?.createButton({
onClick: ppcpOnClickGoogle,
buttonType: 'short',
buttonSizeMode: 'fill',
allowedPaymentMethods: allowedPaymentMethods
}) as HTMLButtonElement;

button.className = 'ppcp-google-pay-button';
button.id = 'ppcp-google-pay-button';
button.dataset.testid = 'ppcp-google-pay-button';
ppcpGoogleDiv.appendChild(button);

const container = document.getElementById('express-payment-container');
if (!container) {
enableDisableSection( showPaymentMethodTypes.PPCP_GOOGLE, false);
return;
}
container.appendChild(ppcpGoogleDiv);
}
enableDisableSection( showPaymentMethodTypes.PPCP_GOOGLE, true);
}
27 changes: 27 additions & 0 deletions src/paypal/ppcp_google/formatGooglePayContactToCheckoutAddress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {IAddress} from '@boldcommerce/checkout-frontend-library';
import {getCountryName, getFirstAndLastName, getPhoneNumber, getProvinceDetails} from 'src';
import Address = google.payments.api.Address;

export function formatGooglePayContactToCheckoutAddress(address: Address | undefined, phoneNumberOverwrite = false): IAddress {
const {administrativeArea, countryCode, postalCode, locality, name, address1, address2, phoneNumber} = address ?? {};
const {firstName, lastName} = getFirstAndLastName(name);
const countryIso = countryCode ?? '';
const region = administrativeArea ?? '';
const {code: provinceCode, name: provinceName} = getProvinceDetails(countryIso, region);
const countryName = getCountryName(countryIso);

return {
'first_name': firstName,
'last_name': lastName,
'address_line_1': address1 ?? '',
'address_line_2': address2 ?? '',
'country': countryName,
'city': locality ?? '',
'province':provinceName,
'country_code': countryIso,
'province_code': provinceCode,
'postal_code': postalCode ?? '',
'business_name': '',
'phone_number': phoneNumber || (phoneNumberOverwrite ? getPhoneNumber(phoneNumber) : '')
};
}
25 changes: 25 additions & 0 deletions src/paypal/ppcp_google/getPPCPShippingOptionsGoogle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {getValueByCurrency} from 'src';
import {getCurrency, getShipping} from '@boldcommerce/checkout-frontend-library';
import ShippingOptionParameters = google.payments.api.ShippingOptionParameters;
import SelectionOption = google.payments.api.SelectionOption;

export function getPPCPShippingOptionsGoogle(): ShippingOptionParameters | undefined {
const {iso_code: currencyCode} = getCurrency();
const {available_shipping_lines: shippingLines, selected_shipping: selectedShipping} = getShipping();
const defaultSelectedOptionId = selectedShipping?.id;

if (!shippingLines || (Array.isArray(shippingLines) && shippingLines.length < 1)) {
return;
}

const shippingOptions = shippingLines.map(p => ({
id: p.id,
label: `${getValueByCurrency(p.amount, currencyCode)}: ${p.description} `,
description: ''
})) as Array<SelectionOption>;

return {
shippingOptions,
defaultSelectedOptionId
};
}
8 changes: 8 additions & 0 deletions src/paypal/ppcp_google/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export * from './createPPCPGoogle';
export * from './initPPCPGoogle';
export * from './ppcpOnClickGoogle';
export * from './ppcpOnLoadGoogle';
export * from './ppcpOnPaymentAuthorizedGoogle';
export * from './ppcpOnPaymentDataChangeGoogle';
export * from './formatGooglePayContactToCheckoutAddress';
export * from './getPPCPShippingOptionsGoogle';
32 changes: 32 additions & 0 deletions src/paypal/ppcp_google/initPPCPGoogle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {IExpressPayPaypalCommercePlatform} from '@boldcommerce/checkout-frontend-library';
import {loadScript} from '@paypal/paypal-js';
import {PayPalScriptOptions} from '@paypal/paypal-js/types/script-options';
import {
getPaypalScriptOptions,
hasPaypalNameSpaceGoogle,
loadJS,
paypalConstants,
setPaypalNameSpace,
setPPCPGoogleCredentials,
ppcpOnLoadGoogle
} from 'src';

export async function initPPCPGoogle(payment: IExpressPayPaypalCommercePlatform): Promise<void> {
setPPCPGoogleCredentials(payment);

if (!hasPaypalNameSpaceGoogle()) {
const components = payment.google_pay_enabled ? 'googlepay' : undefined;
const paypalScriptOptions: PayPalScriptOptions = getPaypalScriptOptions(payment.partner_id, payment.is_test, payment.merchant_id, components);

await loadJS(paypalConstants.GOOGLEPAY_JS);
const paypal = await loadScript(paypalScriptOptions);

setPaypalNameSpace(paypal);

if (paypal) {
ppcpOnLoadGoogle();
}
} else {
await loadJS(paypalConstants.GOOGLEPAY_JS, ppcpOnLoadGoogle);
}
}
45 changes: 45 additions & 0 deletions src/paypal/ppcp_google/ppcpOnClickGoogle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {getCurrency, getOrderInitialData} from '@boldcommerce/checkout-frontend-library';
import {
getPPCPGooglePayConfigChecked, getPPCPGooglePaySession,
} from 'src';
import {getTotals, getValueByCurrency} from 'src/utils';
import PaymentDataRequest = google.payments.api.PaymentDataRequest;

export function ppcpOnClickGoogle(): void {
const googlePayConfig = getPPCPGooglePayConfigChecked();
const {allowedPaymentMethods,merchantInfo, apiVersion, apiVersionMinor , countryCode} = googlePayConfig;

const {iso_code: currencyCode} = getCurrency();
const {totalAmountDue} = getTotals();
const {general_settings: {checkout_process: {phone_number_required: isPhoneRequired}}} = getOrderInitialData();
const {country_info: countryInfo} = getOrderInitialData();
const allowedShippingCountries = countryInfo.filter(c => c.valid_for_shipping);
const allowedCountryCodes = allowedShippingCountries.map(c => c.iso_code.toUpperCase());
const paymentMethod = allowedPaymentMethods[0];
paymentMethod.parameters.billingAddressRequired = true;
paymentMethod.parameters.billingAddressParameters = {format: 'FULL', phoneNumberRequired: isPhoneRequired};

const paymentRequest: PaymentDataRequest = {
transactionInfo: {
currencyCode: currencyCode,
countryCode: countryCode,
totalPrice: getValueByCurrency(totalAmountDue, currencyCode),
totalPriceStatus: 'ESTIMATED',
},
shippingAddressRequired: true,
emailRequired: true,
shippingAddressParameters: {
allowedCountryCodes: allowedCountryCodes,
phoneNumberRequired: isPhoneRequired,
},
merchantInfo: merchantInfo,
apiVersion: apiVersion,
apiVersionMinor: apiVersionMinor,
allowedPaymentMethods: allowedPaymentMethods,
shippingOptionRequired: true,
callbackIntents: ['SHIPPING_ADDRESS', 'SHIPPING_OPTION', 'PAYMENT_AUTHORIZATION'],
};

const paymentsClient = getPPCPGooglePaySession();
paymentsClient?.loadPaymentData(paymentRequest);
}
Loading
Loading