mirror of
https://gh.wpcy.net/https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2026-04-30 04:42:19 +08:00
248 lines
5.8 KiB
TypeScript
248 lines
5.8 KiB
TypeScript
/**
|
|
* External dependencies
|
|
*/
|
|
import {
|
|
expect,
|
|
RequestUtils,
|
|
WooCommerceApi as WooCommerceApiBase,
|
|
} from '@inpsyde/playwright-utils/build';
|
|
/**
|
|
* Internal dependencies
|
|
*/
|
|
import { Pcp } from '../resources';
|
|
import urls from './urls';
|
|
import { generateRandomString } from './helpers';
|
|
|
|
/**
|
|
* Class for REST API interactions with PCP Settings.
|
|
*/
|
|
export class PcpApi extends WooCommerceApiBase {
|
|
requestUtils: RequestUtils;
|
|
|
|
constructor( { request, requestUtils } ) {
|
|
super( { request } );
|
|
this.requestUtils = requestUtils;
|
|
}
|
|
|
|
/**
|
|
* Connects merchant via REST API.
|
|
*
|
|
* @param clientId PayPal merchant's client ID
|
|
* @param clientSecret PayPal merchant's client Isecret
|
|
* @param onboardingOptions
|
|
*/
|
|
connectMerchant = async (
|
|
clientId: string,
|
|
clientSecret: string,
|
|
onboardingOptions: Pcp.Api.OnboardingOptions = {
|
|
isCasualSeller: false,
|
|
products: [ 'physical', 'virtual' ],
|
|
}
|
|
) => {
|
|
// Preset onboarding options
|
|
await this.wcRequest( 'post', 'wc_paypal/onboarding', {
|
|
...onboardingOptions,
|
|
gatewaysRefreshed: true,
|
|
gatewaysSynced: true,
|
|
_locale: 'user',
|
|
} );
|
|
// Merchant connection request
|
|
const response = await this.wcRequest(
|
|
'post',
|
|
'wc_paypal/authenticate/direct',
|
|
{
|
|
clientId,
|
|
clientSecret,
|
|
useSandbox: onboardingOptions?.useSandbox || true,
|
|
_locale: 'user',
|
|
}
|
|
);
|
|
await this.updatePcpSettings( {
|
|
invoicePrefix: `${ generateRandomString( 8 ) }-`,
|
|
} );
|
|
return response;
|
|
};
|
|
|
|
/**
|
|
* Disconnects merchant via REST API with optional DB reset parameter.
|
|
*
|
|
* @param reset
|
|
*/
|
|
disconnectMerchant = async ( reset: boolean = false ) => {
|
|
const response = await this.wcRequest(
|
|
'post',
|
|
'wc_paypal/authenticate/disconnect',
|
|
{
|
|
reset,
|
|
_locale: 'user',
|
|
}
|
|
);
|
|
return response;
|
|
};
|
|
|
|
/**
|
|
* Disconnects merchant with DB reset via REST API.
|
|
*/
|
|
resetDb = () => this.disconnectMerchant( true );
|
|
|
|
/**
|
|
* Updates Payment Methods tab via REST API.
|
|
*
|
|
* @example of data (all params are optional):
|
|
* {
|
|
* fastlaneCardholderName: false,
|
|
* fastlaneDisplayWatermark: true,
|
|
* paypalShowLogo: false,
|
|
* threeDSecure: 'always-3d-secure',
|
|
* "ppcp-gateway": { enabled: true },
|
|
* "pay-later": { enabled: true },
|
|
* }
|
|
*
|
|
* @param data
|
|
*/
|
|
updatePcpPaymentMethods = async ( data: Pcp.Api.PaymentMethods ) => {
|
|
const response = await this.wcRequest( 'post', `wc_paypal/payment`, {
|
|
...data,
|
|
_locale: 'user',
|
|
} );
|
|
return response;
|
|
};
|
|
|
|
/**
|
|
* Updates Settings tab via REST API.
|
|
*
|
|
* @param data
|
|
*/
|
|
updatePcpSettings = async ( data: Pcp.Api.Settings ) => {
|
|
const response = await this.wcRequest( 'post', `wc_paypal/settings`, {
|
|
...data,
|
|
_locale: 'user',
|
|
} );
|
|
return response;
|
|
};
|
|
|
|
/**
|
|
* Triggers Vaulting Subscription Renewal process
|
|
*
|
|
* @param subscriptionId
|
|
*/
|
|
triggerVaultingSubscriptionRenewal = async ( subscriptionId: number ) => {
|
|
const url = urls.admin.wooCommerce.subscription.edit + subscriptionId;
|
|
const wpnonce = await this.requestUtils.getPageNonce( url );
|
|
const formData = {
|
|
_wpnonce: wpnonce,
|
|
post_ID: subscriptionId,
|
|
action: 'edit_order',
|
|
wc_order_action: 'wcs_process_renewal',
|
|
};
|
|
const response = await this.requestUtils.submitPageForm(
|
|
url,
|
|
formData
|
|
);
|
|
return response.ok();
|
|
};
|
|
|
|
isPayPalSubscription( subscription: WooCommerce.Subscription ): boolean {
|
|
return !! subscription?.meta_data?.some(
|
|
( meta ) => meta.key === 'ppcp_subscription'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get's renewal order IDs
|
|
* Utilizes the retry mechanism because after the renewal there appeared to be a delay
|
|
*
|
|
* @param subscriptionId
|
|
*/
|
|
getSubscriptionRenewalOrderIds = async (
|
|
subscriptionId: number
|
|
): Promise< number[] > => {
|
|
let subscription = await this.getSubscription( subscriptionId );
|
|
|
|
if ( ! subscription ) {
|
|
console.error( `Subscription #${ subscriptionId } was not found.` );
|
|
return [];
|
|
}
|
|
|
|
const MAX_RETRY_COUNT = 10;
|
|
const RETRY_INTERVAL_MS = 1000;
|
|
|
|
let retryCount = 0;
|
|
let subscriptionMeta;
|
|
|
|
do {
|
|
subscriptionMeta = subscription.meta_data.find(
|
|
( meta ) => meta.key === '_subscription_renewal_order_ids_cache'
|
|
);
|
|
|
|
if ( subscriptionMeta?.value?.length ) {
|
|
return subscriptionMeta.value;
|
|
}
|
|
|
|
// Add a delay before making the getSubscription call
|
|
await new Promise( ( resolve ) =>
|
|
setTimeout( resolve, RETRY_INTERVAL_MS )
|
|
);
|
|
|
|
subscription = await this.getSubscription( subscriptionId );
|
|
retryCount++;
|
|
} while ( retryCount < MAX_RETRY_COUNT );
|
|
|
|
console.error(
|
|
`_subscription_renewal_order_ids_cache was not found in ${ MAX_RETRY_COUNT } sec.`
|
|
);
|
|
return [];
|
|
};
|
|
|
|
getPayPalSubscriptionBillingId = async ( subscriptionId: number ) => {
|
|
const subscription = await this.getSubscription( subscriptionId );
|
|
|
|
if ( ! subscription ) {
|
|
console.error( `Subscription #${ subscriptionId } was not found.` );
|
|
return 0;
|
|
}
|
|
|
|
const subscriptionMeta = subscription.meta_data.find(
|
|
( meta ) => meta.key === 'ppcp_subscription'
|
|
);
|
|
|
|
return subscriptionMeta.value;
|
|
};
|
|
|
|
/**
|
|
* Triggers PayPal Subscription Renewal process
|
|
*
|
|
* @param subscriptionId
|
|
*/
|
|
triggerPayPalSubscriptionRenewal = async ( subscriptionId: number ) => {
|
|
const billingId = await this.getPayPalSubscriptionBillingId(
|
|
subscriptionId
|
|
);
|
|
|
|
const data = {
|
|
id: 'NOT-IMPORTANT',
|
|
event_type: 'PAYMENT.SALE.COMPLETED',
|
|
resource: {
|
|
billing_agreement_id: billingId,
|
|
id: 'NOT-IMPORTANT',
|
|
},
|
|
};
|
|
|
|
const response = await this.requestUtils.request.post(
|
|
urls.payPalWebhook,
|
|
{ data }
|
|
);
|
|
await expect( response.ok() ).toBeTruthy();
|
|
console.log( await response.json() );
|
|
|
|
// 2nd request to trigger renewal (stopped working from v3.2.0)
|
|
const response2 = await this.requestUtils.request.post(
|
|
urls.payPalWebhook,
|
|
{ data }
|
|
);
|
|
await expect( response2.ok() ).toBeTruthy();
|
|
console.log( await response2.json() );
|
|
|
|
return response.ok() && response2.ok();
|
|
};
|
|
}
|