From 75be10be20052b67fc17b563adbfddcd9fde741a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E5=B0=8F=E5=A2=A8?= <2291200076@qq.com> Date: Tue, 30 Jan 2024 15:28:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9D=A5=E6=AD=A4=E5=8A=A0=E5=AF=86=20SSL?= =?UTF-8?q?=E8=AF=81=E4=B9=A6=E5=8D=8A=E8=87=AA=E5=8A=A8=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- letsencrypt-autorenew/.gitignore | 1 + letsencrypt-autorenew/config.template.js | 6 ++ letsencrypt-autorenew/index.js | 112 +++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 letsencrypt-autorenew/.gitignore create mode 100644 letsencrypt-autorenew/config.template.js create mode 100644 letsencrypt-autorenew/index.js diff --git a/letsencrypt-autorenew/.gitignore b/letsencrypt-autorenew/.gitignore new file mode 100644 index 0000000..a2d72a2 --- /dev/null +++ b/letsencrypt-autorenew/.gitignore @@ -0,0 +1 @@ +config.js \ No newline at end of file diff --git a/letsencrypt-autorenew/config.template.js b/letsencrypt-autorenew/config.template.js new file mode 100644 index 0000000..85bd8fb --- /dev/null +++ b/letsencrypt-autorenew/config.template.js @@ -0,0 +1,6 @@ +// console : https://letsencrypt.osfipin.com/user-0408/my/api +// Api docs: https://letsencrypt.apifox.cn/ +const APIToken = '' +const User = '' + +module.exports = { APIToken, User } diff --git a/letsencrypt-autorenew/index.js b/letsencrypt-autorenew/index.js new file mode 100644 index 0000000..e94197b --- /dev/null +++ b/letsencrypt-autorenew/index.js @@ -0,0 +1,112 @@ +const { APIToken, User } = require('./config') + +/** + * 来此加密 SSL证书半自动申请 + * + * 功能:将账号下的证书逐个提交重申 + * 用法:运行脚本挂着,然后就可以去做别的,脚本会逐一将账号下证书提交重申,等待一段时间后即可去后台下载证书 + * + * 注意:需要验证状态的证书会阻塞 + * + * https://letsencrypt.osfipin.com/user-0408/order/list + * + * @author coder-xiaomo + * @since 2024.01.30 + */ + +var myHeaders = new Headers(); +myHeaders.append("Authorization", `Bearer ${APIToken}:${User}`); +myHeaders.append("User-Agent", "Apifox/1.0.0 (https://apifox.com)"); + +var requestOptions = { + method: 'GET', + headers: myHeaders, + redirect: 'follow' +}; + +async function renew(certId) { + let response = await fetch("https://api.osfipin.com/letsencrypt/api/order/renew?id=" + certId, requestOptions) + .then(response => response.text()) + // .then(result => console.log(result)) + .catch(error => console.log('error', error)); + let result = JSON.parse(response) + console.log('result', result) + + // 一些返回示例 + // {"c":40,"m":"\u65e0\u6cd5\u91cd\u7533,\u8fc7\u671f\u524d14\u5929\u5185\u53ef\u91cd\u65b0\u7533\u8bf7","v":""} + // '无法重申,过期前14天内可重新申请' + // { c: 40, m: 'param id error', v: '' } + // { c: 40, m: '请先完成正在处理的证书', v: '' } + + // if (result.c == 40 || result.c == 50) { + // console.log('出错了:', unescape(result.m)) + // } + return result +} + +async function getList() { + let totalPage = 1, currentPage = 1 + let list = [] + while (currentPage <= totalPage) { + let response = await fetch("https://api.osfipin.com/letsencrypt/api/order/list?page=" + currentPage, requestOptions) + .then(response => response.text()) + // .then(result => console.log(result)) + .catch(error => console.log('error', error)); + let result = JSON.parse(response) + totalPage = result.v.mpage + currentPage++ + // console.log('result', result) + list.push(...result.v.list) + } + // console.log('currentPage', currentPage) + // console.log('totalPage', totalPage) + + // console.log('list', list) + return list +} + +let startTimestamp = 0 +let forTime = 0 +let needRenewList = [] +async function _timer() { + let list = await getList() + // console.log('list', list) + + const needRenewList = list + // 排除正在申请中的 + .filter(i => i.status !== '验证中') + // 留下最近 14 天将要过期的 + .filter(i => { + return new Date(i.time_end).getTime() - Date.now() <= 14 * 24 * 3600 * 1000 // 小于 14 天 + }) + // console.log('needRenewList', needRenewList) + + if (needRenewList.length === 0) { + clearInterval(timerInstanse) + console.log('完成!') + } + let displaySpendTime = ((Date.now() - startTimestamp) / (1000 * 60)).toFixed(3) + console.log(`第${++forTime}次尝试,已耗时${displaySpendTime}min,剩余待申请证书:`, needRenewList.map(cert => `${cert.id}(${cert.status})`).join('、')) + for (let cert of needRenewList) { + let result = await renew(cert.id) + if (result.c == 20) { + console.log('申请证书返回成功') + // 有证书申请中,剩下的申请等下次循环 + break + } else if (result.c == 40) { + if (result.m === '请先完成正在处理的证书') { + console.log('有证书正在申请中,跳过') + break + } + } + } +} + +async function main() { + startTimestamp = Date.now() + timerInstanse = setInterval(_timer, 10 * 1000) + _timer() + // renew('1') +} + +main()