diff --git a/src/AKSRT/Identity/Provider/AliyunProvider.php b/src/AKSRT/Identity/Provider/AliyunProvider.php index 98d5eec5..d4568453 100644 --- a/src/AKSRT/Identity/Provider/AliyunProvider.php +++ b/src/AKSRT/Identity/Provider/AliyunProvider.php @@ -155,11 +155,39 @@ final class AliyunProvider implements ProviderInterface { if ($code !== '' && $code !== '200') { return ProviderResult::failed($code, sanitize_text_field((string) ($response['Message'] ?? ''))); } - $object = is_array($response['ResultObject'] ?? null) ? $response['ResultObject'] : []; - $certify_id = sanitize_text_field((string) ($object['CertifyId'] ?? $response['CertifyId'] ?? '')); - $url = esc_url_raw((string) ($object['CertifyUrl'] ?? $object['Url'] ?? $response['CertifyUrl'] ?? '')); + $object = $this->normalize_result_object($response['ResultObject'] ?? []); + $certify_id = sanitize_text_field((string) $this->first_response_value($response, [ + ['ResultObject', 'CertifyId'], + ['ResultObject', 'certifyId'], + ['CertifyId'], + ['certifyId'], + ['Data', 'CertifyId'], + ['Data', 'certifyId'], + ])); + $url = esc_url_raw((string) $this->first_response_value(array_merge($response, ['ResultObject' => $object]), [ + ['ResultObject', 'CertifyUrl'], + ['ResultObject', 'certifyUrl'], + ['ResultObject', 'Url'], + ['ResultObject', 'url'], + ['CertifyUrl'], + ['certifyUrl'], + ['Url'], + ['url'], + ['Data', 'CertifyUrl'], + ['Data', 'certifyUrl'], + ['Data', 'Url'], + ['Data', 'url'], + ])); if ($certify_id === '' || $url === '') { - return ProviderResult::failed('aliyun_invalid_response', __('阿里云未返回有效认证会话', 'aksrt')); + $debug = $this->response_debug_summary($response, $object, [ + 'has_certify_id' => $certify_id !== '', + 'has_certify_url' => $url !== '', + ]); + $this->log_debug('InitFaceVerify invalid response', $debug); + return ProviderResult::failed('aliyun_invalid_response', sprintf( + __('阿里云未返回有效认证会话:%s', 'aksrt'), + $debug + )); } return ProviderResult::pending([ 'provider_session_id' => $certify_id, @@ -199,8 +227,24 @@ final class AliyunProvider implements ProviderInterface { if (is_wp_error($response)) { return new \WP_Error('aliyun_network_error', __('阿里云接口请求失败', 'aksrt')); } - $decoded = json_decode((string) wp_remote_retrieve_body($response), true); - return is_array($decoded) ? $decoded : new \WP_Error('aliyun_invalid_json', __('阿里云返回格式无效', 'aksrt')); + $status_code = (int) wp_remote_retrieve_response_code($response); + $body = (string) wp_remote_retrieve_body($response); + $decoded = json_decode($body, true); + if (!is_array($decoded)) { + $this->log_debug('Aliyun invalid JSON response', [ + 'http_status' => $status_code, + 'body_preview' => $this->truncate_debug($body, 800), + ]); + return new \WP_Error('aliyun_invalid_json', __('阿里云返回格式无效', 'aksrt')); + } + if (defined('WP_DEBUG') && WP_DEBUG) { + $this->log_debug('Aliyun RPC response', [ + 'action' => $action, + 'http_status' => $status_code, + 'summary' => $this->response_debug_summary($decoded), + ]); + } + return $decoded; } private function enterprise_passed(array $response): bool { @@ -209,4 +253,58 @@ final class AliyunProvider implements ProviderInterface { && (string) ($result['BizCode'] ?? '') === '1' && (string) ($result['Status'] ?? '') === '1'; } + + /** @param mixed $value @return array */ + private function normalize_result_object($value): array { + if (is_array($value)) { + return $value; + } + if (is_string($value) && $value !== '') { + $decoded = json_decode($value, true); + return is_array($decoded) ? $decoded : []; + } + return []; + } + + /** @param array $response @param array> $paths */ + private function first_response_value(array $response, array $paths): string { + foreach ($paths as $path) { + $value = $response; + foreach ($path as $segment) { + if (!is_array($value) || !array_key_exists($segment, $value)) { + $value = null; + break; + } + $value = $value[$segment]; + } + if (is_scalar($value) && (string) $value !== '') { + return (string) $value; + } + } + return ''; + } + + /** @param array $response @param array $object @param array $extra */ + private function response_debug_summary(array $response, array $object = [], array $extra = []): string { + $summary = array_merge([ + 'code' => (string) ($response['Code'] ?? ''), + 'message' => (string) ($response['Message'] ?? ''), + 'request_id' => (string) ($response['RequestId'] ?? ''), + 'top_keys' => implode(',', array_slice(array_keys($response), 0, 20)), + 'result_keys' => $object !== [] ? implode(',', array_slice(array_keys($object), 0, 20)) : '', + ], $extra); + return wp_json_encode($summary, JSON_UNESCAPED_UNICODE) ?: ''; + } + + /** @param mixed $data */ + private function log_debug(string $message, $data): void { + if (!defined('WP_DEBUG') || !WP_DEBUG) { + return; + } + error_log('[AKSRT Identity Aliyun] ' . $message . ': ' . (is_string($data) ? $data : (wp_json_encode($data, JSON_UNESCAPED_UNICODE) ?: ''))); + } + + private function truncate_debug(string $value, int $length): string { + return function_exists('mb_substr') ? mb_substr($value, 0, $length) : substr($value, 0, $length); + } }