diff --git a/server/payserver/app.cc b/server/payserver/app.cc index e3bb7e7..0820368 100644 --- a/server/payserver/app.cc +++ b/server/payserver/app.cc @@ -15,6 +15,7 @@ #include "app.h" #include "jsondatamgr.h" #include "handlermgr.h" +#include "ApiListener.h" struct MsgNode { @@ -67,10 +68,10 @@ void App::Init(int argc, char* argv[]) if (!ParseOpt()) { terminated = true; - a8::XPrintf("masterserver启动失败,缺少-i参数\n", {}); + a8::XPrintf("payserver启动失败,缺少-i参数\n", {}); return; } - a8::XPrintf("masterserver starting instance_id:%d pid:%d\n", {instance_id, getpid()}); + a8::XPrintf("payserver starting instance_id:%d pid:%d\n", {instance_id, getpid()}); loop_mutex_ = new std::mutex(); loop_cond_ = new std::condition_variable(); @@ -83,8 +84,9 @@ void App::Init(int argc, char* argv[]) a8::Timer::Instance()->Init(); JsonDataMgr::Instance()->Init(); uuid.SetMachineId(instance_id); + ApiListener::Instance()->Init(); - a8::UdpLog::Instance()->Info("masterserver starting instance_id:%d pid:%d", {instance_id, getpid()}); + a8::UdpLog::Instance()->Info("payserver starting instance_id:%d pid:%d", {instance_id, getpid()}); { int perf_log_time = 1000 * 60 * 5; if (getenv("is_dev_env")) { @@ -104,6 +106,7 @@ void App::UnInit() if (terminated) { return; } + ApiListener::Instance()->UnInit(); JsonDataMgr::Instance()->UnInit(); a8::Timer::Instance()->UnInit(); HandlerMgr::Instance()->UnInit(); @@ -125,7 +128,7 @@ int App::Run() return 0; } int ret = 0; - a8::UdpLog::Instance()->Info("masterserver running", {}); + a8::UdpLog::Instance()->Info("payserver running", {}); while (!terminated) { a8::tick_t begin_tick = a8::XGetTickCount(); QuickExecute(); diff --git a/server/payserver/handlermgr.cc b/server/payserver/handlermgr.cc index 42bffa7..4b50a9c 100644 --- a/server/payserver/handlermgr.cc +++ b/server/payserver/handlermgr.cc @@ -3,6 +3,7 @@ #include #include "handlermgr.h" +#include "ApiListener.h" static void _GMOpsSelfChecking(f8::JsonHttpRequest* request) { @@ -12,10 +13,24 @@ static void _GMOpsSelfChecking(f8::JsonHttpRequest* request) request->resp_xobj->SetVal("max_rundelay", 10); } +static void _GMPayGetOrderId(f8::JsonHttpRequest* request) +{ + request->resp_xobj->SetVal("errcode", 0); + request->resp_xobj->SetVal("errmsg", ""); +} + +static void _GMPayNotify(f8::JsonHttpRequest* request) +{ + request->resp_xobj->SetVal("errcode", 0); + request->resp_xobj->SetVal("errmsg", ""); +} + void HandlerMgr::Init() { RegisterNetMsgHandlers(); RegisterGMMsgHandler("Ops$selfChecking", _GMOpsSelfChecking); + RegisterGMMsgHandler("Pay$getOrderId", _GMPayGetOrderId); + RegisterGMMsgHandler("Pay$payNotify", _GMPayNotify); } void HandlerMgr::UnInit() @@ -30,9 +45,7 @@ void HandlerMgr::ProcGMMsg(unsigned long saddr, int sockhandle, const std::string& url, const std::string& querystr) { if (url != "/webapp/index.php") { - #if 0 - GCListener::Instance()->SendText(sockhandle, a8::HttpResponse(404, "")); - #endif + ApiListener::Instance()->SendText(sockhandle, a8::HttpResponse(404, "")); return; } @@ -52,16 +65,12 @@ void HandlerMgr::ProcGMMsg(unsigned long saddr, int sockhandle, if (!request->pending){ std::string response; request->resp_xobj->ToJsonStr(response); - #if 0 - GCListener::Instance()->SendText(sockhandle, a8::HttpResponse(response)); - #endif + ApiListener::Instance()->SendText(sockhandle, a8::HttpResponse(response)); delete request; } } else { - #if 0 - GCListener::Instance()->SendText(sockhandle, a8::HttpResponse("{}")); - #endif + ApiListener::Instance()->SendText(sockhandle, a8::HttpResponse("{}")); } } diff --git a/server/payserver/ordermgr.cc b/server/payserver/ordermgr.cc new file mode 100644 index 0000000..944eb22 --- /dev/null +++ b/server/payserver/ordermgr.cc @@ -0,0 +1,684 @@ +#include "precompile.h" +#include +#include "ordermgr.h" +#if 0 +#include "DBSListener.h" +#endif + +struct AddOrderNode +{ + int seqid = 0; + int payresult = 0; + OrderInfo orderinfo; + AddOrderNode* next = nullptr; +}; + +struct PayNotifyNode +{ + int seqid; + int pay_type;//0:normal 1:ios 2:jinqi + std::string accountid; + std::string roleid; + std::string rolename; + int serverid; + int itemid; + std::string itemid_str; + std::string orderid; + std::string sp_orderid; + std::string sp_accountid; + double fee; + int payresult; + PayNotifyNode* next; + + PayNotifyNode() + { + seqid = 0; + pay_type = 0; + serverid = 0; + itemid = 0; + payresult = 0; + next = NULL; + } +}; + +struct ReissueNode +{ + int seqid = 0; + std::string orderid; + ReissueNode* next = NULL; +}; + +void OrderMgr::Init() +{ + top_node_ = NULL; + bot_node_ = NULL; + work_node_ = NULL; + pay_notify_top_node_ = NULL; + pay_notify_bot_node_ = NULL; + pay_notify_work_node_ = NULL; + reissue_top_node_ = NULL; + reissue_bot_node_ = NULL; + reissue_work_node_ = NULL; + add_order_mutex_ = new std::mutex(); + pay_notify_mutex_ = new std::mutex(); + reissue_mutex_ = new std::mutex(); + seq_mutex_ = new std::mutex(); + add_order_result_mutex_ = new std::mutex(); + pay_notify_result_mutex_ = new std::mutex(); + + current_seqid_ = 1000; + sub_orderid_ = 1; + #if 0 + last_gen_order_time_ = g_nowtime; + #endif + last_ping_db_tick_ = a8::XGetTickCount(); + #if 0 + //assert(mysql_conn_.Connect("127.0.0.1", 3306, "root", "keji178", "paydb")); + assert(mysql_conn_.Connect(g_mysql_host, 3306, g_mysql_user, g_mysql_passwd, "paydb")); + query_.SetConnection(&mysql_conn_); + DumpMysqlInfo(query_); + RegisterNetMsgHandler(g_dbsmsghandler, &OrderMgr::_SSMPing); + RegisterNetMsgHandler(g_dbsmsghandler, &OrderMgr::_D2PPayNotifyACK); + #endif + LoadPedingOrders(); +} + +void OrderMgr::UnInit() +{ +} + +void OrderMgr::Update() +{ + if (a8::XGetTickCount() - last_ping_db_tick_ > 1000 * 60 * 5) { + last_ping_db_tick_ = a8::XGetTickCount(); + #if 0 + if (query_.ExecQuery("SELECT 1;", {}) <= 0) { + g_udplog->Warning("mysql disconnect", {}); + if (mysql_conn_.Connect()) { + DumpMysqlInfo(query_); + g_udplog->Info("mysql reconnect successed", {}); + } else { + g_udplog->Info("mysql reconnect failed", {}); + } + } + #endif + } + ProcessOrderMsg(); + ProcessNotifyMsg(); + ProcessReissueMsg(); + UpdatePedingOrders(); +} + +bool OrderMgr::HasTask() +{ + { + if (!work_node_) { + add_order_mutex_->lock(); + if (!work_node_ && top_node_) { + work_node_ = top_node_; + top_node_ = NULL; + bot_node_ = NULL; + } + add_order_mutex_->unlock(); + } + if (work_node_) { + return true; + } + } + { + if (!pay_notify_work_node_) { + pay_notify_mutex_->lock(); + if (!pay_notify_work_node_ && pay_notify_top_node_) { + pay_notify_work_node_ = pay_notify_top_node_; + pay_notify_top_node_ = NULL; + pay_notify_bot_node_ = NULL; + } + pay_notify_mutex_->unlock(); + } + if (pay_notify_work_node_) { + return true; + } + } + { + if (!reissue_work_node_) { + reissue_mutex_->lock(); + if (!reissue_work_node_ && reissue_top_node_) { + reissue_work_node_ = reissue_top_node_; + reissue_top_node_ = NULL; + reissue_bot_node_ = NULL; + } + reissue_mutex_->unlock(); + } + if (reissue_work_node_) { + return true; + } + } + return false; +} + +int OrderMgr::AddOrder(const std::string& seqid, const std::string& accountid, + const std::string& roleid, const std::string& rolename, + const std::string& channel, const std::string& sp_accountid, int serverid, + int productid, int price,const std::string& sp_orderid) +{ + int new_seqid = GenSeqId(); + AddOrderNode *p = new AddOrderNode(); + p->orderinfo.seqid = seqid; + p->orderinfo.accountid = accountid; + p->orderinfo.orderid = GenOrderId(productid); + p->orderinfo.roleid = roleid; + p->orderinfo.rolename = rolename; + p->orderinfo.sp_accountid = sp_accountid; + p->orderinfo.channel = channel; + p->orderinfo.itemid = productid; + p->orderinfo.price = price; + p->orderinfo.serverid = serverid; + p->orderinfo.sp_accountid = sp_orderid; + p->seqid = new_seqid; + add_order_mutex_->lock(); + if (bot_node_) { + bot_node_->next = p; + bot_node_ = p; + } else { + top_node_ = p; + bot_node_ = p; + } + add_order_mutex_->unlock(); + return new_seqid; +} + +bool OrderMgr::WaitForAddOrderFinished(int seqid, AddOrderResult& addresult, int seconds) +{ + a8::tick_t tick = a8::XGetTickCount(); + while (true) { + if (a8::XGetTickCount() - tick > 1000 * seconds) { //timeout + return false; + } + add_order_result_mutex_->lock(); + std::map::iterator itr = add_order_results_.find(seqid); + if (itr != add_order_results_.end()) { + addresult = itr->second; + add_order_results_.erase(itr); + add_order_result_mutex_->unlock(); + return true; + } else { + add_order_result_mutex_->unlock(); + #if 0 + g_application->NotifyLoopCond(); + #endif + } + } + return false; +} + +int OrderMgr::AddPayNotify(int pay_type, + const std::string& accountid, + const std::string& roleid, + const std::string& rolename, + int serverid, + int itemid, + const std::string& itemid_str, + const std::string& orderid, + const std::string& sp_orderid, + double fee, + int payresult) +{ + int new_seqid = GenSeqId(); + PayNotifyNode *p = new PayNotifyNode(); + p->seqid = new_seqid; + p->pay_type = pay_type; + p->accountid = accountid; + p->roleid = roleid; + p->rolename = rolename; + p->serverid = serverid; + p->itemid = itemid; + p->itemid_str = itemid_str; + p->orderid = orderid; + p->sp_orderid = sp_orderid; + p->fee = fee; + p->payresult = payresult; + pay_notify_mutex_->lock(); + if (pay_notify_bot_node_) { + pay_notify_bot_node_->next = p; + pay_notify_bot_node_ = p; + } else { + pay_notify_top_node_ = p; + pay_notify_bot_node_ = p; + } + pay_notify_mutex_->unlock(); + return new_seqid; +} + +int OrderMgr::AddReissue(const std::string& orderid) +{ + int new_seqid = GenSeqId(); + ReissueNode *p = new ReissueNode(); + p->seqid = new_seqid; + p->orderid = orderid; + reissue_mutex_->lock(); + if (reissue_bot_node_) { + reissue_bot_node_->next = p; + reissue_bot_node_ = p; + } else { + reissue_top_node_ = p; + reissue_bot_node_ = p; + } + reissue_mutex_->unlock(); + return new_seqid; +} + +bool OrderMgr::WaitForReissueFinished(int seqid, int& result, int seconds) +{ +} + +bool OrderMgr::WaitForPayNotifyFinished(int seqid, int& result, int seconds) +{ + a8::tick_t tick = a8::XGetTickCount(); + while (true) { + if (a8::XGetTickCount() - tick > 1000 * seconds) { //timeout + return false; + } + pay_notify_result_mutex_->lock(); + std::map::iterator itr = pay_notify_results_.find(seqid); + if (itr != pay_notify_results_.end()) { + result = itr->second; + pay_notify_results_.erase(itr); + pay_notify_result_mutex_->unlock(); + return true; + } else { + pay_notify_result_mutex_->unlock(); + #if 0 + g_application->NotifyLoopCond(); + #endif + } + } + return false; +} + +void OrderMgr::ProcessOrderMsg() +{ + if (!work_node_ && top_node_) { + add_order_mutex_->lock(); + work_node_ = top_node_; + top_node_ = NULL; + bot_node_ = NULL; + add_order_mutex_->unlock(); + } + + while (work_node_) { + AddOrderNode *delnode = work_node_; + work_node_ = work_node_->next; + + AddOrderResult result; + result.orderinfo = delnode->orderinfo; + result.isok = ProcAddOrder(result.orderinfo); + add_order_result_mutex_->lock(); + add_order_results_[delnode->seqid] = result; + add_order_result_mutex_->unlock(); + + delete delnode; + } +} + +void OrderMgr::ProcessReissueMsg() +{ + if (!reissue_work_node_ && reissue_top_node_) { + reissue_mutex_->lock(); + reissue_work_node_ = reissue_top_node_; + reissue_top_node_ = NULL; + reissue_bot_node_ = NULL; + reissue_mutex_->unlock(); + } + + while (reissue_work_node_) { + ReissueNode *delnode = reissue_work_node_; + reissue_work_node_ = reissue_work_node_->next; + + ProcReissue(delnode->orderid); + + delete delnode; + } +} + +void OrderMgr::ProcessNotifyMsg() +{ + if (!pay_notify_work_node_ && pay_notify_top_node_) { + pay_notify_mutex_->lock(); + pay_notify_work_node_ = pay_notify_top_node_; + pay_notify_top_node_ = NULL; + pay_notify_bot_node_ = NULL; + pay_notify_mutex_->unlock(); + } + + while (pay_notify_work_node_) { + PayNotifyNode *delnode = pay_notify_work_node_; + pay_notify_work_node_ = pay_notify_work_node_->next; + + int result = 0; + + switch (delnode->pay_type) { + case 1: + result = ProcIosPayOrderNotify(delnode); + break; + case 4: + result = ProcOrderNotify(delnode); + break; + case 5: + result = ContinueSubscriptions(delnode); + break; + } + pay_notify_mutex_->lock(); + pay_notify_results_[delnode->seqid] = result; + pay_notify_mutex_->unlock(); + + delete delnode; + } +} + +bool OrderMgr::ProcAddOrder(OrderInfo& orderinfo) +{ + #if 1 + return false; + #else + return query_.ExecScript("INSERT INTO orderinfo(orderid, serverid, roleid, rolename, channel, itemid, price, status, createtime, accountid, sp_orderid)" \ + "VALUES('%s', %d, '%s', '%s', '%s', '%s', %d, %d, %d, '%s','%s');", + { + orderinfo.orderid, + orderinfo.serverid, + orderinfo.roleid, + orderinfo.rolename, + orderinfo.channel, + orderinfo.itemid, + orderinfo.price, + 0, + g_nowtime, + orderinfo.accountid, + orderinfo.sp_accountid + }); + + #endif +} + +int OrderMgr::ProcOrderNotify(PayNotifyNode* node) +{ + + if (node->payresult != 0 && node->payresult != 1) { + return 4; + } + + #if 0 + int ret = query_.ExecQuery("SELECT orderid, itemid, roleid, rolename, price, sp_pay_result, serverid " + "FROM orderinfo WHERE orderid='%s' and sp_confirm_time=0;", + { node->orderid}); + if (ret > 0) { + if (query_.GetValue(5).GetInt() == 0) { + OrderInfo info; + info.orderid = query_.GetValue(0).GetString(); + info.itemid = query_.GetValue(1); + info.roleid = query_.GetValue(2).GetString(); + info.rolename = query_.GetValue(3).GetString(); + info.price = query_.GetValue(4); + info.lastchecktime = g_nowtime - 60 * 3; + info.serverid = query_.GetValue(6); + if (query_.ExecScript("UPDATE orderinfo SET sp_pay_result=%d, sp_confirm_time=%d, sp_orderid='%s' WHERE orderid='%s';", + { + node->payresult, + g_nowtime, + node->sp_orderid, + node->orderid + })) { + if (node->payresult == 1) { + peding_orders_[info.orderid] = info; + } + return 0; + } else { + return 2; + } + } else { + return 3; + } + } else { + return 1; + } + #endif +} + +int OrderMgr::ContinueSubscriptions(PayNotifyNode* node) +{ + #if 1 + return 0; + #else + int ret = query_.ExecQuery("SELECT orderid, itemid, roleid, rolename, price, sp_pay_result, serverid " + "FROM orderinfo WHERE orderid='%s' ", + { node->orderid }); + + if (ret <= 0) + return 1; + + OrderInfo info; + info.orderid = query_.GetValue(0).GetString(); + info.itemid = query_.GetValue(1); + info.roleid = query_.GetValue(2).GetString(); + info.rolename = query_.GetValue(3).GetString(); + info.price = query_.GetValue(4); + info.lastchecktime = g_nowtime - 60 * 3; + info.serverid = query_.GetValue(6); + peding_orders_[info.orderid] = info; + + return 0; + #endif +} + +int OrderMgr::ProcIosPayOrderNotify(PayNotifyNode* node) +{ + #if 0 + Template::RechargeCard *cardtpl = g_configtable->GetRechargeCard(node->itemid); + if (!cardtpl) { + return 4; + } + + int retcode = query_.ExecQuery("SELECT orderid FROM orderinfo WHERE channel='%s' and sp_orderid='%s';", + { + std::string(IOS_CHANNEL), + node->sp_orderid + }); + if (retcode < 0) { + return 2; + } + if (retcode > 0) { + return 0; + } + + std::string orderid = GenOrderId(node->itemid); + bool ret = query_.ExecScript("INSERT INTO orderinfo(orderid, accountid, roleid, rolename, channel, serverid, itemid, price, status, createtime, sp_orderid, sp_accountid, sp_confirm_time, sp_pay_result)" + "VALUES('%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, %d, '%s', '%s', %d, 1);", + { + orderid, + node->accountid, + node->roleid, + node->rolename, + IOS_CHANNEL, + node->serverid, + node->itemid, + cardtpl->price * 10, + g_nowtime, + node->sp_orderid, + node->sp_accountid, + g_nowtime + }); + if (!ret) { + printf("prociospaynotify %s\n", mysql_conn_.GetError().c_str()); + return 3; + } + OrderInfo info; + info.orderid = orderid; + info.accountid = node->accountid; + info.itemid = node->itemid; + info.price = cardtpl->price * 10; + info.customprice = info.price; + info.serverid = node->serverid; + info.roleid = node->roleid; + info.rolename = node->rolename; + info.sp_accountid = node->sp_accountid; + info.channel = IOS_CHANNEL; + peding_orders_[info.orderid] = info; + return 0; + #endif +} + +void OrderMgr::ProcReissue(const std::string& orderid) +{ + #if 0 + //超过30天的不能补发 + int ret = query_.ExecQuery("SELECT orderid, itemid, roleid, rolename, price, sp_pay_result, serverid " + "FROM orderinfo WHERE orderid='%s' AND status=1 AND confirmtime + 3600 * 24 * 30 > %d;", + { + orderid, + g_nowtime + }); + if (ret > 0) { + OrderInfo info; + info.orderid = query_.GetValue(0).GetString(); + info.itemid = query_.GetValue(1); + info.roleid = query_.GetValue(2).GetString(); + info.rolename = query_.GetValue(3).GetString(); + info.price = query_.GetValue(4); + info.lastchecktime = g_nowtime - 60 * 3; + info.serverid = query_.GetValue(6); + if (query_.ExecScript("UPDATE orderinfo SET status=0, confirmtime=0 WHERE orderid='%s';", + {orderid})) { + peding_orders_[info.orderid] = info; + } + } + #endif +} + +void OrderMgr::UpdatePedingOrders() +{ + #if 0 + g_udplog->Debug("UpdatePedingOrders peding_orders_ size:%d", { peding_orders_.size() }); + for (std::map::iterator itr = peding_orders_.begin(); + itr != peding_orders_.end(); ++itr){ + if (g_nowtime - itr->second.lastchecktime > 15) { + itr->second.lastchecktime = g_nowtime; + P2DPayNotify msg; + msg.orderid = itr->second.orderid; + msg.roleid = itr->second.roleid; + msg.name = itr->second.rolename; + msg.itemid = itr->second.itemid; + msg.price = itr->second.price; + msg.serverid = itr->second.serverid; + g_dbslistener->SendToDBServer(msg); + g_udplog->Debug("UpdatePedingOrders send P2DPayNotify orderid:%s roleid:%d name:%s serverid:%d", { msg.orderid,msg.roleid,msg.name,msg.serverid }); + } + } + #endif +} + +#if 0 +void OrderMgr::_SSMPing(MsgHdr& hdr, const SSMPing& msg) +{ + SSMPong respmsg; + g_dbslistener->SendToDBServer(respmsg); +} + +void OrderMgr::_D2PPayNotifyACK(MsgHdr& hdr, const D2PPayNotifyACK& msg) +{ + if (peding_orders_.find(msg.orderid) != peding_orders_.end()) { + if (query_.ExecScript("UPDATE orderinfo SET status=%d, confirmtime=%d WHERE orderid='%s';", + { + 1, + g_nowtime, + msg.orderid + })) { + peding_orders_.erase(msg.orderid); + } + } +} +#endif + +//支付成功并且gameserver没有确认的订单 +void OrderMgr::LoadPedingOrders() +{ + #if 0 + int ret = query_.ExecQuery("SELECT orderid, itemid, roleid, rolename, price, serverid, accountid " + "FROM orderinfo WHERE sp_pay_result=1 AND status=0;", {}); + if (ret < 0) { + return; + } + while (!query_.Eof()) { + OrderInfo info; + info.orderid = query_.GetValue(0).GetString(); + info.itemid = query_.GetValue(1); + info.roleid = query_.GetValue(2).GetString(); + info.rolename = query_.GetValue(3).GetString(); + info.price = query_.GetValue(4); + info.lastchecktime = g_nowtime - 60 * 1; + info.serverid = query_.GetValue(5); + info.accountid = query_.GetValue(6).GetString(); + peding_orders_[info.orderid] = info; + query_.Next(); + } + #endif +} + +long OrderMgr::GenSeqId() +{ + long new_seqid = 0; + seq_mutex_->lock(); + new_seqid = ++current_seqid_; + seq_mutex_->unlock(); + return new_seqid; +} + +std::string OrderMgr::GenOrderId(int itemid) +{ + #if 1 + return ""; + #else + char orderid[80] = {0}; + { + time_t nowtime = time(NULL); + if (nowtime == last_gen_order_time_) { + sub_orderid_++; + if (sub_orderid_ >= 10000) { + while (nowtime <= last_gen_order_time_) { + ::usleep(100 * 10000); + nowtime = time(NULL); + } + sub_orderid_ = 1; + } + } else { + sub_orderid_ = 1; + } + last_gen_order_time_ = nowtime; + + struct tm tm_nowtime = {0}; + struct tm *ptr = localtime_r(&nowtime, &tm_nowtime); + char strtime[80] = {0}; + strftime(strtime, 80, "%y%m%d%H%M%S", ptr); + + sprintf(orderid, "%s%5d", strtime, sub_orderid_); + for (int i = 0; i < a8::arraysize(orderid); i++) { + if (orderid[i] == ' ') { + orderid[i] = '0'; + } + } + } + int price = 0; + Template::RechargeCard *cardtpl = g_configtable->GetRechargeCard(itemid); + if (cardtpl) { + price = cardtpl->price * 10; + } + + std::string strorderid; + strorderid = a8::format("%d_%d_%s", + { + itemid, + price, + std::string(orderid) + } + ); + return strorderid; + #endif +} diff --git a/server/payserver/ordermgr.h b/server/payserver/ordermgr.h new file mode 100644 index 0000000..5ee64b8 --- /dev/null +++ b/server/payserver/ordermgr.h @@ -0,0 +1,135 @@ +#pragma once + +struct OrderInfo +{ + std::string seqid; + std::string orderid; + std::string accountid; + int itemid; + int price; + int customprice; + int serverid; + std::string roleid; + std::string rolename; + std::string sp_accountid; + std::string channel; + std::string itemname; + std::string itemmemo; + std::string sp_orderid; + time_t lastchecktime; + + OrderInfo() + { + serverid = 0; + itemid = 0; + price = 0; + lastchecktime = 0; + customprice = 0; + } +}; + +struct AddOrderResult +{ + bool isok; + OrderInfo orderinfo; + + AddOrderResult() + { + isok = false; + } +}; + +struct AddOrderNode; +struct PayNotifyNode; +struct ReissueNode; +class OrderMgr : public a8::Singleton +{ + + private: + OrderMgr() {}; + friend class a8::Singleton; + + public: + void Init(); + void UnInit(); + + void Update(); + bool HasTask(); + + int AddOrder(const std::string& seqid, + const std::string& accountid, + const std::string& roleid, + const std::string& rolename, + const std::string& channel, + const std::string& sp_accountid, int serverid, + int productid, int price, + const std::string& sp_orderid); + bool WaitForAddOrderFinished(int seqid, + AddOrderResult& addresult, + int seconds); + + int AddPayNotify( + int pay_type, + const std::string& accountid, + const std::string& roleid, + const std::string& rolename, + int serverid, + int itemid, + const std::string& itemid_str, + const std::string& orderid, + const std::string& sp_orderid, + double fee, + int payresult); + bool WaitForPayNotifyFinished(int seqid, int& result, int seconds); + + int AddReissue(const std::string& orderid); + bool WaitForReissueFinished(int seqid, int& result, int seconds); + + private: + void ProcessOrderMsg(); + void ProcessNotifyMsg(); + void ProcessReissueMsg(); + bool ProcAddOrder(OrderInfo& orderinfo); + int ProcOrderNotify(PayNotifyNode* node); + int ContinueSubscriptions(PayNotifyNode* node); + int ProcIosPayOrderNotify(PayNotifyNode* node); + void ProcReissue(const std::string& orderid); + void UpdatePedingOrders(); + void LoadPedingOrders(); + std::string GenOrderId(int itemid); + long GenSeqId(); + + #if 0 + void _SSMPing(MsgHdr& hdr, const SSMPing& msg); + + void _D2PPayNotifyACK(MsgHdr& hdr, const D2PPayNotifyACK& msg); + #endif + private: + #if 0 + a8::mysql::Connection mysql_conn_; + a8::mysql::Query query_; + #endif + a8::tick_t last_ping_db_tick_ = 0; + + std::mutex *add_order_mutex_ = nullptr; + AddOrderNode *top_node_, *bot_node_, *work_node_; + + std::mutex *pay_notify_mutex_; + PayNotifyNode *pay_notify_top_node_, *pay_notify_bot_node_, *pay_notify_work_node_; + + std::mutex *reissue_mutex_; + ReissueNode *reissue_top_node_, *reissue_bot_node_, *reissue_work_node_; + + int last_gen_order_time_; + int sub_orderid_; + + std::mutex *seq_mutex_; + volatile int current_seqid_; + std::mutex *add_order_result_mutex_; + std::map add_order_results_; + + std::mutex *pay_notify_result_mutex_; + std::map pay_notify_results_; + + std::map peding_orders_; +};