477 lines
18 KiB
TypeScript
477 lines
18 KiB
TypeScript
import {ApiCall} from 'tsrpc';
|
||
import {YangChengMuBiaofun} from '../api_s2c/event/yangchengmubiao/fun';
|
||
import {MsgPayChange} from '../shared/protocols/msg_s2c/MsgPayChange';
|
||
import {payLog} from '../shared/protocols/pay/PtlGetList';
|
||
import {player} from '../shared/protocols/user/type';
|
||
import {PublicShared} from '../shared/public/public';
|
||
import {EmailFun} from './email';
|
||
import {HuoDongFun} from './huodongfun';
|
||
import {call, PlayerFun} from './player';
|
||
import {number} from "mathjs";
|
||
import {getGud} from './gud';
|
||
import {getConf as zmlbGetConf} from '../api_s2c/event/zhoumolibao/ApiOpen';
|
||
|
||
async function checkPayIsActive(payId: string, logs: payLog[], payArgs) {
|
||
let conf: any = await this.getConf(payId, payArgs);
|
||
if (!conf) return false;
|
||
|
||
let lastLog = logs.last();
|
||
if (!lastLog) return false;
|
||
|
||
if (conf.time == -1) return true;
|
||
return G.time < lastLog.eTime;
|
||
}
|
||
|
||
export class PayFun {
|
||
static async addPayLog(uid: string, payId: string, type: "system" | "user" | "legu", payArgs) {
|
||
let conf: any = await this.getConf(payId, payArgs);
|
||
let time = PublicShared.getToDayZeroTime(G.time);
|
||
|
||
let obj: payLog = {time: G.time, type: type};
|
||
if (conf.time != -1) obj.eTime = time + conf.time;
|
||
|
||
if (payId == 'G123SendGift') {
|
||
obj.popup_id = payArgs.popup_id
|
||
obj.template_id = payArgs.template_id
|
||
obj.buyNumber = conf.buyNumber
|
||
}
|
||
|
||
let result = await G.mongodb.collection('payLogNew').findOneAndUpdate(
|
||
{uid: uid, key: payId, del_time: {$exists: false}},
|
||
{$push: {values: obj}},
|
||
{upsert: true, returnDocument: 'after'}
|
||
);
|
||
|
||
let msg: MsgPayChange = {[payId]: result.value?.values || []};
|
||
if (payId == 'G123SendGift') {
|
||
G.server.sendMsgByUid(uid, 'msg_s2c/PayChange', R.groupBy(i => i.popup_id)(result.value?.values));
|
||
} else {
|
||
G.server.sendMsgByUid(uid, 'msg_s2c/PayChange', msg);
|
||
}
|
||
}
|
||
|
||
static changeG123GiftLog(uid: string, popupId: string) {
|
||
G.mongodb.collection('giftLog').updateOne({popup_id: popupId}, {$inc: {buyNumber: 1}}, {upsert: true});
|
||
}
|
||
|
||
static async delPayLog(uid: string, ...args: { payId: string, val: payLog[]; }[]) {
|
||
args.map(a => {
|
||
G.mongodb.collection('payLogNew').updateOne(
|
||
{uid: uid, key: a.payId, del_time: {$exists: false}},
|
||
{$set: {del_time: G.time}},
|
||
{upsert: true}
|
||
);
|
||
|
||
})
|
||
|
||
G.mongodb.collection('payLogNew').insertMany(args.map(i => ({key: i.payId, uid: uid, values: i.val})));
|
||
|
||
G.server.sendMsgByUid(uid, 'msg_s2c/PayChange', Object.fromEntries(args.map(a => [a.payId, a.val])));
|
||
}
|
||
|
||
static async getPayLog(uid: string, payId: string): Promise<payLog[]>;
|
||
static async getPayLog(uid: string, payId: string) {
|
||
// let allPlayerPayLog = await G.redis.hGet('player:payLog', uid)
|
||
|
||
let val = await G.mongodb.collection("payLogNew").findOne({uid: uid, key: payId, del_time: {$exists: false}}, {
|
||
projection: {
|
||
_id: 0,
|
||
uid: 0
|
||
}
|
||
});
|
||
let allPlayerPayLog = {[payId]: val?.values || []}
|
||
|
||
return allPlayerPayLog?.[payId] || [];
|
||
}
|
||
|
||
static async getPayLogs(uid: string, payIds?: string[]) {
|
||
let where = {
|
||
uid: uid,
|
||
del_time: {$exists: false}
|
||
}
|
||
if (payIds?.length) where['key'] = {$in: payIds}
|
||
|
||
let logs = await G.mongodb.collection("payLogNew").find(where, {
|
||
projection: {
|
||
_id: 0,
|
||
uid: 0
|
||
}
|
||
}).toArray();
|
||
|
||
if (payIds?.length) {
|
||
return Object.fromEntries(payIds.map(id => [id, logs[id] || []]));
|
||
}
|
||
let allLogs = {}
|
||
logs.map(i => allLogs[i.key] = i.values)
|
||
return allLogs
|
||
}
|
||
|
||
/**
|
||
* 获取支付配置,主要是针对G123礼包、GM后台内部充值的特殊处理
|
||
* 让这两个不在预设充值挡位内的,可以正常发奖
|
||
* @param payId
|
||
* @param payArgs
|
||
*/
|
||
static async getConf(payId, payArgs) {
|
||
let conf: any = G.gc.pay[payId]
|
||
if (payId == 'G123SendGift') {
|
||
let giftInfo = await G.mongodb.collection('giftLog').findOne({popup_id: payArgs.popup_id});
|
||
|
||
let gPrize = giftInfo.items
|
||
let bPrize = []
|
||
for (let index in gPrize) {
|
||
let args = index.split('^')
|
||
bPrize.push({a: args[0], t: args[1], n: gPrize[index]})
|
||
}
|
||
|
||
conf = {
|
||
id: 'G123SendGift',
|
||
money: giftInfo.price,
|
||
payExp: [{"a": "attr", "t": "payExp", "n": giftInfo.vipPoints}],
|
||
prize: bPrize,
|
||
firstPayPrize: [],
|
||
name: 'G123SendGift',
|
||
time: -1,
|
||
buys: giftInfo.purchaseLimitAmount,
|
||
needVip: 0,
|
||
front: {},
|
||
buyNumber: giftInfo.buyNumber
|
||
}
|
||
} else if (payId == 'LeguSendGift') {
|
||
conf = {
|
||
id: 'LeguSendGift',
|
||
money: payArgs.money,
|
||
payExp: payArgs.payExp,
|
||
prize: payArgs.prize,
|
||
firstPayPrize: [],
|
||
name: 'LeguSendGift',
|
||
time: -1,
|
||
buys: 0,
|
||
needVip: 0,
|
||
front: {}
|
||
}
|
||
}
|
||
return conf
|
||
}
|
||
|
||
/**
|
||
* 实际作用是支付后发奖
|
||
* 针对G123礼包有特殊处理,不在游戏配置内预设的充值挡位
|
||
* todo 目前还缺验证通道,内部充值可以直接调用
|
||
* @param uid
|
||
* @param payId
|
||
* @param payArgs
|
||
* @param type
|
||
* @param orderNo
|
||
*/
|
||
static async pay(uid: string, payId: string, payArgs?: any, type?: "system" | "user" | "legu", orderNo: string = '') {
|
||
|
||
if (orderNo) {
|
||
//判断订单号是否已经支付过
|
||
let payed = await G.mongodb.collection('payOrderLog' as any).count({"orderNo": orderNo});
|
||
if (payed) {
|
||
console.log(uid, payId, payArgs, orderNo);
|
||
console.log('订单号已存在');
|
||
}
|
||
}
|
||
|
||
let conf: any = await this.getConf(payId, payArgs);
|
||
|
||
let isReplaceConf = await this.checkBuysAfterPay(uid, payId, conf, payArgs)
|
||
if (isReplaceConf) {
|
||
let prizePayId = `zuanshi_${conf.money}`
|
||
payArgs.toPrizePayId = prizePayId
|
||
conf = this.replacePrizeToChongzhi(prizePayId, conf)
|
||
}
|
||
|
||
let prize = [...conf.prize];
|
||
//let player = await G.redis.get('user', uid);
|
||
let player = await getGud(uid);
|
||
|
||
if (conf.firstPayPrize.length > 0) {
|
||
let logs = await this.getPayLog(uid, payId);
|
||
|
||
if (!logs || logs.length < 1) {
|
||
prize = PublicShared.mergePrize([].concat(conf.prize, conf.firstPayPrize));
|
||
}
|
||
}
|
||
|
||
let call = this.getCall(player);
|
||
call.req = {
|
||
uid: uid,
|
||
payId: payId,
|
||
payArgs: payArgs,
|
||
orderNo: orderNo
|
||
}
|
||
if (payId.indexOf('zixuanlibao') != -1) {
|
||
// 后端唯一标识 htype 4 自选/定制 礼包
|
||
// @ts-ignore
|
||
let _hdList = await HuoDongFun.gethdList(call, 4)
|
||
_hdList.forEach(ele => {
|
||
let selectPrize = ele.data.gift.find(v => v.payId == payId)?.prize;
|
||
if (prize) {
|
||
let index = payArgs instanceof Array ? payArgs : [];
|
||
let select = selectPrize.map((v, i) => v[index[i]] ? v[index[i]] : v[0]);
|
||
prize.push(...select);
|
||
}
|
||
})
|
||
}
|
||
if (payId.indexOf('ycmb') != -1) {
|
||
// @ts-ignore // 养成活动充值礼包
|
||
let _hdids = await YangChengMuBiaofun.getCon(call);
|
||
Object.values(_hdids).forEach(ele => {
|
||
let selectPrize = ele.data.gift.find(v => v.payId == payId)?.prize;
|
||
if (selectPrize) {
|
||
prize.push(...selectPrize);
|
||
}
|
||
});
|
||
}
|
||
await PlayerFun.sendPrize(call, prize);
|
||
await PlayerFun.addAttr(call, conf.payExp);
|
||
if (payId == 'G123SendGift') {
|
||
this.changeG123GiftLog(uid, payArgs.popup_id)
|
||
}
|
||
|
||
await this.addPayLog(player.uid, payId, type, payArgs);
|
||
// this.addPayLogNew(player.uid, payId, type);
|
||
|
||
//记录支付信息log
|
||
if (orderNo) {
|
||
await G.mongodb.collection('payOrderLog' as any).insertOne({
|
||
"orderNo": orderNo,
|
||
"payId": payId,
|
||
"uid": uid,
|
||
"payArgs": payArgs,
|
||
"type": type,
|
||
"ctime": new Date().getTime()
|
||
});
|
||
}
|
||
|
||
|
||
G.server.sendMsgByUid(uid, 'msg_s2c/Collection', {
|
||
fromApi: `pay_${payId}`,
|
||
msg: call.eventMsg
|
||
});
|
||
|
||
G.server.sendMsgByUid(uid, 'msg_s2c/PayResult', {
|
||
code: 1,
|
||
data: {
|
||
id: payId,
|
||
prize: prize,
|
||
price: payArgs?.price
|
||
}
|
||
});
|
||
|
||
G.emit('PLAYER_PAY', player, payId, payArgs);
|
||
G.emit("Class_task_116", 'Class_task_116', call, 1, 0);
|
||
}
|
||
|
||
/**
|
||
* 转换订单奖励成直冲钻石奖励
|
||
* @param payId
|
||
* @param conf
|
||
*/
|
||
static async replacePrizeToChongzhi(payId, conf) {
|
||
return {
|
||
id: payId,
|
||
money: conf.money,
|
||
payExp: [
|
||
{
|
||
"a": "attr",
|
||
"t": "payExp",
|
||
"n": conf.money * 10
|
||
}
|
||
],
|
||
prize: [
|
||
{
|
||
"a": "attr",
|
||
"t": "rmbmoney",
|
||
"n": conf.money * 10
|
||
}
|
||
],
|
||
firstPayPrize: [],
|
||
name: `replacePrize`,
|
||
time: -1,
|
||
buys: 0,
|
||
needVip: 0,
|
||
front: {}
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* 支付成功后,某些情况下会有超出限购次数的限购订单
|
||
* 这种情况需检查,返回true是需要转换成钻石的订单
|
||
* @param uid
|
||
* @param payId
|
||
* @param conf
|
||
* @param payArgs
|
||
*/
|
||
static async checkBuysAfterPay(uid, payId, conf, payArgs) {
|
||
if (payId == 'G123SendGift') {
|
||
let giftInfo = await G.mongodb.collection('giftLog').findOne({popup_id: payArgs.popup_id});
|
||
if (giftInfo.purchaseLimitAmount && giftInfo.buyNumber >= giftInfo.purchaseLimitAmount && number(giftInfo.price) > 0) {
|
||
return true
|
||
}
|
||
} else {
|
||
let buyLog = await this.getPayLog(uid, payId) || [];
|
||
if (conf.buys > 0 && conf.time > 0) {
|
||
buyLog = buyLog.filter(v => v.time >= PublicShared.getToDayZeroTime(G.time));
|
||
}
|
||
if (conf.buys > 0 && buyLog.length >= conf.buys) return true;
|
||
}
|
||
return false
|
||
}
|
||
|
||
/**
|
||
* 拉起订单前检查购买前置条件,如符合,通知前端拉起支付
|
||
* 针对G123礼包有特殊处理,不在游戏配置内预设的充值挡位
|
||
* todo 目前没有订单锁,所以会造成限购商品可以二次拉起支付
|
||
* @param player
|
||
* @param payId
|
||
* @param payArgs
|
||
*/
|
||
static async check(player: player, payId: string, payArgs?: any) {
|
||
let conf: any = await this.getConf(payId, payArgs);
|
||
|
||
if (!conf) return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: 0});
|
||
if (player.vip < conf.needVip) return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: -3});
|
||
if (conf.front.cond) {
|
||
let pays = await this.getPayLogs(player.uid, conf.front.pays);
|
||
//@ts-ignore
|
||
let actives = Object.entries(pays).map(v => checkPayIsActive(v[0], v[1], payArgs)).filter(v => v);
|
||
if (conf.front.cond == '|' && actives.length < 1) return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: -4});
|
||
if (conf.front.cond == '&' && actives.length < conf.front.pays.length) return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: -4});
|
||
}
|
||
|
||
if (payId == 'G123SendGift') {
|
||
let giftInfo = await G.mongodb.collection('giftLog').findOne({popup_id: payArgs.popup_id});
|
||
|
||
if (giftInfo.purchaseLimitAmount && giftInfo.buyNumber >= giftInfo.purchaseLimitAmount) {
|
||
return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: -1});
|
||
}
|
||
|
||
if (number(giftInfo.price) <= 0) {
|
||
await this.pay(player.uid, payId, payArgs, 'user');
|
||
return
|
||
}
|
||
} else {
|
||
let buyLog = await this.getPayLog(player.uid, payId) || [];
|
||
|
||
if (conf.buys > 0 && conf.time > 0) {
|
||
buyLog = buyLog.filter(v => v.time >= PublicShared.getToDayZeroTime(G.time));
|
||
}
|
||
|
||
if (conf.buys > 0 && buyLog.length >= conf.buys) return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: -1});
|
||
if (conf.time != -1 && buyLog.slice(-1)[0]?.eTime > G.time && conf.buys == 0) return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: -2});
|
||
if (payId.indexOf('136Gift') != -1 && payId != '136Gift1') {
|
||
buyLog = await this.getPayLog(player.uid, '136Gift1');
|
||
if (buyLog.slice(-1)[0]?.eTime > G.time) return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: -3});
|
||
}
|
||
if (payId.indexOf('wkdlibao') != -1) {
|
||
let call = this.getCall(player)
|
||
let conf = await zmlbGetConf(call, {payId})
|
||
buyLog = await this.getPayLog(player.uid, payId);
|
||
if (buyLog.length && buyLog.length >= conf.buyNum) return G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: -1});
|
||
}
|
||
}
|
||
|
||
if (G.config.debug) {
|
||
await this.pay(player.uid, payId, payArgs, 'user', "debuger_" + new Date().getTime());
|
||
} else {
|
||
G.server.sendMsgByUid(player.uid, 'msg_s2c/PayResult', {code: 200});
|
||
}
|
||
}
|
||
|
||
static getCall(player: player): call {
|
||
|
||
return {
|
||
get otherBuff() {
|
||
return this.conn.otherBuff;
|
||
},
|
||
uid: player.uid,
|
||
conn: G.server.uid_connections[player.uid] ? G.server.uid_connections[player.uid] : {
|
||
id: null,
|
||
uid: player.uid,
|
||
gud: player,
|
||
item: null,
|
||
otherBuff: null,
|
||
heroPos: null,
|
||
refreshPower: null,
|
||
sendMsg: null,
|
||
},
|
||
service: {name: "pay"},
|
||
req: {},
|
||
eventMsg: null,
|
||
addEventMsg() {
|
||
return ApiCall.prototype.addEventMsg.call(this, ...arguments);
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 当玩家购买过有时间期效性的礼包 并且在生效期内每天有邮件奖励时 每天首次登陆时根据时间补发邮件 玩家每天首次登陆会进入检查
|
||
* @param lastTime 上一次登陆时间
|
||
* @param curTime 每日首次登陆时间
|
||
*/
|
||
static async checkGiftDayEmail(player: player, lastTime: number, curTime: number) {
|
||
const buyLogs = await this.getPayLogs(player.uid);
|
||
const keys = Object.keys(buyLogs).filter(payId => G.gc.payEmail[payId]?.length > 0);
|
||
const curZeroTime = PublicShared.getToDayZeroTime(curTime);
|
||
const lastZeroTime = PublicShared.getToDayZeroTime(lastTime);
|
||
|
||
keys.forEach(payId => {
|
||
let payEmailConf = G.gc.payEmail[payId] as _gcType['payEmail']['caifutequan'];
|
||
let latelyLog = buyLogs[payId].slice(-1)[0];
|
||
if (!latelyLog || (latelyLog.eTime && lastZeroTime >= latelyLog.eTime)) return;
|
||
|
||
let countDay = 1;
|
||
let payZeroTime = PublicShared.getToDayZeroTime(latelyLog.time);
|
||
let payZeroEtime = PublicShared.getToDayZeroTime(latelyLog.eTime);
|
||
|
||
let days: number
|
||
if (curZeroTime > payZeroEtime) {
|
||
days = (payZeroEtime - lastZeroTime) / (24 * 3600);
|
||
} else {
|
||
days = (curZeroTime - lastZeroTime) / (24 * 3600);
|
||
}
|
||
|
||
for (let n = 1; n <= days; n++) {
|
||
countDay++;
|
||
// if (payZeroTime + n * 24 * 3600 <= payZeroEtime) continue;
|
||
payEmailConf.forEach(conf => {
|
||
if (conf.day == 1 || countDay % conf.day == 0) {
|
||
EmailFun.addEmail({
|
||
uid: player.uid,
|
||
type: 'system',
|
||
title: conf.title,
|
||
content: conf.content,
|
||
prize: conf.prize,
|
||
createTime: lastZeroTime + n * 24 * 3600
|
||
});
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 获取某个时间段内 玩家充值x元以上的天数
|
||
*/
|
||
static async getPayDaysBuyPayNum(uid: string, sTime: number, eTime: number, ckeckNeed: number) {
|
||
let logs = await G.mongodb.collection('dayPay').find({uid: uid}).toArray() || [];
|
||
return logs.filter(log => log.time >= sTime && log.time <= eTime && log.payNum >= ckeckNeed).length;
|
||
}
|
||
|
||
/**
|
||
* 获取某个时间段内 玩家的充值总金额
|
||
*/
|
||
static async getPayDaysAllPayNum(uid: string, sTime: number, eTime: number) {
|
||
let logs = await G.mongodb.collection('dayPay').find({uid: uid}).toArray() || [];
|
||
|
||
logs = logs.filter(log => log.time >= sTime && log.time < eTime);
|
||
|
||
if (logs.length <= 0) return 0;
|
||
return logs.map(log => log.payNum).reduce((a, b) => a + b);
|
||
}
|
||
} |