CrowdyPartner Revenue Sync & Wallet Manager
PHP
Snippet Description
Automatically creates a Wallet CPT for every user, calculates their total, pending, and completed contributions, and keeps wallet balances synced with JetEngine user meta. Includes cron-based batch processing for existing users and real-time updates when wallet data changes.
<?php
/*
Plugin Name: Auto Create Wallets with JetEngine Meta Sync + Wallet Auto Sync
Description: Creates Wallet CPTs for all users, writes balances to JetEngine user meta, keeps them synced, and auto-syncs contributions from JetEngine CCT.
Version: 2.0
Author: Ezekiel Ozi Momoh
*/
if (!defined('ABSPATH')) exit;
// ---------------------------------------------------
// 1. Create wallet for new users
// ---------------------------------------------------
add_action('user_register', 'jetengine_create_wallet_for_user', 20, 1);
function jetengine_create_wallet_for_user($user_id) {
create_wallet_if_not_exists($user_id);
}
// ---------------------------------------------------
// 2. Batch-create wallets for existing users (hourly cron)
// ---------------------------------------------------
register_activation_hook(__FILE__, function() {
if (!wp_next_scheduled('jetengine_create_wallets_cron')) {
wp_schedule_event(time(), 'hourly', 'jetengine_create_wallets_cron');
}
if (!wp_next_scheduled('crowdy_wallet_sync_cron')) {
wp_schedule_event(time(), 'every_five_minutes', 'crowdy_wallet_sync_cron');
}
});
// Clear cron on plugin deactivation
register_deactivation_hook(__FILE__, function() {
wp_clear_scheduled_hook('jetengine_create_wallets_cron');
wp_clear_scheduled_hook('crowdy_wallet_sync_cron');
});
// Support a 5-minute cron schedule
add_filter('cron_schedules', function($schedules) {
$schedules['every_five_minutes'] = [
'interval' => 300,
'display' => __('Every 5 Minutes')
];
return $schedules;
});
// Cron hook for batch wallet creation
add_action('jetengine_create_wallets_cron', 'jetengine_create_wallets_for_existing_users_batch');
function jetengine_create_wallets_for_existing_users_batch() {
$offset = (int) get_transient('jetengine_wallets_batch_offset') ?: 0;
$batch_size = 50;
$users = get_users([
'number' => $batch_size,
'offset' => $offset,
'fields' => ['ID'],
]);
if (empty($users)) {
set_transient('jetengine_wallets_batch_done', 1, 0);
delete_transient('jetengine_wallets_batch_offset');
return;
}
foreach ($users as $user) {
create_wallet_if_not_exists($user->ID);
}
$offset += $batch_size;
set_transient('jetengine_wallets_batch_offset', $offset, HOUR_IN_SECONDS);
}
// ---------------------------------------------------
// 3. Helper function to create wallet
// ---------------------------------------------------
function create_wallet_if_not_exists($user_id) {
$existing = get_posts([
'post_type' => 'wallets',
'meta_key' => 'user_id',
'meta_value' => $user_id,
'post_status'=> 'any',
'numberposts'=> 1,
]);
if (!empty($existing)) return;
$user = get_userdata($user_id);
if (!$user) return;
$username = $user->display_name ?: $user->user_login;
$suffix = strtoupper(substr(md5(uniqid('', true)), 0, 4));
$wallet_id = wp_insert_post([
'post_type' => 'wallets',
'post_status' => 'publish',
'post_title' => $username . ' Wallet-' . $suffix,
]);
if (is_wp_error($wallet_id) || !$wallet_id) {
error_log('Failed to create wallet for user ' . $user_id);
return;
}
$wallet_meta = [
'user_id' => $user_id,
'available_balance' => 0.00,
'pending_balance' => 0.00,
'total_withdrawn' => 0.00,
'total_earned' => 0.00,
'created_at' => current_time('mysql'),
'updated_at' => current_time('mysql'),
];
foreach ($wallet_meta as $key => $value) {
update_post_meta($wallet_id, $key, $value);
}
update_user_meta($user_id, 'wallet_available_balance', 0);
update_user_meta($user_id, 'wallet_pending_balance', 0);
update_user_meta($user_id, 'wallet_total_withdrawn', 0);
update_user_meta($user_id, 'wallet_total_earned', 0);
}
// ---------------------------------------------------
// 4. Sync Wallet CPT meta to JetEngine user meta
// ---------------------------------------------------
add_action('save_post_wallets', 'sync_wallet_cpt_to_user_meta', 20, 2);
function sync_wallet_cpt_to_user_meta($post_id, $post) {
if ($post->post_status !== 'publish') return;
remove_action('save_post_wallets', 'sync_wallet_cpt_to_user_meta', 20, 2);
$user_id = get_post_meta($post_id, 'user_id', true);
if (!$user_id) {
add_action('save_post_wallets', 'sync_wallet_cpt_to_user_meta', 20, 2);
return;
}
$wallet_meta_keys = [
'available_balance' => 'wallet_available_balance',
'pending_balance' => 'wallet_pending_balance',
'total_withdrawn' => 'wallet_total_withdrawn',
'total_earned' => 'wallet_total_earned',
];
foreach ($wallet_meta_keys as $wallet_key => $user_meta_key) {
$value = floatval(get_post_meta($post_id, $wallet_key, true));
update_user_meta($user_id, $user_meta_key, $value);
}
add_action('save_post_wallets', 'sync_wallet_cpt_to_user_meta', 20, 2);
}
// ---------------------------------------------------
// 5. SHORTCODE: [wallet_balance type="available"]
// ---------------------------------------------------
add_shortcode('wallet_balance', function($atts){
$atts = shortcode_atts([
'type' => 'available_balance',
], $atts, 'wallet_balance');
$user_id = get_current_user_id();
if (!$user_id) return 'Please log in to view your balance.';
$meta_map = [
'available_balance' => 'wallet_available_balance',
'pending_balance' => 'wallet_pending_balance',
'total_withdrawn' => 'wallet_total_withdrawn',
'total_earned' => 'wallet_total_earned',
];
$key = $meta_map[$atts['type']] ?? null;
if (!$key) return '';
$value = floatval(get_user_meta($user_id, $key, true));
return '$' . number_format($value, 2);
});
// ---------------------------------------------------
// 6. MAIN WALLET SYNC ENGINE (CCT → Wallet)
// ---------------------------------------------------
add_action('crowdy_wallet_sync_cron', 'crowdy_sync_all_wallet_balances');
function crowdy_sync_all_wallet_balances() {
global $wpdb;
$table = $wpdb->prefix . "jet_cct_contributions";
// Get all authors who have contributions
$authors = $wpdb->get_col("
SELECT DISTINCT campaign_author_id
FROM $table
WHERE campaign_author_id IS NOT NULL
");
if (empty($authors)) return;
foreach ($authors as $author_id) {
// Ensure the wallet exists
create_wallet_if_not_exists($author_id);
// Get wallet ID
$wallet = get_posts([
'post_type' => 'wallets',
'meta_key' => 'user_id',
'meta_value' => $author_id,
'post_status'=> 'any',
'numberposts'=> 1,
]);
if (empty($wallet)) continue;
$wallet_id = $wallet[0]->ID;
// Query pending contributions
$pending = (float) $wpdb->get_var($wpdb->prepare("
SELECT SUM(contribution_amount)
FROM $table
WHERE campaign_author_id = %d
AND payment_status = 'pending'
", $author_id));
// Query completed contributions
$completed = (float) $wpdb->get_var($wpdb->prepare("
SELECT SUM(contribution_amount)
FROM $table
WHERE campaign_author_id = %d
AND payment_status = 'completed'
", $author_id));
$pending = $pending ?: 0;
$completed = $completed ?: 0;
$total = $pending + $completed;
// Update Wallet meta
update_post_meta($wallet_id, 'pending_balance', $pending);
update_post_meta($wallet_id, 'available_balance', $completed);
update_post_meta($wallet_id, 'total_earned', $total);
// Sync to user meta
update_user_meta($author_id, 'wallet_pending_balance', $pending);
update_user_meta($author_id, 'wallet_available_balance', $completed);
update_user_meta($author_id, 'wallet_total_earned', $total);
}
}
Usage Instructions
Usage Instructions
-
Paste the full code into WPCode Snippets as a PHP snippet.
-
Set the snippet to Run Everywhere.
-
Activate the snippet.
-
When activated, it will:
-
Automatically generate a Wallet custom post for every user who does not have one.
-
Sync earnings, pending, available balance, and total withdrawn based on JetEngine CCT “contributions”.
-
Keep Wallet CPT meta and JetEngine user meta updated in real time.
-
-
Existing users’ wallets will be created in safe batches using a scheduled hourly cron job.
No further configuration is required.