feat(sign): 补齐医护端与患者端签署流程
This commit is contained in:
+20
-27
@@ -5,16 +5,20 @@ import type {
|
||||
ApiResponse,
|
||||
SignatureUploadInput,
|
||||
SignatureUploadResponse,
|
||||
SigningProof,
|
||||
SigningContextResponse,
|
||||
TokenConsumeRequest,
|
||||
TokenConsumeResponse,
|
||||
} from './types'
|
||||
|
||||
export function consumeSigningToken(payload: TokenConsumeRequest): Promise<TokenConsumeResponse> {
|
||||
export function consumeSigningToken(
|
||||
payload: TokenConsumeRequest,
|
||||
idempotencyKey: string,
|
||||
): Promise<TokenConsumeResponse> {
|
||||
return request
|
||||
.post<ApiResponse<TokenConsumeResponse>>('/v1/sign-deliveries/token/consume', payload, {
|
||||
headers: {
|
||||
'Idempotency-Key': createIdempotencyKey(),
|
||||
'Idempotency-Key': idempotencyKey,
|
||||
},
|
||||
})
|
||||
.then(unwrapApiResponse)
|
||||
@@ -23,48 +27,37 @@ export function consumeSigningToken(payload: TokenConsumeRequest): Promise<Token
|
||||
/**
|
||||
* 读取本次签署的完整上下文:患者信息 / 签署人 / 文书正文 / 医生已填结果。
|
||||
*
|
||||
* 契约见 `.workbuddy-ai/患者端H5真实接入方案-2026-09-28.md` 第三节。
|
||||
* **后端就绪前这个调用会失败**,所以调用方必须能优雅降级 ——
|
||||
* 拿不到正文就不能放行签署(见 `useSignFlow` 的 `documentError`)。
|
||||
* Context 使用已消费凭证,不再把原始一次性 Token 放进请求 URL、日志或后续请求。
|
||||
*/
|
||||
export function fetchSigningContext(token: string): Promise<SigningContextResponse> {
|
||||
export function fetchSigningContext(proof: SigningProof): Promise<SigningContextResponse> {
|
||||
return request
|
||||
.get<ApiResponse<SigningContextResponse>>('/v1/sign-deliveries/token/context', {
|
||||
params: { token },
|
||||
})
|
||||
.post<ApiResponse<SigningContextResponse>>('/v1/sign-deliveries/token/context', proof)
|
||||
.then(unwrapApiResponse)
|
||||
}
|
||||
|
||||
function createIdempotencyKey(value?: string) {
|
||||
if (value) {
|
||||
return value
|
||||
}
|
||||
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
||||
return `patient-h5-${crypto.randomUUID()}`
|
||||
}
|
||||
|
||||
return `patient-h5-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
||||
}
|
||||
|
||||
export function uploadSigningSignature(
|
||||
payload: SignatureUploadInput,
|
||||
): Promise<SignatureUploadResponse> {
|
||||
const formData = new FormData()
|
||||
formData.append('file', payload.file, 'signature.png')
|
||||
formData.append('metadata', payload.metadata)
|
||||
formData.append('deliveryId', payload.deliveryId)
|
||||
formData.append('uploadToken', payload.uploadToken)
|
||||
formData.append(
|
||||
'metadata',
|
||||
new Blob([JSON.stringify(payload.metadata)], { type: 'application/json' }),
|
||||
)
|
||||
formData.append(
|
||||
'signer',
|
||||
new Blob([JSON.stringify(payload.signer)], { type: 'application/json' }),
|
||||
)
|
||||
|
||||
return request
|
||||
.post<ApiResponse<SignatureUploadResponse>>(
|
||||
`/v1/sign-deliveries/${encodeURIComponent(payload.taskId)}/signature`,
|
||||
formData,
|
||||
{
|
||||
params: {
|
||||
deliveryId: payload.deliveryId,
|
||||
uploadToken: payload.uploadToken,
|
||||
},
|
||||
headers: {
|
||||
'Idempotency-Key': createIdempotencyKey(payload.idempotencyKey),
|
||||
'Idempotency-Key': payload.idempotencyKey,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user