-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Bluelink and Kia Connect(only signin tested) China ve…
…rsion. (#243)
- Loading branch information
Showing
10 changed files
with
1,217 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { ChineseBlueLinkConfig } from '../controllers/chinese.controller'; | ||
import { Brand } from '../interfaces/common.interfaces'; | ||
|
||
export interface ChineseBrandEnvironment { | ||
brand: Brand; | ||
host: string; | ||
baseUrl: string; | ||
clientId: string; | ||
appId: string; | ||
endpoints: { | ||
integration: string; | ||
silentSignIn: string; | ||
session: string; | ||
login: string; | ||
language: string; | ||
redirectUri: string; | ||
token: string; | ||
}; | ||
basicToken: string; | ||
GCMSenderID: string; | ||
providerDeviceId: string; | ||
pushRegId: string; | ||
} | ||
|
||
const getEndpoints = ( | ||
baseUrl: string, | ||
clientId: string | ||
): ChineseBrandEnvironment['endpoints'] => ({ | ||
session: `${baseUrl}/api/v1/user/oauth2/authorize?response_type=code&state=test&client_id=${clientId}&redirect_uri=${baseUrl}:443/api/v1/user/oauth2/redirect`, | ||
login: `${baseUrl}/api/v1/user/signin`, | ||
language: `${baseUrl}/api/v1/user/language`, | ||
redirectUri: `${baseUrl}:443/api/v1/user/oauth2/redirect`, | ||
token: `${baseUrl}/api/v1/user/oauth2/token`, | ||
integration: `${baseUrl}/api/v1/user/integrationinfo`, | ||
silentSignIn: `${baseUrl}/api/v1/user/silentsignin`, | ||
}); | ||
|
||
type BrandEnvironmentConfig = Pick<ChineseBlueLinkConfig, 'brand'>; | ||
|
||
const getHyundaiEnvironment = (): ChineseBrandEnvironment => { | ||
const host = 'prd.cn-ccapi.hyundai.com'; | ||
const baseUrl = `https://${host}`; | ||
const clientId = '72b3d019-5bc7-443d-a437-08f307cf06e2'; | ||
const appId = 'ed01581a-380f-48cd-83d4-ed1490c272d0'; | ||
return { | ||
brand: 'hyundai', | ||
host, | ||
baseUrl, | ||
clientId, | ||
appId, | ||
endpoints: Object.freeze(getEndpoints(baseUrl, clientId)), | ||
basicToken: | ||
'Basic NzJiM2QwMTktNWJjNy00NDNkLWE0MzctMDhmMzA3Y2YwNmUyOnNlY3JldA==', | ||
GCMSenderID: '414998006775', | ||
providerDeviceId: '59af09e554a9442ab8589c9500d04d2e', | ||
pushRegId: '1', | ||
}; | ||
}; | ||
|
||
const getKiaEnvironment = (): ChineseBrandEnvironment => { | ||
const host = 'prd.cn-ccapi.kia.com'; | ||
const baseUrl = `https://${host}`; | ||
const clientId = '9d5df92a-06ae-435f-b459-8304f2efcc67'; | ||
const appId = 'eea8762c-adfc-4ee4-8d7a-6e2452ddf342'; | ||
return { | ||
brand: 'kia', | ||
host, | ||
baseUrl, | ||
clientId, | ||
appId, | ||
endpoints: Object.freeze(getEndpoints(baseUrl, clientId)), | ||
basicToken: 'Basic OWQ1ZGY5MmEtMDZhZS00MzVmLWI0NTktODMwNGYyZWZjYzY3OnRzWGRrVWcwOEF2MlpaelhPZ1d6Snl4VVQ2eWVTbk5OUWtYWFBSZEtXRUFOd2wxcA==', | ||
GCMSenderID: '345127537656', | ||
providerDeviceId: '32dedba78045415b92db816e805ed47b', | ||
pushRegId: 'ogc+GB5gom7zDEQjPhb3lP+bjjM=DG2rQ9Zuq0otwOU7n9y08LKjYpo=', | ||
}; | ||
}; | ||
|
||
export const getBrandEnvironment = ({ | ||
brand, | ||
}: BrandEnvironmentConfig): ChineseBrandEnvironment => { | ||
switch (brand) { | ||
case 'hyundai': | ||
return Object.freeze(getHyundaiEnvironment()); | ||
case 'kia': | ||
return Object.freeze(getKiaEnvironment()); | ||
default: | ||
throw new Error(`Constructor ${brand} is not managed.`); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import got from 'got'; | ||
import { CookieJar } from 'tough-cookie'; | ||
import {ChineseBrandEnvironment } from '../../constants/china'; | ||
|
||
export type Code = string; | ||
|
||
export interface AuthStrategy { | ||
readonly name: string; | ||
login( | ||
user: { username: string; password: string }, | ||
options?: { cookieJar?: CookieJar } | ||
): Promise<{ code: Code; cookies: CookieJar }>; | ||
} | ||
|
||
export async function initSession( | ||
environment: ChineseBrandEnvironment, | ||
cookies?: CookieJar | ||
): Promise<CookieJar> { | ||
const cookieJar = cookies ?? new CookieJar(); | ||
await got(environment.endpoints.session, { cookieJar }); | ||
await got(environment.endpoints.language, { | ||
method: 'POST', | ||
body: `{"lang":"zh"}`, | ||
cookieJar, | ||
}); | ||
return cookieJar; | ||
} |
48 changes: 48 additions & 0 deletions
48
src/controllers/authStrategies/chinese.legacyAuth.strategy.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import got from 'got'; | ||
import { CookieJar } from 'tough-cookie'; | ||
import { ChineseBrandEnvironment } from '../../constants/china'; | ||
import { AuthStrategy, Code, initSession } from './china.authStrategy'; | ||
import Url from 'url'; | ||
|
||
export class ChineseLegacyAuthStrategy implements AuthStrategy { | ||
constructor( | ||
private readonly environment: ChineseBrandEnvironment, | ||
) {} | ||
|
||
public get name(): string { | ||
return 'ChineseLegacyAuthStrategy'; | ||
} | ||
|
||
async login( | ||
user: { username: string; password: string }, | ||
options?: { cookieJar: CookieJar } | ||
): Promise<{ code: Code; cookies: CookieJar }> { | ||
const cookieJar = await initSession(this.environment, options?.cookieJar); | ||
const { body, statusCode } = await got(this.environment.endpoints.login, { | ||
method: 'POST', | ||
json: true, | ||
body: { | ||
'email': user.username, | ||
'password': user.password, | ||
}, | ||
cookieJar, | ||
}); | ||
if (!body.redirectUrl) { | ||
throw new Error( | ||
`@ChineseLegacyAuthStrategy.login: sign In didn't work, could not retrieve auth code. status: ${statusCode}, body: ${JSON.stringify( | ||
body | ||
)}` | ||
); | ||
} | ||
const { code } = Url.parse(body.redirectUrl, true).query; | ||
if (!code) { | ||
throw new Error( | ||
'@ChineseLegacyAuthStrategy.login: AuthCode was not found, you probably need to migrate your account.' | ||
); | ||
} | ||
return { | ||
code: code as Code, | ||
cookies: cookieJar, | ||
}; | ||
} | ||
} |
Oops, something went wrong.