修改应用内充值,记录中的账号不再作为购买者, 增加passport token的验证
This commit is contained in:
parent
959740af19
commit
252368e51e
49
docs/inapp.md
Normal file
49
docs/inapp.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#
|
||||||
|
|
||||||
|
## 说明
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
1. 如无特殊说明, 所有接口返回 json, 顶级结构如下, 接口 Response 的数据结构说明只包含 data 部分
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"errcode": 0, //0:成功 100: 所有未定义的错误, 其他根据errmsg判断
|
||||||
|
"errmsg": "", //错误描述, 一般在code=0时, 该字段为空
|
||||||
|
"data": {}, // 数据
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 接口列表
|
||||||
|
|
||||||
|
### 1. 验证订单信息
|
||||||
|
|
||||||
|
1. Method: POST
|
||||||
|
2. URI: google: /native_pay/google/verify
|
||||||
|
apple: /native_pay/apple/verify
|
||||||
|
3. HOST: 测试: https://pay.cebggame.com/v2
|
||||||
|
生产: https://pay.cebggame.com/v0
|
||||||
|
|
||||||
|
> header 参数
|
||||||
|
|
||||||
|
|
||||||
|
> url param 参数
|
||||||
|
|
||||||
|
| 字段 | 说明 |
|
||||||
|
| --------- | -------------------- |
|
||||||
|
| list | 通过queryPurchase或buyProduct获取的数据中的data对象 |
|
||||||
|
|
||||||
|
5. Response: JSON
|
||||||
|
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{
|
||||||
|
productId: 'google或apple后台获取的productId',
|
||||||
|
gameOrderId: '游戏订单号',
|
||||||
|
orderId: 'google或apple返回的orderId',
|
||||||
|
status: '订单状态',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
status: 0:默认状态, 未支付 3: 已支付, 未确认 9: 已成功支付和确认
|
@ -28,6 +28,7 @@
|
|||||||
"fast-rbac": "^2.0.1",
|
"fast-rbac": "^2.0.1",
|
||||||
"fastify": "^4.8.1",
|
"fastify": "^4.8.1",
|
||||||
"fastify-plugin": "^4.2.1",
|
"fastify-plugin": "^4.2.1",
|
||||||
|
"get-jwks": "^9.0.2",
|
||||||
"google-auth-library": "^8.5.2",
|
"google-auth-library": "^8.5.2",
|
||||||
"googleapis": "^120.0.0",
|
"googleapis": "^120.0.0",
|
||||||
"jose": "^4.14.4",
|
"jose": "^4.14.4",
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit b982e43cd717e09acafba79f40c63e2572dbef96
|
Subproject commit cf4af92b819c06a6263a7b06075154b1db5cff49
|
14
src/common/ReadOnlyCache.ts
Normal file
14
src/common/ReadOnlyCache.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { singleton } from 'zutils'
|
||||||
|
|
||||||
|
@singleton
|
||||||
|
export class ReadOnlyCache {
|
||||||
|
map: Map<string, any> = new Map()
|
||||||
|
|
||||||
|
public getData(key: string) {
|
||||||
|
return this.map.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
public setData(key: string, value: any) {
|
||||||
|
this.map.set(key, value)
|
||||||
|
}
|
||||||
|
}
|
@ -7,10 +7,18 @@ import { BaseController, router, ZError, role, ROLE_ANON } from 'zutils'
|
|||||||
|
|
||||||
class ApplePayController extends BaseController {
|
class ApplePayController extends BaseController {
|
||||||
@router('post /pay/apple/verify')
|
@router('post /pay/apple/verify')
|
||||||
|
@router('post /native_pay/apple/verify')
|
||||||
async verifyApplePay(req, res) {
|
async verifyApplePay(req, res) {
|
||||||
logger.db('applepay_verify', req)
|
logger.db('applepay_verify', req)
|
||||||
const user = req.user
|
const { openId } = req.user
|
||||||
const { list } = req.params
|
let { list } = req.params
|
||||||
|
if (typeof list === 'string') {
|
||||||
|
try {
|
||||||
|
list = JSON.parse(list)
|
||||||
|
} catch (err) {
|
||||||
|
throw new ZError(10, 'purchase data is empty')
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!list || !list.length) {
|
if (!list || !list.length) {
|
||||||
throw new ZError(10, 'purchase data is empty')
|
throw new ZError(10, 'purchase data is empty')
|
||||||
}
|
}
|
||||||
@ -23,15 +31,16 @@ class ApplePayController extends BaseController {
|
|||||||
if (!tx) {
|
if (!tx) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
await InAppRecord.addRecord(user.id, tx, 'apple')
|
await InAppRecord.addRecord(openId, tx, 'apple')
|
||||||
logger.info('getTransactionInfo:: ', tx)
|
logger.info('getTransactionInfo:: ', tx)
|
||||||
if (tx.transactionReason === 'PURCHASE' && tx.inAppOwnershipType === 'PURCHASED') {
|
if (tx.transactionReason === 'PURCHASE' && tx.inAppOwnershipType === 'PURCHASED') {
|
||||||
status = ApplePayStatus.SUCCESS
|
status = ApplePayStatus.SUCCESS
|
||||||
}
|
}
|
||||||
if (status === ApplePayStatus.SUCCESS) {
|
if (status === ApplePayStatus.SUCCESS) {
|
||||||
let record = await AppleInApp.insertOrUpdate(
|
let record = await AppleInApp.insertOrUpdate(
|
||||||
{ account: user.id, outOrderId: tx.transactionId },
|
{ outOrderId: tx.transactionId },
|
||||||
{
|
{
|
||||||
|
account: openId,
|
||||||
productId: tx.productId,
|
productId: tx.productId,
|
||||||
gameOrderId: tx.appAccountToken,
|
gameOrderId: tx.appAccountToken,
|
||||||
country: tx.storefront,
|
country: tx.storefront,
|
||||||
|
@ -7,10 +7,19 @@ import { BaseController, router, ZError } from 'zutils'
|
|||||||
|
|
||||||
class GooglePayController extends BaseController {
|
class GooglePayController extends BaseController {
|
||||||
@router('post /pay/google/verify')
|
@router('post /pay/google/verify')
|
||||||
|
@router('post /native_pay/google/verify')
|
||||||
async verifyGooglePay(req, res) {
|
async verifyGooglePay(req, res) {
|
||||||
logger.db('googlepay_verify', req)
|
logger.db('googlepay_verify', req)
|
||||||
const user = req.user
|
const { openId } = req.user
|
||||||
const { list } = req.params
|
let { list } = req.params
|
||||||
|
// check if list is string
|
||||||
|
if (typeof list === 'string') {
|
||||||
|
try {
|
||||||
|
list = JSON.parse(list)
|
||||||
|
} catch (err) {
|
||||||
|
throw new ZError(10, 'purchase data is empty')
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!list || !list.length) {
|
if (!list || !list.length) {
|
||||||
throw new ZError(10, 'purchase data is empty')
|
throw new ZError(10, 'purchase data is empty')
|
||||||
}
|
}
|
||||||
@ -23,7 +32,7 @@ class GooglePayController extends BaseController {
|
|||||||
throw new ZError(20, 'fetch purchase data failed')
|
throw new ZError(20, 'fetch purchase data failed')
|
||||||
}
|
}
|
||||||
let info = infoRes.data
|
let info = infoRes.data
|
||||||
await InAppRecord.addRecord(user.id, info, 'google')
|
await InAppRecord.addRecord(openId, info, 'google')
|
||||||
let status = GooglePayStatus.PENDING
|
let status = GooglePayStatus.PENDING
|
||||||
if (info.purchaseState === 0 && info.consumptionState === 0) {
|
if (info.purchaseState === 0 && info.consumptionState === 0) {
|
||||||
status = GooglePayStatus.PURCHASED
|
status = GooglePayStatus.PURCHASED
|
||||||
@ -31,8 +40,9 @@ class GooglePayController extends BaseController {
|
|||||||
if (status === GooglePayStatus.PURCHASED) {
|
if (status === GooglePayStatus.PURCHASED) {
|
||||||
try {
|
try {
|
||||||
let record = await GoogleInApp.insertOrUpdate(
|
let record = await GoogleInApp.insertOrUpdate(
|
||||||
{ account: user.id, outOrderId: info.orderId },
|
{ outOrderId: info.orderId },
|
||||||
{
|
{
|
||||||
|
account: openId,
|
||||||
purchaseToken: sub.token,
|
purchaseToken: sub.token,
|
||||||
productId: sub.id,
|
productId: sub.id,
|
||||||
gameOrderId: info.obfuscatedExternalAccountId,
|
gameOrderId: info.obfuscatedExternalAccountId,
|
||||||
|
@ -18,16 +18,16 @@ export enum ApplePayStatus {
|
|||||||
|
|
||||||
@dbconn('pay')
|
@dbconn('pay')
|
||||||
@index({ gameOrderId: 1 }, { unique: true, partialFilterExpression: { gameOrderId: { $exists: true } } })
|
@index({ gameOrderId: 1 }, { unique: true, partialFilterExpression: { gameOrderId: { $exists: true } } })
|
||||||
@index({ account: 1, outOrderId: 1 }, { unique: true })
|
@index({ outOrderId: 1 }, { unique: true })
|
||||||
@index({ account: 1 }, { unique: false })
|
@index({ account: 1 }, { unique: false })
|
||||||
@modelOptions({
|
@modelOptions({
|
||||||
schemaOptions: { collection: 'apple_inapp_record', timestamps: true },
|
schemaOptions: { collection: 'apple_inapp_record_202410', timestamps: true },
|
||||||
options: { allowMixed: Severity.ALLOW },
|
options: { allowMixed: Severity.ALLOW },
|
||||||
})
|
})
|
||||||
export class AppleInAppClass extends BaseModule {
|
export class AppleInAppClass extends BaseModule {
|
||||||
// 用户账号
|
// 用户账号
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
public account: string
|
public account: string // 这里只表示谁来消耗这个订单, 不代表购买者
|
||||||
// 渠道返回的订单id
|
// 渠道返回的订单id
|
||||||
// transactionId
|
// transactionId
|
||||||
@prop()
|
@prop()
|
||||||
|
@ -18,16 +18,16 @@ export enum GooglePayStatus {
|
|||||||
|
|
||||||
@dbconn('pay')
|
@dbconn('pay')
|
||||||
@index({ gameOrderId: 1 }, { unique: true, partialFilterExpression: { gameOrderId: { $exists: true } } })
|
@index({ gameOrderId: 1 }, { unique: true, partialFilterExpression: { gameOrderId: { $exists: true } } })
|
||||||
@index({ account: 1, outOrderId: 1 }, { unique: true })
|
@index({ outOrderId: 1 }, { unique: true })
|
||||||
@index({ account: 1 }, { unique: false })
|
@index({ account: 1 }, { unique: false })
|
||||||
@modelOptions({
|
@modelOptions({
|
||||||
schemaOptions: { collection: 'google_inapp_record', timestamps: true },
|
schemaOptions: { collection: 'google_inapp_record_202410', timestamps: true },
|
||||||
options: { allowMixed: Severity.ALLOW },
|
options: { allowMixed: Severity.ALLOW },
|
||||||
})
|
})
|
||||||
export class GoogleInAppClass extends BaseModule {
|
export class GoogleInAppClass extends BaseModule {
|
||||||
// 用户账号
|
// 用户账号
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
public account: string
|
public account: string // 这里只表示谁来消耗这个订单, 不代表购买者
|
||||||
// 渠道返回的订单id
|
// 渠道返回的订单id
|
||||||
@prop()
|
@prop()
|
||||||
public outOrderId: string
|
public outOrderId: string
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'
|
import { FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'
|
||||||
import fastifyPlugin from 'fastify-plugin'
|
import fastifyPlugin from 'fastify-plugin'
|
||||||
import { Account } from 'modules/Account'
|
import { Account } from 'modules/Account'
|
||||||
|
import { verifyCombinedToken } from 'utils/jwt.utils'
|
||||||
|
|
||||||
declare module 'fastify' {
|
declare module 'fastify' {
|
||||||
interface FastifyRequest {
|
interface FastifyRequest {
|
||||||
@ -33,16 +34,23 @@ const apiAuthPlugin: FastifyPluginAsync<ApiAuthOptions> = async function (fastif
|
|||||||
if (!request.token) {
|
if (!request.token) {
|
||||||
return reply.send({ errcode: 11, errmsg: 'need login' })
|
return reply.send({ errcode: 11, errmsg: 'need login' })
|
||||||
}
|
}
|
||||||
//@ts-ignore
|
if (request.url.indexOf('native_pay/') >= 0) {
|
||||||
const data = this.jwt.verify(request.token)
|
const data = await verifyCombinedToken(request.token)
|
||||||
if (!data || !data.id) {
|
data.openId = data.openId || data.openid || data.passport?.zkevm_eth_address || data.passport?.eth_key
|
||||||
return reply.send({ errcode: 10, errmsg: 'need login' })
|
request.user = data
|
||||||
|
} else {
|
||||||
|
//@ts-ignore
|
||||||
|
const data = this.jwt.verify(request.token)
|
||||||
|
if (!data || !data.id) {
|
||||||
|
return reply.send({ errcode: 10, errmsg: 'need login' })
|
||||||
|
}
|
||||||
|
let account = await Account.findById(data.id)
|
||||||
|
if (!account) {
|
||||||
|
return reply.send({ errcode: 10, errmsg: 'need login' })
|
||||||
|
}
|
||||||
|
request.user = account
|
||||||
}
|
}
|
||||||
let account = await Account.findById(data.id)
|
|
||||||
if (!account) {
|
|
||||||
return reply.send({ errcode: 10, errmsg: 'need login' })
|
|
||||||
}
|
|
||||||
request.user = account
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return reply.send({ errcode: 401, errmsg: 'need auth' })
|
return reply.send({ errcode: 401, errmsg: 'need auth' })
|
||||||
}
|
}
|
||||||
|
91
src/utils/jwt.utils.ts
Normal file
91
src/utils/jwt.utils.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
import { ReadOnlyCache } from 'common/ReadOnlyCache'
|
||||||
|
import { createSigner, createVerifier } from 'fast-jwt'
|
||||||
|
|
||||||
|
import buildGetJwks from 'get-jwks'
|
||||||
|
|
||||||
|
const domain = 'https://auth.immutable.com'
|
||||||
|
|
||||||
|
const privateKey = `-----BEGIN PRIVATE KEY-----
|
||||||
|
${process.env.REFRESH_TOKEN_SECRET_PRIVATE}
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
const publicKey = `-----BEGIN PUBLIC KEY-----
|
||||||
|
${process.env.REFRESH_TOKEN_SECRET_PUBLIC}
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
`
|
||||||
|
const REFRESH_TOKEN_EXPIRES_IN = 30 * 24 * 60 * 60 * 1000
|
||||||
|
const privateKeyWallet = `-----BEGIN PRIVATE KEY-----
|
||||||
|
${process.env.API_TOKEN_SECRET_PRIVATE}
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
`
|
||||||
|
const publicKeyWallet = `-----BEGIN PUBLIC KEY-----
|
||||||
|
${process.env.API_TOKEN_SECRET_PUBLIC}
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
`
|
||||||
|
const WALLET_TOKEN_EXPIRES_IN = 30 * 24 * 60 * 60 * 1000
|
||||||
|
|
||||||
|
const getJwks = buildGetJwks({ })
|
||||||
|
|
||||||
|
export const generateRefreshToken = (data: any) => {
|
||||||
|
const signSync = createSigner({
|
||||||
|
algorithm: 'EdDSA',
|
||||||
|
expiresIn: REFRESH_TOKEN_EXPIRES_IN,
|
||||||
|
key: privateKey,
|
||||||
|
})
|
||||||
|
return signSync(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const verifyRefreshToken = (token: string) => {
|
||||||
|
const verifier = createVerifier({
|
||||||
|
algorithms: ['EdDSA'],
|
||||||
|
key: publicKey,
|
||||||
|
})
|
||||||
|
return verifier(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateWalletToken = (data: any) => {
|
||||||
|
const signSync = createSigner({
|
||||||
|
algorithm: 'EdDSA',
|
||||||
|
expiresIn: WALLET_TOKEN_EXPIRES_IN,
|
||||||
|
key: privateKeyWallet,
|
||||||
|
})
|
||||||
|
return signSync(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const verifyWalletToken = (token: string) => {
|
||||||
|
const verifier = createVerifier({
|
||||||
|
algorithms: ['EdDSA'],
|
||||||
|
key: publicKeyWallet,
|
||||||
|
})
|
||||||
|
return verifier(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const verifyPassportToken = (token: string) => {
|
||||||
|
const verifyWithPromise = createVerifier({
|
||||||
|
key: async function (header) {
|
||||||
|
let publicKey = new ReadOnlyCache().getData('passport_public_key')
|
||||||
|
if (!publicKey) {
|
||||||
|
publicKey = await getJwks.getPublicKey({
|
||||||
|
kid: header.kid,
|
||||||
|
alg: header.alg,
|
||||||
|
domain,
|
||||||
|
})
|
||||||
|
new ReadOnlyCache().setData('passport_public_key', publicKey)
|
||||||
|
}
|
||||||
|
return Promise.resolve(publicKey)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return verifyWithPromise(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const verifyCombinedToken = (token: string) => {
|
||||||
|
let tokenSuffix = token.split('.')[3]
|
||||||
|
tokenSuffix = tokenSuffix || 'passport'
|
||||||
|
token = token.replace(`.${tokenSuffix}`, '')
|
||||||
|
if (tokenSuffix === 'passport') {
|
||||||
|
return verifyPassportToken(token)
|
||||||
|
} else {
|
||||||
|
return verifyWalletToken(token)
|
||||||
|
}
|
||||||
|
}
|
29
start.json
29
start.json
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"apps": [
|
"apps": [
|
||||||
{
|
{
|
||||||
"name": "wallet-svr",
|
"name": "pay-svr-release",
|
||||||
"script": "npm",
|
"script": "npm",
|
||||||
"args": "run prod:api",
|
"args": "run prod:api",
|
||||||
"cwd": "/data/apps/wallet-svr",
|
"cwd": "/home/kingsome/code/pay-svr",
|
||||||
"max_memory_restart": "1024M",
|
"max_memory_restart": "1024M",
|
||||||
"log_date_format" : "YYYY-MM-DD HH:mm Z",
|
"log_date_format" : "YYYY-MM-DD HH:mm Z",
|
||||||
"watch": true,
|
"watch": true,
|
||||||
@ -15,13 +15,36 @@
|
|||||||
"tasks"
|
"tasks"
|
||||||
],
|
],
|
||||||
"instances": 1,
|
"instances": 1,
|
||||||
"exec_mode": "cluster",
|
"exec_mode": "fork",
|
||||||
"env": {
|
"env": {
|
||||||
"NODE_ENV": "production"
|
"NODE_ENV": "production"
|
||||||
},
|
},
|
||||||
"env_production": {
|
"env_production": {
|
||||||
"NODE_ENV": "production"
|
"NODE_ENV": "production"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pay-svr-test-v0",
|
||||||
|
"script": "npm",
|
||||||
|
"args": "run dev:api",
|
||||||
|
"cwd": "/home/kingsome/code/pay-svr",
|
||||||
|
"max_memory_restart": "1024M",
|
||||||
|
"log_date_format" : "YYYY-MM-DD HH:mm Z",
|
||||||
|
"watch": true,
|
||||||
|
"ignore_watch": [
|
||||||
|
"node_modules",
|
||||||
|
"logs",
|
||||||
|
"fixtures",
|
||||||
|
"tasks"
|
||||||
|
],
|
||||||
|
"instances": 1,
|
||||||
|
"exec_mode": "fork",
|
||||||
|
"env": {
|
||||||
|
"NODE_ENV": "development"
|
||||||
|
},
|
||||||
|
"env_production": {
|
||||||
|
"NODE_ENV": "development"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
38
yarn.lock
38
yarn.lock
@ -1560,6 +1560,19 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.4:
|
|||||||
minimalistic-assert "^1.0.1"
|
minimalistic-assert "^1.0.1"
|
||||||
minimalistic-crypto-utils "^1.0.1"
|
minimalistic-crypto-utils "^1.0.1"
|
||||||
|
|
||||||
|
elliptic@^6.5.7:
|
||||||
|
version "6.5.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b"
|
||||||
|
integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==
|
||||||
|
dependencies:
|
||||||
|
bn.js "^4.11.9"
|
||||||
|
brorand "^1.1.0"
|
||||||
|
hash.js "^1.0.0"
|
||||||
|
hmac-drbg "^1.0.1"
|
||||||
|
inherits "^2.0.4"
|
||||||
|
minimalistic-assert "^1.0.1"
|
||||||
|
minimalistic-crypto-utils "^1.0.1"
|
||||||
|
|
||||||
encodeurl@~1.0.2:
|
encodeurl@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||||
@ -2277,6 +2290,15 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2:
|
|||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
hasown "^2.0.0"
|
hasown "^2.0.0"
|
||||||
|
|
||||||
|
get-jwks@^9.0.2:
|
||||||
|
version "9.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-jwks/-/get-jwks-9.0.2.tgz#9364efb7a48b126a8df88e67757c413d6abf747d"
|
||||||
|
integrity sha512-zn2OvElozYtckpYJvgRWMOMhEkW8KgFp+lN0B7Q6SXPZg/CFfeiPoh73Wbhacj4fYXDJxkxbcwI9j+/cubpzSQ==
|
||||||
|
dependencies:
|
||||||
|
jwk-to-pem "^2.0.4"
|
||||||
|
lru-cache "^10.0.0"
|
||||||
|
node-fetch "^2.6.1"
|
||||||
|
|
||||||
get-stream@^5.1.0:
|
get-stream@^5.1.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
|
||||||
@ -2904,6 +2926,15 @@ jwa@^2.0.0:
|
|||||||
ecdsa-sig-formatter "1.0.11"
|
ecdsa-sig-formatter "1.0.11"
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
|
jwk-to-pem@^2.0.4:
|
||||||
|
version "2.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/jwk-to-pem/-/jwk-to-pem-2.0.6.tgz#0810c03307e873d5c81faeb650408fa3ae91eb9c"
|
||||||
|
integrity sha512-zPC/5vjyR08TpknpTGW6Z3V3lDf9dU92oHbf0jJlG8tGOzslF9xk2UiO/seSx2llCUrNAe+AvmuGTICSXiYU7A==
|
||||||
|
dependencies:
|
||||||
|
asn1.js "^5.3.0"
|
||||||
|
elliptic "^6.5.7"
|
||||||
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
jwks-rsa@^2.1.3:
|
jwks-rsa@^2.1.3:
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
resolved "https://registry.npmmirror.com/jwks-rsa/-/jwks-rsa-2.1.5.tgz#bb7bf8c5767836bc273bf5b27870066aca39c1bb"
|
resolved "https://registry.npmmirror.com/jwks-rsa/-/jwks-rsa-2.1.5.tgz#bb7bf8c5767836bc273bf5b27870066aca39c1bb"
|
||||||
@ -3052,6 +3083,11 @@ lowercase-keys@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2"
|
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2"
|
||||||
integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==
|
integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==
|
||||||
|
|
||||||
|
lru-cache@^10.0.0:
|
||||||
|
version "10.4.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
|
||||||
|
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
|
||||||
|
|
||||||
lru-cache@^6.0.0:
|
lru-cache@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||||
@ -3388,7 +3424,7 @@ node-addon-api@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
|
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
|
||||||
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
|
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
|
||||||
|
|
||||||
node-fetch@^2.6.12:
|
node-fetch@2, node-fetch@^2.6.1, node-fetch@^2.6.12:
|
||||||
version "2.7.0"
|
version "2.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||||
|
Loading…
x
Reference in New Issue
Block a user