WooCommerce Subscriptions subscription helpers
Look up, cancel and reschedule WooCommerce Subscriptions subscriptions from Python, returning the raw WooCommerce Subscriptions subscription.
Plain helpers for the common WooCommerce Subscriptions subscription tasks. They read the business's WooCommerce Subscriptions connection with get_integration_credentials, call the WooCommerce Subscriptions REST API and return subscriptions as WooCommerce Subscriptions returns them; see the WooCommerce Subscriptions API reference for every field. Like the order helpers, they leave out the customer's IP address and browser, the order key and payment URL, and tracking and payment-gateway meta. They raise ValueError if WooCommerce Subscriptions isn't connected and requests.HTTPError if WooCommerce Subscriptions rejects the request.
| Helper | What it does |
|---|---|
woocommerce_get_subscription(context, subscription_id) | The subscription, or None. |
woocommerce_find_subscriptions(context, email=None, phone=None) | The subscriptions whose billing email is exactly email. |
woocommerce_cancel_subscription(context, subscription_id) | Sets the subscription to cancelled. |
woocommerce_next_charge_date(subscription) | The next renewal as a UTC datetime, or None. |
woocommerce_set_next_charge_date(context, subscription_id, when) | Moves the next renewal to when. |
Businesses moved off the built-in subscription actions get default actions with the built-in names (getSubscriptionById, getSubscriptionByEmail, cancelSubscription, skipSubscriptionMonths, ...) that call these helpers. They are ordinary Python actions you can read and change.
The full source is below. Copy it into your own action when you need something it doesn't do.
Sidebar widget and cancellation
woocommerce_subscription_widget(context, cancel_action="cancel_subscription") returns a ready-to-render subscription panel with confirmation buttons. Pair it with woocommerce_cancel_widget_subscription(context) in a widget-owned action. Setup, business scoping and shared source.
Source
from datetime import datetime, timezone
import requests
def woocommerce_get_subscription(context, subscription_id):
"""The WooCommerce Subscriptions subscription with this ID, or None."""
subscription_id = str(subscription_id).strip().lstrip("#")
if not subscription_id.isdigit():
return None
subscription = _woocommerce_get(_woocommerce_store(context), f"subscriptions/{subscription_id}")
# Subscriptions are orders: the same customer IP, order key and payment URL are left out.
return _woocommerce_clean_order(subscription) if subscription else None
def woocommerce_find_subscriptions(context, email=None, phone=None):
"""The customer's subscriptions with this billing email."""
if not email:
return []
email = email.strip().lower()
hits = _woocommerce_get(_woocommerce_store(context), "subscriptions", {"search": email}) or []
return [
_woocommerce_clean_order(s) for s in hits
if ((s.get("billing") or {}).get("email") or "").strip().lower() == email
]
def _woocommerce_update_subscription(context, subscription_id, changes):
store = _woocommerce_store(context)
response = requests.put(
f"https://{store['domain']}/wp-json/wc/v3/subscriptions/{subscription_id}",
auth=(store["consumerKey"], store["consumerSecret"]),
headers={"User-Agent": "octocom"},
json=changes,
timeout=20,
)
response.raise_for_status()
def woocommerce_cancel_subscription(context, subscription_id):
_woocommerce_update_subscription(context, subscription_id, {"status": "cancelled"})
def woocommerce_subscription_widget(context, cancel_action="cancel_subscription"):
"""Sidebar data for the current customer's WooCommerce subscriptions, with cancel buttons."""
_, email = _subscription_widget_identity(context)
items = []
for sub in woocommerce_find_subscriptions(context, email=email) if email else []:
lines = sub.get("line_items") or []
currency = sub.get("currency") or ""
date = woocommerce_next_charge_date(sub)
items.append(_subscription_widget_item(
context, sub["id"], (lines[0].get("name") if lines else None) or "Subscription",
sub.get("status"), {
"Total": _subscription_widget_value(sub.get("total"), currency),
"Next charge": date.strftime("%Y-%m-%d UTC") if date else None,
"Billing": _subscription_widget_value(sub.get("billing_interval"), sub.get("billing_period")),
}, [{"title": str(line.get("name") or "Product"), "fields": {
"Quantity": line.get("quantity"), "SKU": line.get("sku"),
"Total": _subscription_widget_value(line.get("total"), currency),
}} for line in lines], cancel_action,
))
return {"title": "Subscriptions", "items": items}
def woocommerce_cancel_widget_subscription(context):
"""Action for woocommerce_subscription_widget; validates the current customer before cancelling."""
return _subscription_widget_cancel(context, woocommerce_find_subscriptions, woocommerce_cancel_subscription)
def woocommerce_next_charge_date(subscription):
"""When the subscription next renews (UTC), or None."""
value = subscription.get("next_payment_date_gmt")
return datetime.fromisoformat(value.replace("Z", "")).replace(tzinfo=timezone.utc) if value else None
def woocommerce_set_next_charge_date(context, subscription_id, when):
_woocommerce_update_subscription(
context, subscription_id, {"next_payment_date_gmt": when.strftime("%Y-%m-%dT%H:%M:%S")}
)