comment_ID; } function get_comment_link(WP_Comment $comment): string { return 'https://site.test/post/#comment-' . $comment->comment_ID; } $GLOBALS['wpdb'] = new class { public function prepare(string $query, int $id): string { return str_replace('%d', (string) $id, $query); } public function get_var(string $query): string { return str_contains($query, 'wp_revenue') ? 'O-3' : 'O-4'; } }; require_once dirname(__DIR__, 2) . '/src/Ledger/AssetType.php'; require_once dirname(__DIR__, 2) . '/src/Ledger/AssetAmount.php'; require_once dirname(__DIR__, 2) . '/src/Ledger/LedgerCommand.php'; require_once dirname(__DIR__, 2) . '/src/Ledger/LedgerResult.php'; require_once dirname(__DIR__, 2) . '/src/Payment/Withdrawal.php'; require_once dirname(__DIR__, 2) . '/src/Payment/WeChatNotifyEvents.php'; } namespace Jio\Core { final class DBMigrator { public static function table(string $name): string { return 'wp_' . $name; } } } namespace Jio\Payment { final class RecordingWechatSender { use WeChatNotifyEvents; public array $messages = []; public function init(): void { $this->register_event_hooks(); } public function send_event(int $user_id, string $type, array $values, string $url = ''): bool { $this->messages[] = compact('user_id', 'type', 'values', 'url'); return true; } } } namespace { $check = static function (bool $condition, string $message): void { if (!$condition) { fwrite(STDERR, $message . "\n"); exit(1); } }; $sender = new \Jio\Payment\RecordingWechatSender(); $sender->init(); $sender->init(); $check(count($GLOBALS['wechat_event_hooks']['jio_order_paid'] ?? []) === 1, 'order hook registered twice'); $check(count($GLOBALS['wechat_event_hooks']['jio_wechat_comment_parent'] ?? []) === 1, 'comment hook registered twice'); do_action('jio_order_paid', 'O-1', [ 'user_id' => 1, 'product_id' => 9, 'amount' => '12.50', 'currency' => 'CNY', 'paid_at' => '2026-11-09 09:00:00', ]); $check(count($sender->messages) === 3, 'order should notify buyer and two admins once'); $check($sender->messages[0]['type'] === 'payment_order', 'buyer order type'); $check($sender->messages[0]['values'] === [ 'name' => 'Product 9', 'price' => '12.50 CNY', 'time' => '2026-11-09 09:00:00', 'num' => 'O-1', ], 'buyer order fields'); $check($sender->messages[0]['url'] === 'https://site.test/user/orders/', 'buyer order URL'); $check($sender->messages[1]['type'] === 'payment_order_admin', 'admin order type'); $check($sender->messages[1]['values']['user'] === 'User 1', 'admin buyer field'); $check($sender->messages[1]['url'] === 'https://site.test/wp-admin/admin.php?page=jio_orders&order=O-1', 'admin order URL'); $sender->messages = []; $row = ['gross_amount' => '20.00', 'amount' => '19.00', 'created_at' => '2026-11-08 08:00:00']; do_action('jio_withdrawal_submitted', 1, $row); $check(count($sender->messages) === 2, 'withdraw request should notify admins'); $check($sender->messages[0]['type'] === 'apply_withdraw_admin', 'withdraw request type'); $check($sender->messages[0]['values']['price'] === '20.00 CNY', 'withdraw request amount'); $check(str_contains($sender->messages[0]['url'], 'page=jio_withdraw'), 'withdraw admin URL'); $sender->messages = []; do_action('jio_withdrawal_status_changed', 1, $row, \Jio\Payment\Withdrawal::STATUS_PROCESSING, ''); $check($sender->messages === [], 'intermediate withdrawal status should not send'); do_action('jio_withdrawal_status_changed', 1, $row, \Jio\Payment\Withdrawal::STATUS_COMPLETED, ''); $check(count($sender->messages) === 1, 'processed withdrawal should send once'); $check($sender->messages[0]['type'] === 'withdraw_process', 'processed withdrawal type'); $check($sender->messages[0]['values']['service_price'] === '1.00 CNY', 'withdraw fee field'); $check($sender->messages[0]['values']['received_price'] === '19.00 CNY', 'withdraw received field'); $sender->messages = []; $comment = new WP_Comment(11, 9, '2026-11-10 09:00:00', 'Hello'); do_action('jio_wechat_comment_postauthor', 1, $comment); do_action('jio_wechat_comment_parent', 2, $comment); $check(count($sender->messages) === 2, 'comment should produce two distinct event types'); $check($sender->messages[0]['type'] === 'comment_to_postauthor', 'post author comment type'); $check($sender->messages[0]['values']['post'] === 'Product 9', 'post title field'); $check($sender->messages[1]['type'] === 'comment_to_parent', 'parent comment type'); $check($sender->messages[1]['values']['content'] === 'Hello', 'reply content field'); $check($sender->messages[1]['url'] === 'https://site.test/post/#comment-11', 'comment URL'); $sender->messages = []; $command = new \Jio\Ledger\LedgerCommand('income-1', 'creator_income', [], 'revenue', '12', 0, ['order_number' => 'O-2']); $entry = ['user_id' => 1, 'asset' => 'balance', 'delta_minor' => 250, 'entry_type' => 'credit']; do_action('jio_asset_transaction_committed', new \Jio\Ledger\LedgerResult(1, true, [$entry], []), $command); $check($sender->messages === [], 'replayed ledger result should not send'); do_action('jio_asset_transaction_committed', new \Jio\Ledger\LedgerResult(2, false, [$entry], []), $command); $check(count($sender->messages) === 1, 'committed income should send once'); $check($sender->messages[0]['type'] === 'payment_order_to_income', 'income type'); $check($sender->messages[0]['values']['price'] === '2.50 CNY', 'income amount'); $check($sender->messages[0]['values']['num'] === 'O-2', 'income order number'); $sender->messages = []; $command = new \Jio\Ledger\LedgerCommand('income-2', 'creator_income', [], 'revenue', '12', 0, ['order_number' => '12']); do_action('jio_asset_transaction_committed', new \Jio\Ledger\LedgerResult(3, false, [$entry], []), $command); $check(count($sender->messages) === 1 && $sender->messages[0]['values']['num'] === 'O-3', 'ledger record id resolved to order number'); echo "WeChat events harness passed\n"; }