这是sign.ts文件:import CryptoJS from 'crypto-js'
// import { localStg } from '@/utils/storage';
// import { useUserStore } from '@/store/hooks/userStore'
// const userStore = useUserStore()
export function signRequest(config: any) {
// const path = config.url;
const timestamps = Date.now().toString()
const key = 'shDOUArrDhpeAMw9FGY79Zmy3MLWwNWy'
// 添加 timestamps 到 headers
config.headers.timestamps = timestamps
// const test = loadParam(path, config.data);
const test = loadParam(config)
// const token = userStore.userInfo.token
// 添加token
// config.headers.token = token || ''
config.headers.os = 'web'
config.headers.businessType = 'earnify_customer'
// AES 加密 timestamps
const aesTimestamp = CryptoJS.AES.encrypt(timestamps, CryptoJS.enc.Utf8.parse('4d5bc50346c22dde12be2c3b1b89ada6'), {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.ZeroPadding
})
config.headers.envTimestamps = aesTimestamp.toString()
// 计算签名
config.headers.sign = CryptoJS.MD5(test + timestamps + key)
.toString(CryptoJS.enc.Hex)
.toLowerCase()
return config
}
function loadParam(config: any): string {
let str = ''
if (config.headers['Content-Type'] !== 'multipart/form-data') {
if (config.data || config.params) {
if (config.method === 'get') {
if (config.params) {
const params = config.params
const keyList = Object.keys(config.params)
// 解析 GET 请求的查询参数
for (const key of keyList) {
str +=
keyList[keyList.length - 1] !== key
? `${ key }=${ encodeURI(<string>params[key]) }&`
: `${ key }=${ encodeURI(<string>params[key]) }`
}
}
} else if (config.data) {
// 处理 URLSearchParams 格式的数据
// if (config.data instanceof URLSearchParams) {
// str = config.data.toString()
// } else {
str = JSON.stringify(config.data)
// }
}
}
} else {
const url = config.url
if (url.includes('?')) {
str += url.substring(url.indexOf('?') + 1, url.length)
}
}
return str
}
这是request.ts文件:import type { AxiosInstance } from 'axios'
import axios from 'axios'
import Cookies from 'js-cookie'
import { useUserStore } from '@/store/hooks/userStore'
const userStore = useUserStore()
import { useOutsideRouter } from '@/store/hooks/useOutsideRouter'
import { signRequest } from './sign'
export interface RespData<T> {
success?: boolean
errorCode?: number
error?: number | string | null
msg?: string
data?: T
[key: string]: any
}
// redirect error
function errorRedirect(url: string) {
const { router } = useOutsideRouter()
router.push(url)
}
// code Message
const codeMessage: {
[key: number]: string
} = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
206: '进行范围请求成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
405: '请求不允许。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。'
}
// 创建axios实例
const service: AxiosInstance = axios.create({
// api 的 base_url
baseURL: 'https://tapi.shenyantuling.com:10000',
// 请求超时时间
timeout: 6000000
})
// request拦截器
service.interceptors.request.use(
request => {
const token: string | undefined = userStore.userInfo.token
// Conversion of hump nomenclature
/**
* 让每个请求携带自定义 token
* 请根据实际情况自行修改
*/
if (request.url === '/login') {
return request
}
request.headers!.token = token as string
// request.headers!.extendData =
// TODO: 临时使用
signRequest(request)
request.headers['ngrok-skip-browser-warning'] = '69420'
return request
},
error => {
return Promise.reject(error)
}
)
// respone拦截器
service.interceptors.response.use(
response => {
/**
* response data
* {
* data: {},
* msg: "",
* error: 0 0 success | 1 error | 5000 failed | HTTP code
* }
*/
const data: any = response.data
const msg: string = data.msg || ''
if (msg.indexOf('user not log in') !== -1 && data.error === -1) {
// TODO 写死的 之后要根据语言跳转
errorRedirect('login')
return
}
if (response.config.autoDownLoadFile === undefined || response.config.autoDownLoadFile) {
Promise.resolve().then(() => {
useResHeadersAPI(response.headers, data)
})
}
if (
response.request.responseType === 'blob' &&
/json$/gi.test(response.headers['content-type'])
) {
return new Promise(resolve => {
const reader = new FileReader()
reader.readAsText(<Blob>response.data)
reader.onload = () => {
if (!reader.result || typeof reader.result !== 'string') return resolve(response.data)
response.data = JSON.parse(reader.result)
resolve(response.data)
}
})
} else if (data instanceof Blob) {
return {
data,
msg: '',
error: 0
}
}
if (data.msg === null) {
data.msg = 'Unknown error'
}
return data
},
error => {
/**
* 某些特定的接口 404 500 需要跳转
* 在需要重定向的接口中传入 redirect字段 值为要跳转的路由
* redirect之后 调用接口的地方会继续执行
* 因为此时 response error
* 所以需要前端返回一个前端构造好的数据结构 避免前端业务部分逻辑出错
* 不重定向的接口则不需要传
*/
if (error.config?.redirect) {
errorRedirect(error.config.redirect)
}
if (error.response) {
return {
data: {},
error: error.response.status,
msg: codeMessage[error.response.status] || error.response.data.message
}
} else {
// 某些特定的接口 failed 需要跳转
return {
data: {},
error: 5000,
msg: '服务请求不可用,请重试或检查您的网络。'
}
}
}
)
export function sleep(time = 0) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({})
}, time)
})
}
function extractFileNameFromContentDispositionHeader(value: string) {
const patterns = [
/filename\*=[^']+'\w*'"([^"]+)";?/i,
/filename\*=[^']+'\w*'([^;]+);?/i,
/filename="([^;]*);?"/i,
/filename=([^;]*);?/i
]
let responseFilename: any = null
patterns.some(regex => {
responseFilename = regex.exec(value)
return responseFilename !== null
})
if (responseFilename !== null && responseFilename.length > 1) {
try {
return decodeURIComponent(responseFilename[1])
} catch (e) {
console.error(e)
}
}
return null
}
export function downloadFile(boldData: BlobPart, filename = 'shinewing', type: any) {
const blob = boldData instanceof Blob
? boldData
: new Blob([boldData], {
type
})
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.download = filename
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
export function useResHeadersAPI(headers: any, resData: any) {
const disposition = headers['content-disposition']
if (disposition) {
let filename: string | null = ''
filename = extractFileNameFromContentDispositionHeader(disposition)
if (filename) {
downloadFile(resData, filename, headers['content-type'])
}
}
}
const requestSuite: IRequestSuite = {
get(uri, params, config) {
return service.get(uri, {
params,
...config
})
},
post(uri, data, config) {
if (config && config.params) {
return service.post(uri, data, config)
}
return service.post(uri, data, config)
},
put(uri, data, config) {
return service.put(uri, data, config)
},
patch(uri, data, config) {
return service.patch(uri, data, config)
},
delete(uri, config) {
return service.delete(uri, config)
}
}
export default requestSuite
我的post请求传的是params参数,但是返回{
"code": 402,
"data": null,
"message": "Failed to verify the signature. Please download the latest app from the landing page.",
"result": "fail"
}
问题出在哪里,怎么解决 还需要配置什么
最新发布