v1.10.0: 新增「当前商品选择页」——侧边栏购买入口改为插件内置 buy.html
- buy.html/css/js:实时拉取授权系统当前在售商品 → 选商品 → 选支付方式 → 下单 - background.js:新增 getCardTypes / authCreateOrder / authQueryOrder 三个消息与实现 - 支付成功自动发卡并激活本机;新增 alarms 权限做后台订单轮询(关页仍完成),12 小时未完成自动停 - sidepanel.js:licBuy 从跳 https://auth.88531.cn 改为打开内置 buy.html(不改服务端) - manifest 1.9.0 → 1.10.0 + alarms 权限 - CHANGELOG/README 同步:新增条目、文件结构、内置购买页说明、Gitea 源
This commit is contained in:
1 parent
6a697a2663
commit
ec8bfda853
8 files changed
+460
-3
No files matched your search
+118
@@ -552,6 +552,111 @@ async function handleGetDownloadInfo(p, sendResponse) {
|
||||
}
|
||||
}
|
||||
|
||||
// ============ 购买:当前商品(套餐)→ 订单 → 支付 → 自动激活本机 ============
|
||||
// 只调用授权系统的公开接口读取在售商品、创建订单,不改动服务端任何配置。
|
||||
|
||||
// 当前在售商品:由授权系统实时下发(页面显示的就是当前在售的)
|
||||
async function getCardTypes() {
|
||||
try {
|
||||
const r = await authFetch("/public/projects/" + PROJECT_ID + "/card-types", {}, 8000);
|
||||
if (r && r.code === 200 && Array.isArray(r.data)) return { ok: true, data: r.data };
|
||||
return { ok: false, data: [], message: (r && r.message) || "商品加载失败" };
|
||||
} catch (e) {
|
||||
return { ok: false, data: [], message: String(e && e.message || e) };
|
||||
}
|
||||
}
|
||||
|
||||
// 创建订单:contact_info 带机器码 → 支付成功后服务端自动发卡并绑定本机
|
||||
async function authCreateOrder(payType, cardTypeId) {
|
||||
const pay = payType === "wxpay" ? "wxpay" : "alipay";
|
||||
const types = await getCardTypes();
|
||||
if (!types.ok || !types.data.length) return { ok: false, message: types.message || "当前暂无在售商品" };
|
||||
const cardType = types.data.find(t => String(t.id) === String(cardTypeId))
|
||||
|| types.data.find(t => Number(t.price) > 0)
|
||||
|| types.data[0];
|
||||
if (!cardType) return { ok: false, message: "商品不存在,请重新选择" };
|
||||
|
||||
const machine = await getMachineId();
|
||||
const price = Number(cardType.price);
|
||||
const r = await authFetch("/public/orders", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json", "X-Api-Key": CARD_API_KEY },
|
||||
body: JSON.stringify({
|
||||
project_id: PROJECT_ID,
|
||||
card_type_id: cardType.id,
|
||||
amount: price,
|
||||
pay_type: pay,
|
||||
contact_info: "MACHINE:" + machine
|
||||
})
|
||||
}, 15000);
|
||||
|
||||
if (!r || r.code !== 200 || !r.data) return { ok: false, message: (r && r.message) || "创建订单失败" };
|
||||
|
||||
// 记住进行中的订单,供后台轮询恢复
|
||||
const pendingOrder = {
|
||||
orderNo: r.data.order_no,
|
||||
payType: pay,
|
||||
amount: r.data.pay_amount != null ? Number(r.data.pay_amount) : price,
|
||||
originalPrice: price,
|
||||
packageName: cardType.name || "",
|
||||
createdAt: Date.now()
|
||||
};
|
||||
await chrome.storage.local.set({ pendingOrder });
|
||||
scheduleOrderPolling();
|
||||
|
||||
return { ok: true, order: pendingOrder, payUrl: r.data.pay_url || "", cardTypeName: cardType.name };
|
||||
}
|
||||
|
||||
// 查询订单:服务端发卡后返回 card_key,拿到即自动激活本机
|
||||
async function authQueryOrder(orderNo) {
|
||||
const r = await authFetch("/public/orders/query?order_no=" + encodeURIComponent(orderNo), {}, 8000);
|
||||
if (!r || r.code !== 200 || !r.data) return { ok: false, message: (r && r.message) || "订单查询失败" };
|
||||
const d = r.data;
|
||||
const out = {
|
||||
ok: true,
|
||||
paid: d.status === "paid" || !!d.card_key,
|
||||
status: d.status || "",
|
||||
cardKey: d.card_key || "",
|
||||
expireTime: d.expire_time || ""
|
||||
};
|
||||
if (out.cardKey) {
|
||||
const act = await activateCard(out.cardKey);
|
||||
out.activated = !!(act && act.ok);
|
||||
out.message = (act && act.message) || "";
|
||||
if (out.activated) {
|
||||
await chrome.storage.local.remove(["pendingOrder"]);
|
||||
await clearOrderAlarm();
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// 后台轮询:购买页被关掉也能走完「支付 → 发卡 → 激活」
|
||||
async function scheduleOrderPolling() {
|
||||
try { if (chrome.alarms) await chrome.alarms.create("orderPoll", { periodInMinutes: 1 }); } catch (e) {}
|
||||
}
|
||||
async function clearOrderAlarm() {
|
||||
try { if (chrome.alarms) await chrome.alarms.clear("orderPoll"); } catch (e) {}
|
||||
}
|
||||
if (chrome.alarms && chrome.alarms.onAlarm) {
|
||||
chrome.alarms.onAlarm.addListener(async (alarm) => {
|
||||
if (!alarm || alarm.name !== "orderPoll") return;
|
||||
try {
|
||||
const st = await chrome.storage.local.get("pendingOrder");
|
||||
const po = st.pendingOrder;
|
||||
if (!po || !po.orderNo) { await clearOrderAlarm(); return; }
|
||||
// 超过 12 小时未完成就不再追问,避免永久轮询
|
||||
if (Date.now() - (Number(po.createdAt) || 0) > 12 * 3600 * 1000) {
|
||||
await chrome.storage.local.remove(["pendingOrder"]);
|
||||
await clearOrderAlarm();
|
||||
return;
|
||||
}
|
||||
const res = await authQueryOrder(po.orderNo);
|
||||
if (res && res.activated) await clearOrderAlarm();
|
||||
} catch (e) { /* 单次轮询失败不影响下次 */ }
|
||||
});
|
||||
}
|
||||
|
||||
// ============ 消息路由 ============
|
||||
|
||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
@@ -593,6 +698,19 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
})();
|
||||
return true;
|
||||
}
|
||||
// 当前商品选择页(buy.html)用
|
||||
if (msg.action === "getCardTypes") {
|
||||
getCardTypes().then(sendResponse).catch(e => sendResponse({ ok: false, data: [], message: String(e && e.message || e) }));
|
||||
return true;
|
||||
}
|
||||
if (msg.action === "authCreateOrder") {
|
||||
authCreateOrder(msg.payType, msg.cardTypeId).then(sendResponse).catch(e => sendResponse({ ok: false, message: String(e && e.message || e) }));
|
||||
return true;
|
||||
}
|
||||
if (msg.action === "authQueryOrder") {
|
||||
authQueryOrder(msg.orderNo).then(sendResponse).catch(e => sendResponse({ ok: false, message: String(e && e.message || e) }));
|
||||
return true;
|
||||
}
|
||||
if (msg.action === "setTask") {
|
||||
ACTIVE_TASK = msg.task || null;
|
||||
sendResponse({ ok: true });
|
||||
|
||||
Reference in new issue
Block a user