var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
// redis 鏈接
var redis = require('redis');
var client = redis.createClient('8383', '127.0.0.1');
//rabbitmq連接
var amqp = require("amqp");
var amqpConn = amqp.createConnection({url: "amqp:guest:[email protected]:5672"});
// redis 鏈接錯誤
client.on("error", function(error) {
console.log(error);
});
//mysql
var mysql = require('mysql');
var mysqlConn = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'root',
database : 'test'
});
var orderQueue;
var amqpConnReady = false;
//amqp監聽消息進行消費
amqpConn.on('ready', function () {
amqpConnReady = true;
amqpConn.queue('orderQueue', { durable: true, autoDelete: false }, function (queue) {
console.log('Queue ' + queue.name + ' is consuming!');
orderQueue = queue;
mysqlConn.connect();
queue.subscribe(function (message, header, deliveryInfo) {
if (message.data) {
var messageText = message.data.toString();
//console.log(messageText);
var data = JSON.parse(messageText);
//獲得用戶地址詳細信息
var sql = 'SELECT * FROM `address` WHERE `id` = '+ parseInt(data.address) + ' AND `user_id` = ' + data.user_id;
mysqlConn.query(sql,function (err, result) {
if(err){
console.log('[SELECT address ERROR] - ',err.message);
return;
}
if(result) {
data.address = JSON.stringify(result[0]);
//插入訂單
var addSql = 'INSERT INTO `order` (`user_id`,`orderno`,`goods_id`,`address`,`status`,`amount`,`ip`,`express`,`invoice`,`message`,`create_time`,`update_time`) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)';
var addSqlParams = [data.user_id, data.orderno, data.goods_id, data.address, data.status, data.amount, data.ip, data.express, data.invoice, data.message, data.create_time, data.update_time];
mysqlConn.query(addSql,addSqlParams,function (err, result) {
if(err){
console.log('[INSERT Order ERROR] - ',err.message);
return;
}else{
//mysql 商品庫存減少
var modSql = 'UPDATE `goods` SET `stock` = `stock`-1,`sold` = `sold`+1 WHERE `id` = ?';
var modSqlParams = [data.goods_id];
mysqlConn.query(modSql,modSqlParams,function (err, result) {
if(err){
console.log('[UPDATE Goods stock ERROR] - ',err.message);
return;
}
//mysqlConn.end();
});
console.log('INSERT Order Ok');
}
})
}
});
}
});
});
});
//根據token獲得用戶ID
function getUserId(res, token, callback) {
if(!token) {
jsonResponse(res, 500, '身份驗證失敗');
}else{
return client.get(token, function(err, tokenInfo) {
if(err) {
console.log(err);
}else{
if(!tokenInfo) {
jsonResponse(res, 500, '身份驗證失敗,請重新登錄');
}else{
var user_id = JSON.parse(tokenInfo).id;
callback(user_id);
}
}
})
}
}
/**
* [jsonResponse 接口返回json]
* @param {[type]} res [res]
* @param {[type]} status [狀態嗎]
* @param {[type]} message [信息]
* @param {[type]} data [數據]
* @return {[type]} [json]
*/
function jsonResponse(res, code, message, data) {
return res.json({ code: code, message: message, data: data });
};
//生成唯一訂單號
function getOrderNo() {
var date = new Date();
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = date.getFullYear() + month + strDate + date.getHours() + date.getMinutes() + date.getSeconds();
return currentdate + Math.floor(Math.random()*10000) + '';
}
/**
* [publishOrderMessage 發佈下單消息]
* @param {[type]} res [res]
* @param {[type]} data [下單信息]
*/
function publishOrderMessage(res, data) {
if(amqpConnReady) {
amqpConn.publish('orderQueue', JSON.stringify(data));
}
}
/**
* @getClientIP
* @desc 獲取用戶 ip 地址
* @param {Object} req - 請求
*/
function getClientIP(req) {
return req.headers['x-forwarded-for'] || // 判斷是否有反向代理 IP
req.connection.remoteAddress || // 判斷 connection 的遠程 IP
req.socket.remoteAddress || // 判斷後端的 socket 的 IP
req.connection.socket.remoteAddress;
};
//請求下單
app.post('/order', function(req, res) {
var goods_id = req.body.id;
var address_id = req.body.address_id;
var express = req.body.express;
var invoice = req.body.invoice;
var message = req.body.message;
var token = req.get('HTTP_TOKEN');
if(!address_id) {
jsonResponse(res, 500, '請選擇一個收貨地址');
}else{
getUserId(res, token, function(user_id) {
//從redis獲取商品信息
var goods_key = 'goods:' + goods_id;
client.get(goods_key, function(err, goods) {
if(err) {
console.log(err);
}else{
goods = JSON.parse(goods);
if(goods == null) {
jsonResponse(res, 404, '404');
}else{
var time = Date.parse( new Date()) + '';
time = parseInt(time.substr(0, 10));
if(goods.end_time < time) {
jsonResponse(res, 500, '秒殺已結束');
}else if(goods.start_time > time) {
jsonResponse(res, 500, '秒殺還未開始');
}else{
//判斷庫存
var goods_stock_key = 'goods_stock:'+goods_id;
client.llen(goods_stock_key, function(err, stock) {
if(err) {
console.log(err);
}else{
if(stock <= 0) {
jsonResponse(res, 500, '庫存不足');
}else{
var orderNo = getOrderNo();
var data = {
user_id: user_id,
orderno: orderNo,
goods_id: goods_id,
address: address_id,
status: 1,
amount: goods.kill_price,
ip: getClientIP(req),
express: express,
invoice: invoice,
message: message,
create_time: time,
update_time: time,
};
//減少庫存
client.lpop(goods_stock_key, function(err, ret) {
if(err) {
console.log(err);
}else{
//加入rabbitmq消息隊列,發佈下單消息
publishOrderMessage(res, data);
var response_data = {
'amount': data.amount,
'orderno': data.orderno
};
jsonResponse(res, 200, 'ok', response_data);
}
})
}
}
})
}
}
}
})
})
}
});
var server = app.listen(3000, function() {
var host = server.address().address;
var port = server.address().port;
console.log('app listening at http://%s:%s', host, port);
});
node.js下express+redis+mysql+rabbitmq實現簡單的秒殺購物
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.