diff --git a/app/miniapi/controller/VisaApplication.php b/app/miniapi/controller/VisaApplication.php index 9365c8c..d1c9cb8 100644 --- a/app/miniapi/controller/VisaApplication.php +++ b/app/miniapi/controller/VisaApplication.php @@ -12,6 +12,11 @@ final class VisaApplication extends Base public function application() { return $this->call(fn($service, $userId) => $service->application($userId, trim((string)$this->request->param('public_id', '')))); } public function draft() { return $this->call(fn($service, $userId) => $service->saveDraft($userId, $this->postData()), '草稿已保存'); } public function submit() { return $this->call(fn($service, $userId) => $service->submit($userId, $this->postData()), '提交成功'); } + public function agree() + { + $result = (new VisaApplicationService())->agree(trim((string)$this->request->param('doc_code', ''))); + return (int)($result['code'] ?? 0) === 1 ? $this->ok((array)($result['data'] ?? [])) : $this->fail((string)($result['msg'] ?? '协议内容暂不可用')); + } public function dataSource() { $filters = (array)$this->request->get(); unset($filters['type'], $filters['s'], $filters['mini_app_code'], $filters['token']); $filters['source_code'] = $this->orderSource(); diff --git a/app/miniapi/route/app.php b/app/miniapi/route/app.php index 34c99a1..7f257d9 100644 --- a/app/miniapi/route/app.php +++ b/app/miniapi/route/app.php @@ -66,4 +66,5 @@ Route::group(function () { Route::post('visa/draft', 'VisaApplication/draft'); Route::post('visa/submit', 'VisaApplication/submit'); Route::get('visa/data-source', 'VisaApplication/dataSource'); + Route::get('visa/agree', 'VisaApplication/agree'); })->namespace('app\\miniapi\\controller'); diff --git a/app/miniapi/service/VisaApplication/VisaApplicationService.php b/app/miniapi/service/VisaApplication/VisaApplicationService.php index 11f38fa..aa69fba 100644 --- a/app/miniapi/service/VisaApplication/VisaApplicationService.php +++ b/app/miniapi/service/VisaApplication/VisaApplicationService.php @@ -8,7 +8,7 @@ use think\facade\Log; final class VisaApplicationService { - private const ACTIONS = ['options', 'start', 'application', 'saveDraft', 'submit', 'dataSource']; + private const ACTIONS = ['options', 'start', 'application', 'saveDraft', 'submit', 'dataSource', 'agree']; private const DATA_SOURCE_PARAMS = ['model', 'source_code', 'page', 'size', 'state_id', 'hotel_state', 'provinceCode', 'country', 'entry_mode', 'province', 'accommodation_province', 'accommodation_municipality', 'city', 'id', 'air_transport_type', 'state', 'japan_province', 'travel_country', 'hotel_city', 'districtCode', 'nationality_iso2', 'next_destination']; public function options(int $userId, string $orderSource): array { return $this->request('options', $userId, ['order_source' => $orderSource]); } @@ -16,6 +16,11 @@ final class VisaApplicationService public function application(int $userId, string $publicId): array { return $this->request('application', $userId, ['public_id' => $publicId]); } public function saveDraft(int $userId, array $data): array { return $this->request('saveDraft', $userId, $data); } public function submit(int $userId, array $data): array { return self::decorateSubmitForCheck($this->request('submit', $userId, $data)); } + public function agree(string $docCode): array + { + if (!preg_match('/^[A-Za-z0-9._-]{1,64}$/', $docCode)) return ['code' => 0, 'msg' => '协议参数错误', 'data' => []]; + return $this->request('agree', 0, ['doc_code' => $docCode]); + } public static function decorateSubmitForCheck(array $result): array { if ((int)($result['code'] ?? 0) === 1 && !empty($result['data']['requires_payment']) && !empty($result['data']['order_sn'])) $result['data']['pay_url'] = 'https://www.qlevisa.com/index/pay/h5pay.html?order_sn=' . rawurlencode((string)$result['data']['order_sn']); return $result; } public function payload(int $userId, array $params = []): array { $source = (string)($params['order_source'] ?? ''); unset($params['order_source']); return ['user_token' => authcode((string)json_encode(['purpose' => 'visa_api', 'user_id' => $userId, 'order_source' => $source], JSON_UNESCAPED_UNICODE), 'ENCODE', MINIAPI_TOKEN_KEY, 120)] + $params; } public function endpoint(string $userUrl, string $action): string diff --git a/tests/visa_application_facade_self_check.php b/tests/visa_application_facade_self_check.php index 790bb83..9abe1de 100644 --- a/tests/visa_application_facade_self_check.php +++ b/tests/visa_application_facade_self_check.php @@ -11,6 +11,7 @@ use app\miniapi\service\VisaApplication\VisaApplicationService; $service = new VisaApplicationService(); if ($service->endpoint('https://user.example.com/users/list', 'start') !== 'https://user.example.com/visa_service/start') throw new RuntimeException('endpoint construction failed'); if ($service->endpoint('https://user.example.com/users/list', 'dataSource') !== 'https://user.example.com/visa_service/dataSource') throw new RuntimeException('data source forwarding endpoint failed'); +if ($service->endpoint('https://user.example.com/users/list', 'agree') !== 'https://user.example.com/visa_service/agree') throw new RuntimeException('legal document forwarding endpoint failed'); if ($service->endpoint('https://user.example.com/users/list', 'invalid') !== '') throw new RuntimeException('action allowlist failed'); $payload = $service->payload(9, ['order_source' => 'jnwxmini']); if (isset($payload['user_id']) || (json_decode((string)($payload['user_token'] ?? ''), true) !== ['purpose' => 'visa_api', 'user_id' => 9, 'order_source' => 'jnwxmini'])) throw new RuntimeException('trusted token payload failed'); @@ -20,4 +21,7 @@ $neutral = VisaApplicationService::decorateSubmitForCheck(['code' => 1, 'data' = $payable = VisaApplicationService::decorateSubmitForCheck(['code' => 1, 'data' => ['order_sn' => 'V 1', 'requires_payment' => true]]); if (isset($neutral['data']['pay_url']) || ($payable['data']['pay_url'] ?? '') !== 'https://www.qlevisa.com/index/pay/h5pay.html?order_sn=V%201') throw new RuntimeException('miniapi payment decoration failed'); if (VisaApplicationService::dataSourceQueryForCheck('inac.city', ['model' => 'region', 'source_code' => 'jnwxmini', 'state_id' => '11', 'hotel_state' => '12', 'provinceCode' => '13', 'country' => 'CN', 'application_token' => 'secret', 'user_token' => 'secret']) !== ['type' => 'inac.city', 'model' => 'region', 'source_code' => 'jnwxmini', 'state_id' => '11', 'hotel_state' => '12', 'provinceCode' => '13', 'country' => 'CN']) throw new RuntimeException('miniapi data source filtering failed'); +$controllerSource = (string)file_get_contents(dirname(__DIR__) . '/app/miniapi/controller/VisaApplication.php'); +$routeSource = (string)file_get_contents(dirname(__DIR__) . '/app/miniapi/route/app.php'); +if (!str_contains($controllerSource, 'public function agree()') || !str_contains($routeSource, "Route::get('visa/agree'")) throw new RuntimeException('miniapi legal document route missing'); echo "PASS visa_application_facade_self_check\n";