registration_default_recharge_group.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <?php
  2. namespace app\api\service {
  3. final class UserTokenService {
  4. public static function setToken($userId): array {
  5. $row = \think\facade\Db::table('bot_users')->where('user_id', $userId)->find();
  6. $GLOBALS['registration_token_groups'][] = $row['recharge_channel_group_id'];
  7. return ['user_id' => $userId, 'account' => $row['account'], 'token' => 'test-only-token', 'expire_time' => time() + 3600];
  8. }
  9. }
  10. }
  11. namespace app\common\service {
  12. final class FileService { public static function getFileUrl($value): string { return (string)$value; } }
  13. }
  14. namespace app\common\model {
  15. final class UserLogin { public const STATUS_SUCCESS = 1; public static function record(...$args): void {} }
  16. }
  17. namespace {
  18. error_reporting(E_ALL & ~E_DEPRECATED);
  19. function request() { return $GLOBALS['registration_request']; }
  20. function generateUserCode(): string { static $sequence = 0; return 'OWN' . str_pad((string)++$sequence, 5, '0', STR_PAD_LEFT); }
  21. function create_password($password, $salt): string { return hash('sha256', $salt . $password); }
  22. function avatarUrl($value): string { return (string)$value; }
  23. function getDeviceUniqueId(): string { return 'test-device'; }
  24. class RegistrationRequest {
  25. public function ip(): string { return '127.0.0.1'; }
  26. public function header($name, $default = '') { return $name === 'referer' ? 'https://test.example.test/register' : $default; }
  27. public function param($name, $default = null) { return $default; }
  28. }
  29. $GLOBALS['registration_request'] = new RegistrationRequest();
  30. $GLOBALS['registration_token_groups'] = [];
  31. $repo = getenv('REGISTRATION_SITE_REPO') ?: dirname(__DIR__, 3) . '/melbet_sport-api';
  32. $stage = getenv('REGISTRATION_SITE_STAGE') ?: $repo;
  33. $loader = require $repo . '/vendor/autoload.php';
  34. $loader->setPsr4('app\\', [$stage . '/app/', $repo . '/app/']);
  35. $app = new \think\App($repo . '/');
  36. \think\Container::setInstance($app);
  37. $db = new \think\DbManager();
  38. $db->setConfig(['default' => 'isolated', 'connections' => ['isolated' => [
  39. 'type' => 'sqlite', 'database' => ':memory:', 'prefix' => '', 'fields_strict' => true, 'debug' => false,
  40. ]], 'auto_timestamp' => false]);
  41. $app->instance(\think\DbManager::class, $db);
  42. $app->instance('log', new \Psr\Log\NullLogger());
  43. \think\Model::setInvoker([$app, 'invoke']);
  44. \think\facade\Config::set(['unique_identification' => 'test-only-salt'], 'project');
  45. $db->execute('CREATE TABLE bot_users (id INTEGER PRIMARY KEY AUTOINCREMENT,user_id TEXT,member_id TEXT,account TEXT,first_name TEXT,realname TEXT,avatar TEXT,password TEXT,phone TEXT,email TEXT,register_ip TEXT DEFAULT "",register_domain TEXT,device_id TEXT DEFAULT "",last_active_time INTEGER,agent_user_code TEXT,user_code TEXT,"from" INTEGER DEFAULT 1,recharge_channel_group_id INTEGER DEFAULT 0,delete_time TEXT,created_at TEXT,updated_at TEXT)');
  46. $db->execute('CREATE TABLE bot_wallets (id INTEGER PRIMARY KEY AUTOINCREMENT,user_id INTEGER,member_id TEXT,net TEXT,coin TEXT,available_balance TEXT DEFAULT "0",created_at TEXT,updated_at TEXT)');
  47. $db->execute('CREATE TABLE bot_share_system_state ("key" TEXT PRIMARY KEY,value TEXT)');
  48. $db->execute('CREATE TABLE bot_share_members (user_id INTEGER PRIMARY KEY,parent_user_id INTEGER,invitation_code TEXT,binding_status TEXT,level INTEGER,bound_at TEXT,created_at TEXT,updated_at TEXT)');
  49. $db->execute('CREATE TABLE bot_share_tree (ancestor_user_id INTEGER,descendant_user_id INTEGER,depth INTEGER,bound_at TEXT,PRIMARY KEY(ancestor_user_id,descendant_user_id))');
  50. \think\facade\Db::table('bot_users')->insert(['id' => 1, 'user_id' => '10000001', 'member_id' => '10000001', 'account' => 'inviter', 'user_code' => 'INVITE01', 'recharge_channel_group_id' => 7]);
  51. \think\facade\Db::table('bot_share_members')->insert(['user_id' => 1, 'parent_user_id' => null, 'invitation_code' => 'INVITE01', 'binding_status' => 'root', 'level' => 1, 'bound_at' => '2000-01-01 00:00:00']);
  52. \think\facade\Db::table('bot_share_tree')->insert(['ancestor_user_id' => 1, 'descendant_user_id' => 1, 'depth' => 0, 'bound_at' => '2000-01-01 00:00:00']);
  53. \think\facade\Db::table('bot_share_system_state')->insert(['key' => 'relations_lock', 'value' => '1']);
  54. $checks = 0;
  55. function check($actual, $expected, string $message): void {
  56. global $checks; ++$checks;
  57. if ($actual !== $expected) throw new \RuntimeException($message . ': actual=' . json_encode($actual) . ' expected=' . json_encode($expected));
  58. }
  59. foreach (['account' => 'new-account', 'phone' => '13800000001', 'email' => 'new@example.test'] as $type => $account) {
  60. $result = \app\api\logic\LoginLogic::register(['account' => $account, 'password' => 'secret12', 'type' => $type, 'invitationCode' => 'INVITE01', 'recharge_channel_group_id' => 9]);
  61. check(is_array($result), true, 'Real registration succeeds: ' . ($result === false ? \app\api\logic\LoginLogic::getError() : $type));
  62. $row = \think\facade\Db::table('bot_users')->where('account', $account)->find();
  63. check($row['recharge_channel_group_id'], 1, 'All registration types assign default group instead of database zero or client input');
  64. check($row['from'], 1, 'Real registration remains real');
  65. check(\think\facade\Db::table('bot_share_members')->where('user_id', $row['id'])->value('parent_user_id'), 1, 'Referral binding is unchanged');
  66. check(\think\facade\Db::table('bot_wallets')->where('user_id', $row['id'])->value('available_balance'), '0', 'Real wallet does not receive demo funds');
  67. }
  68. $guest = \app\api\logic\LoginLogic::guestRegister();
  69. check(is_array($guest), true, 'Guest registration succeeds: ' . ($guest === false ? \app\api\logic\LoginLogic::getError() : 'ok'));
  70. $guestRow = \think\facade\Db::table('bot_users')->where('user_id', $guest['user_id'])->find();
  71. check($guestRow['recharge_channel_group_id'], 1, 'Guest registration also assigns group one');
  72. check($guestRow['from'], 2, 'Guest remains a demo user');
  73. check((string)\think\facade\Db::table('bot_wallets')->where('user_id', $guestRow['id'])->value('available_balance'), '100000', 'Demo wallet behavior is unchanged');
  74. check($GLOBALS['registration_token_groups'], [1, 1, 1, 1], 'Token creation sees the persisted default group');
  75. foreach ([[], ['recharge_channel_group_id' => 0], ['recharge_channel_group_id' => null], ['recharge_channel_group_id' => ''], ['recharge_channel_group_id' => 7]] as $index => $extra) {
  76. $model = \app\common\model\User::create(['user_id' => 'direct-' . $index, 'member_id' => 'direct-' . $index, 'account' => 'direct-' . $index] + $extra);
  77. check((int)$model->recharge_channel_group_id, $extra['recharge_channel_group_id'] ?? null ? 7 : 1, 'Model insertion fallback preserves a valid assigned group');
  78. }
  79. \think\facade\Db::table('bot_users')->insert(['user_id' => 'legacy-zero', 'account' => 'legacy-zero', 'recharge_channel_group_id' => 0]);
  80. foreach (['legacy-zero' => 0, '10000001' => 7] as $userId => $group) {
  81. $user = \app\common\model\User::where('user_id', $userId)->find();
  82. $user->first_name = 'profile edit'; $user->save();
  83. check((int)\think\facade\Db::table('bot_users')->where('user_id', $userId)->value('recharge_channel_group_id'), $group, 'Updating an existing user never resets their group');
  84. }
  85. echo 'PASS ' . $checks . " registration/default-group assertions (isolated SQLite, token/file/login-log adapters)\n";
  86. }