Subscription Initialization Process
Overview
When a subscription payment is completed, the system asynchronously initializes several key attributes:
- Copies owed (number of issues the subscriber is entitled to)
- Deferred amount (revenue to be recognized over the subscription term)
- Issue shipping basis (how issues are determined for shipping)
- Shipping information (address and soundex for duplicate detection)
Initialization Flow
1. Payment Completion Hook
The process begins when a payment is completed for a new subscription:
// Hook into payment completion
add_action('woocommerce_subscription_payment_complete', 'subscription_payment_complete', 30, 1);
2. Asynchronous Action Scheduling
The controller schedules an asynchronous action to handle the initialization:
public function subscription_payment_complete($subscription) {
// Only process original orders, not renewals
if ($subscription->get_payment_count() > 1 || false === $subscription->get_parent()) {
return;
}
// Schedule async action with 20 second delay
as_schedule_single_action(
time() + 20,
'jc_new_subscription_payment_complete_async',
['subscription_id' => $subscription->get_id()],
'jc_subscriptions'
);
}
3. Hook Registration
The async action handler is registered in the plugin initialization:
// Register the async action handler
$this->loader->add_action(
'jc_new_subscription_payment_complete_async',
$subscription_controller,
'new_subscription_payment_complete',
10,
1
);
4. Copies Owed Calculation
The number of copies owed is calculated based on:
- The subscription term length
- Any existing copies owed
- The issues per term setting
// Increment copies owed by issues per term
$tsj_subscription->set_copies_owed(
$tsj_subscription->get_copies_owed() +
$tsj_subscription->get_issues_per_term()
);
5. Deferred Amount Assignment
The deferred amount is set based on:
- The parent order’s total
- Any existing deferred amount
$new_deferred_amount = $last_order->get_total();
$tsj_subscription->set_deferred_amount(
$tsj_subscription->get_deferred_amount() +
$new_deferred_amount
);
6. Post-Initialization Tasks
After saving the subscription, additional async actions are scheduled:
// Save the subscription
$tsj_subscription->save();
// Create detailed notes
$notes = "SKU: " . $tsj_subscription->get_sku() . "<br/>";
$notes .= "expiry issue: " . get_the_title($tsj_subscription->get_expiry_issue_id()) . "<br/>";
$notes .= "copies owed: " . $tsj_subscription->get_copies_owed() . "<br/>";
$notes .= "deferred amount: " . $tsj_subscription->get_deferred_amount();
// Add notes to the subscription
$wc_subscription->add_order_note($notes);
// Schedule post-initialization tasks
as_enqueue_async_action(
'journal_subscription_created',
[
'tsj_subscription' => $tsj_subscription->get_id(),
'notes' => $notes
],
'jc_subscriptions'
);
Data Storage
The subscription data is stored in a custom table jc_subscriptions
with the following relevant fields:
CREATE TABLE {$wpdb->prefix}jc_subscriptions (
subscription_id BIGINT UNSIGNED NOT NULL,
copies_owed INT NOT NULL DEFAULT 0,
deferred_amount DECIMAL(10,2) NOT NULL DEFAULT 0.00,
-- other fields...
);
Error Handling and Validation
The system includes several safeguards:
- Nonce verification for admin operations
- Input validation for numeric values
- Proper rounding of monetary amounts
- Error logging for failed operations
- Validation of subscription status before processing
Best Practices
- Data Consistency
- Always validate input before saving
- Use proper data types for numeric values
- Round monetary amounts to 2 decimal places
- Handle existing values when incrementing
- Performance
- Use asynchronous processing for non-critical tasks
- Batch operations where possible
- Implement proper indexing on database tables
- Delay initialization to avoid payment processing conflicts
- Monitoring
- Log initialization events
- Track deferred amount changes
- Monitor copies owed adjustments
- Record detailed notes for audit purposes
- Security
- Validate all user input
- Implement proper access controls
- Use WordPress nonces for form submissions
- Verify subscription ownership and status