325 lines
8.9 KiB
JavaScript
325 lines
8.9 KiB
JavaScript
const util = require('util');
|
|
const utils = require('./utils');
|
|
const db = require("./db");
|
|
const log = require("./log");
|
|
const boxrepairer = require('./boxrepairer');
|
|
const bc = require('./blockchain');
|
|
const C = require('./C');
|
|
|
|
class BoxOrder {
|
|
|
|
constructor(orderDb, isNewOrder) {
|
|
this.isNewOrder = isNewOrder;
|
|
this.orderDb = orderDb;
|
|
this.repairer = new boxrepairer.BoxRepairer(this);
|
|
}
|
|
|
|
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.repairer.repairPaidOrder();
|
|
return;
|
|
}
|
|
if (this.isExpired()) {
|
|
//修复已过期订单的t_box表关系
|
|
await this.repairer.repairExpiredOrder();
|
|
return;
|
|
}
|
|
if (this.isFail()) {
|
|
//修复支付失败的订单
|
|
await this.repairer.repairFailOrder();
|
|
return;
|
|
}
|
|
|
|
if (!this.isSynced()) {
|
|
//查询
|
|
const found = await this.bcSearch();
|
|
if (!found) {
|
|
//上链
|
|
const ok = await this.bcSync();
|
|
if (!ok) {
|
|
utils.emitEvent(C.REMOVE_PENDING_ORDER_EVENT, this.getOrderId());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
//等待确认支付成功
|
|
await this.bcConfirm();
|
|
}
|
|
|
|
async bcSearch() {
|
|
const logClass = 'bcSearch';
|
|
const events = await bc.mallInstance.getPastEvents(
|
|
'BEBoxPaid',
|
|
{
|
|
fromBlock: 0,
|
|
toBlock: 'latest',
|
|
filter: {
|
|
boxId: this.getOrderId()
|
|
}
|
|
});
|
|
if (events.length > 0) {
|
|
while (true) {
|
|
const err = await this.setSynced(logClass);
|
|
if (!err) {
|
|
break;
|
|
}
|
|
await utils.sleep(1000 * 3);
|
|
}
|
|
this.orderDb['bc_synced'] = 1;
|
|
}
|
|
return events.length > 0;
|
|
}
|
|
|
|
async bcSync() {
|
|
const logClass = 'bcSync';
|
|
const doSync = async () => {
|
|
console.log(this.orderDb);
|
|
const result = await bc.mallInstance.methods.buyBoxWithSignature(
|
|
this.orderDb['order_id'],
|
|
this.orderDb['item_id'],
|
|
this.orderDb['buyer_address'],
|
|
this.orderDb['price'],
|
|
this.orderDb['payment_token_address'],
|
|
this.orderDb['nonce'],
|
|
this.orderDb['signature']).send({gas: 1000000});
|
|
return result;
|
|
};
|
|
while (true) {
|
|
try {
|
|
const result = doSync();
|
|
} catch (e) {
|
|
log.warning(util.format('%s end orderDb:%s err:s',
|
|
logClass,
|
|
JSON.stringify(this.orderDb),
|
|
e
|
|
)
|
|
);
|
|
}
|
|
await utils.sleep(1000 * 3 + Math.random() * 1000);
|
|
}
|
|
}
|
|
|
|
async bcConfirm() {
|
|
const logClass = 'bcConfirm';
|
|
|
|
while (true) {
|
|
if (bc.isComfirmed(this.getBlockNumber())) {
|
|
break;
|
|
}
|
|
await utils.sleep(1000 * 3);
|
|
}
|
|
|
|
while (true) {
|
|
const err = await this.setPaidState(logClass);
|
|
if (!err) {
|
|
break;
|
|
}
|
|
await utils.sleep(1000 * 3);
|
|
}
|
|
|
|
{
|
|
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.boxOrder.getOrderDb()),
|
|
err
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
while (true) {
|
|
const err = await this.setBoxPaidState(logClass, boxDb);
|
|
if (!err) {
|
|
break;
|
|
}
|
|
await utils.sleep(1000 * 3);
|
|
}
|
|
}
|
|
|
|
while (true) {
|
|
const err = await this.setDone(logClass);
|
|
if (!err) {
|
|
break;
|
|
}
|
|
await utils.sleep(1000 * 3);
|
|
}
|
|
|
|
utils.emitEvent(C.REMOVE_PENDING_ORDER_EVENT, this.getOrderId());
|
|
}
|
|
|
|
async getBoxDb(logClass) {
|
|
const {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 setSynced(logClass) {
|
|
const err = await db.execScript('UPDATE t_box_order SET bc_synced=1 WHERE order_id=?',
|
|
[
|
|
this.getOrderId()
|
|
]);
|
|
if (err) {
|
|
log.error(util.format('%s setSynced orderDb:%s err:%s',
|
|
logClass,
|
|
JSON.stringify(this.orderDb),
|
|
err
|
|
)
|
|
);
|
|
} else {
|
|
log.info(util.format('%s setSynced orderDb:%s',
|
|
logClass,
|
|
JSON.stringify(this.orderDb)
|
|
)
|
|
);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
async setDone(logClass) {
|
|
const 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.info(util.format('%s setDoneOk orderDb:%s',
|
|
logClass,
|
|
JSON.stringify(this.orderDb)
|
|
)
|
|
);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
async setPaidState(logClass) {
|
|
const err = await db.execScript('UPDATE t_box_order SET state=? WHERE order_id=?',
|
|
[
|
|
C.ORDER_STATE_PAID,
|
|
this.getOrderId()
|
|
]);
|
|
if (err) {
|
|
log.error(util.format('%s setPaidState orderDb:%s err:%s',
|
|
logClass,
|
|
JSON.stringify(this.orderDb),
|
|
err
|
|
)
|
|
);
|
|
} else {
|
|
log.error(util.format('%s setPaidState orderDb:%s',
|
|
logClass,
|
|
JSON.stringify(this.orderDb)
|
|
)
|
|
);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
async setBoxPaidState(logClass, boxDb) {
|
|
const err = await db.execScript('UPDATE t_box SET state=? WHERE idx=?',
|
|
[
|
|
C.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) {
|
|
const 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;
|
|
}
|
|
|
|
getOrderDb() {
|
|
return this.orderDb;
|
|
}
|
|
|
|
getOrderId() {
|
|
return this.orderDb['order_id'];
|
|
}
|
|
|
|
getBlockNumber() {
|
|
return this.orderDb['bc_block_number'];
|
|
}
|
|
|
|
isExpired() {
|
|
return this.orderDb['expired'];
|
|
}
|
|
|
|
isPaid() {
|
|
return this.orderDb['state'] == C.ORDER_STATE_PAID;
|
|
}
|
|
|
|
isSynced() {
|
|
return this.orderDb['bc_synced'] != 0;
|
|
}
|
|
|
|
isFail() {
|
|
return this.isSynced() && this.orderDb['bc_result'] != C.BC_RESULT_OK;
|
|
}
|
|
|
|
};
|
|
|
|
exports.BoxOrder = BoxOrder;
|