diff --git a/game-server/app/servers/gm/handler/gmOrderHandler.ts b/game-server/app/servers/gm/handler/gmOrderHandler.ts index c871a45f4..e7c08dd32 100644 --- a/game-server/app/servers/gm/handler/gmOrderHandler.ts +++ b/game-server/app/servers/gm/handler/gmOrderHandler.ts @@ -101,7 +101,7 @@ export class GmOrderHandler { continue; } let paramStr = await getParamStr(activityData, productID, role); - let orderInfo = await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message); + let orderInfo = await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, false); //订单成功 if(!orderInfo) { diff --git a/game-server/app/servers/order/handler/orderHandler.ts b/game-server/app/servers/order/handler/orderHandler.ts index 9aa1356ba..424fae4e7 100644 --- a/game-server/app/servers/order/handler/orderHandler.ts +++ b/game-server/app/servers/order/handler/orderHandler.ts @@ -1,16 +1,19 @@ import { Application, BackendSession, HandlerService, } from 'pinus'; import { genCode, resResult } from '../../../pubUtils/util'; -import { ACTIVITY_TYPE, DEBUG_MAGIC_WORD, DEBUG_PRICE, ORDER_STATE, PAY_TYPE, STATUS, TASK_TYPE, TA_EVENT } from '../../../consts'; +import { ACTIVITY_TYPE, DEBUG_MAGIC_WORD, DEBUG_PRICE, ITEM_CHANGE_REASON, ORDER_STATE, PAY_TYPE, STATUS, TASK_TYPE, TA_EVENT } from '../../../consts'; import { dicRMB } from '../../../pubUtils/dictionary/DicRMB'; import { UserOrderModel } from '../../../db/UserOrder'; import _ = require('underscore'); import { applyOrderWX } from '../../../services/pay/weixinPay'; import { applyOrderALI } from '../../../services/pay/aliPay'; import { applyOrder37 } from '../../../services/pay/37Pay'; -import { checkOrderCanBuy, settleOrder, settleOrderAli, settleOrderWx } from '../../../services/orderService'; +import { checkOrderCanBuy, settleOrder, settleOrderAli, settleOrderFromHandler, settleOrderWx } from '../../../services/orderService'; import { getActivityById } from '../../../services/activity/activityService'; import { reportTAEvent } from '../../../services/sdkService'; -import { isDebugPay } from '../../../pubUtils/sdkUtil'; +import { canPay, isDebugPay } from '../../../pubUtils/sdkUtil'; +import { isDevelopEnv } from '../../../services/utilService'; +import { getVoucherObject, handleCost } from '../../../services/role/rewardService'; +import { CheckMeterial } from '../../../services/role/checkMaterial'; export default function (app: Application) { new HandlerService(app, {}); @@ -29,17 +32,21 @@ export class orderHandler { * @param {BackendSession} session * @memberof orderHandler */ - async applyOrder(msg: { productID: string, payType: number, activityId: number, paramStr: string }, session: BackendSession) { - const { productID, payType, activityId, paramStr } = msg; + async applyOrder(msg: { productID: string, payType: number, activityId: number, paramStr: string, useVoucher: boolean }, session: BackendSession) { + const { productID, payType, activityId, paramStr, useVoucher } = msg; const roleId = session.get('roleId'); const serverId = session.get('serverId'); const ip = session.get('ip'); //如果有特殊情况,activityId可为0 - if (!productID || !_.isString(productID) || !payType || !_.isNumber(payType)) { + if (!productID || !_.isString(productID) || !_.isNumber(payType)) { return resResult(STATUS.WRONG_PARMS); } + if(!canPay()) { + return resResult(STATUS.PAY_NOT_OPEN) + } + //商品价格信息 let productInfo = dicRMB.get(productID) if (!productInfo) { @@ -53,51 +60,65 @@ export class orderHandler { let localOrderID = genCode(32);//本地订单号 let orderID = '';//平台订单号 let sdkOrderInfo = null;//客户端需要的平台订单信息 - switch (payType) { - case PAY_TYPE.THREE_SEVEN: - case PAY_TYPE.THREE_SEVEN_IOS: - { - let pay37Order = await applyOrder37(localOrderID, roleId, productInfo); - if (pay37Order.code == -1) { - console.log('37下单失败') - return pay37Order.resData; - } - sdkOrderInfo = pay37Order.data; - orderID = '' - break; - } - case PAY_TYPE.WX: - { - let weixinOrder = await applyOrderWX(localOrderID, price * 100, message); - if (weixinOrder.code == -1) { - console.log('微信下单失败') - return resResult(STATUS.APPLY_ORDER_ERROR); - } - sdkOrderInfo = weixinOrder.data; - orderID = weixinOrder.data.prepayid;//微信订单号 - break; - } - case PAY_TYPE.ALI: - { - let aliOrder = await applyOrderALI(localOrderID, price, message); - if (aliOrder.code == -1) { - console.log('支付宝下单失败') - return resResult(STATUS.APPLY_ORDER_ERROR); - } - sdkOrderInfo = aliOrder.data; - orderID = aliOrder.data;//支付宝订单 - break; - } - - case PAY_TYPE.TEST: - case PAY_TYPE.APPLE: - { - break; - } - default: - console.log('未知支付类型'); - return resResult(STATUS.NO_PAY_TYPE); + if(useVoucher) { + let voucher = getVoucherObject(price); + let check = new CheckMeterial(roleId); + let isEnough = await check.decrease([voucher]); + if (!isEnough) return resResult(STATUS.VOUCHER_NOT_ENOUGH); + } else { + switch (payType) { + case PAY_TYPE.THREE_SEVEN: + case PAY_TYPE.THREE_SEVEN_IOS: + { + let pay37Order = await applyOrder37(localOrderID, roleId, productInfo); + if (pay37Order.code == -1) { + console.log('37下单失败') + return pay37Order.resData; + } + sdkOrderInfo = pay37Order.data; + orderID = '' + break; + } + case PAY_TYPE.WX: + { + let weixinOrder = await applyOrderWX(localOrderID, price * 100, message); + if (weixinOrder.code == -1) { + console.log('微信下单失败') + return resResult(STATUS.APPLY_ORDER_ERROR); + } + sdkOrderInfo = weixinOrder.data; + orderID = weixinOrder.data.prepayid;//微信订单号 + break; + } + case PAY_TYPE.ALI: + { + let aliOrder = await applyOrderALI(localOrderID, price, message); + if (aliOrder.code == -1) { + console.log('支付宝下单失败') + return resResult(STATUS.APPLY_ORDER_ERROR); + } + sdkOrderInfo = aliOrder.data; + orderID = aliOrder.data;//支付宝订单 + + break; + } + + case PAY_TYPE.TEST: + { + if(!isDevelopEnv()) { + return resResult(STATUS.NO_PAY_TYPE); + } + break; + } + case PAY_TYPE.APPLE: + { + break; + } + default: + console.log('未知支付类型'); + return resResult(STATUS.NO_PAY_TYPE); + } } if(activityId > 0) { @@ -107,7 +128,7 @@ export class orderHandler { } - await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message); + await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, useVoucher); reportTAEvent(roleId, TA_EVENT.RECHARGE, { pay_id: localOrderID, chargeId: productID, pay_name: message, pay_amount: price, pay_channel: payType }, ip) @@ -125,7 +146,7 @@ export class orderHandler { */ async checkOrder(msg: { localOrderID: string }, session: BackendSession) { const { localOrderID } = msg; - // const roleId = session.get('roleId'); + const roleId = session.get('roleId'); const serverId = session.get('serverId'); const sid = session.get('sid'); const roleName = session.get('roleName'); @@ -145,35 +166,55 @@ export class orderHandler { return resResult(STATUS.NO_PRODUCT_ID); } - switch (orderInfo.payType) { - case PAY_TYPE.TEST: - case PAY_TYPE.THREE_SEVEN: - case PAY_TYPE.APPLE: - { - break; - } - case PAY_TYPE.WX: - { - let res = await settleOrderWx(orderInfo, serverId, sid); - if(res.code != 0) { - return resResult(res); - } - orderInfo = await UserOrderModel.findOrder(localOrderID); - break; - } - case PAY_TYPE.ALI: - { - let res = await settleOrderAli(orderInfo, serverId, sid); - if(res.code != 0) { - return resResult(res); - } - orderInfo = await UserOrderModel.findOrder(localOrderID); - break; - } + if(orderInfo.useVoucher) { + let voucher = getVoucherObject(productInfo.price); + let result = await handleCost(roleId, roleName, [voucher], ITEM_CHANGE_REASON.USE_VOUCHER); + if(!result) return resResult(STATUS.VOUCHER_NOT_ENOUGH); - default: - console.log('未知支付类型'); - return resResult(STATUS.NO_PAY_TYPE); + let res = await settleOrderFromHandler(localOrderID, roleId, serverId, sid); + if(res.code != 0) { + return resResult(res); + } + orderInfo = await UserOrderModel.findOrder(localOrderID); + } else { + switch (orderInfo.payType) { + case PAY_TYPE.TEST: + { + let res = await settleOrderFromHandler(localOrderID, roleId, serverId, sid); + if(res.code != 0) { + return resResult(res); + } + orderInfo = await UserOrderModel.findOrder(localOrderID); + break; + } + case PAY_TYPE.THREE_SEVEN: + case PAY_TYPE.APPLE: + { + break; + } + case PAY_TYPE.WX: + { + let res = await settleOrderWx(orderInfo, serverId, sid); + if(res.code != 0) { + return resResult(res); + } + orderInfo = await UserOrderModel.findOrder(localOrderID); + break; + } + case PAY_TYPE.ALI: + { + let res = await settleOrderAli(orderInfo, serverId, sid); + if(res.code != 0) { + return resResult(res); + } + orderInfo = await UserOrderModel.findOrder(localOrderID); + break; + } + + default: + console.log('未知支付类型'); + return resResult(STATUS.NO_PAY_TYPE); + } } //订单成功 @@ -245,7 +286,7 @@ export class orderHandler { let check = await checkOrderCanBuy(roleId, serverId, activityData, productID, paramStr); if(!check) return resResult(STATUS.ORDER_CANNOT_BUY) - let orderInfo = await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message); + let orderInfo = await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, false); //订单成功 if(!orderInfo) { diff --git a/game-server/app/services/orderService.ts b/game-server/app/services/orderService.ts index 0792ef3d8..48cd24df2 100644 --- a/game-server/app/services/orderService.ts +++ b/game-server/app/services/orderService.ts @@ -175,7 +175,7 @@ export async function settleOrder(order: UserOrderModelType, serverId: number, s let result = await makeOrder(order, sid); if (result.code !== 0) {//结算失败 console.log(`支付失败..... ${JSON.stringify(result)}`) - reportTAEvent(order.roleId, TA_EVENT.RECHARGE_FAIL, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType }) + reportTAEvent(order.roleId, TA_EVENT.RECHARGE_FAIL, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType, pay_type: order.useVoucher? "现金": "代金券" }) savePayLog(order); return resResult(result); } @@ -188,7 +188,7 @@ export async function settleOrder(order: UserOrderModelType, serverId: number, s //成长任务 await checkTask(serverId, order.roleId, sid, TASK_TYPE.ACTIVITY_RMB, { count: order.price }); if(order.payType != PAY_TYPE.TEST) { - reportTAEvent(order.roleId, TA_EVENT.RECHARGE_SUCCESS, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType }) + reportTAEvent(order.roleId, TA_EVENT.RECHARGE_SUCCESS, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType, pay_type: order.useVoucher? "现金": "代金券" }) reportTAUserSet(TA_USERSET_TYPE.SET_ONCE, order.roleId, { first_pay_time: new Date() }); reportTAUserSet(TA_USERSET_TYPE.SET, order.roleId, { last_pay_time: new Date() }); reportTAUserSet(TA_USERSET_TYPE.ADD, order.roleId, { total_revenue: order.price }); @@ -291,6 +291,23 @@ export async function settleOrderFromRedisPub(message: string) { return true } +export async function settleOrderFromHandler(localOrderID: string, roleId: string, serverId: number, sid: string ) { + + let order = await UserOrderModel.findOrder(localOrderID); + if(!order || order.state != ORDER_STATE.APPLY) { + return STATUS.DUPLICATE_ORDER; + } + if(order.roleId != roleId) { + console.log('订单玩家错误'); + return STATUS.ORDER_STATUS_ERROR; + } + + let result = await settleOrder(order, serverId, sid); + await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, '', JSON.stringify(result)); + + return STATUS.SUCCESS +} + export async function refundOrderFromRedisPub(message: string) { console.log('**********refundOrderFromRedisPub*******') console.log('message: ', message); diff --git a/game-server/app/services/role/rewardService.ts b/game-server/app/services/role/rewardService.ts index 17e1c3c0d..76e0a41f9 100644 --- a/game-server/app/services/role/rewardService.ts +++ b/game-server/app/services/role/rewardService.ts @@ -474,6 +474,15 @@ export function getHonourObject(count: number) { return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.HONOUR), count }; } +/** + * @description 获取代金券物品 { id, count } + * @param count 元宝数量 + */ + export function getVoucherObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER), count }; +} + + /** * 返回 解锁头像/相框 * @param conditions 解锁条件 diff --git a/game-server/app/services/utilService.ts b/game-server/app/services/utilService.ts index 90a0d1853..507788d20 100644 --- a/game-server/app/services/utilService.ts +++ b/game-server/app/services/utilService.ts @@ -1,6 +1,6 @@ import { pinus } from "pinus"; export function isDevelopEnv() { - const envs = ['development', 'monitor'] + const envs = ['development', 'monitor', 'alpha', 'dev']; return envs.indexOf(pinus.app.get('env')) != -1; } \ No newline at end of file diff --git a/shared/consts/constModules/itemConst.ts b/shared/consts/constModules/itemConst.ts index 5f684788b..9549d8032 100644 --- a/shared/consts/constModules/itemConst.ts +++ b/shared/consts/constModules/itemConst.ts @@ -37,6 +37,7 @@ export const CONSUME_TYPE = { AP: 15, // 回复体力道具 DICE: 16, // 骰子 DRAWING: 17, // 图纸 + VOUCHER: 18, // 代金券 }; export enum ROLE_TERAPH { @@ -147,6 +148,7 @@ const itid_array = [ { id: 60, name: '衣服天晶石', table: 'jewel' }, { id: 61, name: '头饰天晶石', table: 'jewel' }, { id: 62, name: '行具天晶石', table: 'jewel' }, + { id: 63, name: '代金券', table: 'item', type: CONSUME_TYPE.VOUCHER } ]; export const ITID = new Map(); @@ -167,7 +169,8 @@ export const CURRENCY_TYPE = { DUNGEON: "dungeon", NORMAL_DICE: "normalDice", SPECIAL_DICE: "specialDice", - KING_EXP: 'kingExp' + KING_EXP: 'kingExp', + VOUCHER: 'voucher', } const currencyArr = [ @@ -183,7 +186,8 @@ const currencyArr = [ { "gid": 40007, "name": "秘境币", "type": CURRENCY_TYPE.DUNGEON }, { "gid": 72011, "name": "普通骰子", "type": CURRENCY_TYPE.NORMAL_DICE }, { "gid": 72021, "name": "天机骰子", "type": CURRENCY_TYPE.SPECIAL_DICE }, - { "gid": 72030, "name": "主公经验", "type": CURRENCY_TYPE.KING_EXP } + { "gid": 72030, "name": "主公经验", "type": CURRENCY_TYPE.KING_EXP }, + { "gid": 81000, "name": "代金券", "type": CURRENCY_TYPE.VOUCHER} ]; export const CURRENCY = new Map(); export const CURRENCY_BY_TYPE = new Map(); diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index d0b56f581..84335ad9d 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -1011,6 +1011,7 @@ export enum ITEM_CHANGE_REASON { RESET_TALENT = 147, // 洗点 RECEIVE_TOWER_BOX = 148, // 领取镇念塔节点奖励 ACT_DAILY_COIN_RECEIVE_BOX = 149, // 招财进宝领取宝箱 + USE_VOUCHER = 150, // 使用代金券 } export enum TA_EVENT { diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index 190e145a7..c9b33a36f 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -522,7 +522,9 @@ export const STATUS = { CHANNEL_INFO_NOT_FOUND: { code: 70014, simStr: '未找到玩家渠道数据' }, ACTIVITY_TASK_NOT_COMPLETE: { code: 70015, simStr: '条件未达成' }, ORDER_CANNOT_BUY: { code: 70016, simStr: '该礼包不可购买' }, - + VOUCHER_NOT_ENOUGH: { code: 70017, simStr: '代金券不足' }, + ORDER_STATUS_ERROR: { code: 70018, simStr: '订单状态错误' }, + PAY_NOT_OPEN: { code: 70019, simStr: '支付功能暂未开启' } } export const PAY_37_CALLBACK_CODE = { diff --git a/shared/db/UserLog.ts b/shared/db/UserLog.ts index fbc3cdc2b..76a986668 100644 --- a/shared/db/UserLog.ts +++ b/shared/db/UserLog.ts @@ -112,6 +112,9 @@ export default class UserLog extends BaseModel { @prop({ required: false }) orderStatus: number; // 订单状态 + @prop({ required: false }) + useVoucher: boolean; // 是否使用代金券 + // 道具相关 @prop({ required: false }) itemId: number; // 道具id diff --git a/shared/db/UserOrder.ts b/shared/db/UserOrder.ts index 11ce48bcd..8d42dcafe 100644 --- a/shared/db/UserOrder.ts +++ b/shared/db/UserOrder.ts @@ -34,6 +34,8 @@ export default class UserOrder extends BaseModel { activityId: number; // 活动ID @prop({ required: true }) paramStr: string; // 订单参数 + @prop({ required: true }) + useVoucher: boolean; // 使用代金券 //保存平台订单号 @@ -122,9 +124,9 @@ export default class UserOrder extends BaseModel { //新增订单 - public static async applyOrder(serverId: number, roleId: string, productID: string, localOrderID: string, orderID: string, price: number, payType: number, activityId: number, paramStr: string, message: string) { + public static async applyOrder(serverId: number, roleId: string, productID: string, localOrderID: string, orderID: string, price: number, payType: number, activityId: number, paramStr: string, message: string, useVoucher: boolean) { let result: UserOrderModelType = await UserOrderModel.findOneAndUpdate({ serverId, roleId, productID, localOrderID, orderID, payType, activityId }, - { $set: { price, state: ORDER_STATE.APPLY, message, paramStr: paramStr ? paramStr : '' } }, + { $set: { price, state: ORDER_STATE.APPLY, message, paramStr: paramStr ? paramStr : '', useVoucher } }, { upsert: true, new: true }).lean(true); return result; } diff --git a/shared/pubUtils/dictionary/DicServerConst.ts b/shared/pubUtils/dictionary/DicServerConst.ts index fc6207b2d..2bbd17f91 100644 --- a/shared/pubUtils/dictionary/DicServerConst.ts +++ b/shared/pubUtils/dictionary/DicServerConst.ts @@ -33,6 +33,8 @@ export interface DicServerConst { readonly DEBUG_TIME: number; // 是否检查屏蔽词 readonly CHECK_WORD: number; + // 是否可以支付 + readonly CAN_PAY: number; } export const dicServerConst: DicServerConst = {} as DicServerConst; diff --git a/shared/pubUtils/logUtil.ts b/shared/pubUtils/logUtil.ts index 852197d8a..ea9561535 100644 --- a/shared/pubUtils/logUtil.ts +++ b/shared/pubUtils/logUtil.ts @@ -57,10 +57,10 @@ export async function savePayLog(order: UserOrderModelType) { try { let role = await RoleModel.findByRoleId(order.roleId, 'userInfo roleId roleName serverId'); let params = getParamByRole(role); - let { productID, message: productName, price, localOrderID, orderID, state } = order; + let { productID, message: productName, price, localOrderID, orderID, state, useVoucher } = order; let dicRmb = gameData.rmb.get(productID); let isYuanbao = dicRmb.type == ACTIVITY_TYPE.YUAN_BAO_SHOP; - await UserLogModel.createRecord({ type: LOG_TYPE.PAY, ...params, productID, productName, price, isYuanbao, localOrderID, orderID, totalPay: role.totalPay, orderStatus: state }); + await UserLogModel.createRecord({ type: LOG_TYPE.PAY, ...params, productID, productName, price, isYuanbao, localOrderID, orderID, totalPay: role.totalPay, orderStatus: state, useVoucher }); } catch (e) { console.error(e); } diff --git a/shared/pubUtils/sdkUtil.ts b/shared/pubUtils/sdkUtil.ts index 0f07b3e9b..b193f9e88 100644 --- a/shared/pubUtils/sdkUtil.ts +++ b/shared/pubUtils/sdkUtil.ts @@ -157,4 +157,8 @@ export function isDebugPay() { export function isCheckWord(isDevelop = false) { return gameData.serverConst.CHECK_WORD === 1 && !isDevelop; +} + +export function canPay() { + return gameData.serverConst.CAN_PAY === 1; } \ No newline at end of file diff --git a/shared/resource/jsons/server_const.json b/shared/resource/jsons/server_const.json index 47886f86e..6d3dcb500 100644 --- a/shared/resource/jsons/server_const.json +++ b/shared/resource/jsons/server_const.json @@ -18,5 +18,6 @@ ], "DEBUG_PAY": 0, "DEBUG_TIME": 1, - "CHECK_WORD": 1 + "CHECK_WORD": 1, + "CAN_PAY": 1 } \ No newline at end of file