{"version":3,"sources":["../../../src/oauth2/provider/wechat.ts"],"sourcesContent":["import { invariant } from '@shware/utils';\nimport { OAuth2Error } from '../error';\nimport type { OAuth2Token, Provider } from '../types';\n\nexport type Options = { isWechatBrowser: boolean };\n\n/**\n * reference: https://developers.weixin.qq.com/doc/offiaccount/en/OA_Web_Apps/Wechat_webpage_authorization.html\n */\nexport function createWechatProvider(options: Options = { isWechatBrowser: false }): Provider {\n  const { isWechatBrowser } = options;\n  return {\n    authorizationUri: isWechatBrowser\n      ? 'https://open.weixin.qq.com/connect/oauth2/authorize'\n      : 'https://open.weixin.qq.com/connect/qrconnect',\n    tokenUri: 'https://api.weixin.qq.com/sns/oauth2/access_token',\n    tokenRefreshUri: 'https://api.weixin.qq.com/sns/oauth2/refresh_token',\n    userInfoUri: 'https://api.weixin.qq.com/sns/userinfo',\n    defaultScope: [isWechatBrowser ? 'snsapi_userinfo' : 'snsapi_login'],\n    createAuthorizationUri(params) {\n      const url = new URL(this.authorizationUri);\n      url.searchParams.set('appid', params.clientId);\n      url.searchParams.set('scope', (params.scope ?? this.defaultScope).join(','));\n      url.searchParams.set('redirect_uri', params.redirectUri);\n      url.searchParams.set('response_type', 'code');\n      url.searchParams.set('state', params.state);\n      return url;\n    },\n    async exchangeAuthorizationCode(params) {\n      const url = new URL(this.tokenUri);\n      url.searchParams.set('appid', params.clientId);\n      url.searchParams.set('secret', params.clientSecret);\n      url.searchParams.set('code', params.code);\n      url.searchParams.set('grant_type', 'authorization_code');\n      const response = await fetch(url.href);\n      if (!response.ok) {\n        const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n        throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n      }\n      return (await response.json()) as WechatToken;\n    },\n    async getUserInfo({ access_token, openid }) {\n      invariant(this.userInfoUri, 'userInfoUri is required');\n      invariant(openid && typeof openid === 'string', 'openid is required');\n      const url = new URL(this.userInfoUri);\n      url.searchParams.set('access_token', access_token);\n      url.searchParams.set('openid', openid);\n      const response = await fetch(url.href);\n      if (!response.ok) {\n        const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n        throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n      }\n      const data = (await response.json()) as WechatUserInfo;\n\n      return {\n        data,\n        claims: {\n          sub: data.unionid ?? data.openid,\n          name: data.nickname,\n          picture: `${data.headimgurl.split('/').slice(0, -1).join('/')}/0`,\n          gender: data.sex === 1 ? 'male' : data.sex === 2 ? 'female' : undefined,\n        },\n      };\n    },\n    async refreshAccessToken(params) {\n      invariant(this.tokenRefreshUri, 'tokenRefreshUri is required');\n      const url = new URL(this.tokenRefreshUri);\n      url.searchParams.set('appid', params.clientId);\n      url.searchParams.set('grant_type', 'refresh_token');\n      url.searchParams.set('refresh_token', params.refreshToken);\n      const response = await fetch(url.href);\n      if (!response.ok) {\n        const { errcode, errmsg } = (await response.json()) as WechatErrorResponse;\n        throw new OAuth2Error(response.status, errmsg, `errcode: ${errcode}`);\n      }\n      return (await response.json()) as WechatToken;\n    },\n  };\n}\n\nexport const wechat = createWechatProvider();\n\nexport interface WechatUserInfo {\n  openid: string;\n  nickname: string;\n  sex: 0 | 1 | 2; // 0: unknown, 1: male, 2: female\n  province: string;\n  city: string;\n  country: string;\n  /**\n   * User's profile photo. The last numeric value represents the size of a square profile photo\n   * (The value can be 0, 46, 64, 96, or 132. The value 0 represents a 640*640 square profile\n   * photo). This parameter is left blank if a user has no profile photo. If the user changes the\n   * profile photo, the URL of the original profile photo will expire.\n   * e.g. http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46\n   */\n  headimgurl: string;\n  privilege: string[];\n  unionid?: string;\n}\n\nexport interface WechatToken extends OAuth2Token {\n  access_token: string;\n  expires_in: number;\n  refresh_token: string;\n  openid: string;\n  scope: string;\n  unionid?: string;\n}\n\ninterface WechatErrorResponse {\n  errcode: number;\n  errmsg: string;\n}\n"],"mappings":"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","names":[]}