我有一个带有 MemberPress 插件的 WordPress 网站,我的订阅已连接到 Stripe 进行付款。不幸的是,MemberPress 没有内置选项来批量更新订阅价格,而且 Stripe 的仪表板似乎也没有提供本地方法来执行此操作。
我需要将 Stripe 中的大约 5,000 个活跃订阅更新为新价格。我编写了一个在 Stripe 测试模式下成功运行的 PHP 脚本,但我不确定以下内容:
您能看一下我的代码并提供任何反馈或建议吗?我们将非常感谢您的帮助!
这是带有注释的脚本:
<?php
/*
This script is designed to update all Stripe subscriptions tied to a **specific price ID**.
It retrieves all subscriptions that are linked to an old price and updates them to a new price,
but only if both prices belong to the same product.
The update process is triggered by a URL parameter in the WordPress admin interface.
Steps:
1. Retrieve all subscriptions associated with the old price ID.
2. Verify that the old and new prices belong to the same product.
3. If they do, update those subscriptions to the new price.
4. Trigger the update via a URL parameter in the admin area.
*/
// Function to get the product ID for a specific price ID
function get_product_id_for_price($price_id, $api_key) {
// Prepare cURL request to retrieve the price details
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.stripe.com/v1/prices/$price_id");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $api_key . ":");
// Execute the cURL request
$response = curl_exec($ch);
curl_close($ch);
// Decode the response to get the price details
$price_details = json_decode($response, true);
// Return the product ID if the price exists, otherwise return null
return isset($price_details['product']) ? $price_details['product'] : null;
}
// Function to get all subscriptions for a specific price ID
// This retrieves all subscriptions tied to a given price, supporting pagination if needed.
function get_all_subscriptions_for_price($price_id, $api_key) {
$subscriptions = [];
$has_more = true;
$starting_after = null;
// Loop through all pages of subscriptions until all are retrieved
while ($has_more) {
// Build the request URL, and include pagination if necessary
$ch = curl_init();
$url = "https://api.stripe.com/v1/subscriptions?price=$price_id&limit=100";
if ($starting_after) {
$url .= "&starting_after=$starting_after";
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $api_key . ":");
// Execute the API request and store the result
$response = curl_exec($ch);
curl_close($ch);
// Decode the JSON response into an array
$result = json_decode($response, true);
// If subscriptions are found, merge them with the existing list
if (isset($result['data'])) {
$subscriptions = array_merge($subscriptions, $result['data']);
$has_more = $result['has_more'];
$starting_after = end($result['data'])['id'];
} else {
// No more pages of subscriptions
$has_more = false;
}
}
return $subscriptions;
}
// Function to update all retrieved subscriptions to a new price
// This function takes an array of subscriptions and updates them to a new price ID.
function update_subscriptions_with_new_price($subscriptions, $new_price_id, $api_key) {
foreach ($subscriptions as $subscription) {
$subscription_id = $subscription['id'];
$subscription_item_id = $subscription['items']['data'][0]['id'];
// Prepare cURL request to update the subscription with the new price
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.stripe.com/v1/subscriptions/$subscription_id");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $api_key . ":");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'items[0][id]' => $subscription_item_id,
'items[0][price]' => $new_price_id,
]));
// Execute the cURL request
$response = curl_exec($ch);
curl_close($ch);
// Decode the response and check for any errors
$update_result = json_decode($response, true);
if (isset($update_result['error'])) {
echo "Error updating subscription ID $subscription_id: " . $update_result['error']['message'];
} else {
echo "Subscription ID $subscription_id updated successfully.\n";
}
}
}
// Function to update subscriptions for a specific price ID
// This retrieves all subscriptions linked to the old price and updates them to a new price if both prices belong to the same product.
function update_specific_subscriptions_for_price($product_id, $old_price_id, $new_price_id) {
// Your Stripe secret API key to authenticate API requests
$api_key = 'sk_test_xxxxxxxxxxxx'; // Stripe secret key
// Step 1: Get the product IDs for the old and new prices
$old_price_product_id = get_product_id_for_price($old_price_id, $api_key);
$new_price_product_id = get_product_id_for_price($new_price_id, $api_key);
// Step 2: Check if both prices belong to the specified product
if ($old_price_product_id === $product_id && $new_price_product_id === $product_id) {
echo "Both prices belong to the specified product. Proceeding with subscription updates.\n";
// Step 3: Get all subscriptions tied to the old price ID
$subscriptions = get_all_subscriptions_for_price($old_price_id, $api_key);
// Step 4: If there are subscriptions, update them to the new price ID
if (!empty($subscriptions)) {
update_subscriptions_with_new_price($subscriptions, $new_price_id, $api_key);
} else {
echo "No subscriptions found for Price ID: $old_price_id\n";
}
} else {
// Prices do not belong to the same product or specified product, do not proceed
echo "Error: One or both of the price IDs do not belong to the specified product. No updates will be made.\n";
}
}
// Example usage: Admin function to trigger subscription updates via a URL parameter
add_action('admin_init', function() {
// The Product ID that both prices must belong to
$product_id = 'prod_xxxxxxxxx'; // The actual product ID
// The old Price ID that you want to update
$old_price_id = 'price_xxxxxxxxx'; // The actual old price ID from Stripe
// The new Price ID to which subscriptions should be updated
$new_price_id = 'price_xxxxxxxxxx'; // The new price ID
// Check if the update process is triggered by the URL parameter
if (isset($_GET['trigger_subscription_update']) && $_GET['trigger_subscription_update'] === 'true') {
// Run the function to update subscriptions tied to the old price ID
update_specific_subscriptions_for_price($product_id, $old_price_id, $new_price_id);
}
});
?>
目前公共 API 中没有批量订阅更新功能,因此按照您编写的脚本编写的脚本是实现此功能的方法。
虽然我没有详细审查您的代码,但这种方法在大多数情况下应该有效。需要记住的是 API 速率限制,并确保您的请求速度保持在这些限制以下(也为您的正常操作留出空间)并优雅地处理任何 429 响应以重试。