#include "../pch/pch.h" #include "CZidingyiShoukuanWnd.h" #include "CMessageboxWnd.h" #include "../helper/CSpeech.h" #include "../helper/MD5.h" #define WM_TIMER_WND_CLOSE 200001 void CZidingyiShoukuanWnd::Init() { //::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); } void CZidingyiShoukuanWnd::Notify(TNotifyUI& msg) { if (msg.sType == _T("click")) { if (msg.pSender->GetName() == _T("closebtn")) { StartClose(); } else if (msg.pSender->GetName() == _T("shoukuanBtn")) { StartShoukuan(); } } } LRESULT CZidingyiShoukuanWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { LONG styleValue = ::GetWindowLong(*this, GWL_STYLE); styleValue &= ~WS_CAPTION; ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); // 把自己的窗口句柄与窗口绘制管理器挂接在一起 m_pm.Init(m_hWnd); m_pm.AddPreMessageFilter(this); CDialogBuilder builder; CControlUI* pRoot = builder.Create(_T("zidingyi_shoukuan_wnd.xml"), (UINT)0, NULL, &m_pm); ASSERT(pRoot && "Failed to parse XML"); // 把这些控件绘制到本窗口上 m_pm.AttachDialog(pRoot); // 把自己加入到CPaintManagerUI的m_aNotifiers数组中,用于处理Notify函数 m_pm.AddNotifier(this); Init(); return 0; } LRESULT CZidingyiShoukuanWnd::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { //销毁定时器 KillTimer(m_hWnd, WM_TIMER_WND_CLOSE); bHandled = FALSE; return 0; } /* *这个是窗口被销毁的时候调用的 **/ LRESULT CZidingyiShoukuanWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT CZidingyiShoukuanWnd::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if (::IsIconic(*this)) { bHandled = FALSE; } return (wParam == 0) ? TRUE : FALSE; } LRESULT CZidingyiShoukuanWnd::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return 0; } LRESULT CZidingyiShoukuanWnd::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { //自定义支付暂时不需要 //UpdateFocus(); return 0; } LRESULT CZidingyiShoukuanWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); ::ScreenToClient(*this, &pt); RECT rcClient; ::GetClientRect(*this, &rcClient); RECT rcCaption = m_pm.GetCaptionRect(); if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \ && pt.y >= rcCaption.top && pt.y < rcCaption.bottom) { CControlUI* pControl = static_cast(m_pm.FindControl(pt)); if (pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0) { return HTCAPTION; } } return HTCLIENT; } LRESULT CZidingyiShoukuanWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { SIZE szRoundCorner = m_pm.GetRoundCorner(); if (!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)) { CDuiRect rcWnd; ::GetWindowRect(*this, &rcWnd); rcWnd.Offset(-rcWnd.left, -rcWnd.top); rcWnd.right++; rcWnd.bottom++; HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy); ::SetWindowRgn(*this, hRgn, TRUE); ::DeleteObject(hRgn); } bHandled = FALSE; return 0; } LRESULT CZidingyiShoukuanWnd::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = TRUE; return 0; } LRESULT CZidingyiShoukuanWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if (wParam != WM_TIMER_WND_CLOSE) { bHandled = FALSE; return 0; } if (m_shoukuan_status == 0 || m_shoukuan_status == 1) { } else if (m_shoukuan_status == 2) { } else if (m_shoukuan_status == 3) { m_timer_now--; if (m_timer_now > 0) { CLabelUI* attention = static_cast(m_pm.FindControl(_T("shouyin_pay_success_attention"))); std::wstring ws_attention = L"按任意键关闭窗口," + std::to_wstring(m_timer_now) + L" 秒后自动关闭"; attention->SetText(ws_attention.c_str()); } else { Close(IDOK); } } else if (m_shoukuan_status == 4) { m_timer_now--; if (m_timer_now > 0) { CLabelUI* pFailMessage = static_cast(m_pm.FindControl(_T("shouyin_pay_fail_attention"))); std::wstring ws_fail_message = L"失败信息:" + m_fail_message + L",按任意键关闭窗口,"; std::wstring ws_attention = ws_fail_message + std::to_wstring(m_timer_now) + L" 秒后自动关闭"; pFailMessage->SetText(ws_attention.c_str()); } else { Close(IDCANCEL); } } bHandled = TRUE; return 0; } LRESULT CZidingyiShoukuanWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = 0; BOOL bHandled = TRUE; switch (uMsg) { case WM_CREATE: lRes = OnCreate(uMsg, wParam, lParam, bHandled); break; case WM_CLOSE: lRes = OnClose(uMsg, wParam, lParam, bHandled); break; case WM_DESTROY: lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break; case WM_NCACTIVATE: lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break; case WM_NCCALCSIZE: lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break; case WM_NCPAINT: lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break; case WM_NCHITTEST: lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break; case WM_SIZE: lRes = OnSize(uMsg, wParam, lParam, bHandled); break; case WM_MOUSEHOVER: lRes = OnMouseMove(uMsg, wParam, lParam, bHandled); break; case WM_SHOUKUAN_STATUS_NEEDPASSWORD: lRes = OnShoukuanNeedPassword(uMsg, wParam, lParam, bHandled); break; case WM_SHOUKUAN_STATUS_SUCCESS: lRes = OnShoukuanSuccess(uMsg, wParam, lParam, bHandled); break; case WM_SHOUKUAN_STATUS_FAIL: lRes = OnShoukuanFail(uMsg, wParam, lParam, bHandled); break; case WM_TIMER: lRes = OnTimer(uMsg, wParam, lParam, bHandled); break; default: bHandled = FALSE; } if (bHandled) { return lRes; } if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)) { return lRes; } return CWindowWnd::HandleMessage(uMsg, wParam, lParam); } LRESULT CZidingyiShoukuanWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled) { if (uMsg == WM_KEYDOWN) { if (wParam == VK_RETURN) { if (m_shoukuan_status == 0) { StartShoukuan(); } else if (m_shoukuan_status == 1 || m_shoukuan_status == 2 || m_shoukuan_status == 5) { //正在支付的过程中,这个时候按Enter键,不做任何处理 } else if (m_shoukuan_status == 3) { //已经明确成功或者失败了,那么久直接关闭就可以了 Close(IDOK); } else if (m_shoukuan_status == 4) { //Close(IDCANCEL); StartShoukuan(); } return true; } else if (wParam == VK_ESCAPE) { StartClose(); return true; } if (m_shoukuan_status == 3) { Close(IDOK); return true; } else if (m_shoukuan_status == 4) { //Close(IDCANCEL); return true; } } return false; } void CZidingyiShoukuanWnd::InitMoney(std::wstring value) { CLabelUI* pMoneyLabel = static_cast(m_pm.FindControl(_T("shoukuan_money_show_money"))); if (pMoneyLabel) { pMoneyLabel->SetText(value.c_str()); } m_money = value; } void CZidingyiShoukuanWnd::SetCommonParams(std::map params) { m_commonParams = params; } void CZidingyiShoukuanWnd::UpdateFocus() { } LRESULT CZidingyiShoukuanWnd::OnShoukuanNeedPassword(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { std::wstring path = CSystem::GetProgramDir() + L"\\music\\pay_password.wav"; if (CSetting::GetInstance()->GetParam("shoukuan_setting_yuyinbobao") == "1") { PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC); } CLabelUI* pFukuanEdit = static_cast(m_pm.FindControl(_T("shoukuan_paying_status"))); pFukuanEdit->SetText(L"用户支付中,需要输入密码"); //需要用户输入密码,开始查询状态 std::thread(&CZidingyiShoukuanWnd::HandleShoukuanPassword, this).detach(); bHandled = TRUE; return 0; } LRESULT CZidingyiShoukuanWnd::OnShoukuanSuccess(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { //播放收款成功的金额 if (CSetting::GetInstance()->GetParam("setting_is_new_diannei_voice") == "1") { std::thread(&CZidingyiShoukuanWnd::ReadShoukuanValue, this).detach(); } Close(IDOK); bHandled = TRUE; return 0; /* CVerticalLayoutUI* paying_layout = static_cast(m_pm.FindControl(_T("shoukuan_paying_layout"))); paying_layout->SetVisible(false); CVerticalLayoutUI* pay_success_layout = static_cast(m_pm.FindControl(_T("shoukuan_pay_success_layout"))); pay_success_layout->SetVisible(true); CLabelUI* pMoneyPaySuccess = static_cast(m_pm.FindControl(_T("shoukuan_pay_success_money"))); std::wstring valueInfo = L"成功收款:¥" + m_money; pMoneyPaySuccess->SetText(valueInfo.c_str()); CLabelUI* attention = static_cast(m_pm.FindControl(_T("shouyin_pay_success_attention"))); std::wstring ws_attention = L"按任意键关闭窗口," + to_wstring(m_timer_now) + L" 秒后自动关闭"; attention->SetText(ws_attention.c_str()); SetTimer(m_hWnd, WM_TIMER_WND_CLOSE, 1000, NULL); SetFocus(m_hWnd); bHandled = TRUE; return 0; */ } LRESULT CZidingyiShoukuanWnd::OnShoukuanFail(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { std::wstring path = CSystem::GetProgramDir() + L"\\music\\pay_fail.wav"; if (CSetting::GetInstance()->GetParam("setting_is_new_diannei_voice") == "1") { PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC); } CVerticalLayoutUI* paying_layout = static_cast(m_pm.FindControl(_T("shoukuan_paying_layout"))); paying_layout->SetVisible(false); CVerticalLayoutUI* before_pay_layout = static_cast(m_pm.FindControl(_T("shoukuan_before_pay_layout"))); before_pay_layout->SetVisible(true); CLabelUI* pLabel = static_cast(m_pm.FindControl(_T("shoukuanresult"))); pLabel->SetText((L"收款失败:" + m_fail_message).c_str()); pLabel->SetVisible(true); SetFocus(m_hWnd); bHandled = TRUE; return 0; } void CZidingyiShoukuanWnd::StartShoukuan() { CLabelUI* pLabel = static_cast(m_pm.FindControl(_T("shoukuanresult"))); //检查收款金额 if (m_money == L"") { pLabel->SetText(L"收款金额不能为空,请重新输入!"); pLabel->SetVisible(true); return; } if (m_money == L"0.00") { pLabel->SetText(L"收款金额不能为 0 元,请重新输入!"); pLabel->SetVisible(true); return; } double money_value = atof(CLewaimaiString::UnicodeToUTF8(m_money).c_str()); if (!money_value || money_value < 0.01) { pLabel->SetText(L"收款金额错误,请重新输入!"); pLabel->SetVisible(true); return; } if (money_value > 50000) { pLabel->SetText(L"单笔收款金额不能大于5万,请重新输入!"); pLabel->SetVisible(true); return; } //全部验证通过,就可以开始修改状态了 m_shoukuan_status = 1; //不加这个的话,edit按回车之后样式有问题 SetFocus(m_hWnd); CVerticalLayoutUI* before_pay_layout = static_cast(m_pm.FindControl(_T("shoukuan_before_pay_layout"))); before_pay_layout->SetVisible(false); CVerticalLayoutUI* paying_layout = static_cast(m_pm.FindControl(_T("shoukuan_paying_layout"))); paying_layout->SetVisible(true); CLabelUI* pMoneyPaying = static_cast(m_pm.FindControl(_T("shoukuan_paying_money"))); std::wstring valueInfo = L"付款金额:¥" + m_money; pMoneyPaying->SetText(valueInfo.c_str()); //开启一个线程,开始处理登录 std::thread(&CZidingyiShoukuanWnd::HandleShoukuan, this).detach(); } void CZidingyiShoukuanWnd::HandleShoukuan() { //生成随机的order_no m_commonParams["zhifu_type"] = std::to_string(5); m_commonParams["zhifu_code"] = ""; m_commonParams["zidingyi_pay_id"] = m_zidingyi_pay_id; std::string response; std::string url; if (m_nType == 1) { url = "/diancan/sendorder"; } else if (m_nType == 2) { url = "/dinnercash/pay"; } else if (m_nType == 4) { url = "/shouyin/sendorder"; } bool ret = CZhipuziHttpClient::GetInstance()->Request(url.c_str(), m_commonParams, response); if (ret == false) { m_shoukuan_status = 4; m_fail_message = L"请求服务器失败,请检查网络设置!"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Document document; document.Parse(response.c_str()); if (document.HasParseError()) { LOG_INFO("parse response error!"); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } if (!document.HasMember("errcode") || !document.HasMember("errmsg")) { LOG_INFO("json error!"); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Value& v_errcode = document["errcode"]; int errcode = v_errcode.GetInt(); if (errcode != 0) { LOG_INFO("response failed! message:" << document["errmsg"].GetString()); m_shoukuan_status = 4; std::string errmsg = document["errmsg"].GetString(); m_fail_message = CLewaimaiString::UTF8ToUnicode(errmsg); PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } if (!document.HasMember("data")) { LOG_INFO("json error!"); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Value& data = document["data"]; rapidjson::Value& status = data["status"]; std::string s_status = status.GetString(); if (s_status == "success") { //支付成功 m_shoukuan_status = 3; if (m_nType == 1) { //快餐才有取餐号 m_take_food_code = data["take_food_code"].GetString(); Value& stock = data["stock"]; m_kucun_string = CLewaimaiJson::JsonToString(stock); m_show_trade_no = data["show_trade_no"].GetString(); } else if (m_nType == 2) { Value& stock = data["stock"]; m_kucun_string = CLewaimaiJson::JsonToString(stock); m_show_trade_no = data["show_trade_no"].GetString(); } else if (m_nType == 4) { m_show_trade_no = data["trade_no"].GetString(); } PostMessage(WM_SHOUKUAN_STATUS_SUCCESS, 0, 0); } else if (s_status == "fail") { //支付失败 m_shoukuan_status = 4; m_fail_message = CLewaimaiString::UTF8ToUnicode(data["message"].GetString()); PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); } else if (s_status == "password") { m_shoukuan_status = 2; //需要查询支付状态 PostMessage(WM_SHOUKUAN_STATUS_NEEDPASSWORD, 0, 0); } else { m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); } } void CZidingyiShoukuanWnd::HandleShoukuanPassword() { std::map params; params["trade_no"] = ""; while (m_shoukuan_status == 2) { std::string response; std::string url; if (m_nType == 1) { url = "/diancan/queryorderstatus"; } else if (m_nType == 2) { url = "/dinnercash/queryorderstatus"; } else if (m_nType == 4) { url = "/shouyin/queryorderstatus"; } bool ret = CZhipuziHttpClient::GetInstance()->Request(url.c_str(), params, response); if (ret == false) { m_shoukuan_status = 4; m_fail_message = L"请求服务器失败,请检查网络设置!"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Document document; document.Parse(response.c_str()); if (document.HasParseError()) { LOG_INFO("parse response error!"); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } if (!document.HasMember("errcode") || !document.HasMember("errmsg") || !document.HasMember("data")) { LOG_INFO("json error!"); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Value& v_errcode = document["errcode"]; int errcode = v_errcode.GetInt(); if (errcode != 0) { LOG_INFO("response failed! message:" << document["errmsg"].GetString()); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Value& data = document["data"]; rapidjson::Value& status = data["status"]; std::string s_status = status.GetString(); if (s_status == "success") { //支付成功 m_shoukuan_status = 3; Value& stock = data["stock"]; m_kucun_string = CLewaimaiJson::JsonToString(stock); m_show_trade_no = data["show_trade_no"].GetString(); if (m_nType == 1) { //快餐才有取餐号 m_take_food_code = data["take_food_code"].GetString(); } PostMessage(WM_SHOUKUAN_STATUS_SUCCESS, 0, 0); break; } else if (s_status == "closed") { //表示顾客那边出问题,已经失败了 m_shoukuan_status = 4; m_fail_message = L"顾客取消支付,请重新扫码收款"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); break; } else if (s_status == "fail") { //这个只是表示状态未知 Sleep(1000); } else { m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); break; } } } void CZidingyiShoukuanWnd::CancelShoukuanPassword() { m_shoukuan_status = 5; std::thread(&CZidingyiShoukuanWnd::HandleCancelShoukuan, this).detach(); } void CZidingyiShoukuanWnd::HandleCancelShoukuan() { std::map params; params["trade_no"] = ""; std::string response; std::string url; if (m_nType == 1) { url = "/diancan/closeorder"; } else if (m_nType == 2) { url = "/dinnercash/closeorder"; } else if (m_nType == 4) { url = "/shouyin/closeorder"; } bool ret = CZhipuziHttpClient::GetInstance()->Request(url.c_str(), params, response); if (ret == false) { m_shoukuan_status = 4; m_fail_message = L"请求服务器失败,请检查网络设置!"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Document document; document.Parse(response.c_str()); if (document.HasParseError()) { LOG_INFO("parse response error!"); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } if (!document.HasMember("errcode") || !document.HasMember("errmsg") || !document.HasMember("data")) { LOG_INFO("json error!"); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Value& v_errcode = document["errcode"]; int errcode = v_errcode.GetInt(); if (errcode != 0) { LOG_INFO("response failed! message:" << document["errmsg"].GetString()); m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); return; } rapidjson::Value& data = document["data"]; rapidjson::Value& status = data["status"]; std::string s_status = status.GetString(); if (s_status == "success") { //取消成功,订单变为失败状态 m_shoukuan_status = 4; m_fail_message = L"商家取消收款"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); } m_shoukuan_status = 4; m_fail_message = L"服务器错误"; PostMessage(WM_SHOUKUAN_STATUS_FAIL, 0, 0); } void CZidingyiShoukuanWnd::StartClose() { if (m_shoukuan_status == 0) { //还没开始支付,直接退出 Close(IDCANCEL); } else if (m_shoukuan_status == 1 || m_shoukuan_status == 5) { //不能做任何处理 } else if (m_shoukuan_status == 2) { //查询密码的过程中,取消付款 CancelShoukuanPassword(); } else if (m_shoukuan_status == 3) { Sleep(100); Close(IDOK); } else if (m_shoukuan_status == 4) { Sleep(100); Close(IDCANCEL); } } void CZidingyiShoukuanWnd::ReadShoukuanValue() { CSpeech::SpeakNum(1, CLewaimaiString::UnicodeToUTF8(m_money)); } void CZidingyiShoukuanWnd::SetZidingyiName(std::wstring name) { m_zidingyi_name = CLewaimaiString::UnicodeToUTF8(name); CLabelUI* pName = static_cast(m_pm.FindControl(_T("shoukuan_version"))); pName->SetText((name + L"收款").c_str()); CLabelUI* pAttention = static_cast(m_pm.FindControl(_T("shoukuan_attention"))); pAttention->SetText((L"确定使用" + name + L"支付吗?").c_str()); } void CZidingyiShoukuanWnd::SetZidingyiId(std::wstring selfpay_id) { m_zidingyi_pay_id = CLewaimaiString::UnicodeToUTF8(selfpay_id); }