添加google支付相关代码
This commit is contained in:
parent
a40069ef27
commit
e2ab4da847
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ dist
|
||||
tmp
|
||||
target
|
||||
boundle.log
|
||||
google_cloud.json
|
@ -26,6 +26,7 @@
|
||||
"fastify": "^4.8.1",
|
||||
"fastify-plugin": "^4.2.1",
|
||||
"google-auth-library": "^8.5.2",
|
||||
"googleapis": "^120.0.0",
|
||||
"mongoose": "^6.6.5",
|
||||
"mongoose-findorcreate": "^3.0.0",
|
||||
"nanoid": "^3.1.23",
|
||||
@ -35,8 +36,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typegoose/typegoose": "^9.12.1",
|
||||
"@types/node-schedule": "^2.1.0",
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/node-schedule": "^2.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||
"@typescript-eslint/parser": "^5.40.1",
|
||||
"eslint": "^8.25.0",
|
||||
|
@ -8,6 +8,7 @@ import config from 'config/config'
|
||||
import { ConnectOptions } from 'mongoose'
|
||||
import CodeTaskSchedule from 'schedule/codetask.schedule'
|
||||
import { PriceSvr } from 'service/price.svr'
|
||||
import { GooglePaySvr } from 'service/googlepay.svr'
|
||||
|
||||
const zReqParserPlugin = require('plugins/zReqParser')
|
||||
|
||||
@ -108,6 +109,10 @@ export class ApiServer {
|
||||
logger.log(`DB Connection Error: ${err.message}`)
|
||||
}
|
||||
}
|
||||
async initOtherServices() {
|
||||
await new GooglePaySvr().init()
|
||||
}
|
||||
|
||||
private setErrHandler() {
|
||||
this.server.setNotFoundHandler(function (
|
||||
request: any,
|
||||
@ -167,6 +172,7 @@ export class ApiServer {
|
||||
self.setErrHandler()
|
||||
self.setFormatSend()
|
||||
self.initSchedules()
|
||||
await self.initOtherServices()
|
||||
this.server.listen({ port: config.api.port, host: config.api.host }, (err: any, address: any) => {
|
||||
if (err) {
|
||||
logger.log(err)
|
||||
|
63
src/controllers/googlepay.controller.ts
Normal file
63
src/controllers/googlepay.controller.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import BaseController from 'common/base.controller'
|
||||
import { ZError } from 'common/ZError'
|
||||
import { router } from 'decorators/router'
|
||||
import logger from 'logger/logger'
|
||||
import { GoogleInApp, GooglePayStatus } from 'modules/GoogleInApp'
|
||||
import { GooglePaySvr } from 'service/googlepay.svr'
|
||||
|
||||
class GooglePayController extends BaseController {
|
||||
@router('post /pay/google/verify')
|
||||
async verifyGooglePay(req, res) {
|
||||
const user = req.user
|
||||
const { list } = req.params
|
||||
if (!list || !list.length) {
|
||||
throw new ZError(10, 'purchase data is empty')
|
||||
}
|
||||
logger.info(`verify google purchase::list=${list}`)
|
||||
let results = []
|
||||
for (let sub of list) {
|
||||
let infoRes = await new GooglePaySvr().fetchPurchaseData(sub.id, sub.token)
|
||||
// logger.log(JSON.stringify(infoRes))
|
||||
if (infoRes.status !== 200) {
|
||||
throw new ZError(20, 'fetch purchase data failed')
|
||||
}
|
||||
let info = infoRes.data
|
||||
let status = GooglePayStatus.PENDING
|
||||
if (info.purchaseState === 0 && info.consumptionState === 0) {
|
||||
status = GooglePayStatus.PURCHASED
|
||||
}
|
||||
if (status === GooglePayStatus.PURCHASED) {
|
||||
try {
|
||||
let record = await GoogleInApp.insertOrUpdate(
|
||||
{ account: user.id, outOrderId: info.orderId },
|
||||
{
|
||||
purchaseToken: sub.token,
|
||||
productId: sub.id,
|
||||
gameOrderId: info.obfuscatedExternalAccountId,
|
||||
country: info.regionCode,
|
||||
status,
|
||||
kind: info.kind,
|
||||
purchaseTime: info.purchaseTimeMillis,
|
||||
data: info,
|
||||
$inc: { version: 1 },
|
||||
},
|
||||
)
|
||||
await new GooglePaySvr().consumePurchase(sub.id, sub.token)
|
||||
record.status = GooglePayStatus.SUCCESS
|
||||
record.consumeTime = Date.now()
|
||||
await record.save()
|
||||
results.push({
|
||||
productId: sub.id,
|
||||
gameOrderId: record.gameOrderId,
|
||||
orderId: record.outOrderId,
|
||||
status: record.status,
|
||||
})
|
||||
} catch (err) {
|
||||
logger.info(`consume purchase:: productId: ${sub.id} purchaseToken: ${sub.token} failed`, err.message || err)
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO:: 通知游戏服
|
||||
return results
|
||||
}
|
||||
}
|
85
src/modules/GoogleInApp.ts
Normal file
85
src/modules/GoogleInApp.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { getModelForClass, index, modelOptions, mongoose, prop, ReturnModelType, Severity } from '@typegoose/typegoose'
|
||||
import { dbconn } from 'decorators/dbconn'
|
||||
import { BaseModule } from './Base'
|
||||
|
||||
export enum GooglePayStatus {
|
||||
PENDING = 0, // 默认状态, 未支付
|
||||
TRANSFERING = 1, //只有购买链上资产才会有该状态
|
||||
TRANSFERED = 2, //只有购买链上资产才会有该状态
|
||||
PURCHASED = 3, //用户已支付, 但未确认和消费
|
||||
SUCCESS = 9,
|
||||
VOIDED = 96, // 作废, 取消, 退款
|
||||
USER_CANCEL = 97, // 用户取消
|
||||
TRANSFER_FAIL = 98, // 转账错误
|
||||
FAIL = 99, // 交易失败
|
||||
}
|
||||
|
||||
@dbconn('pay')
|
||||
@index({ gameOrderId: 1 }, { unique: true, partialFilterExpression: { gameOrderId: { $exists: true } } })
|
||||
@index({ account: 1, outOrderId: 1 }, { unique: true })
|
||||
@index({ account: 1 }, { unique: false })
|
||||
@modelOptions({
|
||||
schemaOptions: { collection: 'google_inapp_record', timestamps: true },
|
||||
options: { allowMixed: Severity.ALLOW },
|
||||
})
|
||||
export class GoogleInAppClass extends BaseModule {
|
||||
// 用户账号
|
||||
@prop({ required: true })
|
||||
public account: string
|
||||
// 渠道返回的订单id
|
||||
@prop()
|
||||
public outOrderId: string
|
||||
// 国家, 这里取自订单信息中返回的国家代码
|
||||
@prop()
|
||||
public country?: string
|
||||
// 游戏服传入的订单id,
|
||||
// 由于有非游戏内购买的可能, 所以该字段可能不存在
|
||||
@prop()
|
||||
public gameOrderId?: string
|
||||
// 交易状态
|
||||
@prop({ required: true, default: GooglePayStatus.PENDING })
|
||||
public status: GooglePayStatus
|
||||
// 渠道返回的原始资料
|
||||
@prop({ type: mongoose.Schema.Types.Mixed })
|
||||
public outData: any
|
||||
|
||||
// 对应google play console中的 productid
|
||||
@prop({ required: true })
|
||||
public productId: string
|
||||
@prop()
|
||||
public purchaseToken: string
|
||||
|
||||
@prop({ required: true, default: 1 })
|
||||
public amount: number
|
||||
// 表示 androidpublisherservice 中的 inappPurchase 对象
|
||||
@prop()
|
||||
public kind: string
|
||||
|
||||
// 支付时间, 取自渠道订单信息中的purchaseTimeMillis
|
||||
@prop()
|
||||
public purchaseTime: number
|
||||
@prop()
|
||||
public gameAccountId?: string
|
||||
// 消费时间
|
||||
@prop()
|
||||
public consumeTime?: number
|
||||
|
||||
// voided 相关信息
|
||||
@prop()
|
||||
public voidedTime?: number
|
||||
// 发起作废购买交易的发起者(可能的值:0)。用户 1. 开发者 2. Google
|
||||
@prop()
|
||||
public voidedSource?: number
|
||||
// 购买作废的原因可能为:0。其他 1. 反悔 2。未收到: 3. 有缺陷 4. Accidental_purchase 5. 欺诈 6. Friendly_fraud 7. 退款
|
||||
@prop()
|
||||
public voidedReason?: number
|
||||
|
||||
@prop({ default: 0 })
|
||||
public version: number
|
||||
|
||||
public static async findByRecordId(this: ReturnModelType<typeof GoogleInAppClass>, outOrderId: string) {
|
||||
return this.findOne({ outOrderId }).exec()
|
||||
}
|
||||
}
|
||||
|
||||
export const GoogleInApp = getModelForClass(GoogleInAppClass, { existingConnection: GoogleInAppClass.db })
|
54
src/service/googlepay.svr.ts
Normal file
54
src/service/googlepay.svr.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { singleton } from 'decorators/singleton'
|
||||
import { androidpublisher_v3, google } from 'googleapis'
|
||||
import logger from 'logger/logger'
|
||||
|
||||
const PAGEAGE_NAME = 'com.cege.games.release'
|
||||
|
||||
@singleton
|
||||
export class GooglePaySvr {
|
||||
private androidpublisher: androidpublisher_v3.Androidpublisher
|
||||
constructor() {}
|
||||
|
||||
public async init() {
|
||||
// this.androidpublisher = google.androidpublisher('v3')
|
||||
const auth = new google.auth.GoogleAuth({
|
||||
keyFile: 'google_cloud.json',
|
||||
// Scopes can be specified either as an array or as a single, space-delimited string.
|
||||
scopes: ['https://www.googleapis.com/auth/androidpublisher'],
|
||||
})
|
||||
this.androidpublisher = google.androidpublisher({
|
||||
version: 'v3',
|
||||
auth,
|
||||
})
|
||||
}
|
||||
|
||||
public async fetchPurchaseData(productId: string, purchaseToken: string) {
|
||||
logger.info(`fetchPurchaseData::productId=${productId}, purchaseToken=${purchaseToken}`)
|
||||
return this.androidpublisher.purchases.products.get({
|
||||
packageName: PAGEAGE_NAME,
|
||||
productId: productId,
|
||||
token: purchaseToken,
|
||||
})
|
||||
}
|
||||
|
||||
public async consumePurchase(productId: string, purchaseToken: string) {
|
||||
return this.androidpublisher.purchases.products.consume({
|
||||
packageName: PAGEAGE_NAME,
|
||||
productId: productId,
|
||||
token: purchaseToken,
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 查询作废的交易
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
*/
|
||||
public async queryVoidedPurchases(startTime: string, endTime: string) {
|
||||
return this.androidpublisher.purchases.voidedpurchases.list({
|
||||
packageName: PAGEAGE_NAME,
|
||||
type: 0,
|
||||
startTime,
|
||||
endTime,
|
||||
})
|
||||
}
|
||||
}
|
102
yarn.lock
102
yarn.lock
@ -619,6 +619,14 @@ buffer@^6.0.3:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
call-bind@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.0.2"
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
@ -1168,6 +1176,24 @@ gcp-metadata@^5.0.0:
|
||||
gaxios "^5.0.0"
|
||||
json-bigint "^1.0.0"
|
||||
|
||||
gcp-metadata@^5.3.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-5.3.0.tgz#6f45eb473d0cb47d15001476b48b663744d25408"
|
||||
integrity sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==
|
||||
dependencies:
|
||||
gaxios "^5.0.0"
|
||||
json-bigint "^1.0.0"
|
||||
|
||||
get-intrinsic@^1.0.2:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82"
|
||||
integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-proto "^1.0.1"
|
||||
has-symbols "^1.0.3"
|
||||
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
@ -1213,6 +1239,21 @@ globby@^11.1.0:
|
||||
merge2 "^1.4.1"
|
||||
slash "^3.0.0"
|
||||
|
||||
google-auth-library@^8.0.2:
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-8.9.0.tgz#15a271eb2ec35d43b81deb72211bd61b1ef14dd0"
|
||||
integrity sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==
|
||||
dependencies:
|
||||
arrify "^2.0.0"
|
||||
base64-js "^1.3.0"
|
||||
ecdsa-sig-formatter "^1.0.11"
|
||||
fast-text-encoding "^1.0.0"
|
||||
gaxios "^5.0.0"
|
||||
gcp-metadata "^5.3.0"
|
||||
gtoken "^6.1.0"
|
||||
jws "^4.0.0"
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
google-auth-library@^8.5.2:
|
||||
version "8.5.2"
|
||||
resolved "https://registry.npmmirror.com/google-auth-library/-/google-auth-library-8.5.2.tgz#bcdced8f7b475b80bf0e9c109c7c7e930866947b"
|
||||
@ -1235,6 +1276,26 @@ google-p12-pem@^4.0.0:
|
||||
dependencies:
|
||||
node-forge "^1.3.1"
|
||||
|
||||
googleapis-common@^6.0.0:
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/googleapis-common/-/googleapis-common-6.0.4.tgz#bd968bef2a478bcd3db51b27655502a11eaf8bf4"
|
||||
integrity sha512-m4ErxGE8unR1z0VajT6AYk3s6a9gIMM6EkDZfkPnES8joeOlEtFEJeF8IyZkb0tjPXkktUfYrE4b3Li1DNyOwA==
|
||||
dependencies:
|
||||
extend "^3.0.2"
|
||||
gaxios "^5.0.1"
|
||||
google-auth-library "^8.0.2"
|
||||
qs "^6.7.0"
|
||||
url-template "^2.0.8"
|
||||
uuid "^9.0.0"
|
||||
|
||||
googleapis@^120.0.0:
|
||||
version "120.0.0"
|
||||
resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-120.0.0.tgz#0ca260fad6cc7575e5d762e6a33ea88000f8e6bc"
|
||||
integrity sha512-Reo5PpERv0Df/L8Jx8CrPHMI3oEXmPBDHLXCY12biXUtveVgWVEoQN4Inn/85+eoNRsDiVyeEH/MjAa3hPHHrA==
|
||||
dependencies:
|
||||
google-auth-library "^8.0.2"
|
||||
googleapis-common "^6.0.0"
|
||||
|
||||
grapheme-splitter@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
|
||||
@ -1254,6 +1315,16 @@ has-flag@^4.0.0:
|
||||
resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
|
||||
integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
|
||||
|
||||
has-symbols@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
@ -1780,6 +1851,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
object-inspect@^1.9.0:
|
||||
version "1.12.3"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
|
||||
integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
|
||||
|
||||
obliterator@^2.0.1:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npmmirror.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816"
|
||||
@ -1940,6 +2016,13 @@ punycode@^2.1.0, punycode@^2.1.1:
|
||||
resolved "https://registry.npmmirror.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
qs@^6.7.0:
|
||||
version "6.11.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9"
|
||||
integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==
|
||||
dependencies:
|
||||
side-channel "^1.0.4"
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
@ -2100,6 +2183,15 @@ shebang-regex@^3.0.0:
|
||||
resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
side-channel@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
get-intrinsic "^1.0.2"
|
||||
object-inspect "^1.9.0"
|
||||
|
||||
sift@16.0.0:
|
||||
version "16.0.0"
|
||||
resolved "https://registry.npmmirror.com/sift/-/sift-16.0.0.tgz#447991577db61f1a8fab727a8a98a6db57a23eb8"
|
||||
@ -2356,6 +2448,16 @@ uri-js@^4.2.2:
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
url-template@^2.0.8:
|
||||
version "2.0.8"
|
||||
resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21"
|
||||
integrity sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==
|
||||
|
||||
uuid@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
|
||||
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
||||
|
||||
v8-compile-cache-lib@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||
|
Loading…
x
Reference in New Issue
Block a user