testOrderTreeParamError(); $this->testOrderTreeNonExist(); $this->testReissueRiskLimit(); $this->testReissueParamMissing(); $this->testDailyDryRunPreview(); $this->testVoucherDebtCalculation(); echo "\n--------------------------------------------------------\n"; echo "测试执行结果: 通过 {$this->passed} 项, 失败 {$this->failed} 项\n"; echo "========================================================\n"; return $this->failed === 0 ? 0 : 1; } private function assert($condition, $testName, $detail = '') { if ($condition) { echo " [PASS] {$testName}\n"; $this->passed++; } else { echo " [FAIL] {$testName} - {$detail}\n"; $this->failed++; } } /** * 测试 1:订单透视参数校验 (order_id <= 0 抛出异常或错误返回) */ public function testOrderTreeParamError() { $testName = "API: orderTree 参数非法拦截 (order_id=0)"; try { $ctrl = new Reward(); Request::instance()->withGet(['order_id' => 0]); $output = $this->captureResponse(function () use ($ctrl) { $ctrl->orderTree(); }); $res = json_decode($output, true); $this->assert( isset($res['code']) && $res['code'] !== 0 && strpos($res['msg'] ?? '', '订单ID不合法') !== false, $testName, "返回内容: {$output}" ); } catch (\think\exception\HttpResponseException $e) { $res = $e->getResponse()->getData(); $this->assert( isset($res['code']) && $res['code'] !== 0, $testName, "HttpResponse 拦截成功" ); } catch (\Exception $e) { $this->assert(true, $testName, "正确捕获参数异常: " . $e->getMessage()); } } /** * 测试 2:订单透视订单不存在拦截 */ public function testOrderTreeNonExist() { $testName = "API: orderTree 订单不存在拦截 (order_id=99999999)"; try { $ctrl = new Reward(); Request::instance()->withGet(['order_id' => 99999999]); $output = $this->captureResponse(function () use ($ctrl) { $ctrl->orderTree(); }); $res = json_decode($output, true); $this->assert( isset($res['code']) && $res['code'] !== 0 && strpos($res['msg'] ?? '', '订单不存在') !== false, $testName, "返回内容: {$output}" ); } catch (\think\exception\HttpResponseException $e) { $res = $e->getResponse()->getData(); $this->assert( isset($res['code']) && $res['code'] !== 0 && strpos($res['msg'] ?? '', '订单不存在') !== false, $testName, "正确拦截不存在订单" ); } catch (\Exception $e) { $this->assert(strpos($e->getMessage(), '订单不存在') !== false, $testName); } } /** * 测试 3:手工补发 10,000 元风控硬上限拦截 */ public function testReissueRiskLimit() { $testName = "风控: reissue 单笔超 10,000 元硬上限拦截 (amount=10001)"; try { $ctrl = new Reward(); Request::instance()->withPost([ 'user_id' => 1, 'reward_type' => 'push3', 'amount' => 10001, 'memo' => '超额测试', ]); $output = $this->captureResponse(function () use ($ctrl) { $ctrl->reissue(); }); $res = json_decode($output, true); $this->assert( isset($res['code']) && $res['code'] !== 0 && strpos($res['msg'] ?? '', '10,000') !== false, $testName, "返回内容: {$output}" ); } catch (\think\exception\HttpResponseException $e) { $res = $e->getResponse()->getData(); $this->assert( isset($res['code']) && $res['code'] !== 0 && strpos($res['msg'] ?? '', '10,000') !== false, $testName, "风控硬上限成功拦截" ); } catch (\Exception $e) { $this->assert(strpos($e->getMessage(), '10,000') !== false, $testName); } } /** * 测试 4:手工补发必填参数校验 */ public function testReissueParamMissing() { $testName = "API: reissue 必填参数缺失拦截 (缺少 memo)"; try { $ctrl = new Reward(); Request::instance()->withPost([ 'user_id' => 1, 'reward_type' => 'push3', 'amount' => 100, 'memo' => '', ]); $output = $this->captureResponse(function () use ($ctrl) { $ctrl->reissue(); }); $res = json_decode($output, true); $this->assert( isset($res['code']) && $res['code'] !== 0 && strpos($res['msg'] ?? '', '必填') !== false, $testName, "返回内容: {$output}" ); } catch (\think\exception\HttpResponseException $e) { $res = $e->getResponse()->getData(); $this->assert( isset($res['code']) && $res['code'] !== 0 && strpos($res['msg'] ?? '', '必填') !== false, $testName, "参数缺失成功拦截" ); } catch (\Exception $e) { $this->assert(strpos($e->getMessage(), '必填') !== false, $testName); } } /** * 测试 5:日结 Dry Run 预跑试算只读测试 */ public function testDailyDryRunPreview() { $testName = "业务: DailySettleService::preview 只读试算结构完整性"; $service = new DailySettleService(); $testDate = '2026-09-01'; // 模拟日期 $preview = $service->preview($testDate); $hasKeys = isset($preview['settle_date']) && isset($preview['order_count']) && isset($preview['gmv']) && isset($preview['madow']['pool']) && isset($preview['venue']['pool']) && isset($preview['county']['pool']) && isset($preview['financial']['payout_ratio']); $this->assert( $hasKeys && $preview['settle_date'] === $testDate, $testName, "预览结构字段校验完整,返回包含 GMV、均分池及综合拨比" ); } /** * 测试 6:兑换券待履约负债与资格判定 */ public function testVoucherDebtCalculation() { $testName = "财务: 活跃资格判定周期配置 (30天)"; $days = PartnerConfig::activeDays(); $this->assert($days === 30, $testName, "活跃资格判定周期配置为 30 天"); } private function captureResponse(callable $fn) { ob_start(); try { $fn(); } catch (\think\exception\HttpResponseException $e) { ob_end_clean(); throw $e; } catch (\Exception $e) { ob_end_clean(); throw $e; } return ob_get_clean(); } } // 执行测试 if (php_sapi_name() === 'cli') { $tester = new PartnerFinanceTest(); exit($tester->run()); }