using Aop.Api; using Aop.Api.Request; using Aop.Api.Response; using NLog; using POSV.Bill; using POSV.Card; using POSV.Entity; using POSV.Entity.Pormotion; using POSV.MessageEvent; using POSV.PayApi; using POSV.Payment.Saobei; using POSV.Payment.Saobei.Parameter; using POSV.Payment.Saobei.Result; using POSV.ShoppingCart; using POSV.Utils; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace POSV.Member { public partial class GiftCardSaomaForm : BusinessForm { private static Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// PayStep3初始值 /// private int initValue = 10; /// /// 是否等待用户输入支付密码 /// private int timeout = 60; private string OutTradeNo = null; //倒计时计时器 private System.Windows.Forms.Timer timer = null; private const int TIMER_INTERVAL = 1000; private decimal PayMoney = 0.00M; private string CardNo = null; /// /// 支付渠道 /// private PayChannelEnum _payChannel = PayChannelEnum.原生支付; public GiftCardSaomaForm(string cardNo, decimal payMoney, string outTradeNo) { InitializeComponent(); this.controlBox.Text = "礼品卡销售扫码"; this.controlBox.ShowApplicationVersion = false; this.PayMoney = payMoney; this.CardNo = cardNo; this.OutTradeNo = outTradeNo; //支付结果查询的计时器 this.timer = null; //this.timer = new System.Timers.Timer(TIMER_INTERVAL); //this.timer.Elapsed += OnTimerElapsed; this.timer = new System.Windows.Forms.Timer(); this.timer.Interval = TIMER_INTERVAL; this.timer.Tick += OnTimerTick; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.SetStyle(ControlStyles.Selectable, true); if (this.DesignMode) return; this.Focus(); this.txtPayCode.Multiline = false; this.txtPayCode.Focus(); this.txtPayCode.SelectAll(); this.ActiveControl = this.txtPayCode; } private void OnTimerTick(object sender, EventArgs e) { this.Invoke(new Action(() => { switch (this._payChannel) { case PayChannelEnum.原生支付: { QueryPayChannel_0(); } break; case PayChannelEnum.扫呗支付: { QuerySAOBEIPayResult(); } break; } })); LOGGER.Info("查询支付结果中...."); } /// /// 操作是否验证通过 /// private bool PaymentVerify = false; /// /// 当前的支付方式 /// private PayMode CurrentPayMode = null; public string SAOBEI_QRCodeType { get; private set; } public string SAOBEI_PAYTIME { get; private set; } public string SAOBEI_OrderId { get; private set; } private void OnKeyboardBefore(object sender, BillKeyboardEventArgs e) { this.PaymentVerify = false; this.CurrentPayMode = null; if (this.PayMoney > 0) { //获取扫描码 var payCode = this.txtPayCode.Text.Trim(); if (string.IsNullOrEmpty(payCode)) { ShowMessage(this.lblInfo, "请扫描或输入支付码...", true); this.PaymentVerify = false; } else { this.CurrentPayMode = RechargeSaomaUtils.GetPayMode(payCode).Item3; if (this.CurrentPayMode == null) { ShowMessage(this.lblInfo, "支付码不合法或尚未适配...", true); this.PaymentVerify = false; } else { ShowMessage(this.lblInfo, "扫描" + this.CurrentPayMode.Name + "付款码...", true); this.PaymentVerify = RechargeSaomaUtils.VerifyInputValue(payCode, this.CurrentPayMode).Item1; this._payChannel = RechargeSaomaUtils.VerifyInputValue(payCode, this.CurrentPayMode).Item3; } } } else { ShowMessage(this.lblInfo, "付款金额非法...", true); this.PaymentVerify = false; } } private void QueryWxPayResult() { try { var parameter = this.CurrentPayMode.Body; string appId = parameter.ContainsKey("appid") ? parameter["appid"].ToString() : ""; string mchId = parameter.ContainsKey("mchid") ? parameter["mchid"].ToString() : ""; string subMchId = parameter.ContainsKey("submchid") ? parameter["submchid"].ToString() : ""; string key = parameter.ContainsKey("appsecret") ? parameter["appsecret"].ToString() : ""; string nonceStr = "x86" + ObjectId.GenerateNewStringId(); var dataInfo = new WxPayV3OrderQueryRequestData(appId, "", mchId, subMchId, "", nonceStr, OutTradeNo, key); var result = WxPayV3.OrderQuery(dataInfo); if ("SUCCESS".Equals(result.return_code)) { if ("SUCCESS".Equals(result.result_code)) { var tradeState = WxPayTradeState.NONE; Enum.TryParse(result.trade_state, out tradeState); switch (tradeState) { case WxPayTradeState.SUCCESS: { //计时器停止 this.timer.Stop(); this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 ShowMessage(this.lblInfo, "微信支付成功", false); //构建微信支付方式 this.AddWxPayType(result); //清理支付码 this.txtPayCode.Text = string.Empty; //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); } break; case WxPayTradeState.USERPAYING: { string message = string.Format("{0}:{1}秒", "请提示用户输入支付密码", --timeout); //MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, message)); ShowMessage(this.lblInfo, message, true); } break; case WxPayTradeState.NOTPAY: case WxPayTradeState.PAYERROR: { //计时器停止 this.timer.Stop(); //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); ShowMessage(this.lblInfo, "密码错误或未输入,请重新扫码", true); } break; default: { string message = string.Format("{0}:{1}秒", result.trade_state_desc, --timeout); ShowMessage(this.lblInfo, message, true); } break; } } else { string message = string.Format("正在确认微信扣款结果:{0}秒,{1}", --timeout, result.err_code_des); ShowMessage(this.lblInfo, message, true); } } else { LOGGER.Warn("查询支付结果网络通信错误:{0}", result.return_msg); ShowMessage(this.lblInfo, result.return_msg, true); } } catch (Exception ex) { LOGGER.Error(ex, "微信支付结果查询发生异常"); } } private void AddWxPayType(OrderQueryResult result) { if (result != null && "SUCCESS".Equals(result.return_code) && "SUCCESS".Equals(result.result_code)) { //计时器停止 this.timer.Stop(); logger.Info("微信支付成功[{0}]......", OutTradeNo); //商户订单号 CardSaomaResult cardSaomaResult = new CardSaomaResult(); cardSaomaResult.Type = 0; cardSaomaResult.PayModeNo = "05"; cardSaomaResult.PayModeName = "微信支付"; cardSaomaResult.OutTradeNo = OutTradeNo; cardSaomaResult.PayMoney = PayMoney; cardSaomaResult.PayChannel = this._payChannel; Tuple saomaResult = new Tuple(true, cardSaomaResult); OnSaomaResultClick?.Invoke(new GiftCardSaomaEventArgs(saomaResult)); //先关闭父窗体 if (this.Owner != null) { this.Owner.Close(); } this.Close(); } } private void QueryAliPayResult() { try { var parameter = this.CurrentPayMode.Body; string appId = parameter.ContainsKey("appid") ? parameter["appid"].ToString() : ""; string privateKey = parameter.ContainsKey("privatekey") ? parameter["privatekey"].ToString() : ""; string appAuthToken = parameter.ContainsKey("appAuthToken") ? parameter["appAuthToken"].ToString() : ""; string storeNo = parameter.ContainsKey("storeNo") ? parameter["storeNo"].ToString() : ""; string signType = parameter.ContainsKey("signType") ? parameter["signType"].ToString() : "RSA"; DefaultAopClient client = null; if ("RSA2".Equals(signType)) { client = new DefaultAopClient(Global.Instance.AliPayServerUrl, appId, privateKey, "json", "utf-8", "RSA2"); } else { client = new DefaultAopClient(Global.Instance.AliPayServerUrl, appId, privateKey, false); } var request = new AlipayTradeQueryRequest(); var content = new Dictionary(); content.Add("out_trade_no", OutTradeNo); request.BizContent = JsonUtils.Serialize(content); AlipayTradeQueryResponse response = client.Execute(request, string.Empty, appAuthToken); switch (response.TradeStatus) { case "TRADE_SUCCESS": { //计时器停止 this.timer.Stop(); this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 ShowMessage(this.lblInfo, "支付宝付款成功", false); //构建支付宝支付方式 this.AddAliPayType(response); //清理支付码 this.txtPayCode.Text = string.Empty; //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); } break; case "WAIT_BUYER_PAY": { ShowMessage(this.lblInfo, "等待买家付款...", false); } break; default: { ShowMessage(this.lblInfo, "等待买家付款...", false); } break; } } catch (Exception ex) { LOGGER.Error(ex, "支付宝结果查询发生异常"); } } private void AddAliPayType(AlipayTradeQueryResponse result) { if (result != null && "TRADE_SUCCESS".Equals(result.TradeStatus)) { //计时器停止 this.timer.Stop(); logger.Info("支付宝支付成功[{0}]......", OutTradeNo); //商户订单号 CardSaomaResult cardSaomaResult = new CardSaomaResult(); cardSaomaResult.Type = 0; cardSaomaResult.PayModeNo = "04"; cardSaomaResult.PayModeName = "支付宝"; cardSaomaResult.OutTradeNo = OutTradeNo; cardSaomaResult.PayMoney = PayMoney; cardSaomaResult.PayChannel = this._payChannel; Tuple saomaResult = new Tuple(true, cardSaomaResult); OnSaomaResultClick?.Invoke(new GiftCardSaomaEventArgs(saomaResult)); //先关闭父窗体 if (this.Owner != null) { this.Owner.Close(); } this.Close(); } } private void OnKeyboardAfter(object sender, BillKeyboardEventArgs e) { switch (e.KeyCode) { case "clear": //如果当前焦点控件是输入框 if (this.ActiveControl is TextBox) { var activeControl = this.ActiveControl as TextBox; activeControl.Text = string.Empty; } break; case "accept": //验证通过 if (this.PaymentVerify && this.CurrentPayMode != null) { //根据支付状态 SavePayTicket(OutTradeNo, this.txtPayCode.Text.Trim()); switch (this._payChannel) { case PayChannelEnum.原生支付: { this.PayChannel_0(); } break; case PayChannelEnum.扫呗支付: { this.PayChannel_SAOBEI(); } break; } } break; case "100": { //如果当前焦点控件是输入框 if (this.ActiveControl is TextBox) { var activeControl = this.ActiveControl as TextBox; activeControl.Text = string.Empty; } InputSimulatorUtils.SendKey(KeyCodes.Map["1"]); InputSimulatorUtils.SendKey(KeyCodes.Map["0"]); InputSimulatorUtils.SendKey(KeyCodes.Map["0"]); } break; case "50": { //如果当前焦点控件是输入框 if (this.ActiveControl is TextBox) { var activeControl = this.ActiveControl as TextBox; activeControl.Text = string.Empty; } InputSimulatorUtils.SendKey(KeyCodes.Map["5"]); InputSimulatorUtils.SendKey(KeyCodes.Map["0"]); } break; case "20": { //如果当前焦点控件是输入框 if (this.ActiveControl is TextBox) { var activeControl = this.ActiveControl as TextBox; activeControl.Text = string.Empty; } InputSimulatorUtils.SendKey(KeyCodes.Map["2"]); InputSimulatorUtils.SendKey(KeyCodes.Map["0"]); } break; case "10": { //如果当前焦点控件是输入框 if (this.ActiveControl is TextBox) { var activeControl = this.ActiveControl as TextBox; activeControl.Text = string.Empty; } InputSimulatorUtils.SendKey(KeyCodes.Map["1"]); InputSimulatorUtils.SendKey(KeyCodes.Map["0"]); } break; default: { InputSimulatorUtils.SendKey(KeyCodes.Map[e.KeyCode]); } break; } } #region 原生支付渠道 /// /// 查询原生支付结果 /// private void QueryPayChannel_0() { //进度条最大值 int maximum = this.PayStep3.Maximum; this.PayStep3.Value = (initValue++); //判断是否超时,如果超时终止计时器,界面反馈信息 if (initValue % this.PayStep3.Maximum == 0) { //计时器停止 this.timer.Stop(); //修改结果颜色 //this.PayStep3.ProgressColors = new Color[] { Color.Red , Color.Red }; //发送结果通知 ShowMessage(this.lblInfo, "查询支付结果超时", true); LOGGER.Warn("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this.OutTradeNo); var dialog = new DialogForm("支付结果", "没有查询到支付结果,系统无法确认本单已经支付", MessageBoxIcon.Warning, MessageBoxButtons.RetryCancel); if (DialogResult.Retry == dialog.ShowDialog()) { LOGGER.Warn("收银员手动选择重新查询一次结果,订单号<{0}>", this.OutTradeNo); ShowMessage(this.lblInfo, "等待确认扣款状态", true); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { LOGGER.Warn("收银员手动放弃结果确认,订单号<{0}>", this.OutTradeNo); //清理支付码 this.txtPayCode.Text = string.Empty; //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); } } else { switch (this.CurrentPayMode.No) { case "04": { QueryAliPayResult(); } break; case "05": { QueryWxPayResult(); } break; } } } /// /// 原生支付 /// private void PayChannel_0() { switch (this.CurrentPayMode.No) { case "04": { var isQuery = AliPayResult(); if (isQuery) { ShowMessage(this.lblInfo, "正在确认扣款状态", true); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { //清理支付码 this.txtPayCode.Text = string.Empty; //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); } } break; case "05": { var isQuery = WxPayResult(); //需要查询支付结果的两种情况:1)支付提示扣款成功;2)支付结果未知 if (isQuery) { ShowMessage(this.lblInfo, "等待确认扣款状态", true); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { //清理支付码 this.txtPayCode.Text = string.Empty; //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); } } break; } } #endregion #region 原生微信支付 /// /// 微信支付,返回是否确认查询结果 /// /// private bool WxPayResult() { bool isQuery = false; try { string nonceStr = "x86" + ObjectId.GenerateNewStringId(); //门店编号 string deviceInfo = Global.Instance.Authc.StoreNo; //门店名称 string body = Global.Instance.Authc.StoreName + "-店内礼品卡销售"; //商品详情 string detail = ""; //附加数据 string attach = ""; //商户订单号 //订单总金额,单位为分,只能为整数 string totalFee = Convert.ToInt32(PayMoney * 100).ToString(); //货币类型 string feeType = "CNY"; //终端IP string spbillCreateIp = DeviceUtils.Instance.IPAddress; //订单优惠标记 string goodsTag = ""; //扫码支付授权码,设备读取用户微信中的条码或者二维码信息(注:用户刷卡条形码规则:18位纯数字,以10、11、12、13、14、15开头) string authCode = this.txtPayCode.Text.Trim(); //禁止扫码框输入 this.txtPayCode.Enabled = false; //发起微信扣款请求 ShowMessage(this.lblInfo, "发起微信扣款请求", true); this.PayStep2.Value = this.PayStep2.Maximum / 3; var parameter = this.CurrentPayMode.Body; //微信支付的配置参数 string appId = parameter["appid"].ToString(); string mchId = parameter["mchid"].ToString(); string subMchId = parameter["submchid"].ToString(); string key = parameter["appsecret"].ToString(); LOGGER.Info("订单[{0}]发起微信扣款[{1}]分", this.OutTradeNo, totalFee); var dataInfo = new WxPayV3MicroPayRequestData(appId, mchId, subMchId, key, nonceStr, deviceInfo, body, detail, attach, this.OutTradeNo, totalFee, feeType, spbillCreateIp, goodsTag, authCode); //扫码成功,提交被扫支付 MicropayResult result = WxPayV3.MicroPay(dataInfo); LOGGER.Info("订单[{0}]微信扣款返回结果:{1}", this.OutTradeNo, JsonUtils.Serialize(result)); if ("SUCCESS".Equals(result.return_code)) { if ("SUCCESS".Equals(result.result_code)) { this.PayStep2.Value = this.PayStep2.Maximum; //需要直接确认结果,无需等待输入密码 isQuery = true; } else { LOGGER.Warn("订单[{0}]微信支付[{1}]分发生错误,错误代码:{2},错误描述:{3}", this.OutTradeNo, totalFee, result.err_code, result.err_code_des); //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(new Exception("微信支付错误" + JsonUtils.Serialize(result))); //})); //解析错误代码 var errCode = WxPayErrCode.NONE; Enum.TryParse(result.err_code, out errCode); switch (errCode) { //支付结果未知,请立即调用被扫订单结果查询API,查询当前订单状态,并根据订单的状态决定下一步的操作 case WxPayErrCode.SYSTEMERROR: { this.PayStep2.Value = this.PayStep2.Maximum; ShowMessage(this.lblInfo, "网络超时,正在查询支付状态,请稍候...", true); isQuery = true; } break; case WxPayErrCode.BANKERROR: { this.PayStep2.Value = this.PayStep2.Maximum; ShowMessage(this.lblInfo, "银行端超时,正在查询支付状态,请稍候...", true); isQuery = true; } break; case WxPayErrCode.USERPAYING: { this.PayStep2.Value = this.PayStep2.Maximum; ShowMessage(this.lblInfo, "等待用户输入密码,请稍候...", true); //需等待输入密码,需要确认结果 isQuery = true; } break; case WxPayErrCode.ORDERPAID: { this.PayStep2.Value = this.PayStep2.Minimum; ShowMessage(this.lblInfo, "订单号重复支付,请使用新订单", true); isQuery = false; } break; case WxPayErrCode.AUTHCODEEXPIRE: { this.PayStep2.Value = this.PayStep2.Minimum; ShowMessage(this.lblInfo, "二维码过期,请用户在微信上刷新后再试", true); isQuery = false; } break; case WxPayErrCode.NOTENOUGH: { this.PayStep2.Value = this.PayStep2.Minimum; ShowMessage(this.lblInfo, "用户余额不足,请用户换卡支付", true); isQuery = false; } break; case WxPayErrCode.NOTSUPORTCARD: { this.PayStep2.Value = this.PayStep2.Minimum; ShowMessage(this.lblInfo, "不支持当前支付,请用户换卡或绑新卡支付", true); isQuery = false; } break; case WxPayErrCode.INVALID_REQUEST: { this.PayStep2.Value = this.PayStep2.Minimum; if (result.err_code_des == "201 商户订单号重复") { ShowMessage(this.lblInfo, "商户订单号重复,请消单后重新下单", true); } else { ShowMessage(this.lblInfo, result.err_code_des, true); } isQuery = false; } break; default: { this.PayStep2.Value = this.PayStep2.Minimum; ShowMessage(this.lblInfo, result.err_code_des, true); isQuery = false; } break; } } } else { LOGGER.Warn("订单[{0}]微信支付[{1}]分,微信支付网络通信错误:{0}", this.OutTradeNo, totalFee, result.return_msg); ShowMessage(this.lblInfo, result.return_msg, true); //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(new Exception("微信支付错误2" + JsonUtils.Serialize(result))); //})); } } catch (Exception ex) { ShowMessage(this.lblInfo, "微信支付发生异常,开始确认支付结果", true); LOGGER.Error(ex, "微信支付发生异常"); //发起支付发生异常,为了避免客户已经收到请求,开始支付,这里进行补救查询 isQuery = true; //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(ex); //})); } return isQuery; } #endregion #region 原生支付宝 /// /// 支付宝付款,返回是否确认查询结果 /// /// private bool AliPayResult() { bool isQuery = false; try { var parameter = this.CurrentPayMode.Body; string appId = parameter.ContainsKey("appid") ? parameter["appid"].ToString() : ""; string privateKey = parameter.ContainsKey("privatekey") ? parameter["privatekey"].ToString() : ""; string appAuthToken = parameter.ContainsKey("appAuthToken") ? parameter["appAuthToken"].ToString() : ""; string storeNo = parameter.ContainsKey("storeNo") ? parameter["storeNo"].ToString() : ""; string pid = parameter.ContainsKey("pid") ? parameter["pid"].ToString() : ""; string signType = parameter.ContainsKey("signType") ? parameter["signType"].ToString() : "RSA"; DefaultAopClient client = null; if ("RSA2".Equals(signType)) { client = new DefaultAopClient(Global.Instance.AliPayServerUrl, appId, privateKey, "json", "utf-8", "RSA2"); } else { client = new DefaultAopClient(Global.Instance.AliPayServerUrl, appId, privateKey, false); } var request = new AlipayTradePayRequest(); var content = new Dictionary(); //商户订单号 string outTradeNo = this.OutTradeNo; content.Add("out_trade_no", outTradeNo); content.Add("scene", "bar_code");// 支付场景-条码支付 content.Add("auth_code", this.txtPayCode.Text.Trim());// 支付授权码 content.Add("subject", Global.Instance.Worker.StoreInfo.Name + "-店内礼品卡销售");// 订单标题 content.Add("body", Global.Instance.Authc.StoreNo + Global.Instance.Worker.StoreInfo.Name + "-店内礼品卡销售"); content.Add("total_amount", PayMoney); content.Add("operator_id", Global.Instance.Worker.No); content.Add("store_id", Global.Instance.Authc.StoreNo); content.Add("terminal_id", Global.Instance.Authc.PosNo); if (!string.IsNullOrEmpty(appAuthToken)) { var extend = new Dictionary(); extend.Add("sys_service_provider_id", pid); content.Add("extend_params", extend); } var goods = new List>(); var details = new Dictionary(); details.Add("goods_id", ObjectId.GenerateNewStringId()); details.Add("goods_name", "门店充值"); details.Add("quantity", "1"); details.Add("price", PayMoney); details.Add("goods_category", ObjectId.GenerateNewStringId()); details.Add("body", "门店充值"); details.Add("show_url", ""); goods.Add(details); content.Add("goods_detail", goods); request.BizContent = JsonUtils.Serialize(content); LOGGER.Info("订单[{0}]发起支付宝(原生)支付:<{1}>", outTradeNo, JsonUtils.Serialize(request)); AlipayTradePayResponse response = client.Execute(request, string.Empty, appAuthToken); LOGGER.Info("订单[{0}]收到支付宝(原生)支付结果:<{1}>", outTradeNo, JsonUtils.Serialize(response)); if (!response.IsError && (response.Code == "10000" || response.Code == "10003" || response.Code == "20000")) { isQuery = true; ShowMessage(this.lblInfo, "等待确认扣款结果...", true); } else { isQuery = false; ShowMessage(this.lblInfo, string.Format("{ 0}<{ 1}> ", response.SubMsg, response.SubCode), true); //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(new Exception("订单["+ outTradeNo + "]支付宝(原生)支付失败,返回结果:"+ JsonUtils.Serialize(response))); //})); } } catch (Exception ex) { LOGGER.Error(ex, "支付宝付款发生异常"); if (ex.Message.Contains("私钥格式错误")) { ShowMessage(this.lblInfo, "支付宝私钥配置错误...", true); isQuery = false; } else { ShowMessage(this.lblInfo, "支付宝付款发生异常...", true); isQuery = true; } //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(ex); //})); } return isQuery; } #endregion #region 扫呗支付渠道 private void PayChannel_SAOBEI() { var isQuery = SAOBEIPayResult(); if (isQuery) { ShowMessage(this.lblInfo, "正在确认扣款状态", true); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { //清理支付码 this.txtPayCode.Text = string.Empty; //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); } } private bool SAOBEIPayResult() { bool isQuery = false; //商户订单号 string outTradeNo = this.OutTradeNo; var amount = PayMoney; try { var parameter = this.CurrentPayMode.Body; string merchant_no = parameter.ContainsKey("merchant_no") ? parameter["merchant_no"].ToString() : ""; string terminal_id = parameter.ContainsKey("terminal_id") ? parameter["terminal_id"].ToString() : ""; string signKey = parameter.ContainsKey("signKey") ? parameter["signKey"].ToString() : ""; string gatewayUrl = parameter.ContainsKey("gatewayUrl") ? parameter["gatewayUrl"].ToString() : ""; SaobeiPaymentParam request = new SaobeiPaymentParam(); request.Terminal_trace = outTradeNo.Replace("_", ""); request.Auth_no = this.txtPayCode.Text.Trim(); request.Total_fee = string.Format("{0}", Convert.ToInt32(amount * 100)); request.Terminal_time = DateTime.Now.ToString("yyyyMMddHHmmss"); this.SAOBEI_PAYTIME = request.Terminal_time; //支付方式 支付宝1、微信2 request.Pay_type = "020"; if (this.CurrentPayMode.No == "05") { request.Pay_type = "010"; } else if (this.CurrentPayMode.No == "07") { request.Pay_type = "110"; } this.SAOBEI_QRCodeType = request.Pay_type; var saobeiPayment = SaobeiUtils.SaobeiPayment(merchant_no, terminal_id, signKey, gatewayUrl, request); if (saobeiPayment.Item1) { SaobeiPaymentResult saobeiPaymentResult = saobeiPayment.Item3; this.SAOBEI_QRCodeType = saobeiPaymentResult.Pay_type; this.SAOBEI_OrderId = saobeiPaymentResult.Out_trade_no; //支付结果需要查询 isQuery = true; ShowMessage(this.lblInfo, "等待确认扣款结果...", true); } else { this.SAOBEI_QRCodeType = ""; this.SAOBEI_OrderId = ""; isQuery = false; ShowMessage(this.lblInfo, string.Format("{0}", saobeiPayment.Item2), true); } } catch (Exception ex) { LOGGER.Error(ex, "扫呗支付订单[" + outTradeNo + "]金额[" + amount + "]发生异常!"); this.SAOBEI_QRCodeType = ""; this.SAOBEI_OrderId = ""; UpdateSaomaTicket(outTradeNo, this.SAOBEI_OrderId, this.SAOBEI_PAYTIME); isQuery = true; ShowMessage(this.lblInfo, "等待确认扣款结果...", true); } return isQuery; } public bool UpdateSaomaTicket(string orderNo, string serialNo, string payTime) { try { lock (Global.Instance.SyncLock) { using (var db = Global.Instance.OpenDataBase) { using (var transaction = db.GetTransaction()) { string sql = "update pos_saoma_pay_ticket set serialNo ='{0}',payTime='{1}' where orderNo = '{2}' and busType = 1 and storeId ='{3}'"; sql = string.Format(sql, serialNo, payTime, orderNo, Global.Instance.BusinessPlanLog.StoreId); db.Execute(sql, null); transaction.Complete(); return false; } } } } catch (Exception ex) { LOGGER.Error(ex); } return true; } private void QueryPayChannel_SAOBEI() { //进度条最大值 int maximum = this.PayStep3.Maximum; this.PayStep3.Value = (initValue++); //判断是否超时,如果超时终止计时器,界面反馈信息 if (initValue % this.PayStep3.Maximum == 0) { //计时器停止 this.timer.Stop(); //修改结果颜色 //this.PayStep3.ProgressColors = new Color[] { Color.Red , Color.Red }; //发送结果通知 ShowMessage(this.lblInfo, "查询支付结果超时", true); LOGGER.Warn("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this.OutTradeNo); var dialog = new DialogForm("支付结果", "没有查询到支付结果,系统无法确认本单已经支付", MessageBoxIcon.Warning, MessageBoxButtons.RetryCancel); if (DialogResult.Retry == dialog.ShowDialog()) { LOGGER.Warn("收银员手动选择重新查询一次结果,订单号<{0}>", this.OutTradeNo); ShowMessage(this.lblInfo, "等待确认扣款状态", true); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { LOGGER.Warn("收银员手动放弃结果确认,订单号<{0}>", this.OutTradeNo); //清理支付码 this.txtPayCode.Text = string.Empty; //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); } } else { this.QuerySAOBEIPayResult(); } } private void QuerySAOBEIPayResult() { try { var parameter = this.CurrentPayMode.Body; string merchant_no = parameter.ContainsKey("merchant_no") ? parameter["merchant_no"].ToString() : ""; string terminal_id = parameter.ContainsKey("terminal_id") ? parameter["terminal_id"].ToString() : ""; string signKey = parameter.ContainsKey("signKey") ? parameter["signKey"].ToString() : ""; string gatewayUrl = parameter.ContainsKey("gatewayUrl") ? parameter["gatewayUrl"].ToString() : ""; //商户订单号 string outTradeNo = this.OutTradeNo; SaobeiQueryParam request = new SaobeiQueryParam(); request.Pay_type = this.SAOBEI_QRCodeType; request.Terminal_trace = outTradeNo.Replace("_", ""); request.Pay_trace = outTradeNo.Replace("_", ""); request.Pay_time = this.SAOBEI_PAYTIME; request.Out_trade_no = this.SAOBEI_OrderId; var saobeiPayment = SaobeiUtils.SaobeiQuery(merchant_no, terminal_id, signKey, gatewayUrl, request); if (saobeiPayment.Item1) { if (saobeiPayment.Item3 != null && "SUCCESS".Equals(saobeiPayment.Item3.Trade_state)) { //计时器停止 this.timer.Stop(); this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 ShowMessage(this.lblInfo, "扫呗支付付款成功", false); //构建支付方式 this.AddSAOBEIPayType(saobeiPayment.Item3); //清理支付码 this.txtPayCode.Text = string.Empty; //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); } else { ShowMessage(this.lblInfo, "查询结果:" + saobeiPayment.Item3.Return_msg, true); } } else { //明确失败,结束查询 //计时器停止 this.timer.Stop(); //重新扫码,恢复初始值 this.PayStep1.Value = 0; this.PayStep2.Value = 0; this.PayStep3.Value = 0; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); ShowMessage(this.lblInfo, saobeiPayment.Item2, true); } } catch (Exception ex) { LOGGER.Error(ex, "扫呗支付付款结果查询发生异常"); } } private void AddSAOBEIPayType(SaobeiQueryResult queryParam) { if (queryParam != null && "SUCCESS".Equals(queryParam.Trade_state)) { //计时器停止 this.timer.Stop(); logger.Info("扫呗支付成功[{0}]......", OutTradeNo); //商户订单号 CardSaomaResult cardSaomaResult = new CardSaomaResult(); cardSaomaResult.Type = 0; cardSaomaResult.PayModeNo = this.CurrentPayMode.No; cardSaomaResult.PayModeName = this.CurrentPayMode.Name; cardSaomaResult.OutTradeNo = OutTradeNo; cardSaomaResult.Out_trade_no = queryParam.Out_trade_no; cardSaomaResult.PayMoney = PayMoney; cardSaomaResult.PayChannel = this._payChannel; Tuple saomaResult = new Tuple(true, cardSaomaResult); OnSaomaResultClick?.Invoke(new GiftCardSaomaEventArgs(saomaResult)); //先关闭父窗体 if (this.Owner != null) { this.Owner.Close(); } this.Close(); } } #endregion private void OnPayCodeEnterClick(object sender, Component.EnterEventArg e) { this.OnKeyboardBefore(this.billKeyboard1, new BillKeyboardEventArgs("accept")); if (this.PaymentVerify) { this.OnKeyboardAfter(this.billKeyboard1, new BillKeyboardEventArgs("accept")); } } private void OnPayCodeValueChanged(object sender, Component.EnterEventArg e) { if (this.PayStep2.Value > 0 || this.PayStep3.Value > 0) return; string inputString = e.Value; if (!string.IsNullOrEmpty(inputString)) { int intputLength = inputString.Length; this.PayStep1.Value = intputLength * 10; } else { this.PayStep1.Value = 0; } } public delegate void EventHandler(GiftCardSaomaEventArgs e); public event EventHandler OnSaomaResultClick; private void OnCloseTouchClick(object sender, EventArgs e) { //计时器停止 this.timer.Stop(); CardSaomaResult cardSaomaResult = new CardSaomaResult(); cardSaomaResult.Type = 0; cardSaomaResult.PayModeNo = ""; cardSaomaResult.PayModeName = ""; cardSaomaResult.OutTradeNo = ""; cardSaomaResult.PayMoney = 0.00M; cardSaomaResult.PayChannel = this._payChannel; Tuple saomaResult = new Tuple(false, cardSaomaResult); logger.Info("取消支付[{0}]......", ""); OnSaomaResultClick?.Invoke(new GiftCardSaomaEventArgs(saomaResult)); //先关闭父窗体 if (this.Owner != null) { this.Owner.Close(); } //再关闭当前窗体 this.Close(); } /// /// 发起扣钱请求以后创建核销记录 /// /// /// /// public void SavePayTicket(string busNo, string authCode) { try { lock (Global.Instance.SyncLock) { using (var db = Global.Instance.OpenDataBase) { using (var transaction = db.GetTransaction()) { //先查询核销记录是否存在 string querySql = "select * from pos_saoma_pay_ticket where orderNo = '{0}' and storeId ='{1}'"; querySql = string.Format(querySql, busNo, Global.Instance.BusinessPlanLog.StoreId); SaomaPayTicket saomaPayTicket = db.FirstOrDefault(querySql); //如果插入扫码支付记录 if (saomaPayTicket == null) { SaomaPayTicket entity = new SaomaPayTicket(); entity.Id = IdWorkerUtils.Instance.NextId(); entity.TenantId = Global.Instance.BusinessPlanLog.TenantId; entity.StoreId = Global.Instance.BusinessPlanLog.StoreId; entity.WorkerId = Global.Instance.BusinessPlanLog.WorkerId; entity.ShiftNo = Global.Instance.BusinessPlanLog.No; entity.OrderNo = busNo; entity.AuthCode = authCode; entity.Money = this.PayMoney; entity.SerialNo = null; entity.PayTime = null; entity.BusType = 2; entity.PayStatus = 0; entity.PayChannel = (int)this._payChannel; entity.PayTypeNo = this.CurrentPayMode.No; entity.PayTypeName = this.CurrentPayMode.Name; db.Save(entity); } transaction.Complete(); logger.Info("单号:[{0}]插入礼品卡销售记录,支付码{1}", busNo, authCode); } } } } catch (Exception ex) { LOGGER.Error(ex); } } /// /// 手工核销 /// /// /// private void OnSaomaPayClick(object sender, EventArgs e) { //打开提示界面 var form = new GiftSaomaCheckoutForm(this.CardNo, this.PayMoney); form.ShowDialog(); } private void BtnClose(object sender, EventArgs e) { //计时器停止 this.timer.Stop(); CardSaomaResult cardSaomaResult = new CardSaomaResult(); cardSaomaResult.Type = 0; cardSaomaResult.PayModeNo = ""; cardSaomaResult.PayModeName = ""; cardSaomaResult.OutTradeNo = ""; cardSaomaResult.PayMoney = 0.00M; cardSaomaResult.PayChannel = this._payChannel; Tuple saomaResult = new Tuple(false, cardSaomaResult); logger.Info("取消支付[{0}]......", ""); OnSaomaResultClick?.Invoke(new GiftCardSaomaEventArgs(saomaResult)); //先关闭父窗体 if (this.Owner != null) { this.Owner.Close(); } //再关闭当前窗体 this.Close(); } } public class GiftCardSaomaEventArgs : EventArgs { private readonly Tuple _saomaResult; public GiftCardSaomaEventArgs(Tuple saomaResult) { this._saomaResult = saomaResult; } public Tuple SaomaResult { get { return _saomaResult; } } } }