aozhiwei 09e9ad45fd 1
2022-01-24 13:59:49 +08:00

321 lines
9.2 KiB
JavaScript

const util = require('util');
const utils = require('./utils');
const db = require("./db");
const log = require("./log");
const ordermgr = require('./ordermgr');
const bc = require('./blockchain');
const ORDER_STATE_UNPAID = 0; //未支付
const ORDER_STATE_PAID = 1; //已支付
const BOX_STATE_UNPAID = 0; //支付
const BOX_STATE_PAID = 1; //已支付
const BC_RESULT_FAIL = 0;
const BC_RESULT_OK = 1;
class BoxOrder {
constructor(orderDb, isNewOrder) {
this.isNewOrder = isNewOrder;
this.orderDb = orderDb;
}
init () {
if (this.isNewOrder) {
setTimeout(this.start.bind(this), 1000 * 0.1 + Math.floor(Math.random() * 100));
} else {
setTimeout(this.start.bind(this), 1000 * 1 + Math.floor(Math.random() * 1000 * 3));
}
}
async start() {
if (this.isPaid()) {
//修复已经支付成功订单的t_box表关系
await this.repairPaidOrder();
ordermgr.removePendingOrder(this.getOrderId());
return;
}
if (this.isExpired()) {
//修复已过期订单的t_box表关系
await this.repairExpiredOrder();
ordermgr.removePendingOrder(this.getOrderId());
return;
}
if (this.isFail()) {
//修复支付失败的订单
await this.repairFailOrder();
ordermgr.removePendingOrder(this.getOrderId());
return;
}
if (!this.isSynced()) {
//查询
let found = await this.bcSearch();
if (!found) {
//上链
let ok = await this.bcSync();
if (!ok) {
ordermgr.removePendingOrder(this.getOrderId());
return;
}
}
}
//等待确认支付成功
await this.bcConfirm();
ordermgr.removePendingOrder(this.getOrderId());
}
async repairPaidOrder() {
const logClass = 'repairPaidOrder';
const {err, boxDb} = await this.getBoxDb(logClass);
if (err || !boxDb) {
utils.throwError(util.format('%s box not found orderDb:%s err:%s',
logClass,
JSON.stringify(this.orderDb),
err
)
);
return;
}
log.info(util.format('%s begin orderDb:%s boxDb:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb)
)
);
if (boxDb['state'] == BOX_STATE_PAID) {
await this.setDone(logClass);
} else {
let err = await this.setBoxPaidState(logClass, boxDb);
if (!err) {
await this.setDone(logClass);
}
}
log.info(util.format('%s end orderDb:%s boxDb:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb)
)
);
}
async repairExpiredOrder() {
const logClass = 'repairExpiredOrder';
const {err, boxDb} = await this.getBoxDb(logClass);
if (err || !boxDb) {
log.warning(util.format('%s box not found orderDb:%s err:%s',
logClass,
JSON.stringify(this.orderDb),
err
)
);
return;
}
log.info(util.format('%s begin orderDb:%s boxDb:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb)
));
if (!boxDb['order_valid']) {
await this.setDone(logClass);
} else {
let err = await this.setBoxOrderInvalid(logClass, boxDb);
if (!err) {
await this.setDone(logClass);
}
}
log.info(util.format('%s end orderDb:%s boxDb:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb)
)
);
}
async repairFailOrder() {
const logClass = 'repairFailOrder';
const {err, boxDb} = await this.getBoxDb(logClass);
if (err || !boxDb) {
log.warning(util.format('%s box not found orderDb:%s err:%s',
logClass,
JSON.stringify(this.orderDb),
err
));
return;
}
log.info(util.format('%s begin orderDb:%s boxDb:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb)
)
);
if (!boxDb['order_valid']) {
await this.setDone(logClass);
} else {
let err = await this.setBoxOrderInvalid(logClass, boxDb);
if (!err) {
await this.setDone(logClass);
}
}
log.info(util.format('%s end orderDb:%s boxDb:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb)
)
);
}
async bcSearch() {
return true;
}
async bcSync() {
const logClass = 'bcSync';
let syncFunc = async () => {
let result = await bc.mallInstance.methods.buyBoxWithSignature(
boxId,
type,
buyerAddress,
price,
paymentTokenAddress,
nonce,
signature).send({gas: 1000000});
};
while (true) {
try {
let result = syncFunc();
} catch (e) {
log.warning(util.format('%s end orderDb:%s err:',
logClass,
JSON.stringify(this.orderDb),
e
)
);
}
await utils.sleep(1000 * 3);
}
}
async bcConfirm() {
while (true) {
await utils.sleep(1000 * 3);
}
}
async getBoxDb(logClass) {
let {err, row} = await db.execOneQuery('SELECT * FROM t_box where order_id=?',
[
this.getOrderId()
]);
if (!row) {
log.warning(util.format('%s box not found orderDb:%s',
logClass,
JSON.stringify(this.orderDb),
)
);
}
return {
'err': err,
'boxDb': row
};
}
async setDone(logClass) {
let err = await db.execScript('UPDATE t_box_order SET done=1 WHERE order_id=?',
[
this.getOrderId()
]);
if (err) {
log.error(util.format('%s setDoneErr orderDb:%s err:%s',
logClass,
JSON.stringify(this.orderDb),
err
)
);
} else {
log.error(util.format('%s setDoneOk orderDb:%s',
logClass,
JSON.stringify(this.orderDb)
)
);
}
return err;
}
async setBoxPaidState(logClass, boxDb) {
let err = await db.execScript('UPDATE t_box SET state=? WHERE idx=?',
[
BOX_STATE_PAID,
boxDb['idx']
]);
if (err) {
log.error(util.format('%s setBoxPaidState orderDb:%s boxDb:%s err:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb),
err
)
);
} else {
log.error(util.format('%s setBoxPaidState orderDb:%s boxDb:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb),
)
);
}
return err;
}
async setBoxOrderInvalid(logClass, boxDb) {
let err = await db.execScript('UPDATE t_box SET order_valid=0 WHERE idx=?',
[
boxDb['idx']
]);
if (err) {
log.error(util.format('%s setBoxOrderInvalid orderDb:%s boxDb:%s err:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb),
err
)
);
} else {
log.error(util.format('%s setBoxOrderInvalid orderDb:%s boxDb:%s',
logClass,
JSON.stringify(this.orderDb),
JSON.stringify(boxDb),
)
);
}
return err;
}
getOrderId() {
return this.orderDb['order_id'];
}
isExpired() {
return this.orderDb['expired'];
}
isPaid() {
return this.orderDb['state'] == ORDER_STATE_PAID;
}
isSynced() {
return this.orderDb['bc_synced'] != 0;
}
isFail() {
return this.isSynced() && this.orderDb['bc_result'] != BC_RESULT_OK;
}
};
exports.BoxOrder = BoxOrder;