|
|
@@ -56,11 +56,23 @@ public class OpenAiRegisterService {
|
|
|
|
|
|
// ===== 步骤2: 访问 OpenAI 授权页获取 Device ID =====
|
|
|
log.info("[步骤2] 访问 OpenAI 授权页获取 Device ID...");
|
|
|
- OAuthStart oauth = oauthService.generateOAuthUrl(OAuthService.DEFAULT_REDIRECT_URI);
|
|
|
+ OAuthStart oauth = oauthService.generateOAuthUrl(OAuthService.DEFAULT_REDIRECT_URI, "signup");
|
|
|
Response authPageResp = s.newCall(new Request.Builder().url(oauth.getAuthUrl())
|
|
|
.header("user-agent", UA).header("accept", "application/json, text/plain, */*").build()).execute();
|
|
|
+ String authBody = authPageResp.body() != null ? authPageResp.body().string() : "";
|
|
|
authPageResp.close();
|
|
|
|
|
|
+ try {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ Map<String, Object> authJson = mapper.readValue(authBody, Map.class);
|
|
|
+ String continueUrl = String.valueOf(authJson.getOrDefault("continue_url", "")).strip();
|
|
|
+ if (!continueUrl.isBlank()) {
|
|
|
+ s.newCall(new Request.Builder().url(continueUrl).header("user-agent", UA).get().build()).execute()
|
|
|
+ .close();
|
|
|
+ }
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
+
|
|
|
String did = getCookieValue(s, "oai-did");
|
|
|
if (did == null || did.isBlank()) {
|
|
|
log.warn("[失败] 未能从 Cookie 获取 oai-did");
|
|
|
@@ -88,7 +100,8 @@ public class OpenAiRegisterService {
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
.header("openai-sentinel-token", authorizeContinueSentinel)
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(usernamePayload), MediaType.parse("application/json")))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(usernamePayload),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] 邮箱提交状态: {}", signupRes.code());
|
|
|
if (signupRes.code() != 200) {
|
|
|
@@ -101,13 +114,16 @@ public class OpenAiRegisterService {
|
|
|
|
|
|
// ===== 步骤4: 设置账户密码 =====
|
|
|
log.info("[步骤4] 设置账户密码...");
|
|
|
- Map<String, String> pwdPayload = Map.of("password", password, "username", email);
|
|
|
+ Map<String, String> pwdPayload = new LinkedHashMap<>();
|
|
|
+ pwdPayload.put("username", email);
|
|
|
+ pwdPayload.put("password", password);
|
|
|
Response pwdRes = s.newCall(new Request.Builder()
|
|
|
.url("https://auth.openai.com/api/accounts/user/register")
|
|
|
.header("referer", "https://auth.openai.com/create-account/password")
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(pwdPayload), MediaType.parse("application/json")))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(pwdPayload),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] 密码设置状态: {}", pwdRes.code());
|
|
|
if (pwdRes.code() != 200) {
|
|
|
@@ -147,12 +163,15 @@ public class OpenAiRegisterService {
|
|
|
|
|
|
// ===== 步骤7: 提交验证码 =====
|
|
|
log.info("[步骤7] 提交验证码至 OpenAI...");
|
|
|
+ Map<String, String> otpPayload = new LinkedHashMap<>();
|
|
|
+ otpPayload.put("code", code);
|
|
|
Response valRes = s.newCall(new Request.Builder()
|
|
|
.url("https://auth.openai.com/api/accounts/email-otp/validate")
|
|
|
.header("referer", "https://auth.openai.com/email-verification")
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(Map.of("code", code)), MediaType.parse("application/json")))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(otpPayload),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] 验证码校验状态: {}", valRes.code());
|
|
|
if (valRes.code() != 200) {
|
|
|
@@ -173,14 +192,17 @@ public class OpenAiRegisterService {
|
|
|
return Optional.empty();
|
|
|
}
|
|
|
|
|
|
- Map<String, String> accPayload = Map.of("name", PkceUtil.randomName(), "birthdate", PkceUtil.randomBirthdate());
|
|
|
+ Map<String, String> accPayload = new LinkedHashMap<>();
|
|
|
+ accPayload.put("name", PkceUtil.randomName());
|
|
|
+ accPayload.put("birthdate", PkceUtil.randomBirthdate());
|
|
|
Response accRes = s.newCall(new Request.Builder()
|
|
|
.url("https://auth.openai.com/api/accounts/create_account")
|
|
|
.header("referer", "https://auth.openai.com/about-you")
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
.header("openai-sentinel-token", createAccountSentinel)
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(accPayload), MediaType.parse("application/json")))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(accPayload),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] 账户创建状态: {}", accRes.code());
|
|
|
if (accRes.code() != 200) {
|
|
|
@@ -198,8 +220,23 @@ public class OpenAiRegisterService {
|
|
|
try {
|
|
|
log.info("[*] 正在通过登录流程获取 Token...{}", loginAttempt > 0 ? " (重试 " + loginAttempt + "/3)" : "");
|
|
|
OkHttpClient s2 = buildClient(proxy);
|
|
|
- OAuthStart oauth2 = oauthService.generateOAuthUrl(OAuthService.DEFAULT_REDIRECT_URI);
|
|
|
- s2.newCall(new Request.Builder().url(oauth2.getAuthUrl()).header("user-agent", UA).build()).execute().close();
|
|
|
+ OAuthStart oauth2 = oauthService.generateOAuthUrl(OAuthService.DEFAULT_REDIRECT_URI, "login");
|
|
|
+ Response lRes = s2
|
|
|
+ .newCall(new Request.Builder().url(oauth2.getAuthUrl()).header("user-agent", UA).build())
|
|
|
+ .execute();
|
|
|
+ String lBody = lRes.body() != null ? lRes.body().string() : "";
|
|
|
+ lRes.close();
|
|
|
+
|
|
|
+ try {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ Map<String, Object> lJson = mapper.readValue(lBody, Map.class);
|
|
|
+ String lContinueUrl = String.valueOf(lJson.getOrDefault("continue_url", "")).strip();
|
|
|
+ if (!lContinueUrl.isBlank()) {
|
|
|
+ s2.newCall(new Request.Builder().url(lContinueUrl).header("user-agent", UA).get().build())
|
|
|
+ .execute().close();
|
|
|
+ }
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
|
|
|
String did2 = getCookieValue(s2, "oai-did");
|
|
|
if (did2 == null || did2.isBlank()) {
|
|
|
@@ -217,8 +254,10 @@ public class OpenAiRegisterService {
|
|
|
.header("referer", "https://auth.openai.com/log-in")
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
- .header("openai-sentinel-token", sentinelService.buildSentinelPayload(s2, did2, "authorize_continue"))
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(loginUsernamePayload), MediaType.parse("application/json")))
|
|
|
+ .header("openai-sentinel-token",
|
|
|
+ sentinelService.buildSentinelPayload(s2, did2, "authorize_continue"))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(loginUsernamePayload),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] 登录邮箱提交状态: {}", lc.code());
|
|
|
if (lc.code() != 200) {
|
|
|
@@ -233,17 +272,22 @@ public class OpenAiRegisterService {
|
|
|
Map<String, Object> lcData = mapper.readValue(lcBody, Map.class);
|
|
|
String continueUrl = String.valueOf(lcData.getOrDefault("continue_url", "")).strip();
|
|
|
if (!continueUrl.isBlank()) {
|
|
|
- s2.newCall(new Request.Builder().url(continueUrl).header("user-agent", UA).get().build()).execute().close();
|
|
|
+ s2.newCall(new Request.Builder().url(continueUrl).header("user-agent", UA).get().build())
|
|
|
+ .execute().close();
|
|
|
}
|
|
|
|
|
|
// 提交密码
|
|
|
+ Map<String, String> lPwdPayload = new LinkedHashMap<>();
|
|
|
+ lPwdPayload.put("password", password);
|
|
|
Response pw = s2.newCall(new Request.Builder()
|
|
|
.url("https://auth.openai.com/api/accounts/password/verify")
|
|
|
.header("referer", "https://auth.openai.com/log-in/password")
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
- .header("openai-sentinel-token", sentinelService.buildSentinelPayload(s2, did2, "authorize_continue"))
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(Map.of("password", password)), MediaType.parse("application/json")))
|
|
|
+ .header("openai-sentinel-token",
|
|
|
+ sentinelService.buildSentinelPayload(s2, did2, "authorize_continue"))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(lPwdPayload),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] 登录密码验证状态: {}", pw.code());
|
|
|
if (pw.code() != 200) {
|
|
|
@@ -273,12 +317,15 @@ public class OpenAiRegisterService {
|
|
|
log.info("[成功] 捕获登录 OTP: {}", otp2);
|
|
|
|
|
|
// 提交登录 OTP
|
|
|
+ Map<String, String> lOtpPayload = new LinkedHashMap<>();
|
|
|
+ lOtpPayload.put("code", otp2);
|
|
|
Response val2 = s2.newCall(new Request.Builder()
|
|
|
.url("https://auth.openai.com/api/accounts/email-otp/validate")
|
|
|
.header("referer", "https://auth.openai.com/email-verification")
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(Map.of("code", otp2)), MediaType.parse("application/json")))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(lOtpPayload),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] 登录 OTP 校验状态: {}", val2.code());
|
|
|
if (val2.code() != 200) {
|
|
|
@@ -295,7 +342,8 @@ public class OpenAiRegisterService {
|
|
|
|
|
|
String consentUrl = String.valueOf(val2Data.getOrDefault("continue_url", "")).strip();
|
|
|
if (!consentUrl.isBlank()) {
|
|
|
- s2.newCall(new Request.Builder().url(consentUrl).header("user-agent", UA).get().build()).execute().close();
|
|
|
+ s2.newCall(new Request.Builder().url(consentUrl).header("user-agent", UA).get().build())
|
|
|
+ .execute().close();
|
|
|
}
|
|
|
|
|
|
// 获取 auth cookie 中的 workspace
|
|
|
@@ -325,7 +373,8 @@ public class OpenAiRegisterService {
|
|
|
.header("referer", consentUrl)
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(Map.of("workspace_id", workspaceId)), MediaType.parse("application/json")))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(Map.of("workspace_id", workspaceId)),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] Workspace 选择状态: {}", selResp.code());
|
|
|
if (selResp.code() != 200) {
|
|
|
@@ -352,12 +401,14 @@ public class OpenAiRegisterService {
|
|
|
.url("https://auth.openai.com/api/accounts/organization/select")
|
|
|
.header("accept", "application/json")
|
|
|
.header("content-type", "application/json")
|
|
|
- .post(RequestBody.create(mapper.writeValueAsString(orgPayload), MediaType.parse("application/json")))
|
|
|
+ .post(RequestBody.create(mapper.writeValueAsString(orgPayload),
|
|
|
+ MediaType.parse("application/json")))
|
|
|
.build()).execute();
|
|
|
log.info("[日志] Organization 选择状态: {}", orgSel.code());
|
|
|
if (orgSel.code() != 200) {
|
|
|
String body = orgSel.body() != null ? orgSel.body().string() : "";
|
|
|
- log.warn("[失败] Organization 选择失败: {}", body.length() > 200 ? body.substring(0, 200) : body);
|
|
|
+ log.warn("[失败] Organization 选择失败: {}",
|
|
|
+ body.length() > 200 ? body.substring(0, 200) : body);
|
|
|
orgSel.close();
|
|
|
continue;
|
|
|
}
|
|
|
@@ -390,8 +441,10 @@ public class OpenAiRegisterService {
|
|
|
cbk = loc;
|
|
|
break;
|
|
|
}
|
|
|
- if ((r.code() < 301 || r.code() > 303) || loc == null || loc.isBlank()) break;
|
|
|
- r = s2NoRedir.newCall(new Request.Builder().url(loc).header("user-agent", UA).get().build()).execute();
|
|
|
+ if ((r.code() < 301 || r.code() > 303) || loc == null || loc.isBlank())
|
|
|
+ break;
|
|
|
+ r = s2NoRedir.newCall(new Request.Builder().url(loc).header("user-agent", UA).get().build())
|
|
|
+ .execute();
|
|
|
}
|
|
|
|
|
|
if (cbk == null) {
|
|
|
@@ -399,7 +452,8 @@ public class OpenAiRegisterService {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- String tokenJson = oauthService.submitCallbackUrl(s2, cbk, oauth2.getState(), oauth2.getCodeVerifier(), oauth2.getRedirectUri());
|
|
|
+ String tokenJson = oauthService.submitCallbackUrl(s2, cbk, oauth2.getState(),
|
|
|
+ oauth2.getCodeVerifier(), oauth2.getRedirectUri());
|
|
|
log.info("[大功告成] 账号注册完毕!");
|
|
|
|
|
|
RegisterResult result = new RegisterResult();
|
|
|
@@ -443,12 +497,14 @@ public class OpenAiRegisterService {
|
|
|
}
|
|
|
|
|
|
private String getCookieValue(OkHttpClient client, String name) {
|
|
|
- // OkHttp's CookieJar is backed by JavaNetCookieJar/CookieManager — inspect via cookie jar
|
|
|
+ // OkHttp's CookieJar is backed by JavaNetCookieJar/CookieManager — inspect via
|
|
|
+ // cookie jar
|
|
|
// We iterate all URLs we know cookies might be on
|
|
|
for (String domain : List.of("https://auth.openai.com", "https://openai.com")) {
|
|
|
List<Cookie> cookies = client.cookieJar().loadForRequest(HttpUrl.parse(domain));
|
|
|
for (Cookie c : cookies) {
|
|
|
- if (c.name().equals(name)) return c.value();
|
|
|
+ if (c.name().equals(name))
|
|
|
+ return c.value();
|
|
|
}
|
|
|
}
|
|
|
return null;
|
|
|
@@ -458,7 +514,8 @@ public class OpenAiRegisterService {
|
|
|
private String getNestedStr(Map<String, Object> map, String... keys) {
|
|
|
Object current = map;
|
|
|
for (String key : keys) {
|
|
|
- if (!(current instanceof Map)) return "";
|
|
|
+ if (!(current instanceof Map))
|
|
|
+ return "";
|
|
|
current = ((Map<String, Object>) current).get(key);
|
|
|
}
|
|
|
return current == null ? "" : String.valueOf(current);
|
|
|
@@ -468,7 +525,8 @@ public class OpenAiRegisterService {
|
|
|
private List<?> getNestedList(Map<String, Object> map, String... keys) {
|
|
|
Object current = map;
|
|
|
for (String key : keys) {
|
|
|
- if (!(current instanceof Map)) return null;
|
|
|
+ if (!(current instanceof Map))
|
|
|
+ return null;
|
|
|
current = ((Map<String, Object>) current).get(key);
|
|
|
}
|
|
|
return current instanceof List ? (List<?>) current : null;
|