├── .gitignore ├── .vscode └── settings.json ├── README.md ├── api ├── get_login_openai_token.go ├── get_openai_token.go ├── refresh_openai_token.go └── revoke_openai_token.go ├── go.mod ├── public ├── login.html └── third.html └── vercel.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vercel 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ayuayue/chatgpt_token_vercel/ac9dd586e46f162a7dae1684c28a34bfbefa00fd/.vscode/settings.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 官方文档: https://vercel.com/docs/concepts/functions/serverless-functions 4 | 5 | 这是一个部署在 vercel 上的 serverless,使用 go,js,或者其他语言来写。 6 | 7 | 所有的接口都要在 api 目录下。 8 | 9 | | 接口 | 说明 | 10 | |---------|---------| 11 | | / | 官网直登获取 Token 功能页面 | 12 | | /third | 第三方账号获取 Token 页面 | 13 | | /getOpenAItoken | 官网直登获取 Token 接口 | 14 | | /getOpenAItokenByCode | 通过 Code 获取 Token 接口 | 15 | | /revokeOpenAIToken | 撤销 refresh_token 接口 | 16 | | /refreshOpenAIToken | 刷新 Token 接口 | 17 | 18 | 19 | 部署地区:regions :sin1 新加坡 20 | 21 | 22 | 如果要部署官网直登的api接口,需要在 vercel 上设置环境变量,key 是 LoginURL,值就是自己部署的 pandora 项目域名,注意不要用 cf 的安全模式,不然没法直接调用,因为安全问题需要手动验证。 23 | 24 | 25 | Vercel 26 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fayuayue%2Fchatgpt_token_vercel) -------------------------------------------------------------------------------- /api/get_login_openai_token.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "strings" 7 | "regexp" 8 | "os" 9 | "net/url" 10 | ) 11 | 12 | func GetLoginToken(w http.ResponseWriter, r *http.Request) { 13 | loginUrl := os.Getenv("LoginURL")+"/auth/login" 14 | method := "POST" 15 | params := url.Values{} 16 | params.Set("username", r.PostFormValue("username")) 17 | params.Set("password", r.PostFormValue("password")) 18 | params.Set("mfa_code", r.PostFormValue("mfa_code")) 19 | params.Set("action", "default") 20 | params.Set("next", "") 21 | payload := strings.NewReader(params.Encode()) 22 | fmt.Println(params.Encode()) 23 | 24 | client := &http.Client{ 25 | CheckRedirect: func(req *http.Request, via []*http.Request) error { 26 | return http.ErrUseLastResponse 27 | }, 28 | } 29 | 30 | req, err := http.NewRequest(method, loginUrl, payload) 31 | if err != nil { 32 | fmt.Fprint(w, err.Error()) 33 | return 34 | } 35 | req.Header.Add("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)") 36 | req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 37 | res, err := client.Do(req) 38 | if err != nil { 39 | fmt.Fprint(w, err) 40 | } 41 | defer res.Body.Close() 42 | 43 | 44 | // 获取重定向返回的 header 45 | redirectHeaders := res.Header 46 | 47 | // 将 header 转换为字符串 48 | var sb strings.Builder 49 | for key, values := range redirectHeaders { 50 | for _, value := range values { 51 | sb.WriteString(key) 52 | sb.WriteString(": ") 53 | sb.WriteString(value) 54 | sb.WriteString("\r\n") 55 | } 56 | } 57 | redirectHeadersStr := sb.String() 58 | 59 | 60 | // 使用正则表达式匹配 access_token 的内容 61 | regex := regexp.MustCompile(`access-token=(.*?);`) 62 | matches := regex.FindStringSubmatch(redirectHeadersStr) 63 | 64 | if len(matches) > 1 { 65 | accessToken := matches[1] 66 | fmt.Fprint(w, "Access Token:"+accessToken) 67 | } else { 68 | fmt.Fprint(w, "Access Token not found in the response.") 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /api/get_openai_token.go: -------------------------------------------------------------------------------- 1 | 2 | package api 3 | 4 | import ( 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | "strings" 9 | ) 10 | 11 | func GetToken(w http.ResponseWriter, r *http.Request) { 12 | url := "https://auth0.openai.com/oauth/token" 13 | method := "POST" 14 | code := r.PostFormValue("code") 15 | payload := `{ 16 | "redirect_uri": "com.openai.chat://auth0.openai.com/ios/com.openai.chat/callback", 17 | "grant_type": "authorization_code", 18 | "client_id": "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh", 19 | "code": "` + code + `", 20 | "code_verifier": "yGrXROHx_VazA0uovsxKfE263LMFcrSrdm4SlC-rob8" 21 | }` 22 | client := &http.Client{} 23 | req, err := http.NewRequest(method, url, strings.NewReader(payload)) 24 | 25 | if err != nil { 26 | fmt.Fprint(w, err.Error()) 27 | } 28 | req.Header.Add("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)") 29 | req.Header.Add("Content-Type", "application/json") 30 | 31 | res, err := client.Do(req) 32 | if err != nil { 33 | fmt.Fprint(w, err) 34 | } 35 | defer res.Body.Close() 36 | 37 | body, err := ioutil.ReadAll(res.Body) 38 | if err != nil { 39 | fmt.Fprint(w, err.Error()) 40 | } 41 | fmt.Fprint(w, string(body)) 42 | } 43 | -------------------------------------------------------------------------------- /api/refresh_openai_token.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | "strings" 8 | ) 9 | 10 | func RefreshToken(w http.ResponseWriter, r *http.Request) { 11 | url := "https://auth0.openai.com/oauth/token" 12 | method := "POST" 13 | token := r.PostFormValue("refresh_token") 14 | payload := `{ 15 | "redirect_uri": "com.openai.chat://auth0.openai.com/ios/com.openai.chat/callback", 16 | "grant_type": "refresh_token", 17 | "client_id": "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh", 18 | "refresh_token": "` + token + `" 19 | }` 20 | client := &http.Client{} 21 | req, err := http.NewRequest(method, url, strings.NewReader(payload)) 22 | 23 | if err != nil { 24 | fmt.Fprint(w, err.Error()) 25 | } 26 | req.Header.Add("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)") 27 | req.Header.Add("Content-Type", "application/json") 28 | 29 | res, err := client.Do(req) 30 | if err != nil { 31 | fmt.Fprint(w, err) 32 | } 33 | defer res.Body.Close() 34 | 35 | body, err := ioutil.ReadAll(res.Body) 36 | if err != nil { 37 | fmt.Fprint(w, err.Error()) 38 | } 39 | fmt.Fprint(w, string(body)) 40 | } 41 | -------------------------------------------------------------------------------- /api/revoke_openai_token.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | "strings" 8 | ) 9 | 10 | 11 | func RevokeToken(w http.ResponseWriter, r *http.Request) { 12 | url := "https://auth0.openai.com/oauth/revoke" 13 | method := "POST" 14 | token := r.PostFormValue("token") 15 | payload := `{ 16 | "client_id": "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh", 17 | "token": "` + token + `" 18 | }` 19 | client := &http.Client{} 20 | req, err := http.NewRequest(method, url, strings.NewReader(payload)) 21 | 22 | if err != nil { 23 | fmt.Fprint(w, err.Error()) 24 | } 25 | req.Header.Add("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)") 26 | req.Header.Add("Content-Type", "application/json") 27 | 28 | res, err := client.Do(req) 29 | if err != nil { 30 | fmt.Fprint(w, err) 31 | } 32 | defer res.Body.Close() 33 | 34 | body, err := ioutil.ReadAll(res.Body) 35 | if err != nil { 36 | fmt.Fprint(w, err.Error()) 37 | } 38 | fmt.Fprint(w, string(body)) 39 | } 40 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module my-vercel-function 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /public/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Pandora 7 | 21 | 22 | 23 |

这是一个获取 openai token 的辅助工具(由 chatgpt、github copilot 协助开发)

24 |
25 |

官方账号直接登录获取Token,MFA两步验证功能未经验证,如失败请转到 Github issues

26 |

如该站被限制,可以自己 fork 项目使用 vercel 搭建pandora及此服务,自用基本比较稳,并且不需要服务器 跳转到项目地址

27 |

关于在 vercel 上部署 pandora

28 |
29 |

30 |

31 | 32 | 33 | 34 | 35 | 36 | 37 |

38 | 39 |
40 | 41 |

42 |

43 | 返回信息:(只需要 access_token 即可登录) 44 |

45 |

46 |

没有官方直登账号,想要使用第三方(谷歌、微软等)登录?

47 | 点击此处使用第三方账号获取Token 48 |

49 |

如果上面的服务不可用,可以使用下面这个

50 | 点击此处使用第三方账号获取Token 51 |

52 |

53 | 本项目由 zhile.io 博客 指导 并由 vercel 部署完成。 54 |

55 |
56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /public/third.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Pandora 7 | 21 | 22 | 23 |

这是一个获取 openai token 的辅助工具(由 chatgpt、github copilot 协助开发)

24 | 25 |
26 |

27 | 1. 首先需要能正常登录 chat.openai.com 。然后点击下面的登录链接。

28 | 2. 然后在浏览器中打开开发者工具,切换到 Network 选项卡。

29 | 3. 登录后最后会卡住,并最后有一个重定向的请求,参数携带的有 code,并且只有一个 code 参数的那个请求才是。需要把 code 复制过来,获取 token。

30 | 4. 不会保存任何的信息,只充当一个调用工具,不做任何处理就返回原数据。

31 | 5. 获取token后,进入 Pandora 页面,并填写使用获取到的 access_token 登录即可。 32 |

33 |

点击跳转到登录页面 34 |

35 | 36 |

37 |

38 |

39 | 40 |

41 | 42 |
43 | 44 |

45 |

46 |

47 |

48 | 49 |

50 | 51 |
52 |

53 |

54 |

55 |

56 | 57 |

58 | 59 |
60 |

61 |

62 | 返回信息:(只需要 access_token 即可登录) 63 |

64 |

65 |
66 |

67 | 本项目由 zhile.io 博客 指导 并由 vercel 部署完成。 68 |

69 |
70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "env": { 4 | "GO_BUILD_FLAGS": "-ldflags '-s -w'" 5 | } 6 | }, 7 | 8 | "routes": [ 9 | { "handle": "filesystem" }, 10 | { 11 | "src": "/", 12 | "status": 200, 13 | "dest": "login.html" 14 | }, 15 | { 16 | "src": "/third", 17 | "status": 200, 18 | "dest": "third.html" 19 | }, 20 | { 21 | "src": "/getOpenAItoken", 22 | "status": 200, 23 | "dest": "/api/get_login_openai_token" 24 | }, 25 | { 26 | "src": "/getOpenAItokenByCode", 27 | "status": 200, 28 | "dest": "/api/get_openai_token" 29 | }, 30 | { 31 | "src": "/revokeOpenAIToken", 32 | "status": 200, 33 | "dest": "/api/revoke_openai_token" 34 | }, 35 | { 36 | "src": "/refreshOpenAIToken", 37 | "status": 200, 38 | "dest": "/api/refresh_openai_token" 39 | } 40 | ], 41 | "regions": ["sin1"] 42 | } 43 | --------------------------------------------------------------------------------