增加小游戏码的生成
This commit is contained in:
parent
dfbe89f10b
commit
2884da21a8
@ -1,9 +1,20 @@
|
|||||||
import BaseController from '../../common/base.controller'
|
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 { ZError } from '../../common/ZError'
|
||||||
import { Game } from '../../models/content/Game'
|
import { Game } from '../../models/content/Game'
|
||||||
|
import { generateQrFile } from '../../services/File'
|
||||||
|
|
||||||
|
|
||||||
class GameController extends BaseController{
|
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'])
|
@permission(['game:read', 'shop:game_setting'])
|
||||||
@router('post /games')
|
@router('post /games')
|
||||||
async list(req, res) {
|
async list(req, res) {
|
||||||
|
@ -3,6 +3,7 @@ import { permission, router } from '../../decorators/router'
|
|||||||
import { Shop } from '../../models/shop/Shop'
|
import { Shop } from '../../models/shop/Shop'
|
||||||
import { ZError } from '../../common/ZError'
|
import { ZError } from '../../common/ZError'
|
||||||
import { Game } from '../../models/content/Game'
|
import { Game } from '../../models/content/Game'
|
||||||
|
import { generateQrFile } from '../../services/File'
|
||||||
|
|
||||||
class ShopController extends BaseController {
|
class ShopController extends BaseController {
|
||||||
|
|
||||||
@ -149,6 +150,15 @@ class ShopController extends BaseController {
|
|||||||
versionid: shop.gameInfo.versionid
|
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')
|
@permission('shop:edit')
|
||||||
@router('post /shop/save_qtype')
|
@router('post /shop/save_qtype')
|
||||||
async updateQTypes(req) {
|
async updateQTypes(req) {
|
||||||
|
@ -25,6 +25,9 @@ export class GameVersion extends Base{
|
|||||||
@prop()
|
@prop()
|
||||||
public appid: string
|
public appid: string
|
||||||
|
|
||||||
|
@prop()
|
||||||
|
public appsecret: string
|
||||||
|
|
||||||
@prop()
|
@prop()
|
||||||
public image: string
|
public image: string
|
||||||
|
|
||||||
@ -61,26 +64,14 @@ class GameClass extends BaseModule {
|
|||||||
public createdBy: string
|
public createdBy: string
|
||||||
|
|
||||||
public static parseQueryParam(params) {
|
public static parseQueryParam(params) {
|
||||||
let {key, timeBegin, timeEnd, shop, hasVersion} = params
|
let options: any = {
|
||||||
let opt: any = {deleted: false}
|
matchKey: 'name'
|
||||||
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 { opt, sort } = super.parseQueryParam(params, options)
|
||||||
|
let { hasVersion } = params
|
||||||
if (hasVersion) {
|
if (hasVersion) {
|
||||||
Object.assign(opt, {'versions.0': {$exists: true}})
|
Object.assign(opt, {'versions.0': {$exists: true}})
|
||||||
}
|
}
|
||||||
|
|
||||||
let sort = {_id: 1}
|
|
||||||
return { opt, sort }
|
return { opt, sort }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +79,14 @@ class GameClass extends BaseModule {
|
|||||||
return this.findOne({deleted: false, 'versions.0': {$exists: true} }).exec()
|
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 })
|
export const Game = getModelForClass(GameClass, { existingConnection: GameClass.db })
|
||||||
|
53
src/services/File.ts
Normal file
53
src/services/File.ts
Normal 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'
|
||||||
|
}
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user