// D:\GitProject\etradeclient\central_clearing_system\ETradeClient\mfc_ui\pay_dlg.cpp : 实现文件 // #include "stdafx.h" #include "ETradeClient.h" #include "D:\GitProject\etradeclient\central_clearing_system\ETradeClient\mfc_ui\pay_dlg.h" #include "afxdialogex.h" #include "etradeclient/hardware/hardware_cmd.h" #include "etradeclient/boost_patch/property_tree/json_parser.hpp" #include "ETradeClient/utility/win_msg_define.h" #include "ETradeClient/utility/logging.h" #include "etradeclient/utility/url_config.h" #include "etradeclient/utility/application_config.h" #include "etradeclient/browser/session.h" #include "ETradeClient/utility/string_converter.h" #include "ETradeClient/utility/win_msg_define.h" #include <vector> #include "pay_dlg.h" #include "etradeclient/hardware/hardware_cmd.h" #include "ETradeClient/utility/logging.h" #include <sstream> #include "LoginDialog.h" #include "place_order_dlg.h" // PayDlg 对话框 IMPLEMENT_DYNAMIC(PayDlg, CDialogEx) PayDlg::PayDlg(long statement_id, CString total_money, int card_type, CWnd* pParent /*=NULL*/) : CDialogEx(PayDlg::IDD, pParent) { statement_id_ = statement_id; total_money_ = total_money; card_type_ = card_type; } PayDlg::~PayDlg() { } void PayDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_PAY_STATIC_TOTAL_MONEY, total_money_static_); DDX_Control(pDX, IDC_PAY_STATIC_REAL_MONEY, real_money_static_); DDX_Control(pDX, IDC_PAY_STATIC_PASSWORD, password_static_); DDX_Control(pDX, IDC_PAY_EDIT_PASSWORD, password_edit_); DDX_Control(pDX, IDC_PAY_BUTTON_PAY, pay_button_); DDX_Control(pDX, IDC_PAY_BUTTON_CLOSE, close_button_); DDX_Control(pDX, IDC_PAY_BUTTON_PASSWORD, password_button_); DDX_Control(pDX, IDC_STATIC_ERROR_MSG, error_msg_static_); } BEGIN_MESSAGE_MAP(PayDlg, CDialogEx) ON_BN_CLICKED(IDC_PAY_BUTTON_CLOSE, &PayDlg::OnBnClickedPayButtonClose) ON_BN_CLICKED(IDC_PAY_BUTTON_PAY, &PayDlg::OnBnClickedPayButtonPay) ON_WM_CTLCOLOR() ON_BN_CLICKED(IDC_PAY_BUTTON_PASSWORD, &PayDlg::OnBnClickedPayButtonPassword) ON_COMMAND(ID_ACCELERATOR_A, &PayDlg::OnBnClickedPayButtonPassword) ON_COMMAND(ID_ACCELERATOR_F, &PayDlg::OnBnClickedPayButtonPay) ON_COMMAND(ID_ACCELERATOR_X, &PayDlg::OnBnClickedPayButtonClose) ON_COMMAND(ID_ACCELERATOR_ENTER, &PayDlg::OnBnClickedEnter) ON_MESSAGE(WM_CEF_SESSION_EXPIRED, &PayDlg::OnSessionExpired) END_MESSAGE_MAP() // PayDlg 消息处理程序 BOOL PayDlg::OnInitDialog() { CDialogEx::OnInitDialog(); SetCtrlPos(); real_money_static_.SetWindowText(total_money_); if (card_type_ == 30) { password_static_.ShowWindow(SW_HIDE); password_edit_.ShowWindow(SW_HIDE); password_button_.ShowWindow(SW_HIDE); pay_button_.SetFocus(); } else { password_static_.ShowWindow(SW_SHOW); password_edit_.ShowWindow(SW_SHOW); password_button_.ShowWindow(SW_SHOW); password_button_.SetFocus(); } acce_ = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR_PAY)); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void PayDlg::SetCtrlPos() { const int StaticWidth = 80, StaticHeigth = 35; const int EditWidth = 140, EditHeigth = 35; const int EditWidthShort = 70, StaticWidthShort = 70; const int ButtonWidth = 120, ButtonHeight = 40; CRect ctrl_rect; ctrl_rect.top = 30 + 10; ctrl_rect.bottom = ctrl_rect.top + StaticHeigth; ctrl_rect.left = 30; ctrl_rect.right = ctrl_rect.left + StaticWidth; total_money_static_.MoveWindow(&ctrl_rect); CRect dlg_rect; GetClientRect(&dlg_rect); ctrl_rect.left = ctrl_rect.right; ctrl_rect.right = dlg_rect.right - 2; real_money_static_.MoveWindow(&ctrl_rect); ctrl_rect.top = ctrl_rect.bottom + 30; ctrl_rect.bottom = ctrl_rect.top + StaticHeigth; ctrl_rect.left = 30; ctrl_rect.right = ctrl_rect.left + StaticWidth; password_static_.MoveWindow(ctrl_rect); ctrl_rect.left = ctrl_rect.right; ctrl_rect.right += EditWidth; password_edit_.MoveWindow(&ctrl_rect); ctrl_rect.left = ctrl_rect.right + 10; ctrl_rect.right += ButtonWidth; password_button_.MoveWindow(&ctrl_rect); ctrl_rect.top = ctrl_rect.bottom + 10; ctrl_rect.bottom = ctrl_rect.top + StaticHeigth; ctrl_rect.left = 30; ctrl_rect.right = dlg_rect.right - 30; error_msg_static_.MoveWindow(&ctrl_rect); ctrl_rect.bottom = dlg_rect.bottom - 20; ctrl_rect.top = ctrl_rect.bottom - ButtonHeight; ctrl_rect.right = dlg_rect.right - 100; ctrl_rect.left = ctrl_rect.right - ButtonWidth; close_button_.MoveWindow(&ctrl_rect); ctrl_rect.right = ctrl_rect.left - 100; ctrl_rect.left = ctrl_rect.right - ButtonWidth; pay_button_.MoveWindow(ctrl_rect); CRect rect; password_edit_.GetClientRect(&rect); OffsetRect(&rect, 0, 10); password_edit_.SendMessage(EM_SETRECT, 0, (LPARAM)&rect); password_edit_.EnableWindow(FALSE); } void PayDlg::OnBnClickedPayButtonClose() { CDialogEx::OnCancel(); } #include "etradeclient/hardware/hardware_cmd.h" #include "etradeclient/boost_patch/property_tree/json_parser.hpp" #include "ETradeClient/utility/logging.h" void PayDlg::OnBnClickedPayButtonPay() { LOG_TRACE(L"支付订单"); CString error_msg; std::string statement_data; do { CString pass_word; password_edit_.GetWindowText(pass_word); if (card_type_ != 30) { if (pass_word.IsEmpty() || pass_word.GetLength() < 6) { SetErrorMsg(L"错误提示:密码为空或密码长度不足!"); break; } } const uint32_t kHTTPOK = 200; WinHttp win_http; auto& url_cfg = URLConfig::Instance(); win_http.ConnectHost(url_cfg.Host(), url_cfg.Port(), url_cfg.IsHttps()); std::string url = url_cfg.GetFinishStatementPath(); auto& request = win_http.OpenRequest(WinHttp::Method::JSONPOST, url); std::ostringstream os; os << statement_id_; std::string statement_id_str; std::istringstream is(os.str()); is >> statement_id_str; std::string post_data = "{\"statementId\":" + statement_id_str + ",\"password\":\"" + wstr_2_str(pass_word) + "\"}"; request.SetPostData(post_data); if (url_cfg.IsHttps()) { auto& app_cfg = ApplicationConfig::Instance(); request.SetClientCertificate(app_cfg.ClientCertStore(), app_cfg.ClientCertSubject()); } request.SetCookies(Session::Instance().Cookies()); request.Send(); uint32_t status_code = request.GetResponseStatus(); if (kHTTPOK != status_code) { std::string err_msg = "网络请求错误! 错误码: " + std::to_string(status_code); LOG_ERROR(CString(err_msg.c_str()).GetBuffer()); error_msg = err_msg.c_str(); break; } std::string response_header = request.ReadResponseHeader(); std::string response_body = request.ReadResponseBody(); if (response_body.empty()) { LOG_ERROR(L"获取服务器响应数据失败,请确保网络连接正常!"); error_msg = CString(L"获取服务器响应数据失败,请确保网络连接正常!"); break; } namespace PT = boost::property_tree; bool card_res = false; try //Parse the configuration file { int status_index = response_header.find("sessionStatus"); if (std::string::npos == status_index) { LOG_ERROR(L"解析服务器返回的登录结果信息时出错!请确认返回数据不为空,返回的数据格式为正确的Json格式!"); error_msg = CString(L"解析服务器返回的登录结果信息时出错!请确认返回数据不为空,返回的数据格式为正确的Json格式!"); break; } std::string status = response_header.substr(status_index + 15, 1); if (status.compare("0") == 0) { SendMessage(WM_CEF_SESSION_EXPIRED); break; } PT::ptree ptree; std::stringstream ss; ss << response_body; PT::read_json(ss, ptree); if (ptree.get<long>("code") == 0) { PT::ptree data_child = ptree.get_child("data"); std::ostringstream os; PT::write_json(os, data_child); CString data = str_2_wstr(std::string(os.str())).c_str(); statement_data = CT2A(data); } else { error_msg = str_2_wstr(ptree.get<std::string>("message")).c_str(); break; } } catch (...) { LOG_ERROR(L"解析服务器返回的登录结果信息时出错!请确认返回数据不为空,返回的数据格式为正确的Json格式!"); error_msg = CString(L"解析服务器返回的登录结果信息时出错!请确认返回数据不为空,返回的数据格式为正确的Json格式!"); break; } } while (0); if (!error_msg.IsEmpty()) { SetErrorMsg(error_msg); } else if (!statement_data.empty()) { auto printer_device = StylusPrinterCmd(); HardwareCmd::Reply reply = printer_device.Execute(statement_data); CDialogEx::OnCancel(); } } void PayDlg::SetErrorMsg(CString error) { error_msg_static_.SetWindowTextW(error); } HBRUSH PayDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); if (nCtlColor == CTLCOLOR_STATIC) { if (IDC_STATIC_ERROR_MSG == pWnd->GetDlgCtrlID()) { pDC->SetTextColor(RGB(200, 0, 0)); } } return hbr; } void PayDlg::OnBnClickedPayButtonPassword() { password_edit_.SetWindowTextW(L""); auto pin_pad = ReadPINPadCmd(); HardwareCmd::Reply reply = pin_pad.Execute(""); CString error_msg; do { if (reply.error_code.compare("") != 0) { if (reply.error_code.compare("100") == 0) { error_msg = L"连接密码键盘失败"; } else if (reply.error_code.compare("101") == 0) { error_msg = L"用户密码输入超时"; } else if (reply.error_code.compare("102") == 0) { error_msg = L"用户取消密码输入"; } else if (reply.error_code.compare("103") == 0) { error_msg = L"读取密码失败"; } else { error_msg = L"读卡失败"; } std::wstring log = L"支付时输入密码错误,错误码:" + str_2_wstr(reply.error_code); LOG_ERROR(log); break; } boost::property_tree::ptree password_child = reply.data.get_child("password"); std::string password = password_child.data(); password_edit_.SetWindowText(CString(password.c_str())); } while (0); if (!error_msg.IsEmpty()) { SetErrorMsg(error_msg); password_edit_.SetWindowTextW(L""); } else { SetErrorMsg(CString(L"")); } } BOOL PayDlg::PreTranslateMessage(MSG* pMsg) { if (WM_KEYFIRST <= pMsg->message&&pMsg->message <= WM_KEYLAST) { if (acce_ && ::TranslateAccelerator(m_hWnd, acce_, pMsg)) return TRUE; } return CDialogEx::PreTranslateMessage(pMsg); } LRESULT PayDlg::OnSessionExpired(WPARAM wParam, LPARAM lParam) { if (!CLoginDialog(L"当前连接已过期,请重新登录!", this).Launch()) { AfxGetMainWnd()->PostMessage(WM_CLOSE); return 0; } Session::Instance().OnValid(); // If login succeeded, recover the session state to be "not expired". return 0; } void PayDlg::OnBnClickedEnter() { int item_id = GetFocus()->GetDlgCtrlID(); switch (item_id) { case IDC_PAY_BUTTON_PASSWORD: { OnBnClickedPayButtonPassword(); CString error; error_msg_static_.GetWindowText(error); if (error.IsEmpty()) { pay_button_.SetFocus(); } else { password_button_.SetFocus(); } break; } case IDC_PAY_BUTTON_PAY: { OnBnClickedPayButtonPay(); break; } case IDC_PAY_BUTTON_CLOSE: { OnBnClickedPayButtonClose(); break; } } }