增加小游戏码的生成

This commit is contained in:
zhl 2021-05-19 14:36:53 +08:00
parent dfbe89f10b
commit 2884da21a8
5 changed files with 127 additions and 19 deletions

View File

@ -1,9 +1,20 @@
import BaseController from '../../common/base.controller'
import { permission, router } from '../../decorators/router'
import { permission, role, router } from '../../decorators/router'
import { ZError } from '../../common/ZError'
import { Game } from '../../models/content/Game'
import { generateQrFile } from '../../services/File'
class GameController extends BaseController{
@role('anon')
@router('get /api/test')
async test(req) {
let gameId= '60810dd156af0e8550832a44'
let version = '608117912ff0238a3e607d33'
let shop = 'sa6xtgbmj7'
const { file, url } = await generateQrFile({gameId, version, shop})
return {file, url}
}
@permission(['game:read', 'shop:game_setting'])
@router('post /games')
async list(req, res) {

View File

@ -3,6 +3,7 @@ import { permission, router } from '../../decorators/router'
import { Shop } from '../../models/shop/Shop'
import { ZError } from '../../common/ZError'
import { Game } from '../../models/content/Game'
import { generateQrFile } from '../../services/File'
class ShopController extends BaseController {
@ -149,6 +150,15 @@ class ShopController extends BaseController {
versionid: shop.gameInfo.versionid
}
}
@permission('shop:edit')
@router('post /shop/gameqr')
async getGameQr(req: any) {
let { shop, gameId, version } = req.params
const { url } = await generateQrFile({gameId, version, shop})
return { url }
}
@permission('shop:edit')
@router('post /shop/save_qtype')
async updateQTypes(req) {

View File

@ -25,6 +25,9 @@ export class GameVersion extends Base{
@prop()
public appid: string
@prop()
public appsecret: string
@prop()
public image: string
@ -61,26 +64,14 @@ class GameClass extends BaseModule {
public createdBy: string
public static parseQueryParam(params) {
let {key, timeBegin, timeEnd, shop, hasVersion} = params
let opt: any = {deleted: false}
if (key) {
opt.name = {$regex: key, $options: 'i'}
}
if (shop) {
opt.shop = shop
}
if (timeBegin && !timeEnd) {
opt.createdAt = {$gte: timeBegin};
} else if (timeBegin && timeEnd) {
opt['$and'] = [{createdAt: {$gte: timeBegin}}, {createdAt: {$lte: timeEnd}}];
} else if (!timeBegin && timeEnd) {
opt.createdAt = {$lte: timeEnd};
let options: any = {
matchKey: 'name'
}
let { opt, sort } = super.parseQueryParam(params, options)
let { hasVersion } = params
if (hasVersion) {
Object.assign(opt, {'versions.0': {$exists: true}})
}
let sort = {_id: 1}
return { opt, sort }
}
@ -88,6 +79,14 @@ class GameClass extends BaseModule {
return this.findOne({deleted: false, 'versions.0': {$exists: true} }).exec()
}
public static async fetchVersionInfo(gameId: string, version: string) {
let game = await Game.findById(gameId)
if (!game) {
return null
}
return game.versions.find( o => o._id.toHexString() === version)
}
}
export const Game = getModelForClass(GameClass, { existingConnection: GameClass.db })

53
src/services/File.ts Normal file
View File

@ -0,0 +1,53 @@
import config from '../config/config'
import * as jetpack from 'fs-jetpack'
import { Game } from '../models/content/Game'
import { ZError } from '../common/ZError'
import { generateQr } from './Wechat'
export function generateUploadPath(subPath: string) {
const base = config.file.upload_location
const path = `${base}${subPath}`
jetpack.dir(path)
return path
}
/**
*
* @param {string} gameId
* @param {string} version
* @param {string} shop
* @return {{file: string, url: string}}
*/
export async function generateQrFile({gameId, version, shop } : {gameId: string, version: string, shop: string}) {
let subPath = `/qr/${gameId}/${version}`
let path = generateUploadPath(subPath)
let file = `${path}/${shop}.png`
let url = `${config.file.show_url}${subPath}/${shop}.png`
if ( jetpack.exists(file) !== 'file' ) {
let versionData = await Game.fetchVersionInfo(gameId, version)
if (!versionData || !versionData.appid || !versionData.appsecret) {
throw new ZError(20, 'game version not found')
}
await generateQr({
appId: versionData.appid,
appSecret: versionData.appsecret,
scene: shop,
file
})
}
return {file, url}
}
/**
*
* @param {string} gameId
* @param {string} version
* @param {string} shop
* @return {boolean}
*/
export function checkQrExists(gameId: string, version: string, shop: string) {
let subPath = `/qr/${gameId}/${version}`
let path = generateUploadPath(subPath)
let file = `${path}/${shop}.png`
return jetpack.exists(file) === 'file'
}

View File

@ -1,5 +1,40 @@
import axios, { AxiosRequestConfig } from 'axios'
import fs from 'fs'
export async function generateQr({appId, appSecret, scene, filePath}) {
export async function generateQr({appId, appSecret, scene, file }) {
const stream = fs.createWriteStream(file);
const token = await refreshToken(appId, appSecret)
const url = `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${token}`
const reqParams = {
scene: scene,
width: 430,
auto_color: false,
line_color: {'r': '0', 'g': '0', 'b': '0'},
}
let reqConfig: AxiosRequestConfig = {
method: 'post',
url,
headers: {
'Cache-Control': 'no-cache',
'Content-Type': 'application/json',
},
responseType: 'stream',
data: reqParams
}
const { data } = await axios(reqConfig)
data.pipe(stream)
return true
}
export async function refreshToken(appId: string, appSecret: string) {
const link =
`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`
const { data } = await axios.get(link)
if (!data.errcode) {
return data.access_token
} else {
throw new Error(data.errmsg)
}
}