mirror of
https://github.com/certd/certd.git
synced 2026-04-22 19:17:25 +08:00
270 lines
6.9 KiB
TypeScript
270 lines
6.9 KiB
TypeScript
import { HttpRequestConfig } from '@certd/basic';
|
|
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
|
|
import qs from 'qs';
|
|
import iconv from 'iconv-lite';
|
|
/**
|
|
* 这个注解将注册一个授权配置
|
|
* 在certd的后台管理系统中,用户可以选择添加此类型的授权
|
|
*/
|
|
@IsAccess({
|
|
name: 'west',
|
|
title: '西部数码授权',
|
|
desc: '',
|
|
icon: 'tabler:map-west',
|
|
})
|
|
export class WestAccess extends BaseAccess {
|
|
/**
|
|
* 授权属性配置
|
|
*/
|
|
@AccessInput({
|
|
title: '权限范围',
|
|
component: {
|
|
name: 'a-select',
|
|
vModel: 'value',
|
|
options: [
|
|
{ value: 'account', label: '账户级别,对所有域名都有权限管理' },
|
|
{ value: 'domain', label: '域名级别,仅能管理单个域名' },
|
|
],
|
|
},
|
|
helper: '选择权限范围',
|
|
required: true,
|
|
})
|
|
scope = '';
|
|
|
|
/**
|
|
* 授权属性配置
|
|
*/
|
|
@AccessInput({
|
|
title: '账号',
|
|
helper: '你的登录账号',
|
|
encrypt: false,
|
|
required: false,
|
|
mergeScript: `
|
|
return {
|
|
show:ctx.compute(({form})=>{
|
|
return form.access.scope === 'account'
|
|
})
|
|
}
|
|
`,
|
|
})
|
|
username = '';
|
|
|
|
/**
|
|
* 授权属性配置
|
|
*/
|
|
@AccessInput({
|
|
title: 'ApiKey',
|
|
component: {
|
|
placeholder: '账户级别的key,对整个账户都有管理权限',
|
|
},
|
|
helper: '账户级别的key,对整个账户都有管理权限\n前往[API接口配置](https://www.west.cn/manager/API/APIconfig.asp),手动设置“api连接密码”',
|
|
encrypt: true,
|
|
required: false,
|
|
mergeScript: `
|
|
return {
|
|
show:ctx.compute(({form})=>{
|
|
return form.access.scope === 'account'
|
|
})
|
|
}
|
|
`,
|
|
})
|
|
apikey = '';
|
|
|
|
/**
|
|
* 授权属性配置
|
|
*/
|
|
@AccessInput({
|
|
title: 'apidomainkey',
|
|
component: {
|
|
placeholder: '域名级别的key,仅对单个域名有权限',
|
|
},
|
|
helper: '域名级别的key,仅对单个域名有权限。 \n前往[西部数据域名管理](https://www.west.cn/manager/domain/),点击域名,右上方点击ApiKey获取密钥',
|
|
encrypt: true,
|
|
required: false,
|
|
mergeScript: `
|
|
return {
|
|
show:ctx.compute(({form})=>{
|
|
return form.access.scope === 'domain'
|
|
})
|
|
}
|
|
`,
|
|
})
|
|
apidomainkey = '';
|
|
|
|
|
|
/**
|
|
* 授权属性配置
|
|
*/
|
|
@AccessInput({
|
|
title: '域名',
|
|
component: {
|
|
placeholder: '域名级别的key对应的域名',
|
|
},
|
|
encrypt: false,
|
|
required: false,
|
|
mergeScript: `
|
|
return {
|
|
show:ctx.compute(({form})=>{
|
|
return form.access.scope === 'domain'
|
|
})
|
|
}
|
|
`,
|
|
})
|
|
domain = '';
|
|
|
|
|
|
@AccessInput({
|
|
title: "测试",
|
|
component: {
|
|
name: "api-test",
|
|
action: "TestRequest"
|
|
},
|
|
helper: "点击测试接口是否正常"
|
|
})
|
|
testRequest = true;
|
|
|
|
async onTestRequest() {
|
|
|
|
if(this.scope === 'domain'){
|
|
if(!this.domain){
|
|
throw new Error('domain 必填');
|
|
}
|
|
await this.getDomainRecordList({limit:1});
|
|
return "ok";
|
|
}
|
|
|
|
await this.getDomainList();
|
|
return "ok";
|
|
}
|
|
|
|
async getDomainRecordList(req:{limit:number}){
|
|
// 获取域名解析记录列表
|
|
return await this.doDoimainApiRequest('https://api.west.cn/API/v2/domain/dns/',{
|
|
act:'dnsrec.list',
|
|
domain:this.domain,
|
|
limit: req.limit || 10,
|
|
})
|
|
}
|
|
|
|
|
|
async doDoimainApiRequest(url: string, data: any = null, method = 'post') {
|
|
data.apidomainkey = this.apidomainkey;
|
|
const res = await this.ctx.http.request<any, any>({
|
|
url,
|
|
method,
|
|
data,
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
});
|
|
if (res.msg !== 'success') {
|
|
if(res.msg.includes('500 already exists')){
|
|
return res;
|
|
}
|
|
throw new Error(`${JSON.stringify(res.msg)}`);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
async getDomainList() {
|
|
const res = await this.doRequest({
|
|
url: '/v2/domain',
|
|
method: 'GET',
|
|
data:{
|
|
act:'getdomains',
|
|
limit:1,
|
|
page:1
|
|
}
|
|
});
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
public async doRequest(req: HttpRequestConfig) {
|
|
let { url, method, data } = req;
|
|
if (data == null) {
|
|
data = {};
|
|
}
|
|
if (!method) {
|
|
method = 'POST';
|
|
}
|
|
|
|
if (this.scope === 'account') {
|
|
/**
|
|
* token text 身份验证字符串,取值为:md5(username+api_password+timestamp),其中:
|
|
username:您在我司注册的用户名。
|
|
api_password:您设置的API密码。您可登录官网管理中心,在“代理商管理”-<API接口配置>""页面查看您的api密码。
|
|
timestamp:当前时间的毫秒时间戳。
|
|
将字符串username与字符串api_password连接,再与timestamp连接,然后将生成的字符串进行md5求值,md5算法要求为:
|
|
32位16进制字符串,小写格式。
|
|
身份验证串有效期10分钟。
|
|
|
|
比如,您的用户名为:zhangsan,您的API密码为:5dh232kfg!* ,当前毫秒时间戳为:1554691950854,则:
|
|
token=md5(zhangsan + 5dh232kfg!* + 1554691950854)=cfcd208495d565ef66e7dff9f98764da
|
|
*/
|
|
// data.apikey = this.ctx.utils.hash.md5(this.apikey);
|
|
data.username = this.username;
|
|
const timestamp = new Date().getTime();
|
|
const token = this.ctx.utils.hash.md5(`${this.username}${this.apikey}${timestamp}`).toLowerCase();
|
|
data.token = token;
|
|
data.time = timestamp;
|
|
} else {
|
|
data.apidomainkey = this.apidomainkey;
|
|
}
|
|
|
|
|
|
const headers = {}
|
|
const body: any = {}
|
|
if (method.toUpperCase() === 'POST') {
|
|
headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
|
|
body.data = data
|
|
} else if (method.toUpperCase() === 'GET') {
|
|
let queryString = '';
|
|
if (method.toUpperCase() === 'GET') {
|
|
queryString = qs.stringify(data);
|
|
}
|
|
url = `${url}?${queryString}`
|
|
}
|
|
|
|
|
|
const res = await this.ctx.http.request<any, any>({
|
|
baseURL: 'https://api.west.cn/api',
|
|
url,
|
|
method,
|
|
...body,
|
|
headers,
|
|
responseType: 'arraybuffer', // 关键:获取原始二进制数据
|
|
transformResponse: [
|
|
function(data, headers) { // headers 参数包含响应头
|
|
try {
|
|
const contentType = headers['content-type'] || '';
|
|
// 判断是否是 GB2312/GBK 编码
|
|
if (contentType.includes('gb2312') || contentType.includes('gbk')) {
|
|
// 使用 iconv-lite 解码
|
|
data = iconv.decode(data, 'gb2312');
|
|
}else{
|
|
// 默认按 UTF-8 处理
|
|
data = data.toString('utf-8');
|
|
}
|
|
} catch (error) {
|
|
console.error('解码失败:', error);
|
|
}
|
|
return JSON.parse(data);
|
|
}
|
|
]
|
|
});
|
|
this.ctx.logger.info(`request ${url} ${method} res:${JSON.stringify(res)}`);
|
|
if (res.msg !== 'success' && res.result!= 200) {
|
|
if(res.msg.includes('500 already exists')){
|
|
return res;
|
|
}
|
|
throw new Error(`${JSON.stringify(res.msg)}`);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
}
|
|
|
|
new WestAccess();
|