UNPKG

qrcode-framework

Version:

598 lines 45.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const moment = require("moment"); const sequelize_1 = require("sequelize"); const Common_1 = require("../common/Common"); const ErrorCode_1 = require("../common/ErrorCode"); const BaseService_1 = require("../core/BaseService"); const model_1 = require("../model"); const NumberUtil_1 = require("../util/NumberUtil"); const DCodeWhite_1 = require("../model/dynamicCode/DCodeWhite"); class CodeService extends BaseService_1.default { async getPasswordTip(mid) { return model_1.ModelPasswordTip.findByPk(mid); } async getBySign(sign) { const record = await model_1.ModelRecord.findOne({ where: { sign, }, }); return record; } async getById(id) { return model_1.DynamicCode.findOne({ where: { id, deleted: false, }, }); } async getToUrlByDCodeId(id) { const dCode = await model_1.DynamicCode.findOne({ where: { id, status: model_1.DYNAMIC_CODE_STATUS.UN_LOCK, deleted: false, invalidAt: { [sequelize_1.Op.or]: { [sequelize_1.Op.is]: null, [sequelize_1.Op.gte]: Date.now(), }, }, }, }); if (!dCode || dCode.status !== model_1.DYNAMIC_CODE_STATUS.UN_LOCK) { const url = await this.ctx.service.configService.getConfig('INACTIVE_DYNAMIC_CODE_URL'); return url ? url.url : null; } if (dCode.to.type === model_1.DYNAMIC_CODE_TYPE.MODEL) { return this.ctx.helper.getModelUrl(dCode.to.sign); } else { return dCode.to.url; } } async listDynamicCode(uid) { const list = await model_1.DynamicCode.findAll({ where: { uid, deleted: false, status: model_1.DYNAMIC_CODE_STATUS.UN_LOCK, }, }); return list; } async getDynamicCode(uid, id) { const code = await model_1.DynamicCode.findOne({ where: { id, uid, deleted: false, }, }); return code; } async getDynamicCodeById(id) { const code = await model_1.DynamicCode.findOne({ where: { id, deleted: false, }, }); return code; } async createModelCode(uid, code) { if (!code || !code.styleId) { throw new ErrorCode_1.HttpError({ message: '参数[styleId]无效', errorCode: ErrorCode_1.ERROR_CODE.COMMON.PARAMS_INVALID, status: 400, }); } const user = await this.ctx.service.userService.getWithIntegral(uid); const userIntegral = user.integral.value; const modelView = await model_1.HtmlModelView.findByPk(code.styleId); if (!modelView) { throw new ErrorCode_1.HttpError({ message: '模板不存在', errorCode: ErrorCode_1.ERROR_CODE.HTML_MODEL.NOT_FOUND, }); } if (userIntegral < modelView.integral) { throw new ErrorCode_1.HttpError({ message: '积分值不足', errorCode: ErrorCode_1.ERROR_CODE.INTEGRAL.NOT_ENOUGH, }); } const sign = await this.genSign(); return await global.sequelize.transaction(async (t) => { // 创建二维码模板记录 const record = await model_1.ModelRecord.create({ uid, content: code.content, title: code.title, password: code.password, sign, musicId: code.musicId || 0, styleId: code.styleId, }, { transaction: t, }); // 如果模板需要消耗积分,进行相应的逻辑 if (modelView.integral) { await Promise.all([ // 消减用户积分 user.integral.decrement({ value: modelView.integral }, { transaction: t, }), model_1.UserIntegralRecord.create({ uid, value: modelView.integral, latestValue: userIntegral, type: model_1.INTEGRAL_TYPE.MAKE_EXPEND, description: '制作模板代码消耗', meta: { code, sign, }, }, { transaction: t, }), ]); } return record; }); } async createDynamicCode(uid, code) { if (!code || !code.to) { throw new ErrorCode_1.HttpError({ message: '参数[to]无效', errorCode: ErrorCode_1.ERROR_CODE.COMMON.PARAMS_INVALID, status: 400, }); } let sign; if (NumberUtil_1.isEqual(code.type, model_1.DYNAMIC_CODE_TYPE.MODEL)) { sign = await this.genSign(); } return await global.sequelize.transaction(async (t) => { // 创建二维码模板记录 let to; if (NumberUtil_1.isEqual(code.type, model_1.DYNAMIC_CODE_TYPE.MODEL)) { let dataObj = null; try { dataObj = JSON.parse(code.to.data); } catch (e) { dataObj = null; } // 检查内容是否违规 const checkResult = await this.ctx.service.contentChecker.check(dataObj ? { content: [code.to.data] } : { content: [code.to.content] }); const record = await model_1.ModelRecord.create({ uid, content: code.to.content, title: code.to.title, password: code.to.password, sign, musicId: code.to.musicId || 0, styleId: code.to.styleId, data: dataObj, status: checkResult ? model_1.MODEL_RECORD_STATUS.INVALID : model_1.MODEL_RECORD_STATUS.BLOCK, }, { transaction: t, }); await model_1.ModelPasswordTip.create({ mid: record.id, tip: code.to.passwordTip, }); to = { type: model_1.DYNAMIC_CODE_TYPE.MODEL, sign: record.sign, meta: code.to, }; } else { to = { type: model_1.DYNAMIC_CODE_TYPE.URL, url: code.to, meta: code.to, }; } // 如果模板需要消耗积分,进行相应的逻辑 const dynamicCode = await model_1.DynamicCode.create({ uid, name: code.name, description: code.description, thumbUrl: code.thumbUrl, url: code.url, to, status: model_1.DYNAMIC_CODE_STATUS.LOCK, }, { transaction: t, }); return dynamicCode; }); } async deleteDynamicCode(uid, id, meta) { const dCode = await model_1.DynamicCode.findByPk(id); if (!dCode || dCode.deleted) { throw new ErrorCode_1.HttpError({ message: '动态码不存在', errorCode: ErrorCode_1.ERROR_CODE.COMMON.NOT_FOUND, status: 400, }); } if (dCode.uid !== uid) { throw new ErrorCode_1.HttpError({ message: '动态码不属于当前用户,无法进行操作', errorCode: ErrorCode_1.ERROR_CODE.USER.NOT_BELONG, status: 400, }); } return await global.sequelize.transaction(async (t) => { dCode.set('deleted', true); await model_1.ModelRecord.update({ deleted: true, meta, }, { where: { dynamicId: id, }, transaction: t, }); await dCode.save({ transaction: t }); return dCode; }); } async isValidCodes(uid, ids = []) { const now = moment().format('YYYY-MM-DD HH:mm:ss'); const codes = await model_1.DynamicCode.findAll({ where: { id: { [sequelize_1.Op.in]: ids, }, uid, invalidAt: { [sequelize_1.Op.or]: { [sequelize_1.Op.is]: null, [sequelize_1.Op.gt]: now, }, }, status: model_1.DYNAMIC_CODE_STATUS.UN_LOCK, deleted: false, }, }); return codes.length === ids.length; } /** * 更新动态码指向 * @param uid * @param id * @param code * @param transaction */ async updateDynamicCodeTo(uid, id, code, transaction) { if (!code || !code.to) { throw new ErrorCode_1.HttpError({ message: '必要参数[code]无效', errorCode: ErrorCode_1.ERROR_CODE.COMMON.PARAMS_INVALID, status: 400, }); } const dCode = await model_1.DynamicCode.findByPk(id); if (!dCode || dCode.deleted) { throw new ErrorCode_1.HttpError({ message: '动态码不存在', errorCode: ErrorCode_1.ERROR_CODE.COMMON.NOT_FOUND, status: 400, }); } if (dCode.invalidAt && moment(dCode.invalidAt).isBefore(Date.now())) { throw new ErrorCode_1.HttpError({ message: '动态码已经失效, 请续费', errorCode: ErrorCode_1.ERROR_CODE.CODE.INVALID, status: 400, }); } const exec = async (t) => { // 如果to包含任何内容,则更新to相关信息 let sign; // @ts-ignore if (NumberUtil_1.isEqual(code.type, model_1.DYNAMIC_CODE_TYPE.MODEL)) { sign = await this.genSign(); } // 如果原指向是模板,禁用原模板 if (NumberUtil_1.isEqual(dCode.to.type, model_1.DYNAMIC_CODE_TYPE.MODEL)) { await model_1.ModelRecord.update({ status: model_1.MODEL_RECORD_STATUS.INVALID, }, { where: { sign: dCode.to.sign, }, transaction: t, }); } // 创建二维码模板记录 let to; if (NumberUtil_1.isEqual(code.type, model_1.DYNAMIC_CODE_TYPE.MODEL)) { let dataObj = null; try { dataObj = JSON.parse(code.to.data); } catch (e) { dataObj = null; } // 检查内容是否违规 const checkResult = await this.ctx.service.contentChecker.check(dataObj ? { content: [code.to.data] } : { content: [code.to.content] }); const invalidTime = moment.utc(dCode.invalidAt).format('YYYY-MM-DD HH:mm:ss'); const record = await model_1.ModelRecord.create({ uid, content: code.to.content, title: code.to.title, password: code.to.password, sign, dynamicId: dCode.id, musicId: code.to.musicId || 0, styleId: code.to.styleId, status: checkResult ? model_1.MODEL_RECORD_STATUS.VALID : model_1.MODEL_RECORD_STATUS.BLOCK, data: dataObj, invalidAt: dCode.invalidAt ? invalidTime : null, }, { transaction: t, }); await model_1.ModelPasswordTip.create({ mid: record.id, tip: code.to.passwordTip, }); to = { type: model_1.DYNAMIC_CODE_TYPE.MODEL, sign: record.sign, meta: code.to, }; } else { to = { type: model_1.DYNAMIC_CODE_TYPE.URL, url: code.to, meta: code.to, }; } dCode.set('to', to); await dCode.save({ transaction: t, }); return dCode; }; if (transaction) { return await exec(transaction); } else { return await global.sequelize.transaction(async (t) => { return await exec(t); }); } } async updateDynamicCode(uid, id, code) { const dCode = await model_1.DynamicCode.findByPk(id); if (!dCode || dCode.deleted) { throw new ErrorCode_1.HttpError({ message: '动态码不存在', errorCode: ErrorCode_1.ERROR_CODE.COMMON.NOT_FOUND, status: 400, }); } if (!NumberUtil_1.isEqual(dCode.uid, uid)) { throw new ErrorCode_1.HttpError({ message: '操作资源与用户不匹配', errorCode: ErrorCode_1.ERROR_CODE.PERMISSION.DATA_ACCESS_DENIED, status: 403, }); } if (dCode.invalidAt && moment(dCode.invalidAt).isBefore(Date.now())) { throw new ErrorCode_1.HttpError({ message: '动态码已经失效, 请续费', errorCode: ErrorCode_1.ERROR_CODE.CODE.INVALID, status: 400, }); } return await global.sequelize.transaction(async (t) => { dCode.updateProperty(code, { exclude: ['to'] }); await dCode.save({ transaction: t, }); return dCode; }); } /** * 通过时长代码获取 * @param code * @param platform */ async getDynamicCodePayment(code, platform) { let config = await this.ctx.app.redis.get(Common_1.REDIS_KEY.DYNAMIC_CODE_PAYMENT); config = config ? JSON.parse(config) : config; if (!config) { await this.initDynamicCodePayment(); config = await this.ctx.app.redis.get(Common_1.REDIS_KEY.DYNAMIC_CODE_PAYMENT); config = config ? JSON.parse(config) : config; } // 通过平台过滤 if (config && platform !== undefined) { Object.keys(config).forEach((c) => { if (config && config[c].platform !== platform && config[c].platform !== null) { delete config[c]; } }); } return code ? config[code] : config; } /** * 获取动态码价格信息 * @param _id 动态码ID * @param code 动态码购买代码 * @param platform */ async getDCodePrice(_id, code, platform) { const paymentInfo = await this.getDynamicCodePayment(code, platform); const price = []; if (paymentInfo) { price.push({ payType: paymentInfo.payType, price: paymentInfo.payment, payment: paymentInfo, }); } return price; } /** * 获取动态码修改指向价格 * @param id * @param platform */ async getDCodeChangeToPrice(id, platform) { if (!await this.ctx.app.redis.exists(Common_1.REDIS_KEY.DYNAMIC_CODE_CHANGE_PAYMENT)) { await this.initDynamicCodeChangePayment(); } let rArray = await this.ctx.app.redis.zrange(Common_1.REDIS_KEY.DYNAMIC_CODE_CHANGE_PAYMENT, 0, 100); rArray = rArray.map((r) => JSON.parse(r)); const code = id ? await this.getDynamicCodeById(id) : null; const payments = rArray.filter((r) => r.platform === null || r.platform === platform); const price = []; payments.forEach((p) => { price.push({ payType: p.payType, price: code && !code.invalidAt ? 0 : p.price, payment: {}, }); }); return price; } /** * 获取动态码所有支付选项 */ async getDCodePrices(platform) { const config = await this.getDynamicCodePayment(undefined, platform); return Object.values(config); } /** * 激活动态码 * @param id 动态码ID * @param code 持续时间代码 * @param t 事务实例 */ async activeDCodePrice(id, code, t) { const dynamicCode = await model_1.DynamicCode.findByPk(id); if (!dynamicCode) { throw new ErrorCode_1.HttpError({ errorCode: ErrorCode_1.ERROR_CODE.COMMON.NOT_FOUND, message: '动态码不存在', status: 400, }); } const paymentInfo = await this.getDynamicCodePayment(code); // 计算当前过期时间,如果已经过期,则以当前时间作为起始时间 const expiredAt = !dynamicCode.invalidAt || moment(dynamicCode.invalidAt).isBefore(Date.now()) ? moment() : moment(dynamicCode.invalidAt); // 计算新的过期时间 const newExpiredAt = expiredAt.add(paymentInfo.duration, 'm').format('YYYY-MM-DD HH:mm:ss'); dynamicCode.set('status', model_1.DYNAMIC_CODE_STATUS.UN_LOCK); // @ts-ignore // 如果duration是0,表示是永久,则过期时间为null dynamicCode.set('invalidAt', paymentInfo.duration ? newExpiredAt : null); await dynamicCode.save({ transaction: t }); if (dynamicCode.to.type === model_1.DYNAMIC_CODE_TYPE.MODEL) { const record = await this.getBySign(dynamicCode.to.sign); if (record) { if (record.status !== model_1.MODEL_RECORD_STATUS.BLOCK) { record.set('status', model_1.MODEL_RECORD_STATUS.VALID); } // @ts-ignore // 如果duration是0,表示是永久,则过期时间为null record.set('invalidAt', paymentInfo.duration ? newExpiredAt : null); await record.save({ transaction: t }); } } return dynamicCode; } /** * 给动态码添加拥有者 * @param id * @param uid * @param t */ async addOwner(id, uid, t) { const dCode = await model_1.DynamicCode.findByPk(id); if (!dCode) { throw new ErrorCode_1.HttpError({ message: '动态码不存在', errorCode: ErrorCode_1.ERROR_CODE.COMMON.NOT_FOUND, status: 404, }); } if (dCode.uid) { throw new ErrorCode_1.HttpError({ message: '动态码已具有所有者', errorCode: ErrorCode_1.ERROR_CODE.CODE.HAS_OWNER, status: 404, }); } const now = new Date(); dCode.changed('createdAt', true); dCode.set({ uid, status: model_1.DYNAMIC_CODE_STATUS.UN_LOCK, createdAt: now }, { raw: true }); await dCode.save({ fields: ['uid', 'status', 'createdAt'], transaction: t }); return dCode; } async isWhite(id) { return !!await DCodeWhite_1.DCodeWhite.findByPk(id); } async initDynamicCodePayment() { const payments = await model_1.DynamicCodePayment.findAll(); const result = {}; payments.forEach((p) => { result[p.code] = { code: p.code, payType: p.payType, duration: p.duration, payment: p.payment, description: p.description, platform: p.platform, }; }); await this.ctx.app.redis.set(Common_1.REDIS_KEY.DYNAMIC_CODE_PAYMENT, JSON.stringify(result), 'EX', 60 * 60 * 24); } async initDynamicCodeChangePayment() { const payments = await model_1.DCodeChangePayment.findAll(); const args = []; payments.forEach((r, index) => { args.push(index); args.push(JSON.stringify(r)); }); await this.ctx.app.redis.zadd(Common_1.REDIS_KEY.DYNAMIC_CODE_CHANGE_PAYMENT, ...args); } async genSign() { let randomStr = this.ctx.helper.randomStr(false, 6); let i = 0; do { const codeItem = await this.getBySign(randomStr); if (!codeItem) { return randomStr; } else { randomStr += this.ctx.helper.randomStr(false, 1); i++; } } while (i < 5); throw new ErrorCode_1.HttpError({ errorCode: ErrorCode_1.ERROR_CODE.CODE.CREATE_SIGN_ERROR, message: '生成签名失败', status: 500, }); } } exports.default = CodeService; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29kZVNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJDb2RlU2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFpQztBQUNqQyx5Q0FBNkI7QUFDN0IsNkNBQTJDO0FBQzNDLG1EQUEwRDtBQUMxRCxxREFBOEM7QUFDOUMsb0NBWWtCO0FBRWxCLG1EQUEyQztBQUMzQyxnRUFBMkQ7QUFFM0QsTUFBcUIsV0FBWSxTQUFRLHFCQUFXO0lBQ3pDLEtBQUssQ0FBQyxjQUFjLENBQUMsR0FBRztRQUMzQixPQUFPLHdCQUFnQixDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRU0sS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJO1FBQ3ZCLE1BQU0sTUFBTSxHQUFHLE1BQU0sbUJBQVcsQ0FBQyxPQUFPLENBQUM7WUFDckMsS0FBSyxFQUFFO2dCQUNILElBQUk7YUFDUDtTQUNKLENBQUMsQ0FBQztRQUVILE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFFTSxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQVU7UUFDM0IsT0FBTyxtQkFBVyxDQUFDLE9BQU8sQ0FBQztZQUN2QixLQUFLLEVBQUU7Z0JBQ0gsRUFBRTtnQkFDRixPQUFPLEVBQUUsS0FBSzthQUNqQjtTQUNKLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTSxLQUFLLENBQUMsaUJBQWlCLENBQUMsRUFBVTtRQUNyQyxNQUFNLEtBQUssR0FBRyxNQUFNLG1CQUFXLENBQUMsT0FBTyxDQUFDO1lBQ3BDLEtBQUssRUFBRTtnQkFDSCxFQUFFO2dCQUNGLE1BQU0sRUFBRSwyQkFBbUIsQ0FBQyxPQUFPO2dCQUNuQyxPQUFPLEVBQUUsS0FBSztnQkFDZCxTQUFTLEVBQUU7b0JBQ1AsQ0FBQyxjQUFFLENBQUMsRUFBRSxDQUFDLEVBQUU7d0JBQ0wsQ0FBQyxjQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSTt3QkFDYixDQUFDLGNBQUUsQ0FBQyxH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