From 9bcd9168abbec4878b44a5578ba88a355b0dadee Mon Sep 17 00:00:00 2001 From: CounterFire2023 <136581895+CounterFire2023@users.noreply.github.com> Date: Wed, 24 Jan 2024 16:11:12 +0800 Subject: [PATCH] add login with discord --- .env.development | 5 +++ packages/zutils | 2 +- src/controllers/discord.controller.ts | 21 ++++++++++ src/controllers/login.controller.ts | 4 +- src/controllers/wallet.controller.ts | 26 ++++++------ src/plats/PlatDiscord.ts | 60 +++++++++++++++++++++++++++ start.json | 4 +- 7 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 src/controllers/discord.controller.ts create mode 100644 src/plats/PlatDiscord.ts diff --git a/.env.development b/.env.development index f23e290..1059d6a 100644 --- a/.env.development +++ b/.env.development @@ -54,3 +54,8 @@ OKX_API_KEY='5cda794d-b2af-479c-bd75-af1eb877d4ef' OKX_PROJECT_ID='17c69bdda138a6342f9bece529030cbb' OKX_PASS='7654321Cf_' OKX_SECRET_KEY='AF7F4CEE2A10715F9709D38452CE0BFD' + + +DISCORD_CLIENT_ID='1199289311850409984' +DISCORD_CLIENT_SECRET='2ttcY7FgDXSo_izCD1BSZrORh864aR6r' +DISCORD_REDIRECT_URI='https://oauth-svr.cebggame.com/test/discord/oauth_redirect' \ No newline at end of file diff --git a/packages/zutils b/packages/zutils index b5f10e3..c1946bb 160000 --- a/packages/zutils +++ b/packages/zutils @@ -1 +1 @@ -Subproject commit b5f10e3d21e4cad0496ba0659232b3260946189e +Subproject commit c1946bbe7d53e21cf0c85ca13a82577751a04b7c diff --git a/src/controllers/discord.controller.ts b/src/controllers/discord.controller.ts new file mode 100644 index 0000000..52cb3f4 --- /dev/null +++ b/src/controllers/discord.controller.ts @@ -0,0 +1,21 @@ + +import logger from 'logger/logger' +import { IPlat } from 'plats/IPlat' +import { BaseController, ROLE_ANON, role, router } from 'zutils' +import { PlatDiscord } from 'plats/PlatDiscord' + +const plat: IPlat = new PlatDiscord() +class DiscordController extends BaseController { + + @role(ROLE_ANON) + @router('get /discord/oauth_redirect') + async appleWebLoginCb(req, res) { + const { code, state, error } = req.params + console.log(`code: ${code}, state: ${state}, error: ${error}`) + if (error) { + res.redirect(`cebgdiscordcb://discord_login_result?state=${state}&error=${JSON.stringify(error)}`) + } else { + res.redirect(`cebgdiscordcb://discord_login_result?token=${code}&state=${state}`) + } + } +} diff --git a/src/controllers/login.controller.ts b/src/controllers/login.controller.ts index 3f07651..3a7484b 100644 --- a/src/controllers/login.controller.ts +++ b/src/controllers/login.controller.ts @@ -6,6 +6,7 @@ import { Wallet } from 'modules/Wallet' import { IPlat } from 'plats/IPlat' import { PlatApple } from 'plats/PlatApple' import { PlatClient } from 'plats/PlatClient' +import { PlatDiscord } from 'plats/PlatDiscord' import { PlatExternalWallet } from 'plats/PlatExternalWallet' import { PlatFacebook } from 'plats/PlatFacebook' import { PlatGoogle } from 'plats/PlatGoogle' @@ -22,6 +23,7 @@ const plats: Map = new Map([ [PlatEnum.WC, new PlatExternalWallet()], [PlatEnum.EXTERNAL_WALLET, new PlatExternalWallet()], [PlatEnum.RELAY_WALLET, new PlatExternalWallet()], + [PlatEnum.DISCORD, new PlatDiscord()], ]) // 如果客户端有传入account, 则说明该次登录是绑定账号 @@ -101,7 +103,7 @@ class LoginController extends BaseController { } const plat = plats.get(channel) if (!plat) { - throw new ZError(11, 'plat not support') + throw new ZError(11, 'plat not support: ' + channel) } const { openId, data } = await plat.verifyToken(req) const { api_platform } = req.headers diff --git a/src/controllers/wallet.controller.ts b/src/controllers/wallet.controller.ts index dd068ab..42f0228 100644 --- a/src/controllers/wallet.controller.ts +++ b/src/controllers/wallet.controller.ts @@ -38,11 +38,12 @@ class WalletController extends BaseController { record.nweRecord = false await record.save() } - if (!record.toOkx && record.address) { - setImmediate(async () => { - await bindOkx(record) - }) - } + // TODO:: 临时处理 + // if (!record.toOkx && record.address) { + // setImmediate(async () => { + // await bindOkx(record) + // }) + // } Object.assign(data, record.toJson()) return data } @@ -85,13 +86,14 @@ class WalletController extends BaseController { } record.address = address await record.save() - if (!record.toOkx) { - if (!record.toOkx && record.address) { - setImmediate(async () => { - await bindOkx(record) - }) - } - } + // TODO:: 临时处理 + // if (!record.toOkx) { + // if (!record.toOkx && record.address) { + // setImmediate(async () => { + // await bindOkx(record) + // }) + // } + // } return {} } diff --git a/src/plats/PlatDiscord.ts b/src/plats/PlatDiscord.ts new file mode 100644 index 0000000..920a8d3 --- /dev/null +++ b/src/plats/PlatDiscord.ts @@ -0,0 +1,60 @@ +import { ZError } from 'zutils' +import { IPlat } from './IPlat' +import { handleFetch } from 'zutils/utils/net.util' + + +export async function exchangeDiscrodCodeForToken(code: string) { + const clientId = process.env.DISCORD_CLIENT_ID + const clientSecret = process.env.DISCORD_CLIENT_SECRET + const redirectUri = process.env.DISCORD_REDIRECT_URI + + const data = await handleFetch('https://discord.com/api/oauth2/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + client_id: clientId, + client_secret: clientSecret, + redirect_uri: redirectUri, + code, + scope: 'identify email', + }), + }) + + return data +} + +export async function userInfo(token: string) { + const data = await handleFetch('https://discord.com/api/users/@me', { + headers: { + authorization: `Bearer ${token}`, + }, + }) + return data +} + +export class PlatDiscord implements IPlat { + async verifyToken(req: any): Promise { + let { code, token } = req.params + code = code || token + let tokenResponse = await exchangeDiscrodCodeForToken(code) + if (!tokenResponse || tokenResponse.error) { + throw new ZError(60, tokenResponse.error_description) + } + let payload = await userInfo(tokenResponse.access_token) + const openId = payload.id + let data: any = {} + if (payload.username) data.nickname = payload.username + if (payload.avatar) data.avatar = payload.avatar + if (payload.email) data.email = payload.email + if (payload.verified) data.emailVerified = payload.verified + const { api_platform } = req.headers + if (api_platform) { + data.platform = api_platform + } + + return { openId, data } + } +} diff --git a/start.json b/start.json index 24b11f3..c4a667b 100644 --- a/start.json +++ b/start.json @@ -4,7 +4,7 @@ "name": "wallet-svr", "script": "npm", "args": "run prod:api", - "cwd": "/data/apps/wallet-svr", + "cwd": "/home/kingsome/code/wallet-svr", "max_memory_restart": "1024M", "log_date_format" : "YYYY-MM-DD HH:mm Z", "watch": true, @@ -15,7 +15,7 @@ "tasks" ], "instances": 1, - "exec_mode": "cluster", + "exec_mode": "fork", "env": { "NODE_ENV": "production" },