fix(payment): honor schema defaults for balance recharge and fix withdrawal warning

Fixes two issues:

1. **Balance recharge disabled on fresh install**: The `pay_balance_s`
   setting has `default: true` in SchemaPayment but was treated as
   disabled when the key was absent from the database. This meant users
   had to toggle it off and back on to activate the feature.

   Fixed by using `!isset() || !empty()` pattern to honor the schema
   default when the key is missing.

2. **PHP Warning in withdrawal settings**: `get_withdrawal_settings()`
   passed `$s['affiliate_withdrawal_reset_time']` directly to
   `preg_match()` without extracting it first, causing "Undefined
   array key" warnings when the option was unset.

   Fixed by extracting to `$reset_time_raw` before the regex check.

Changed:
- `PaymentRuntime::get_payment_recharge_settings()`: enabled defaults to true
- `PaymentRuntime::get_payment_gateway_settings()`: balance_enabled defaults to true
- `PaymentRuntime::is_gateway_enabled('balance')`: defaults to true
- `PaymentRuntime::get_withdrawal_settings()`: no longer warns on missing key

Added test script `tools/test-payment-runtime-defaults.php` to verify
the fix works with empty settings (fresh install).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Fable 5 committed 2026-11-02 22:33:18 +08:00
1 parent 030baa511e
commit 1549d5b25d
2 files changed
+106 -5

No files matched your search

+6 -5
View File
@@ -88,7 +88,7 @@ class PaymentRuntime {
$desc = sanitize_textarea_field((string) ($settings['pay_balance_desc'] ?? ''));
return [
'enabled' => !empty($settings['pay_balance_s']),
'enabled' => !isset($settings['pay_balance_s']) || !empty($settings['pay_balance_s']),
'withdraw_enabled' => !empty($settings['pay_balance_withdraw_s']),
'desc' => $desc,
'packages_raw' => $packages,
@@ -377,7 +377,7 @@ class PaymentRuntime {
}
$paypal_enabled = !empty($settings['pay_paypal_sdk_s']);
$stripe_enabled = !empty($settings['pay_stripe_sdk_s']);
$balance_enabled = !empty($settings['pay_balance_s']);
$balance_enabled = !isset($settings['pay_balance_s']) || !empty($settings['pay_balance_s']);
// 卡密收款接口随三个兑换开关任一生效(余额 / 积分 / 会员)。
$card_pass_enabled = !empty($settings['pay_balance_pass_charge_s'])
|| !empty($settings['points_pass_exchange_s'])
@@ -512,13 +512,14 @@ class PaymentRuntime {
$s = Settings::get_all();
$channels = array_values(array_intersect(['alipay', 'wechat'], array_map('sanitize_key', (array) ($s['affiliate_payout_channels'] ?? ['alipay', 'wechat']))));
if (!$channels) { $channels = ['alipay', 'wechat']; }
$reset_time_raw = (string) ($s['affiliate_withdrawal_reset_time'] ?? '00:00');
return [
'min_amount' => self::money_decimal($s['affiliate_min_withdrawal'] ?? '50.00', '50.00', 99999900),
'service_charge_rate' => max(0, min(100, (int) ($s['affiliate_withdrawal_fee'] ?? 5))),
'daily_count' => max(0, min(99999, (int) ($s['affiliate_daily_withdrawal_count'] ?? 3))),
'daily_limit' => self::money_decimal($s['affiliate_daily_withdrawal_limit'] ?? '500.00', '500.00', 99999900),
'reset_time' => preg_match('/^(?:[01]\\d|2[0-3]):[0-5]\\d$/', (string) ($s['affiliate_withdrawal_reset_time'] ?? '00:00'))
? (string) $s['affiliate_withdrawal_reset_time']
'reset_time' => preg_match('/^(?:[01]\\d|2[0-3]):[0-5]\\d$/', $reset_time_raw)
? $reset_time_raw
: '00:00',
'payout_channels' => $channels,
];
@@ -553,7 +554,7 @@ class PaymentRuntime {
case 'stripe':
return !empty($settings['pay_stripe_sdk_s']);
case 'balance':
return !empty($settings['pay_balance_s']);
return !isset($settings['pay_balance_s']) || !empty($settings['pay_balance_s']);
case 'card_pass':
// 收款接口随三个兑换开关任一生效(余额 / 积分 / 会员)。
return !empty($settings['pay_balance_pass_charge_s'])
+100
View File
@@ -0,0 +1,100 @@
<?php
/**
* Test script to verify PaymentRuntime default values work correctly
* when database options are empty (fresh install scenario).
*
* Usage: php tools/test-payment-runtime-defaults.php
*/
// Simulate WordPress environment
define('ABSPATH', dirname(__DIR__) . '/');
define('WPINC', 'wp-includes');
// Load Composer autoload
require_once dirname(__DIR__) . '/vendor/autoload.php';
// Mock WordPress functions
if (!function_exists('__')) {
function __($text, $domain = 'default') { return $text; }
}
if (!function_exists('esc_url_raw')) {
function esc_url_raw($url) { return $url; }
}
if (!function_exists('sanitize_text_field')) {
function sanitize_text_field($str) { return trim(strip_tags($str)); }
}
if (!function_exists('sanitize_textarea_field')) {
function sanitize_textarea_field($str) { return trim(strip_tags($str)); }
}
if (!function_exists('sanitize_key')) {
function sanitize_key($key) { return strtolower(preg_replace('/[^a-z0-9_\-]/', '', $key)); }
}
if (!function_exists('wp_kses_post')) {
function wp_kses_post($data) { return $data; }
}
// Mock Settings class with empty data
class MockSettings {
public static function get_all(): array {
// Simulate fresh install: empty settings
return [];
}
public static function credits_enabled(): bool { return true; }
public static function download_default_cost(): int { return 0; }
}
// Replace the real Settings class with mock
class_alias('MockSettings', 'Jio\Settings\Settings');
// Now test PaymentRuntime
use Jio\Settings\PaymentRuntime;
echo "Testing PaymentRuntime with empty database (fresh install)...\n\n";
// Test 1: Recharge settings
echo "1. Testing get_payment_recharge_settings():\n";
$recharge = PaymentRuntime::get_payment_recharge_settings();
echo " - enabled: " . ($recharge['enabled'] ? 'true' : 'false') . " (expected: true)\n";
echo " - withdraw_enabled: " . ($recharge['withdraw_enabled'] ? 'true' : 'false') . " (expected: false)\n";
if ($recharge['enabled'] !== true) {
echo " ❌ FAIL: 'enabled' should be true by default!\n";
} else {
echo " ✅ PASS: 'enabled' is true\n";
}
echo "\n";
// Test 2: Gateway settings
echo "2. Testing get_payment_gateway_settings():\n";
$gateway = PaymentRuntime::get_payment_gateway_settings();
echo " - balance_enabled: " . ($gateway['balance_enabled'] ? 'true' : 'false') . " (expected: true)\n";
if ($gateway['balance_enabled'] !== true) {
echo " ❌ FAIL: 'balance_enabled' should be true by default!\n";
} else {
echo " ✅ PASS: 'balance_enabled' is true\n";
}
echo "\n";
// Test 3: is_gateway_enabled
echo "3. Testing is_gateway_enabled('balance'):\n";
$balance_enabled = PaymentRuntime::is_gateway_enabled('balance');
echo " - Result: " . ($balance_enabled ? 'true' : 'false') . " (expected: true)\n";
if ($balance_enabled !== true) {
echo " ❌ FAIL: balance gateway should be enabled by default!\n";
} else {
echo " ✅ PASS: balance gateway is enabled\n";
}
echo "\n";
// Test 4: Withdrawal settings (no warning)
echo "4. Testing get_withdrawal_settings() (should not trigger PHP warning):\n";
try {
$withdrawal = PaymentRuntime::get_withdrawal_settings();
echo " - reset_time: " . $withdrawal['reset_time'] . " (expected: 00:00)\n";
echo " - min_amount: " . $withdrawal['min_amount'] . " (expected: 50.00)\n";
echo " ✅ PASS: No PHP warning triggered\n";
} catch (Throwable $e) {
echo " ❌ FAIL: " . $e->getMessage() . "\n";
}
echo "\n";
echo "All tests completed.\n";