5 个赞
老哥英国的team车停了,等下次吧
2 个赞
这就是刚才找的呀,只是和土区没有什么优势。我已经有土区 plus 了
刚开通成功。 我运气真好啊,11欧元开的。
2 个赞
他说的11磅的没了,那个两个位置才100
2 个赞
有码子可以分享一下吗~求求了 是一晚上了
1 个赞
老哥用了什么码呀,求求求求,急死了
相当于100两个team子号吗?一个月?连续48个月都是这个价格是吧
1 个赞
主号和一个子号,连续48个月,如果openai不改的话
哦哦哦,那如果中间有一个月断了不相续也没关系吗,反正48个月内,想续都是11刀咯
- 代码直接贴到油猴(tampermonkey)中
- 这个帖子中的优惠码还可以用,https://linux.do/t/topic/2149874
- IP 正确,使用优惠链接就会直接弹出付费框
// ==UserScript==
// @name ChatGPT Team 支付长链接生成器
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 在 ChatGPT 页面右下角添加悬浮按钮,一键生成 Team 计划支付链接。左键生成,右键设置。
// @author Qingyu
// @match https://chatgpt.com/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// ================= 配置管理 =================
const STORAGE_KEYS = { PROMO: 'team_promo_v2', CANCEL: 'team_cancel_v2' };
const getConfig = () => ({
promoCode: GM_getValue(STORAGE_KEYS.PROMO, 'codestonegb'),
cancelUrl: GM_getValue(STORAGE_KEYS.CANCEL, 'https://chatgpt.com/#team-pricing')
});
// ================= SVG 图标 =================
const ICONS = {
link: '<svg size="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.812a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"></path></svg>',
check: '<svg size="16" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"></path></svg>',
x: '<svg size="16" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24"><path d="M6 18L18 6M6 6l12 12"></path></svg>',
config: '<svg size="20" fill="none" stroke="#6e6e80" stroke-width="2" viewBox="0 0 24 24"><path d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><circle cx="12" cy="12" r="3"></circle></svg>'
};
// ================= 样式注入 =================
const injectStyles = () => {
const style = document.createElement('style');
style.textContent = `
/* 主按钮 */
#tm-pro-btn {
position: fixed; bottom: 24px; right: 24px; z-index: 10000;
padding: 10px 20px;
background: linear-gradient(135deg, #10a37f 0%, #15be93 100%);
color: white; border-radius: 20px;
cursor: pointer; font-size: 14px; font-weight: 600;
font-family: Söhne, ui-sans-serif, system-ui, sans-serif;
box-shadow: 0 4px 15px rgba(16, 163, 127, 0.3);
user-select: none; transition: all 0.2s cubic-bezier(0.2, 0, 0, 1);
display: flex; align-items: center; gap: 8px; overflow: hidden;
}
#tm-pro-btn svg { width: 16px; height: 16px; transition: transform 0.2s; }
#tm-pro-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(16, 163, 127, 0.4);
}
#tm-pro-btn:hover svg { transform: rotate(15deg); }
#tm-pro-btn:active { transform: translateY(0px) scale(0.97); }
/* 加载动画 */
#tm-pro-btn.loading { background: #6e6e80; cursor: not-allowed; box-shadow: none; }
#tm-pro-btn.loading svg { animation: spin 1s linear infinite; }
@keyframes spin { 100% { transform: rotate(360deg); } }
#tm-pro-btn.loading::after {
content: ''; position: absolute; top: 0; left: -100%; width: 200%; height: 100%;
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.2) 50%, transparent 100%);
animation: loading-wave 1.5s infinite;
}
@keyframes loading-wave { 0% { left: -100%; } 100% { left: 100%; } }
#tm-pro-btn.success { background: #19c37d; }
#tm-pro-btn.error { background: #ef4444; }
/* 配置模态窗 */
#tm-config-overlay {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px);
z-index: 10001; display: none; justify-content: center; align-items: center;
opacity: 0; transition: opacity 0.2s;
}
#tm-config-overlay.open { display: flex; opacity: 1; }
#tm-config-modal {
background: #fff; width: 400px; padding: 24px; border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
transform: scale(0.9); transition: transform 0.2s cubic-bezier(0.2, 0, 0, 1);
color: #333; font-family: sans-serif;
}
.dark #tm-config-modal { background: #202123; color: #ececf1; }
#tm-config-overlay.open #tm-config-modal { transform: scale(1); }
.tm-modal-header { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; font-weight: bold; font-size: 18px; }
.tm-form-group { margin-bottom: 16px; }
.tm-label { display: block; margin-bottom: 6px; font-size: 13px; color: #6e6e80; }
.dark .tm-label { color: #8e8e93; }
.tm-input {
width: 100%; padding: 10px 12px; border: 1px solid #ddd; border-radius: 6px;
background: #fff; color: #000; font-size: 14px; box-sizing: border-box;
}
.tm-input:focus { outline: 2px solid #10a37f; border-color: transparent; }
.dark .tm-input { background: #343541; border-color: #444654; color: #fff; }
.tm-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 24px; }
.tm-btn { padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: 500; border: none; }
.tm-btn-cancel { background: #eee; color: #333; }
.tm-btn-cancel:hover { background: #ddd; }
.dark .tm-btn-cancel { background: #444654; color: #ececf1; }
.dark .tm-btn-cancel:hover { background: #545664; }
.tm-btn-save { background: #10a37f; color: white; }
.tm-btn-save:hover { background: #1a7f64; }
`;
document.head.appendChild(style);
};
// ================= UI 创建 =================
let overlay, promoInput, cancelInput;
const createUI = () => {
// 1. 创建主按钮
const btn = document.createElement('div');
btn.id = 'tm-pro-btn';
btn.innerHTML = `${ICONS.link}<span id="tm-pro-text">生成 Team 链接</span>`;
document.body.appendChild(btn);
// 2. 创建配置模态窗
overlay = document.createElement('div');
overlay.id = 'tm-config-overlay';
overlay.innerHTML = `
<div id="tm-config-modal">
<div class="tm-modal-header">${ICONS.config} 链接参数设置</div>
<div class="tm-form-group">
<label class="tm-label">优惠码</label>
<input type="text" id="tm-input-promo" class="tm-input" placeholder="codestonegb">
</div>
<div class="tm-form-group">
<label class="tm-label">取消支付跳转</label>
<input type="text" id="tm-input-cancel" class="tm-input" placeholder="https://chatgpt.com/#team-pricing">
</div>
<div class="tm-modal-actions">
<button class="tm-btn tm-btn-cancel" id="tm-config-close">取消</button>
<button class="tm-btn tm-btn-save" id="tm-config-save">保存</button>
</div>
</div>
`;
document.body.appendChild(overlay);
promoInput = document.getElementById('tm-input-promo');
cancelInput = document.getElementById('tm-input-cancel');
return btn;
};
// ================= 交互逻辑 =================
const showConfig = () => {
const config = getConfig();
promoInput.value = config.promoCode;
cancelInput.value = config.cancelUrl;
overlay.classList.add('open');
};
const hideConfig = () => { overlay.classList.remove('open'); };
const saveConfig = () => {
GM_setValue(STORAGE_KEYS.PROMO, promoInput.value.trim());
GM_setValue(STORAGE_KEYS.CANCEL, cancelInput.value.trim());
hideConfig();
showStatus('success', '配置已保存');
};
const setButtonState = (btn, text, state) => {
const textSpan = btn.querySelector('#tm-pro-text');
textSpan.innerText = text;
btn.className = ''; // 移除 loading, success, error
if (state === 'loading') {
btn.classList.add('loading');
btn.innerHTML = `<svg class="animate-spin" size="16" fill="none" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" style="opacity:0.25"></circle><path fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg><span id="tm-pro-text">${text}</span>`;
} else if (state === 'success') {
btn.classList.add('success');
btn.innerHTML = `${ICONS.check}<span id="tm-pro-text">${text}</span>`;
} else if (state === 'error') {
btn.classList.add('error');
btn.innerHTML = `${ICONS.x}<span id="tm-pro-text">${text}</span>`;
} else {
btn.innerHTML = `${ICONS.link}<span id="tm-pro-text">${text}</span>`;
}
};
// 临时状态显示
const showStatus = (state, text) => {
const btn = document.getElementById('tm-pro-btn');
const oldText = getConfig().promoCode;
setButtonState(btn, text, state);
setTimeout(() => setButtonState(btn, `生成 Team 链接`, 'normal'), 2000);
};
// ================= 核心请求 =================
async function run(e) {
const btn = e.currentTarget;
if (btn.classList.contains('loading')) return;
const config = getConfig();
setButtonState(btn, '正在获取 Token...', 'loading');
try {
const session = await fetch("/api/auth/session").then(r => r.json()).catch(()=>({}));
const token = session?.accessToken;
if (!token) throw new Error("请先登录 ChatGPT");
setButtonState(btn, '正在请求 Stripe...', 'loading');
const res = await fetch("https://chatgpt.com/backend-api/payments/checkout", {
method: "POST",
headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
body: JSON.stringify({
plan_name: "chatgptteamplan",
team_plan_data: { workspace_name: "MyTeam", price_interval: "month", seat_quantity: 2 },
billing_details: { country: "GB", currency: "GBP" },
cancel_url: config.cancelUrl,
promo_code: config.promoCode,
checkout_ui_mode: "hosted",
}),
});
const data = await res.json();
const url = data?.url || data?.stripe_hosted_url || data?.checkout_url;
if (url) {
setButtonState(btn, '生成成功!准备跳转', 'success');
setTimeout(() => {
const go = window.confirm(`✅ 生成成功!Promo: ${config.promoCode}\n\n点击“确定”将在当前页跳转至支付页面。\n点击“取消”复制链接。`);
if (go) window.location.href = url;
else window.prompt("请复制链接:", url);
setButtonState(btn, '生成 Team 链接', 'normal');
}, 200);
} else {
throw new Error(data?.detail || "响应未包含链接");
}
} catch (e) {
setButtonState(btn, '失败: ' + e.message, 'error');
setTimeout(() => setButtonState(btn, '生成 Team 链接', 'normal'), 3000);
}
}
// ================= 初始化 =================
injectStyles();
const proBtn = createUI();
// 事件绑定
proBtn.addEventListener('click', run);
proBtn.addEventListener('contextmenu', (e) => {
e.preventDefault();
showConfig();
});
document.getElementById('tm-config-close').addEventListener('click', hideConfig);
document.getElementById('tm-config-save').addEventListener('click', saveConfig);
// 点击遮罩层关闭
overlay.addEventListener('click', (e) => {
if (e.target === overlay) hideConfig();
});
// 快捷键 Esc 关闭
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && overlay.classList.contains('open')) hideConfig();
});
})();
2 个赞
11英镑的优惠码今天下午晚上用完了,我也没赶上,开了美区的。18英镑确实不划算了,不如美区20刀的
2 个赞
佬,请问按照这个搞出来,是多少钱的啊。
现在英区好像已经涨价了,昨天没有赶上可惜了
