add facebook login api

This commit is contained in:
zhl 2023-02-08 14:19:33 +08:00
parent a972435a8d
commit 81ff8b5778
3 changed files with 70 additions and 4 deletions

View File

@ -0,0 +1,45 @@
import BaseController from 'common/base.controller'
import {ZError} from 'common/ZError'
import { role, router } from 'decorators/router'
import {Account, PlatEnum} from 'modules/Account';
import {FACEBOOK_APP_ID, fetchUserInfo, verifyFbUserAccessToken} from 'providers/facebook.provider';
class FacebookController extends BaseController {
@role('anon')
@router('post /wallet/login/facebook')
async checkFacebookJwt(req, res) {
let { code } = req.params;
if (!code) {
throw new ZError(10, 'params mismatch');
}
const result = await verifyFbUserAccessToken(code);
if (!!result.error) {
throw new ZError(10, `${result.error?.message} (${result.error?.code})`)
}
const { data } = result;
if (!data) {
throw new ZError(11, 'no data from facebook');
}
if (data.app_id !== FACEBOOK_APP_ID) {
throw new ZError(12, 'app id mismatch');
}
if (!data.is_valid) {
throw new ZError(13, 'access_token not valid');
}
const infoRes = await fetchUserInfo(code);
if (!!infoRes.error) {
throw new ZError(13, `${infoRes.error?.message} (${infoRes.error.code})`)
}
const openId = infoRes.id || data.user_id;
let user: any = {}
let now = Date.now() / 1000
user.accessToken = code
user.accessTokenExpire = result.data['expires_at']
user.scope = data['scopes']
user.nickname = infoRes['name']
user.email = infoRes['email']
let account = await Account.insertOrUpdate({ plat: PlatEnum.FACEBOOK, openId }, user)
const ztoken = await res.jwtSign({ id: account.id })
return { token: ztoken }
}
}

View File

@ -1,4 +1,4 @@
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
import { getModelForClass, index, modelOptions, mongoose, prop, Severity } from '@typegoose/typegoose'
import { dbconn } from 'decorators/dbconn'
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
import { BaseModule } from './Base'
@ -7,12 +7,14 @@ export enum PlatEnum {
GOOGLE = 0,
APPLE = 1,
TIKTOK = 2,
FACEBOOK = 3,
TWITTER = 4,
}
interface AccountClass extends Base, TimeStamps {}
@dbconn()
@index({ plat: 1, openId: 1 }, { unique: true })
@modelOptions({ schemaOptions: { collection: 'account', timestamps: true } })
@modelOptions({ schemaOptions: { collection: 'account', timestamps: true }, options: { allowMixed: Severity.ALLOW } })
class AccountClass extends BaseModule {
@prop({ enum: PlatEnum, default: PlatEnum.GOOGLE })
public plat!: PlatEnum
@ -46,8 +48,8 @@ class AccountClass extends BaseModule {
public refreshToken?: string
@prop()
public refreshTokenExpire?: number
@prop()
public scope?: string
@prop({type: mongoose.Schema.Types.Mixed})
public scope?: any
}
export const Account = getModelForClass(AccountClass, { existingConnection: AccountClass.db })

View File

@ -0,0 +1,19 @@
import {NetClient} from "net/NetClient";
const FACEBOOK_API_HOST = 'https://graph.facebook.com'
export const FACEBOOK_APP_ID = '1204701000119770';
const FACEBOOK_APP_SECRET = '5a1deba64b30c7326f497fc52691207f';
export async function getAppAccessToken() {
const url = `${FACEBOOK_API_HOST}/oauth/access_token?client_id=${FACEBOOK_APP_ID}&clent_secret=${FACEBOOK_APP_SECRET}&grant_type=client_credentials`;
return new NetClient().httpGet(url);
}
export async function verifyFbUserAccessToken(accessToken: string){
const url = `${FACEBOOK_API_HOST}/debug_token?input_token=${accessToken}&access_token=GG|${FACEBOOK_APP_ID}|${FACEBOOK_APP_SECRET}`;
return new NetClient().httpGet(url);
}
export async function fetchUserInfo(accessToken: string) {
const url = `${FACEBOOK_API_HOST}/me?fields=["email","id", "name"]&access_token=${accessToken}`;
return new NetClient().httpGet(url);
}