Update plan

This commit is contained in:
Emili Castells Guasch 2023-03-28 12:38:43 +02:00
parent 53ab79e576
commit 72be73c5dc
4 changed files with 79 additions and 32 deletions

View file

@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Entity\BillingCycle;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Plan;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
@ -130,38 +131,46 @@ class BillingPlans {
return $this->plan_factory->from_paypal_response($json);
}
/**
* Updates a subscription plan.
*
* @param string $billing_plan_id Billing plan ID.
* @param array $billing_cycles Billing cycles.
*
* @return void
*
* @throws RuntimeException If the request fails.
* @throws PayPalApiException If the request fails.
*/
public function update_pricing(string $billing_plan_id, array $billing_cycles):void {
public function plan(string $id): Plan {
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/billing/plans/' . $id;
$args = array(
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'Prefer' => 'return=representation'
),
);
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) || ! is_array( $response ) ) {
throw new RuntimeException( 'Not able to get product.' );
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
throw new PayPalApiException(
$json,
$status_code
);
}
return $this->plan_factory->from_paypal_response($json);
}
public function update_pricing(string $id, BillingCycle $billing_cycle): void {
$data = array(
"pricing_schemes" => array(
(object)array(
"billing_cycle_sequence" => 1,
"pricing_scheme" => array(
"fixed_price" => array(
"value" => $billing_cycles['pricing_scheme']['fixed_price']['value'],
"currency_code" => "USD"
),
"roll_out_strategy" => array(
"effective_time" => "2022-11-01T00:00:00Z",
"process_change_from" => "NEXT_PAYMENT"
),
),
"pricing_scheme" => $billing_cycle->pricing_scheme(),
),
),
);
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/billing/plans/' . $billing_plan_id . '/update-pricing-schemes';
$url = trailingslashit( $this->host ) . 'v1/billing/plans/' . $id . '/update-pricing-schemes';
$args = array(
'method' => 'POST',
'headers' => array(
@ -173,7 +182,7 @@ class BillingPlans {
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) || ! is_array( $response ) ) {
throw new RuntimeException( 'Not able to create plan.' );
throw new RuntimeException( 'Could not update pricing.' );
}
$json = json_decode( $response['body'] );

View file

@ -169,7 +169,7 @@ class SubscriptionModule implements ModuleInterface {
if ( $product->meta_exists( 'ppcp_subscription_product' ) && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
$subscriptions_api_handler->update_product($product);
$subscriptions_api_handler->update_plan();
$subscriptions_api_handler->update_plan($product);
return;
}
@ -264,7 +264,7 @@ class SubscriptionModule implements ModuleInterface {
$subscription_plan_name = $product->get_meta('_ppcp_subscription_plan_name');
echo '<div class="options_group subscription_pricing show_if_subscription hidden">';
echo '<p class="form-field"><label for="_ppcp_enable_subscription_product">Connect to PayPal</label><input type="checkbox" name="_ppcp_enable_subscription_product" value="yes" '.checked($enable_subscription_product, 'yes', false).'/><span class="description">Connect Product to PayPal Subscriptions Plan</span></p>';
echo '<p class="form-field"><label for="_ppcp_enable_subscription_product">Connect to PayPal</label><input type="checkbox" id="ppcp_enable_subscription_product" name="_ppcp_enable_subscription_product" value="yes" '.checked($enable_subscription_product, 'yes', false).'/><span class="description">Connect Product to PayPal Subscriptions Plan</span></p>';
$subscription_product = $product->get_meta( 'ppcp_subscription_product' );
$subscription_plan = $product->get_meta( 'ppcp_subscription_plan' );
@ -272,7 +272,7 @@ class SubscriptionModule implements ModuleInterface {
echo '<p class="form-field"><label>Product</label><a href="'.esc_url('https://www.sandbox.paypal.com/billing/plans/products/' . $subscription_product['id']).'" target="_blank">'.esc_attr($subscription_product['id']).'</a></p>';
echo '<p class="form-field"><label>Plan</label><a href="'.esc_url('https://www.sandbox.paypal.com/billing/plans/' . $subscription_plan['id']).'" target="_blank">'.esc_attr($subscription_plan['id']).'</a></p>';
} else {
echo '<p class="form-field"><label for="_ppcp_subscription_plan_name">Plan Name</label><input type="text" class="short" name="_ppcp_subscription_plan_name" value="'.esc_attr($subscription_plan_name).'"></p>';
echo '<p class="form-field"><label for="_ppcp_subscription_plan_name">Plan Name</label><input type="text" class="short" id="ppcp_subscription_plan_name" name="_ppcp_subscription_plan_name" value="'.esc_attr($subscription_plan_name).'"></p>';
}
echo '</div>';
}

View file

@ -140,7 +140,27 @@ class SubscriptionsApiHandler {
}
}
public function update_plan() {
public function update_plan(WC_Product $product) {
try {
$subscription_plan_id = $product->get_meta('ppcp_subscription_plan')['id'] ?? '';
if ($subscription_plan_id) {
$subscription_plan = $this->billing_plans_endpoint->plan($subscription_plan_id);
$price = $subscription_plan->billing_cycles()[0]->pricing_scheme()['fixed_price']['value'] ?? '';
if($price && round($price, 2) !== round($product->get_price(), 2)) {
$this->billing_plans_endpoint->update_pricing(
$subscription_plan_id,
$this->billing_cycle_factory->from_wc_product($product)
);
}
}
} catch (RuntimeException $exception) {
$error = $exception->getMessage();
if ( is_a( $exception, PayPalApiException::class ) ) {
$error = $exception->get_details( $error );
}
$this->logger->error( 'Could not update subscription plan on PayPal. ' . $error );
}
}
}

View file

@ -7,7 +7,8 @@ const {
} = process.env;
test.describe.serial('Subscriptions Merchant', () => {
const title = (Math.random() + 1).toString(36).substring(7);
const productTitle = (Math.random() + 1).toString(36).substring(7);
const planName = (Math.random() + 1).toString(36).substring(7);
let product_id = '';
let plan_id = '';
@ -15,9 +16,11 @@ test.describe.serial('Subscriptions Merchant', () => {
await loginAsAdmin(page);
await page.goto('/wp-admin/post-new.php?post_type=product');
await page.fill('#title', title);
await page.fill('#title', productTitle);
await page.selectOption('select#product-type', 'subscription');
await page.fill('#_subscription_price', '10');
await page.locator('#ppcp_enable_subscription_product').check();
await page.fill('#ppcp_subscription_plan_name', planName);
await Promise.all([
page.waitForNavigation(),
@ -37,7 +40,7 @@ test.describe.serial('Subscriptions Merchant', () => {
const productList = await products.json();
const product = productList.products.find((p) => {
return p.name === title;
return p.name === productTitle;
});
await expect(product.id).toBeTruthy;
@ -64,8 +67,9 @@ test.describe.serial('Subscriptions Merchant', () => {
await loginAsAdmin(page);
await page.goto('/wp-admin/edit.php?post_type=product');
await page.getByRole('link', { name: title, exact: true }).click();
await page.getByRole('link', { name: productTitle, exact: true }).click();
await page.fill('#title', `Updated ${productTitle}`);
await page.fill('#_subscription_price', '20');
await Promise.all([
@ -76,6 +80,20 @@ test.describe.serial('Subscriptions Merchant', () => {
const message = await page.locator('.notice-success');
await expect(message).toContainText('Product updated.');
const products = await request.get('https://api.sandbox.paypal.com/v1/catalogs/products?page_size=100&page=1&total_required=true', {
headers: {
'Authorization': AUTHORIZATION,
'Content-Type': 'application/json'
}
});
expect(products.ok()).toBeTruthy();
const productList = await products.json();
const product = productList.products.find((p) => {
return p.name === `Updated ${productTitle}`;
});
await expect(product.id).toBeTruthy;
const plan = await request.get(`https://api.sandbox.paypal.com/v1/billing/plans/${plan_id}`, {
headers: {
'Authorization': AUTHORIZATION,