shadowsocks-manager
Version:
A shadowsocks manager tool for multi user and traffic control.
292 lines (276 loc) • 9.31 kB
JavaScript
const log4js = require('log4js');
const logger = log4js.getLogger('paypal');
const knex = appRequire('init/knex').knex;
const cron = appRequire('init/cron');
const paypal = require('paypal-rest-sdk');
const account = appRequire('plugins/account/index');
const moment = require('moment');
const push = appRequire('plugins/webgui/server/push');
const config = appRequire('services/config').all();
const ref = appRequire('plugins/webgui_ref/time');
const orderPlugin = appRequire('plugins/webgui_order');
const groupPlugin = appRequire('plugins/group');
if(config.plugins.paypal && config.plugins.paypal.use) {
paypal.configure({
mode: config.plugins.paypal.mode,
client_id: config.plugins.paypal.client_id,
client_secret: config.plugins.paypal.client_secret,
});
}
const createOrder = async (user, account, orderId) => {
try {
const orderInfo = await orderPlugin.getOneOrder(orderId);
if(+orderInfo.paypal <= 0) { return Promise.reject('amount error'); }
const userInfo = await knex('user').where({ id: user }).then(s => s[0]);
const groupInfo = await groupPlugin.getOneGroup(userInfo.group);
if(groupInfo.order) {
if(JSON.parse(groupInfo.order).indexOf(orderInfo.id) < 0) {
return Promise.reject('invalid order');
}
}
const create_payment_json = {
intent: 'sale',
payer: {
payment_method: 'paypal'
},
redirect_urls: {
return_url: config.plugins.webgui.site + '/user/account',
cancel_url: config.plugins.webgui.site + '/user/account',
},
transactions: [{
amount: {
currency: 'USD',
total: orderInfo.paypal,
},
description: orderInfo.name || 'ss'
}]
};
const payment = await new Promise((resolve, reject) => {
paypal.payment.create(JSON.stringify(create_payment_json), function (error, payment) {
if (error) {
console.log(error);
reject(error);
} else {
resolve(payment);
}
});
});
const myOrderId = moment().format('YYYYMMDDHHmmss') + Math.random().toString().substr(2, 6);
await knex('paypal').insert({
orderId: myOrderId,
paypalId: payment.id,
orderType: orderId,
amount: orderInfo.paypal + '',
user,
account: (account !== 'undefined' && account !== 'null' && account) ? account : null,
status: 'created',
createTime: Date.now(),
expireTime: Date.now() + 2 * 60 * 60 * 1000,
});
return { paymentID: payment.id };
} catch (err) {
console.log(err);
return Promise.reject(err);
}
};
const executeOrder = async (order) => {
const orderInfo = await new Promise((resolve, reject) => {
paypal.payment.get(order.paymentID, function (error, payment) {
if (error) {
console.log(error);
reject(error);
} else {
resolve(payment);
}
});
});
const execute_payment_json = {
payer_id: orderInfo.payer.payer_info.payer_id,
transactions: [{
amount: orderInfo.transactions[0].amount,
}]
};
return new Promise((resolve, reject) => {
paypal.payment.execute(order.paymentID, JSON.stringify(execute_payment_json), function (error, payment) {
if (error) {
console.log(error);
return reject(error);
} else {
return resolve();
}
});
});
};
exports.createOrder = createOrder;
exports.executeOrder = executeOrder;
const checkOrder = async paypalId => {
const orderInfo = await new Promise((resolve, reject) => {
paypal.payment.get(paypalId, function (error, payment) {
if (error) {
console.log(error);
reject(error);
} else {
resolve(payment);
}
});
});
await knex('paypal').update({ status: orderInfo.state, paypalData: JSON.stringify(orderInfo) }).where({ paypalId });
return;
};
const sendSuccessMail = async userId => {
const emailPlugin = appRequire('plugins/email/index');
const user = await knex('user').select().where({
type: 'normal',
id: userId,
}).then(success => {
if(success.length) {
return success[0];
}
return Promise.reject('user not found');
});
const orderMail = await knex('webguiSetting').select().where({
key: 'mail',
}).then(success => {
if(!success.length) {
return Promise.reject('settings not found');
}
success[0].value = JSON.parse(success[0].value);
return success[0].value.order;
});
await emailPlugin.sendMail(user.email, orderMail.title, orderMail.content);
};
cron.minute(async () => {
if(!config.plugins.paypal || !config.plugins.paypal.use) { return; }
const orders = await knex('paypal').select().whereNotBetween('expireTime', [0, Date.now()]);
const scanOrder = order => {
if(order.status !== 'approved' && order.status !== 'finish') {
return checkOrder(order.paypalId);
} else if(order.status === 'approved') {
const accountId = order.account;
const userId = order.user;
push.pushMessage('支付成功', {
body: `订单[ ${ order.orderId } ][ ${ order.amount } ]支付成功`,
});
return checkOrder(order.paypalId).then(() => {
return account.setAccountLimit(userId, accountId, order.orderType);
}).then(() => {
return knex('paypal').update({
status: 'finish',
}).where({
orderId: order.orderId,
});
}).then(() => {
logger.info(`订单支付成功: [${ order.orderId }][${ order.amount }][account: ${ accountId }]`);
ref.payWithRef(userId, order.orderType);
sendSuccessMail(userId);
}).catch(err => {
logger.error(`订单支付失败: [${ order.orderId }]`, err);
});
};
};
for(const order of orders) {
await scanOrder(order);
}
}, 'CheckPaypalOrder', 1);
const orderList = async (options = {}) => {
const where = {};
if(options.userId) {
where['user.id'] = options.userId;
}
const orders = await knex('paypal').select([
'paypal.orderId',
'paypal.orderType',
'user.id as userId',
'user.username',
'account_plugin.port',
'paypal.amount',
'paypal.status',
'paypal.paypalData',
'paypal.createTime',
'paypal.expireTime',
])
.leftJoin('user', 'user.id', 'paypal.user')
.leftJoin('account_plugin', 'account_plugin.id', 'paypal.account')
.where(where)
.orderBy('paypal.createTime', 'DESC');
orders.forEach(f => {
f.paypalData = JSON.parse(f.paypalData);
});
return orders;
};
const orderListAndPaging = async (options = {}) => {
const search = options.search || '';
const group = options.group;
const filter = options.filter || [];
const sort = options.sort || 'paypal.createTime_desc';
const page = options.page || 1;
const pageSize = options.pageSize || 20;
const start = options.start ? moment(options.start).hour(0).minute(0).second(0).millisecond(0).toDate().getTime() : moment(0).toDate().getTime();
const end = options.end ? moment(options.end).hour(23).minute(59).second(59).millisecond(999).toDate().getTime() : moment().toDate().getTime();
let count = knex('paypal').select().whereBetween('paypal.createTime', [start, end]);
let orders = knex('paypal').select([
'paypal.orderId',
'paypal.orderType',
'user.id as userId',
'user.username',
'account_plugin.port',
'paypal.amount',
'paypal.status',
'paypal.paypalData',
'paypal.createTime',
'paypal.expireTime',
])
.leftJoin('user', 'user.id', 'paypal.user')
.leftJoin('account_plugin', 'account_plugin.id', 'paypal.account')
.whereBetween('paypal.createTime', [start, end]);
if(filter.length) {
count = count.whereIn('paypal.status', filter);
orders = orders.whereIn('paypal.status', filter);
}
if(group >= 0) {
count = count.leftJoin('user', 'user.id', 'paypal.user').where({ 'user.group': group });
orders = orders.where({ 'user.group': group });
}
if(search) {
count = count.where('paypal.orderId', 'like', `%${ search }%`);
orders = orders.where('paypal.orderId', 'like', `%${ search }%`);
}
count = await count.count('orderId as count').then(success => success[0].count);
orders = await orders.orderBy(sort.split('_')[0], sort.split('_')[1]).limit(pageSize).offset((page - 1) * pageSize);
orders.forEach(f => {
f.paypalData = JSON.parse(f.paypalData);
});
const maxPage = Math.ceil(count / pageSize);
return {
total: count,
page,
maxPage,
pageSize,
orders,
};
};
const getUserFinishOrder = async userId => {
let orders = await knex('paypal').select([
'orderId',
'amount',
'createTime',
]).where({
user: userId,
}).orderBy('createTime', 'DESC');
orders = orders.map(order => {
return {
orderId: order.orderId,
type: 'Paypal',
amount: order.amount,
createTime: order.createTime,
};
});
return orders;
};
exports.orderListAndPaging = orderListAndPaging;
exports.orderList = orderList;
exports.getUserFinishOrder = getUserFinishOrder;
cron.minute(() => {
if(!config.plugins.paypal || !config.plugins.paypal.use) { return; }
knex('paypal').delete().where({ status: 'created' }).whereBetween('expireTime', [0, Date.now() - 1 * 24 * 3600 * 1000]).then();
}, 'DeletePaypalOrder', 30);