一些代码移至公用组件

This commit is contained in:
CounterFire2023 2024-01-17 17:36:30 +08:00
parent cf5d4c659c
commit a153eded7b
35 changed files with 2449 additions and 708 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "packages/zutils"]
path = packages/zutils
url = git@git.kingsome.cn:zhanghongliang/zutils.git

View File

@ -37,7 +37,8 @@
"node-schedule": "^2.1.1",
"redis": "^3.1.2",
"tracer": "^1.1.6",
"verify-apple-id-token": "^3.0.0"
"verify-apple-id-token": "^3.0.0",
"zutils": "link:packages/zutils"
},
"devDependencies": {
"@typegoose/typegoose": "^9.12.1",

1
packages/zutils Submodule

@ -0,0 +1 @@
Subproject commit b982e43cd717e09acafba79f40c63e2572dbef96

View File

@ -1,7 +1,6 @@
import fastify, { FastifyError, FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
import helmet from '@fastify/helmet'
import { IncomingMessage, Server, ServerResponse } from 'http'
import { RouterMap } from 'decorators/router'
import { mongoose } from '@typegoose/typegoose'
import logger from 'logger/logger'
import config from 'config/config'
@ -10,6 +9,7 @@ import CodeTaskSchedule from 'schedule/codetask.schedule'
import { PriceSvr } from 'service/price.svr'
import { GooglePaySvr } from 'service/googlepay.svr'
import { GasSvr } from 'service/gas.svr'
import { RouterMap } from 'zutils'
const zReqParserPlugin = require('plugins/zReqParser')

View File

@ -1,4 +1,4 @@
import { singleton } from '../decorators/singleton'
import { singleton } from 'zutils'
import Clock from './ClockTimer'
import { Delayed } from './Delayed'

View File

@ -1,107 +0,0 @@
type Callback<T> = () => Promise<T>
export type AsyncQueue<T = void> = {
push: (task: Callback<T>) => Promise<T>
flush: () => Promise<void>
size: number
}
/**
* Ensures that each callback pushed onto the queue is executed in series.
* Such a quetie 😻
* @param opts.dedupeConcurrent If dedupeConcurrent is `true` it ensures that if multiple
* tasks are pushed onto the queue while there is an active task, only the
* last one will be executed, once the active task has completed.
* e.g. in the below example, only 0 and 3 will be executed.
* ```
* const queue = createAsyncQueue({ dedupeConcurrent: true })
* queue.push(async () => console.log(0)) // returns 0
* queue.push(async () => console.log(1)) // returns 3
* queue.push(async () => console.log(2)) // returns 3
* queue.push(async () => console.log(3)) // returns 3
* ```
* */
export function createAsyncQueue<T = void>(opts = { dedupeConcurrent: false }): AsyncQueue<T> {
const { dedupeConcurrent } = opts
let queue: Callback<T>[] = []
let running: Promise<void> | undefined
let nextPromise = new DeferredPromise<T>()
const push = (task: Callback<T>) => {
let taskPromise = new DeferredPromise<T>()
if (dedupeConcurrent) {
queue = []
if (nextPromise.started) nextPromise = new DeferredPromise<T>()
taskPromise = nextPromise
}
queue.push(() => {
taskPromise.started = true
task().then(taskPromise.resolve).catch(taskPromise.reject)
return taskPromise.promise
})
if (!running) running = start()
return taskPromise.promise
}
const start = async () => {
while (queue.length) {
const task = queue.shift()!
await task().catch(() => {})
}
running = undefined
}
return {
push,
flush: () => running || Promise.resolve(),
get size() {
return queue.length
},
}
}
export const createAsyncQueues = <T = void>(opts = { dedupeConcurrent: false }) => {
const queues: { [queueId: string]: AsyncQueue<T> } = {}
const push = (queueId: string, task: Callback<T>) => {
if (!queues[queueId]) queues[queueId] = createAsyncQueue<T>(opts)
return queues[queueId].push(task)
}
const flush = (queueId: string) => {
if (!queues[queueId]) queues[queueId] = createAsyncQueue<T>(opts)
return queues[queueId].flush()
}
return { push, flush }
}
class DeferredPromise<T = void, E = any> {
started = false
resolve: (x: T | PromiseLike<T>) => void = () => {}
reject: (x: E) => void = () => {}
promise: Promise<T>
constructor() {
this.promise = new Promise<T>((res, rej) => {
this.resolve = res
this.reject = rej
})
}
}
// function main() {
// const queue = createAsyncQueue()
// queue.push(async () => {
// console.log(0)
// }) // returns 0
// queue.push(async () => {
// console.log(1)
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// console.log('12')
// resolve()
// }, 1000)
// })
// }) // returns 3
// queue.push(async () => console.log(2)) // returns 3
// queue.push(async () => console.log(3)) // returns 3
// console.log('hi')
// }
// main()

View File

@ -1,36 +0,0 @@
import { singleton } from "decorators/singleton";
import { FastifyRequest } from "fastify";
import { ZError } from "./ZError";
@singleton
export class SyncLocker {
map: Map<string, boolean> = new Map();
public lock(req: FastifyRequest) {
const key = `${req.method}:${req.url}:${req.user?.id || ''}`
if (this.map.has(key)) {
return false;
}
this.map.set(key, true);
return true;
}
public unlock(req: FastifyRequest) {
const key = `${req.method}:${req.url}:${req.user?.id || ''}`
this.map.delete(key);
}
public checkLock(req: FastifyRequest) {
const key = `${req.method}:${req.url}:${req.user?.id || ''}`
if (this.map.has(key)) {
throw new ZError(100, 'request too fast');
}
this.lock(req);
return true;
}
public isLocked(req: FastifyRequest) {
const key = `${req.method}:${req.url}:${req.user?.id || ''}`
return this.map.has(key);
}
}

View File

@ -1,13 +0,0 @@
import { FastifyError } from 'fastify'
export class ZError implements FastifyError {
code: string
statusCode?: number
message: string
name: string
constructor(statusCode: number, message: string) {
this.statusCode = statusCode
this.message = message
}
}

View File

@ -1,7 +0,0 @@
import fastify = require('fastify')
export const ROLE_ANON = 'anon'
class BaseController {
aotoRoute(req: fastify.FastifyRequest, res) {}
}
export default BaseController

View File

@ -1,12 +1,10 @@
import logger from 'logger/logger'
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { ZError } from 'common/ZError'
import { role, router } from 'decorators/router'
import { checkPrePaySign, createOrder, queryFiat, queryPrice, refreshToken } from 'service/alchemy.svr'
import { PayRecord, PayStatus } from 'modules/PayRecord'
import { PriceSvr } from 'service/price.svr'
import { reportPayResult } from 'service/game.svr'
import { GasSvr } from 'service/gas.svr'
import { BaseController, ROLE_ANON, ZError, role, router } from 'zutils'
const CALL_BACK_URL = `${process.env.ALCHEMY_PAY_CB_URL}/pay/out/alchemy/result`
class AlchemyController extends BaseController {

View File

@ -1,7 +1,4 @@
import logger from 'logger/logger'
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { ZError } from 'common/ZError'
import { role, router } from 'decorators/router'
import { calcNetworkFee, checkPayResultSign, checkSha1Sign } from 'service/alchemy.svr'
import { PayRecord, PayStatus } from 'modules/PayRecord'
import { TransferQueue } from 'queue/transfer.queue'
@ -9,6 +6,7 @@ import { TransferRecord } from 'modules/TransferRecord'
import { reportPayResult } from 'service/game.svr'
import { PriceSvr } from 'service/price.svr'
import { OrderCacheSvr } from 'service/ordercache.svr'
import { BaseController, role, ROLE_ANON, router, ZError } from 'zutils'
import { fromWei, toBigWei } from 'utils/number.util'
let errorRes = function (msg: string) {

View File

@ -1,11 +1,9 @@
import { ZError } from 'common/ZError'
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { role, router } from 'decorators/router'
import logger from 'logger/logger'
import { AppleInApp, ApplePayStatus } from 'modules/AppleInApp'
import { InAppRecord } from 'modules/InAppRecord'
import { IPayResult, reportApplePurchaseResult } from 'service/game.svr'
import { IosPaySvr } from 'service/iospay.svr'
import { BaseController, router, ZError, role, ROLE_ANON } from 'zutils'
class ApplePayController extends BaseController {
@router('post /pay/apple/verify')

View File

@ -1,11 +1,9 @@
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 { InAppRecord } from 'modules/InAppRecord'
import { IPayResult, reportGooglePurchaseResult } from 'service/game.svr'
import { GooglePaySvr } from 'service/googlepay.svr'
import { BaseController, router, ZError } from 'zutils'
class GooglePayController extends BaseController {
@router('post /pay/google/verify')

View File

@ -1,18 +1,16 @@
import { ZError } from 'common/ZError'
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { role, router } from 'decorators/router'
import logger from 'logger/logger'
import { PayRecord, PayRecordClass, PayStatus } from 'modules/PayRecord'
import { TransferRecord, TransferRecordClass } from 'modules/TransferRecord'
import { hmacsha256 } from 'utils/security.util'
import { DocumentType } from '@typegoose/typegoose'
import { updateOrderStatus } from 'service/alchemy.svr'
import { PriceSvr } from 'service/price.svr'
import { assembleGameData, checkGameSign } from 'service/game.svr'
import { BaseController, role, ROLE_ANON, router, ZError } from 'zutils'
import { hmacSha256 } from 'zutils/utils/security.util'
const calcHash = function (data: any) {
let signStr = JSON.stringify(data)
return hmacsha256(signStr, process.env.HASH_SALT_CHAIN)
return hmacSha256(signStr, process.env.HASH_SALT_CHAIN).toLowerCase()
}
const notify = async function (record: DocumentType<PayRecordClass>, subTask: DocumentType<TransferRecordClass>) {

View File

@ -1,7 +1,5 @@
import { ZError } from 'common/ZError'
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { role, router } from 'decorators/router'
import { beginSell, buyOrder, submitOrder } from 'service/okxmarket.svr'
import { BaseController, ROLE_ANON, ZError, role, router } from 'zutils'
class OkxMarketController extends BaseController {
@role(ROLE_ANON)

View File

@ -1,7 +1,5 @@
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { ZError } from 'common/ZError'
import { role, router } from 'decorators/router'
import logger from 'logger/logger'
import { BaseController, role, ROLE_ANON, router } from 'zutils'
class PurchaseController extends BaseController {
/**

View File

@ -1,7 +1,5 @@
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { ZError } from 'common/ZError'
import { role, router } from 'decorators/router'
import { BridgeSvr } from 'service/bridge.svr'
import { BaseController, role, ROLE_ANON, router, ZError } from 'zutils'
const TOKEN_PREFIX = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.'

View File

@ -1,5 +1,5 @@
import 'reflect-metadata'
import { singleton } from './singleton'
import { singleton } from 'zutils'
@singleton
export class NoJsonClass {

View File

@ -1,142 +0,0 @@
import BaseController from '../common/base.controller'
export class RouterData {
target?: any
method?: string
path?: string
fun?: Function
}
export class RouterMap {
static decoratedRouters: Map<
Function,
{
roles?: string[]
permissions?: string[][]
data?: RouterData[]
depts?: string[]
}
> = new Map()
}
export function router(route?: string) {
return (target: BaseController, name: string, value: PropertyDescriptor) => {
if (!route) {
const controller = target.constructor.name
const controllerName = controller.toLowerCase().replace('.controller', '')
route = 'all ' + ['', controllerName, name].join('/')
}
const split = route.split(' ')
if (split.length > 2) {
throw new Error('路由中只允许一个空格')
}
const [method, path] = split
// @ts-ignore
const key = target[name]
let routerData = new RouterData()
routerData.target = target
routerData.method = method
routerData.path = path
// @ts-ignore
routerData.fun = target[name]
if (RouterMap.decoratedRouters.has(key)) {
let objCurrent = RouterMap.decoratedRouters.get(key)
if (!objCurrent.data) {
objCurrent.data = [routerData]
} else {
objCurrent.data.push(routerData)
}
// @ts-ignore
RouterMap.decoratedRouters.set(target[name], objCurrent)
} else {
let routerObj = {
data: [routerData],
}
// @ts-ignore
RouterMap.decoratedRouters.set(target[name], routerObj)
}
}
}
export function role(roles?: string | string[]) {
return (target: BaseController, name: string, value: PropertyDescriptor) => {
let roleList: string[] = []
if (roles) {
if (Array.isArray(roles)) {
roleList = roles
} else {
roleList = [roles]
}
}
// @ts-ignore
const key = target[name]
let roleObj = { roles: roleList }
if (RouterMap.decoratedRouters.has(key)) {
let objCurrent = RouterMap.decoratedRouters.get(key)
Object.assign(objCurrent, roleObj)
// @ts-ignore
RouterMap.decoratedRouters.set(target[name], objCurrent)
} else {
// @ts-ignore
RouterMap.decoratedRouters.set(target[name], roleObj)
}
}
}
export function permission(permissions?: string | string[]) {
return (target: BaseController, name: string, value: PropertyDescriptor) => {
let permissionList: string[][] = [[]]
if (permissions) {
if (Array.isArray(permissions)) {
let arr = []
for (let sub of permissions) {
arr.push(sub.split(':'))
}
permissionList = arr
} else {
permissionList = [permissions.split(':')]
}
}
// @ts-ignore
const key = target[name]
let permissionObj = { permissions: permissionList }
if (RouterMap.decoratedRouters.has(key)) {
let objCurrent = RouterMap.decoratedRouters.get(key)
Object.assign(objCurrent, permissionObj)
// @ts-ignore
RouterMap.decoratedRouters.set(target[name], objCurrent)
} else {
// @ts-ignore
RouterMap.decoratedRouters.set(target[name], permissionObj)
}
}
}
/**
* dept修饰器的, id是否存在
*/
export function dept(depts?: string | string[]) {
return (target: BaseController, name: string, value: PropertyDescriptor) => {
let deptList: string[] = []
if (depts) {
if (Array.isArray(depts)) {
deptList = depts
} else {
deptList = [depts]
}
}
// @ts-ignore
const key = target[name]
let deptObj = { depts: deptList }
if (RouterMap.decoratedRouters.has(key)) {
let objCurrent = RouterMap.decoratedRouters.get(key)
Object.assign(objCurrent, deptObj)
// @ts-ignore
RouterMap.decoratedRouters.set(target[name], objCurrent)
} else {
// @ts-ignore
RouterMap.decoratedRouters.set(target[name], deptObj)
}
}
}

View File

@ -1,29 +0,0 @@
/**
* class
* 使:
* @singleton
* class Test {}
* new Test() === new Test() // returns `true`
* 使 decorator
* const TestSingleton = singleton(Test)
* new TestSingleton() === new TestSingleton() //returns 'true'
*/
export const SINGLETON_KEY = Symbol()
export type Singleton<T extends new (...args: any[]) => any> = T & {
[SINGLETON_KEY]: T extends new (...args: any[]) => infer I ? I : never
}
export const singleton = <T extends new (...args: any[]) => any>(classTarget: T) =>
new Proxy(classTarget, {
construct(target: Singleton<T>, argumentsList, newTarget) {
// Skip proxy for children
if (target.prototype !== newTarget.prototype) {
return Reflect.construct(target, argumentsList, newTarget)
}
if (!target[SINGLETON_KEY]) {
target[SINGLETON_KEY] = Reflect.construct(target, argumentsList, newTarget)
}
return target[SINGLETON_KEY]
},
})

View File

@ -1,16 +1,16 @@
import * as dotenv from 'dotenv'
import logger from 'logger/logger'
import { RedisClient } from 'redis/RedisClient'
const envFile = process.env.NODE_ENV && process.env.NODE_ENV === 'production' ? `.env.production` : '.env.development'
dotenv.config({ path: envFile })
import 'common/Extend'
import { GooglePaySvr } from 'service/googlepay.svr'
import GooglePurchaseSchedule from 'schedule/googlepurchase.schedule'
import { ZRedisClient } from 'zutils'
async function main() {
let opts = { url: process.env.REDIS }
new RedisClient(opts)
new ZRedisClient(opts)
logger.info('REDIS Connected')
await new GooglePaySvr().init()
logger.info('GooglePaySvr Connected')

View File

@ -1,7 +1,6 @@
import { AsyncQueue, createAsyncQueue } from 'common/AsyncQueue'
import { singleton } from 'decorators/singleton'
import logger from 'logger/logger'
import { UserLog } from 'modules/UserLog'
import { singleton, AsyncQueue, createAsyncQueue } from 'zutils'
@singleton
export class LoggerQueue {

View File

@ -1,5 +1,3 @@
import { singleton } from 'decorators/singleton'
import { AsyncQueue, createAsyncQueue } from 'common/AsyncQueue'
import { DocumentType } from '@typegoose/typegoose'
import { PayRecordClass } from 'modules/PayRecord'
import logger from 'logger/logger'
@ -7,6 +5,7 @@ import { pushTaskToChain } from 'service/chain.svr'
import { TransferRecord } from 'modules/TransferRecord'
import config from 'config/config'
import assert from 'assert'
import { AsyncQueue, createAsyncQueue, singleton } from 'zutils'
/**
* let data = {

View File

@ -1,306 +0,0 @@
import { resolveCname } from 'dns'
import redis from 'redis'
import { promisify } from 'util'
import { singleton } from '../decorators/singleton'
type Callback = (...args: any[]) => void
@singleton
export class RedisClient {
public pub: redis.RedisClient
public sub: redis.RedisClient
protected subscribeAsync: any
protected unsubscribeAsync: any
protected publishAsync: any
protected subscriptions: { [channel: string]: Callback[] } = {}
protected smembersAsync: any
protected sismemberAsync: any
protected hgetAsync: any
protected hlenAsync: any
protected pubsubAsync: any
protected incrAsync: any
protected decrAsync: any
constructor(opts?: redis.ClientOpts) {
this.sub = redis.createClient(opts)
this.pub = redis.createClient(opts)
// no listener limit
this.sub.setMaxListeners(0)
// create promisified pub/sub methods.
this.subscribeAsync = promisify(this.sub.subscribe).bind(this.sub)
this.unsubscribeAsync = promisify(this.sub.unsubscribe).bind(this.sub)
this.publishAsync = promisify(this.pub.publish).bind(this.pub)
// create promisified redis methods.
this.smembersAsync = promisify(this.pub.smembers).bind(this.pub)
this.sismemberAsync = promisify(this.pub.sismember).bind(this.pub)
this.hlenAsync = promisify(this.pub.hlen).bind(this.pub)
this.hgetAsync = promisify(this.pub.hget).bind(this.pub)
this.pubsubAsync = promisify(this.pub.pubsub).bind(this.pub)
this.decrAsync = promisify(this.pub.decr).bind(this.pub)
this.incrAsync = promisify(this.pub.incr).bind(this.pub)
}
public async subscribe(topic: string, callback: Callback) {
if (!this.subscriptions[topic]) {
this.subscriptions[topic] = []
}
this.subscriptions[topic].push(callback)
if (this.sub.listeners('message').length === 0) {
this.sub.addListener('message', this.handleSubscription)
}
await this.subscribeAsync(topic)
return this
}
public async unsubscribe(topic: string, callback?: Callback) {
if (callback) {
const index = this.subscriptions[topic].indexOf(callback)
this.subscriptions[topic].splice(index, 1)
} else {
this.subscriptions[topic] = []
}
if (this.subscriptions[topic].length === 0) {
await this.unsubscribeAsync(topic)
}
return this
}
public async publish(topic: string, data: any) {
if (data === undefined) {
data = false
}
await this.publishAsync(topic, JSON.stringify(data))
}
public async exists(roomId: string): Promise<boolean> {
return (await this.pubsubAsync('channels', roomId)).length > 0
}
public async setex(key: string, value: string, seconds: number) {
return new Promise(resolve => this.pub.setex(key, seconds, value, resolve))
}
public async expire(key: string, seconds: number) {
return new Promise(resolve => this.pub.expire(key, seconds, resolve))
}
public async get(key: string): Promise<string | null> {
return new Promise((resolve, reject) => {
this.pub.get(key, (err, data: string | null) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async set(key: string, val: string) {
return new Promise(resolve => {
this.pub.set(key, val, () => {
resolve && resolve('')
})
})
}
public async del(roomId: string) {
return new Promise(resolve => {
this.pub.del(roomId, resolve)
})
}
public async sadd(key: string, value: any) {
return new Promise(resolve => {
this.pub.sadd(key, value, resolve)
})
}
public async smembers(key: string): Promise<string[]> {
return await this.smembersAsync(key)
}
public async sismember(key: string, field: string): Promise<number> {
return await this.sismemberAsync(key, field)
}
public async srem(key: string, value: any) {
return new Promise(resolve => {
this.pub.srem(key, value, resolve)
})
}
public async scard(key: string) {
return new Promise((resolve, reject) => {
this.pub.scard(key, (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async srandmember(key: string) {
return new Promise((resolve, reject) => {
this.pub.srandmember(key, (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async sinter(...keys: string[]) {
return new Promise<string[]>((resolve, reject) => {
this.pub.sinter(...keys, (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async zadd(key: string, value: any, member: string) {
return new Promise(resolve => {
this.pub.zadd(key, value, member, resolve)
})
}
public async zrangebyscore(key: string, min: number, max: number) {
return new Promise((resolve, reject) => {
this.pub.zrangebyscore(key, min, max, 'withscores', (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async zcard(key: string) {
return new Promise((resolve, reject) => {
this.pub.zcard(key, (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async zcount(key: string, min: number, max: number) {
return new Promise((resolve, reject) => {
this.pub.zcount(key, min, max, (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async zrevrank(key: string, member: string) {
return new Promise((resolve, reject) => {
this.pub.zrevrank(key, member, (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async zscore(key: string, member: string) {
return new Promise((resolve, reject) => {
this.pub.zscore(key, member, (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async zrevrange(key: string, start: number, end: number) {
return new Promise((resolve, reject) => {
this.pub.zrevrange(key, start, end, 'withscores', (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
}
public async hset(key: string, field: string, value: string) {
return new Promise(resolve => {
this.pub.hset(key, field, value, resolve)
})
}
public async hincrby(key: string, field: string, value: number) {
return new Promise(resolve => {
this.pub.hincrby(key, field, value, resolve)
})
}
public async hget(key: string, field: string) {
return await this.hgetAsync(key, field)
}
public async hgetall(key: string) {
return new Promise<{ [key: string]: string }>((resolve, reject) => {
this.pub.hgetall(key, (err, values) => {
if (err) {
return reject(err)
}
resolve(values)
})
})
}
public async hdel(key: string, field: string) {
return new Promise((resolve, reject) => {
this.pub.hdel(key, field, (err, ok) => {
if (err) {
return reject(err)
}
resolve(ok)
})
})
}
public async hlen(key: string): Promise<number> {
return await this.hlenAsync(key)
}
public async incr(key: string): Promise<number> {
return await this.incrAsync(key)
}
public async decr(key: string): Promise<number> {
return await this.decrAsync(key)
}
protected handleSubscription = (channel: string, message: string) => {
if (this.subscriptions[channel]) {
for (let i = 0, l = this.subscriptions[channel].length; i < l; i++) {
this.subscriptions[channel][i](JSON.parse(message))
}
}
}
}

View File

@ -1,6 +1,6 @@
import { singleton } from 'decorators/singleton'
import { CodeRecord, CodeStatus } from 'modules/CodeRecord'
import * as schedule from 'node-schedule'
import { singleton } from 'zutils'
/**
*

View File

@ -1,9 +1,9 @@
import { singleton } from 'decorators/singleton'
import logger from 'logger/logger'
import { GoogleInApp } from 'modules/GoogleInApp'
import * as schedule from 'node-schedule'
import { RedisClient } from 'redis/RedisClient'
import { GooglePaySvr } from 'service/googlepay.svr'
import { ZRedisClient, singleton } from 'zutils'
/**
* google voided purchase
@ -22,7 +22,7 @@ import { GooglePaySvr } from 'service/googlepay.svr'
export default class GooglePurchaseSchedule {
async parseAllRecord() {
const timeKey = 'google_inapp_voided_check_time'
let timeStr = await new RedisClient().get(timeKey)
let timeStr = await new ZRedisClient().get(timeKey)
let startTime = timeStr ? parseInt(timeStr) : Date.now() - 24 * 60 * 60 * 1000
let endTime = Date.now()
try {
@ -33,7 +33,7 @@ export default class GooglePurchaseSchedule {
}
const { data } = res
await GoogleInApp.parseVoidedRecords(data.voidedPurchases)
await new RedisClient().set(timeKey, endTime + '')
await new ZRedisClient().set(timeKey, endTime + '')
logger.info(`success check google voided purchase:: voidedPurchases: ${data.voidedPurchases?.length || 0}`)
} catch (err) {
logger.info('error check google voided purchase', err.message || err)

View File

@ -1,8 +1,8 @@
import { singleton } from 'decorators/singleton'
import logger from 'logger/logger'
import { ReportQueue } from 'modules/ReportQueue'
import * as schedule from 'node-schedule'
import { reportApplePurchaseResult, reportGooglePurchaseResult } from 'service/game.svr'
import { singleton } from 'zutils'
/**
* ,

View File

@ -1,6 +1,5 @@
import { ZError } from 'common/ZError'
import { singleton } from 'decorators/singleton'
import { shortUuid, uuid } from 'utils/security.util'
import { ZError, singleton } from 'zutils'
export interface IQrData {
clientId: string

View File

@ -1,5 +1,5 @@
import { singleton } from 'decorators/singleton'
import { NetClient } from 'net/NetClient'
import { singleton } from 'zutils'
export const DEFAULT_VERIFY_HTML = `
<h1>Email Verification</h1>

View File

@ -1,9 +1,10 @@
import axios from 'axios'
import { singleton } from 'decorators/singleton'
import { queryPrice } from './alchemy.svr'
import * as schedule from 'node-schedule'
import logger from 'logger/logger'
import { erc20TransferGas, ethTransferGas } from './chain.svr'
import { singleton } from 'zutils'
@singleton
export class GasSvr {

View File

@ -1,6 +1,6 @@
import { singleton } from 'decorators/singleton'
import { androidpublisher_v3, google } from 'googleapis'
import logger from 'logger/logger'
import { singleton } from 'zutils'
const PAGEAGE_NAME = 'com.cege.games.release'

View File

@ -7,8 +7,9 @@ import {
ProductTypeParameter,
SortParameter,
} from 'apple/Models'
import { singleton } from 'decorators/singleton'
import logger from 'logger/logger'
import { singleton } from 'zutils'
const env = process.env.NODE_ENV || 'development'
const sandbox = env === 'development' ? true : false
@ -29,7 +30,7 @@ const apiSandbox = new AppStoreServerAPI(KEY, KEY_ID, ISSUER_ID, APP_BUNDLE_ID,
export class IosPaySvr {
public async iosPayVerify(orderId: string) {
logger.info('iosPayVerify: ', orderId)
let response;
let response
try {
response = await apiProd.lookupOrder(orderId)
} catch (err) {
@ -78,7 +79,7 @@ export class IosPaySvr {
}
public async getTransactionInfo(originalTransactionId: string) {
let response;
let response
try {
response = await apiProd.getTransactionInfo(originalTransactionId)
} catch (err) {
@ -91,8 +92,8 @@ export class IosPaySvr {
}
}
if (!response) {
throw new Error('empty transaction info')
}
throw new Error('empty transaction info')
}
const transaction = await decodeTransaction(response.signedTransactionInfo)
return transaction
}

View File

@ -1,4 +1,4 @@
import { singleton } from 'decorators/singleton'
import { singleton } from 'zutils'
@singleton
export class OrderCacheSvr {

View File

@ -1,8 +1,8 @@
import axios from 'axios'
import { singleton } from 'decorators/singleton'
import { queryPrice } from './alchemy.svr'
import * as schedule from 'node-schedule'
import logger from 'logger/logger'
import { singleton } from 'zutils'
@singleton
export class PriceSvr {

2421
yarn.lock

File diff suppressed because it is too large Load Diff