mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 10:55:00 +08:00
Update plan
This commit is contained in:
parent
53ab79e576
commit
72be73c5dc
4 changed files with 79 additions and 32 deletions
|
@ -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'] );
|
||||
|
|
|
@ -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>';
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue