using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using POSV.ShoppingCart; using POSV.Utils; using POSV.MessageEvent; using POSV.Entity; using Aop.Api; using Aop.Api.Request; using Aop.Api.Response; using System.Threading; using System.Threading.Tasks; using POSV.PayApi; using POSV.Member; using POSV.Proxy.ThirdPartyPayMent; using POS.Language.Language; using POSV.Payment.Abmcs; using POSV.Payment.Saobei.Result; using POSV.Payment.Saobei.Parameter; using POSV.Payment.Saobei; using POSV.Payment.AllinPay.Models.ParamModels; using POSV.Payment.AllinPay; using POSV.Payment.AllinPay.Models.ResponseModels; namespace POSV.Bill { [ToolboxItem(true)] public partial class AllinPayControl : AbstractBill { /// /// PayStep3初始值 /// private int initValue = 10; /// /// 是否等待用户输入支付密码 /// private int timeout = 60; //倒计时计时器 //private System.Timers.Timer timer = null; private System.Windows.Forms.Timer timer = null; private const int TIMER_INTERVAL = 1000; private int count = 0; public static object _lock = new object(); public bool isPay = false; //subin 20231011 add 上一次支付状态,默认支付成功 public bool lastPayed = true; //subin 20231011 end private bool _paylock = true; private string SAOBEI_QRCodeType = ""; private string SAOBEI_PAYTIME = ""; private string SAOBEI_OrderId = ""; public AllinPayControl() { InitializeComponent(); //支付结果查询的计时器 //this.timer = new System.Timers.Timer(TIMER_INTERVAL); //this.timer.Elapsed += OnTimerElapsed; PayStep1.Text = " " + LangProxy.ToLang("等待扫描") + "
" + LangProxy.ToLang("请扫描付款码") + " "; PayStep2.Text = "" + LangProxy.ToLang("发起扣款") + "
" + LangProxy.ToLang("发起扣款请求") + " "; PayStep3.Text = "" + LangProxy.ToLang("确认结果") + "
" + LangProxy.ToLang("确认扣款结果") + " "; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.SetStyle(ControlStyles.Selectable, true); if (this.DesignMode) return; this.txtPayCode.Multiline = false; this.txtPayCode.Focus(); this.txtPayCode.SelectAll(); } protected override void OnPaintBackground(PaintEventArgs e) { e.Graphics.Clear(Focused ? SystemColors.Control : SystemColors.Control); } protected override void OnGotFocus(EventArgs e) { Invalidate(); base.OnGotFocus(e); } protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); Invalidate(); } public override void SetFocus() { this.txtPayCode.Focus(); this.txtPayCode.SelectAll(); } public override bool Focused { get { if (this.ActiveControl == null) { this.ActiveControl = this.txtPayCode; } return this.ActiveControl.Focused; } } /// /// 订单对象 /// private OrderObject _orderObject = null; /// /// 支付渠道 /// private PayChannelEnum _payChannel = PayChannelEnum.原生支付; public override void BindUi(OrderObject orderObject) { if (orderObject == null) return; this.initValue = 10; this.SAOBEI_QRCodeType = ""; this.SAOBEI_OrderId = ""; this.isPay = false; this._paylock = true; //清理支付码 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(); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "请扫描或输入支付码...")); this._orderObject = orderObject; //初始化支付状态 this.isPay = false; //subin 20231011 add初始化上一次支付状态 this.lastPayed = true; //subin 20231011 end //微信支付不允许抹零 this._orderObject.MalingAmount = 0; //微信支付不允许找零 this._orderObject.ChangeAmount = 0; //将当前应收金额赋值 this.txtPayCode.Focus(); this.txtPayCode.SelectAll(); //刷新支付汇总清单 this.billSummary1.Refresh(orderObject); //支付结果查询的计时器 if (this.timer != null) { this.timer.Stop(); } this.timer = null; this.timer = new System.Windows.Forms.Timer(); this.timer.Interval = TIMER_INTERVAL; this.timer.Tick += OnTimerTick; } private void OnTimerTick(object sender, EventArgs e) { this.Invoke(new Action(() => { switch (this._payChannel) { case PayChannelEnum.原生支付: { QueryPayChannel_0(); } break; case PayChannelEnum.乐刷支付: { QueryPayChannel_LESHUA(); } break; case PayChannelEnum.扫呗支付: { QueryPayChannel_SAOBEI(); } break; #region subin 2023-06-21 增加通联支付 case PayChannelEnum.通联支付: { QueryPayChannel_Allin(); } break; #endregion } })); LOGGER.Info("查询支付结果中...."); } /// /// 操作是否验证通过 /// private bool PaymentVerify = false; /// /// 当前的支付方式 /// private PayMode CurrentPayMode = null; private void OnKeyboardBefore(object sender, BillKeyboardEventArgs e) { this.PaymentVerify = false; this.CurrentPayMode = null; if (this._orderObject == null) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "订单数据错误啦,请拍个照...")); this.PaymentVerify = false; } else { if (this._orderObject.PaidAmount > 0) { //获取扫描码 var payCode = this.txtPayCode.Text.Trim(); if (string.IsNullOrEmpty(payCode)) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "请扫描或输入支付码...")); this.PaymentVerify = false; } else { #region subin 2023-07-02 修改原付款码支付方式 #region 原始 //this.CurrentPayMode = GetPayMode(payCode); #endregion //var tmpPayMode = GetPayMode(payCode); this.CurrentPayMode = (PayMode)this.Tag; //this.CurrentPayMode.No = tmpPayMode.No; //this.CurrentPayMode.Name = tmpPayMode.Name; //判断支付码是否合法 if (payCode.Length < 16) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "支付码不合法...")); this.PaymentVerify = false; } else { if (this.CurrentPayMode == null) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "支付码不合法或尚未适配...")); this.PaymentVerify = false; } else { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "扫描" + this.CurrentPayMode.Name + "付款码...")); this.PaymentVerify = VerifyInputValue(payCode, this.CurrentPayMode); } } #endregion } } else { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "付款金额非法...")); this.PaymentVerify = false; } } } 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 (_paylock) { try { _paylock = false; if (this.PaymentVerify && this.CurrentPayMode != null) { //保存扫描支付单号 SaveSaomaTicket(string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo), this.txtPayCode.Text.Trim()); switch (this._payChannel) { case PayChannelEnum.原生支付: { this.PayChannel_0(); } break; case PayChannelEnum.乐刷支付: { this.PayChannel_LeShua(); } break; case PayChannelEnum.扫呗支付: { if (this.VerifyOrderPay().Item1) { return; } this.PayChannel_SAOBEI(); } break; #region subin 2023-06-26 增加通联支付 case PayChannelEnum.通联支付: { if (this.VerifyOrderAllinPay().Item1) { return; } if (!lastPayed) { var oldTradeNo = this._orderObject.TradeNo; //尝试重新获取一次单号 var ticket = OrderUtils.Instance.GenerateTicketNoEx(); if (ticket.Item1) { this._orderObject.TradeNo = ticket.Item3; using (var db = Global.Instance.OpenDataBase) { //订单保存成功更新核销状态 LOGGER.Info($"订单支付失败,重新生成订单号,原单号:[{Global.Instance.BusinessPlanLog.StoreNo}_{oldTradeNo}]==>新单号:[{Global.Instance.BusinessPlanLog.StoreNo}_{_orderObject.TradeNo}]......开始"); string sql = "update pos_saoma_pay_ticket set orderNo ='{0}' where orderNo = '{1}'"; sql = string.Format(sql, string.Format("{0}_{1}", Global.Instance.BusinessPlanLog.StoreNo, _orderObject.TradeNo), string.Format("{0}_{1}", Global.Instance.BusinessPlanLog.StoreNo, oldTradeNo)); db.Execute(sql, null); LOGGER.Info($"订单支付失败,重新生成订单号,原单号:[{Global.Instance.BusinessPlanLog.StoreNo}_{oldTradeNo}]==>新单号:[{Global.Instance.BusinessPlanLog.StoreNo}_{_orderObject.TradeNo}]......更新成功"); //发送支付失败,重新生成订单号事件 MsgEvent.Send(Constant.ORDER_PAYMENT_ERROR_GENERATENO, _orderObject.TradeNo); } } else { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "获取全局单号失败,收银参数禁止使用本机单号,请重新操作")); } } this.PayChannel_Allin(); } break; #endregion } } _paylock = true; } catch (Exception ex) { _paylock = true; LOGGER.Error(ex, "支付渠道异常"); } } else { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "正在支付中...")); } 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; } } /// /// 优先记录核销 /// /// /// public void SaveSaomaTicket(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 busType = 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._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount; entity.SerialNo = null; entity.PayTime = this.SAOBEI_PAYTIME; entity.BusType = 0; 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); } } 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 = 0 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; } /// /// 根据扫描码适配支付方式 /// /// 支付宝授权码,25~30开头的长度为16~24位的数字 /// /// 微信授权码 18位纯数字,以10、11、12、13、14、15开头 /// /// /// /// private PayMode GetPayMode(string payCode) { PayMode result = null; if (!string.IsNullOrEmpty(payCode) && payCode.Length >= 16) { string prefix = payCode.Substring(0, 2); switch (prefix) { case "10": case "11": case "12": case "13": case "14": case "15": { //微信 result = OrderUtils.GetPayMode("05"); } break; case "25": case "26": case "27": case "28": case "29": case "30": { //支付宝 result = OrderUtils.GetPayMode("04"); } break; case "62": { //云支付 result = OrderUtils.GetPayMode("07"); } break; #region subin 2023-07-02 add case "50": { //通联支付 result = OrderUtils.GetPayMode("50"); } break; #endregion } } return result; } #region 验证付款码、支付参数是否正确 private bool VerifyWxPay(string payCode, PayMode payMode) { if (string.IsNullOrEmpty(payCode) || payCode.Length != 18) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "微信付款码非法...")); return false; } var parameter = payMode.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() : ""; if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(key))//Yao 2023-06-13 test { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "微信支付参数配置不完整...")); return false; } return true; } private bool VerifyAliPay(string payCode, PayMode payMode) { if (string.IsNullOrEmpty(payCode) || (payCode.Length < 16 || payCode.Length > 24)) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "支付宝付款码非法...")); return false; } var parameter = payMode.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() : ""; if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(privateKey)) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "支付宝支付参数配置不完整...")); return false; } return true; } private bool VerifyInputValue(string payCode, PayMode payMode) { bool isVerify = false; var parameter = payMode.Body; if (parameter == null || parameter.Count == 0)//Yao 2023-06-13 test { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "尚未配置支付参数...")); isVerify = false; } else { //获取支付渠道 string channel = (parameter.ContainsKey("channel") ? parameter["channel"].ToString() : "").ToLower(); //没有配置支付渠道,默认原生支付,兼容处理 if (string.IsNullOrEmpty(channel)) { this._payChannel = PayChannelEnum.原生支付; } else { switch (channel) { case "alipay": case "wxpay": case "subalipay": case "subwxpay": { this._payChannel = PayChannelEnum.原生支付; } break; case "leshua": { this._payChannel = PayChannelEnum.乐刷支付; } break; case "saobei": { this._payChannel = PayChannelEnum.扫呗支付; } break; #region subin 2023-06-16 增加通联支付 case "allinpay": { this._payChannel = PayChannelEnum.通联支付; } break; #endregion } } LOGGER.Info("适配到支付渠道:{0}", this._payChannel.ToString()); switch (this._payChannel) { case PayChannelEnum.原生支付: { switch (payMode.No) { case "04": { isVerify = VerifyAliPay(payCode, payMode); } break; case "05": { isVerify = VerifyWxPay(payCode, payMode); } break; default: { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "目前暂不支持该类型付款码...")); isVerify = false; } break; } } break; case PayChannelEnum.乐刷支付: { isVerify = VerifyLeShuaPay(payCode); } break; case PayChannelEnum.扫呗支付: { isVerify = VerifySAOBEIPay(payCode, payMode); } break; case PayChannelEnum.通联支付: { isVerify = VerifyAllinPay(payCode, payMode); } break; } } return isVerify; } #endregion #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 }; //发送结果通知 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "查询支付结果超时")); LOGGER.Warn("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this._orderObject.TradeNo); var dialog = new DialogForm("支付结果", "没有查询到支付结果,系统无法确认本单已经支付", MessageBoxIcon.Warning, MessageBoxButtons.RetryCancel); if (DialogResult.Retry == dialog.ShowDialog()) { LOGGER.Warn("收银员手动选择重新查询一次结果,订单号<{0}>", this._orderObject.TradeNo); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "等待确认扣款状态")); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { LOGGER.Warn("收银员手动放弃结果确认,订单号<{0}>", this._orderObject.TradeNo); //清理支付码 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)//Yao 2023-06-11 test { case "04": { var isQuery = AliPayResult(); if (isQuery) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(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) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(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; } } #region 原生微信支付 /// /// 微信支付,返回是否确认查询结果 /// /// private bool WxPayResult() { bool isQuery = false; try { string nonceStr = "x86" + ObjectId.GenerateNewStringId(); //门店编号 string deviceInfo = Global.Instance.Authc.StoreNo; //门店名称 string body = Global.Instance.Worker.StoreInfo.Name + "-店内消费"; //商品详情 string detail = ""; //附加数据 string attach = ""; //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); //订单总金额,单位为分,只能为整数 string totalFee = Convert.ToInt32((this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount) * 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; //发起微信扣款请求 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(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}]分", outTradeNo, totalFee); var dataInfo = new WxPayV3MicroPayRequestData(appId, mchId, subMchId, key, nonceStr, deviceInfo, body, detail, attach, outTradeNo, totalFee, feeType, spbillCreateIp, goodsTag, authCode); ////扫码成功,提交被扫支付 MicropayResult result = WxPayV3.MicroPay(dataInfo); //Yao 2023-06-11 test //设置package订单参数 //NewParameters.Add("appid", this.AppId); //公众账号ID //NewParameters.Add("mch_id", this.MchId); //商户号 //if (!string.IsNullOrEmpty(this.SubMchId)) //{ // NewParameters.Add("sub_mch_id", this.SubMchId); //子商户号 //} //NewParameters.Add("device_info", this.DeviceInfo); //终端设备号 //NewParameters.Add("nonce_str", this.NonceStr); //随机字符串 //NewParameters.Add("sign_type", this.SignType); //签名类型 //NewParameters.Add("body", this.Body); //商品简单描述 //NewParameters.Add("detail", this.Detail); //商品详细列表 //NewParameters.Add("attach", this.Attach); //附加数据 //NewParameters.Add("out_trade_no", this.OutTradeNo); //商户系统内部的订单号 //NewParameters.Add("total_fee", this.TotalFee); //订单总金额 //NewParameters.Add("fee_type", this.FeeType); //货币类型 //NewParameters.Add("spbill_create_ip", this.SpbillCreateIp); //终端IP //NewParameters.Add("goods_tag", this.GoodsTag); //商品标记 //NewParameters.Add("auth_code", this.AuthCode); //授权码 //Sign = CreateMd5Sign("key", this.Key); //NewParameters.Add("sign", Sign); //签名 //param.setMeruserid("ZHTGR_YST16675473608354765"); //param.setPayuserid("ZHTGR_YST16631207277914507"); //param.setReqsn("po-" + System.currentTimeMillis()); //param.setAmount(1L); //param.setPaytype("H5_CASHIER_VSP"); //param.setConsumer_ip("10.40.8.35"); //param.setRemark("支付测试"); //param.setReturl("https://www.baidu.com"); //param.setNotify_url("https://www.baidu.com"); //param.setVspCusId(""); //param.setAuthCode(""); //param.setFee(0L); //POSV.Helper.HttpHelper.Post("order.consumeApply", param); LOGGER.Info("订单[{0}]微信扣款返回结果:{1}", 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}", 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; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "网络超时,正在查询支付状态,请稍候...")); isQuery = true; } break; case WxPayErrCode.BANKERROR: { this.PayStep2.Value = this.PayStep2.Maximum; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "银行端超时,正在查询支付状态,请稍候...")); isQuery = true; } break; case WxPayErrCode.USERPAYING: { this.PayStep2.Value = this.PayStep2.Maximum; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "等待用户输入密码,请稍候...")); //需等待输入密码,需要确认结果 isQuery = true; } break; case WxPayErrCode.ORDERPAID: { this.PayStep2.Value = this.PayStep2.Minimum; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "订单号重复支付,请使用新订单")); isQuery = false; } break; case WxPayErrCode.AUTHCODEEXPIRE: { this.PayStep2.Value = this.PayStep2.Minimum; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "二维码过期,请用户在微信上刷新后再试")); isQuery = false; } break; case WxPayErrCode.NOTENOUGH: { this.PayStep2.Value = this.PayStep2.Minimum; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "用户余额不足,请用户换卡支付")); isQuery = false; } break; case WxPayErrCode.NOTSUPORTCARD: { this.PayStep2.Value = this.PayStep2.Minimum; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "不支持当前支付,请用户换卡或绑新卡支付")); isQuery = false; } break; case WxPayErrCode.INVALID_REQUEST: { this.PayStep2.Value = this.PayStep2.Minimum; if (result.err_code_des == "201 商户订单号重复") { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "商户订单号重复,请消单后重新下单")); } else { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, result.err_code_des)); } isQuery = false; } break; default: { this.PayStep2.Value = this.PayStep2.Minimum; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, result.err_code_des)); isQuery = false; } break; } } } else { LOGGER.Warn("订单[{0}]微信支付[{1}]分,微信支付网络通信错误:{0}", outTradeNo, totalFee, result.return_msg); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, result.return_msg)); //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(new Exception("微信支付错误2" + JsonUtils.Serialize(result))); //})); } } catch (Exception ex) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "微信支付发生异常,开始确认支付结果")); LOGGER.Error(ex, "微信支付发生异常"); //发起支付发生异常,为了避免客户已经收到请求,开始支付,这里进行补救查询 isQuery = true; //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(ex); //})); } return isQuery; } 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(); //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); var dataInfo = new WxPayV3OrderQueryRequestData(appId, "", mchId, subMchId, "", nonceStr, outTradeNo, key); var result = WxPayV3.OrderQuery(dataInfo); LOGGER.Info("订单[{0}]微信(原生)查询支付结果:{1}", outTradeNo, JsonUtils.Serialize(result)); 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(); //更新付款状态 lock (_lock) { if (!isPay) { isPay = true; } else { return; } } this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "微信支付成功")); //构建微信支付方式 this.AddWxPayType(result); //微信支付更新核销状态 //UpdateSaoMa(outTradeNo); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "微信支付成功"); //清理支付码 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)); } 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(); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "密码错误或未输入,请重新扫码")); } break; default: { string message = string.Format("{0}:{1}秒", result.trade_state_desc, --timeout); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, message)); } break; } } else { if (result.err_code == "ORDERNOTEXIST") { //计时器停止 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(); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "微信:未收到该订单,请重新扫码")); } else { string message = string.Format("正在确认微信扣款结果:{0}秒,{1}", --timeout, result.err_code_des); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, message)); } } } else { LOGGER.Warn("查询支付结果网络通信错误:{0}", result.return_msg); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, result.return_msg)); //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(new Exception("查询微信支付结果网络通信错误" + JsonUtils.Serialize(result))); //})); } } catch (Exception ex) { LOGGER.Error(ex, "微信支付结果查询发生异常"); //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(ex); //})); } } private void AddWxPayType(OrderQueryResult result) { if (result != null && "SUCCESS".Equals(result.return_code) && "SUCCESS".Equals(result.result_code)) { //构建微信支付方式 PayItem item = OrderUtils.ToPayItem(this.CurrentPayMode); //租户ID item.TenantId = Global.Instance.Authc.TenantId; //订单号 item.OrderId = this._orderObject.Id; item.TradeNo = this._orderObject.TradeNo; //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); item.OutTradeNo = outTradeNo; //实收金额 item.PaidAmount = DecimalUtils.Fen2Yuan(result.total_fee); //找零金额 item.ChangeAmount = Convert.ToDecimal(0.00); //已收金额,真正意义上实际收款金额 item.Amount = item.PaidAmount; item.CardNo = ""; item.TradeVoucherNo = result.transaction_id; item.Memo = result.openid; item.Subscribe = result.is_subscribe; item.PayChannel = this._payChannel; //微信支付状态 item.Status = (int)OrderPaymentStatus.已付款; ; item.StatusDesc = string.Format("微信支付<{0}>", result.result_code); //将微信支付压入支付清单 this._orderObject.Pays.Add(item); //刷新界面数据 this.billSummary1.Refresh(this._orderObject); } } #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 = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); 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", this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount); 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", this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount); 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; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "等待确认扣款结果...")); } else { isQuery = false; MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, string.Format("{0}<{1}>", response.SubMsg, response.SubCode))); //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(new Exception("订单["+ outTradeNo + "]支付宝(原生)支付失败,返回结果:"+ JsonUtils.Serialize(response))); //})); } } catch (Exception ex) { LOGGER.Error(ex, "支付宝付款发生异常"); if (ex.Message.Contains("私钥格式错误")) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "支付宝私钥配置错误...")); isQuery = false; } else { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "支付宝付款发生异常...")); isQuery = true; } //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(ex); //})); } return isQuery; } 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(); //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); content.Add("out_trade_no", outTradeNo); request.BizContent = JsonUtils.Serialize(content); AlipayTradeQueryResponse response = client.Execute(request, string.Empty, appAuthToken); LOGGER.Info("支付宝(原生)查询订单[{0}]支付状态结果:<{1}>", outTradeNo, JsonUtils.Serialize(response)); switch (response.TradeStatus) { case "TRADE_SUCCESS": { //计时器停止 this.timer.Stop(); //更新付款状态 lock (_lock) { if (!isPay) { isPay = true; } else { return; } } this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "支付宝付款成功")); //构建支付宝支付方式 this.AddAliPayType(response); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "支付宝付款成功"); //微信支付更新核销状态 //UpdateSaoMa(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(); } break; case "WAIT_BUYER_PAY": { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "等待买家付款...")); } break; default: { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "等待买家付款...")); } break; } } catch (Exception ex) { LOGGER.Error(ex, "支付宝结果查询发生异常"); //Task.Factory.StartNew(new Action(() => //{ // Global.Instance.BugReport(ex); //})); } } private void AddAliPayType(AlipayTradeQueryResponse result) { if (result != null && "TRADE_SUCCESS".Equals(result.TradeStatus)) { //构建微信支付方式 PayItem item = OrderUtils.ToPayItem(this.CurrentPayMode); //租户ID item.TenantId = Global.Instance.Authc.TenantId; //订单号 item.OrderId = this._orderObject.Id; //订单编号 item.TradeNo = this._orderObject.TradeNo; //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); item.OutTradeNo = outTradeNo; //实收金额 item.PaidAmount = StringUtils.GetDecimal(result.TotalAmount); //找零金额 item.ChangeAmount = Convert.ToDecimal(0.00); //已收金额,真正意义上实际收款金额 item.Amount = item.PaidAmount; item.CardNo = ""; item.TradeVoucherNo = result.TradeNo; item.Memo = result.BuyerUserId; item.Subscribe = string.Empty; item.PayChannel = this._payChannel; //支付宝支付状态 item.Status = (int)OrderPaymentStatus.已付款; item.StatusDesc = string.Format("支付宝付款<{0}>", result.TradeStatus); //将支付宝支付压入支付清单 this._orderObject.Pays.Add(item); //刷新界面数据 this.billSummary1.Refresh(this._orderObject); } } #endregion #endregion #region 乐刷支付渠道 private void PayChannel_LeShua() { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "等待确认扣款结果...")); //zhangy 2020-08-12 10:44 修复混合支付情况,扣款金额错误 var amount = this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount; var _data = PayMentOperation.Pay(this.txtPayCode.Text, _orderObject.TradeNo, amount, this._payChannel); //zhangy 2020-08-12 10:44 屏蔽 //var _data = PayMentOperation.Pay(this.txtPayCode.Text, _orderObject.TradeNo, _orderObject.PaidAmount, this._payChannel); if (_data.Item3 != null) { UpdateSaomaTicket(string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo), _data.Item3.OutTradeNo, _data.Item3.FinishDate); } if (!_data.Item1) { if (!_data.Item2.Contains("支付中")) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, _data.Item2)); this.txtPayCode.Enabled = true; return; } //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, _data.Item2)); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); return; } UpdateSaomaTicket(_data.Item3.OutTradeNo, string.Format("{0}_{1}", _orderObject.StoreNo, _data.Item3.TradeNo), _data.Item3.FinishDate); if (this._orderObject.Pays == null) { this._orderObject.Pays = new List(); } _data.Item3.OrderId = this._orderObject.Id; _data.Item3.Order = this._orderObject.Pays.Count; this._orderObject.Pays.Add(_data.Item3); //计时器停止 this.timer.Stop(); this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "乐刷支付付款成功")); //清理支付码 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(); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "乐刷支付付款成功"); } private void QueryPayChannel_LESHUA() { //进度条最大值 int maximum = this.PayStep3.Maximum; this.PayStep3.Value = (initValue++); //判断是否超时,如果超时终止计时器,界面反馈信息 if (initValue % this.PayStep3.Maximum == 0) { //计时器停止 this.timer.Stop(); //发送结果通知 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "查询支付结果超时")); LOGGER.Warn("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this._orderObject.TradeNo); var dialog = new DialogForm("支付结果", "没有查询到支付结果,系统无法确认本单已经支付", MessageBoxIcon.Warning, MessageBoxButtons.RetryCancel); if (DialogResult.Retry == dialog.ShowDialog()) { LOGGER.Warn("收银员手动选择重新查询一次结果,订单号<{0}>", this._orderObject.TradeNo); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "等待确认扣款状态")); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { OnPayCodeCheckClick(null, null); LOGGER.Warn("收银员手动放弃结果确认,订单号<{0}>", this._orderObject.TradeNo); //清理支付码 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 { using (var _db = Global.Instance.OpenDataBase) { var _ticket = _db.FirstOrDefault(string.Format("where orderNo = '{0}_{1}'", this._orderObject.StoreNo, this._orderObject.TradeNo)); if (_ticket == null) { this.LOGGER.Info("在SaomaPayTicket 中查询不到相关数据"); return; } Dictionary keys = new Dictionary(); var _data = PayMentOperation.QueryPay(this.txtPayCode.Text, this._orderObject.TradeNo, _ticket.SerialNo, this._payChannel, keys); if (!_data.Item1) { //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, _data.Item2)); return; } UpdateSaomaTicket(_data.Item3.OutTradeNo, string.Format("{0}_{1}", _orderObject.StoreNo, _data.Item3.TradeNo), _data.Item3.FinishDate); if (this._orderObject.Pays == null) { this._orderObject.Pays = new List(); } _data.Item3.OrderId = this._orderObject.Id; _data.Item3.Order = this._orderObject.Pays.Count; this._orderObject.Pays.Add(_data.Item3); //计时器停止 this.timer.Stop(); this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "乐刷支付付款成功")); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "乐刷支付付款成功"); //微信支付更新核销状态 //UpdateSaoMa(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(); } } } private bool VerifyLeShuaPay(string payCode) { var _data = PayMentOperation.VerifyParameter(payCode); return _data.Item1; } #endregion #region 扫呗支付渠道 private void PayChannel_SAOBEI() { this.SAOBEI_QRCodeType = ""; this.SAOBEI_OrderId = ""; var saobeiPayResult = SAOBEIPayResult(); if (saobeiPayResult.Item1) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(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 Tuple VerifyOrderPay() { using (var _db = Global.Instance.OpenDataBase) { var _data = _db.FirstOrDefault(string.Format("where orderNo = '{0}_{1}'", this._orderObject.StoreNo, this._orderObject.TradeNo)); if (_data == null) { return new Tuple(false, "无需核销"); } if (_data.PayStatus == 1) { if (!string.IsNullOrEmpty(_data.SerialNo)) { SaobeiQueryResult saobeiQuery = new SaobeiQueryResult(); saobeiQuery.Trade_state = "SUCCESS"; saobeiQuery.Total_fee = (_data.Money * 100).ToString(); saobeiQuery.Out_trade_no = _data.SerialNo; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "扫呗支付成功")); //构建支付方式 this.AddSAOBEIPayType(saobeiQuery); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "扫呗支付付款成功"); //微信支付更新核销状态 //UpdateSaoMa(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(); return new Tuple(true, ""); } return new Tuple(false, "支付异常,请联系管理员"); } if (_data.Money != this._orderObject.ReceivableAmount - this._orderObject.MalingAmount) { return new Tuple(false, "金额不相等,该核销数据无效"); } 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 = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); SaobeiQueryParam request = new SaobeiQueryParam(); if (_data.PayTypeNo.Equals("05")) { request.Pay_type = "010"; } else { request.Pay_type = "110"; } 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)) || saobeiPayment.Item3.Return_msg.Equals("支付成功")) { this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "扫呗支付成功")); //构建支付方式 this.AddSAOBEIPayType(saobeiPayment.Item3); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "扫呗支付付款成功"); //微信支付更新核销状态 //UpdateSaoMa(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(); return new Tuple(true, ""); } } return new Tuple(false, ""); } } private Tuple SAOBEIPayResult() { bool isQuery = false; string orderId = ""; decimal payAmount = 0.00M; //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); var amount = this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount; orderId = outTradeNo; 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)); //支付方式 支付宝1、微信2 request.Pay_type = "020"; request.Terminal_time = DateTime.Now.ToString("yyyyMMddHHmmss"); this.SAOBEI_PAYTIME = request.Terminal_time; 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; //请求之前,先把支付时间更新到扫呗支付表,防止软件假死、或者卡死导致核销不了 this.SAOBEI_OrderId = ""; UpdateSaomaTicket(outTradeNo, this.SAOBEI_OrderId, this.SAOBEI_PAYTIME); var saobeiPayment = SaobeiUtils.SaobeiPayment(merchant_no, terminal_id, signKey, gatewayUrl, request); if (saobeiPayment.Item1) { SaobeiPaymentResult saobeiPaymentResult = saobeiPayment.Item3; //支付结果需要查询 isQuery = true; this.SAOBEI_QRCodeType = saobeiPaymentResult.Pay_type; this.SAOBEI_OrderId = saobeiPaymentResult.Out_trade_no; UpdateSaomaTicket(outTradeNo, this.SAOBEI_OrderId, this.SAOBEI_PAYTIME); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "等待确认扣款结果...")); } else { isQuery = false; this.SAOBEI_QRCodeType = ""; this.SAOBEI_OrderId = ""; UpdateSaomaTicket(outTradeNo, this.SAOBEI_OrderId, this.SAOBEI_PAYTIME); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, string.Format("{0}", saobeiPayment.Item2))); } } catch (Exception ex) { LOGGER.Error(ex, "扫呗支付订单[" + outTradeNo + "]金额[" + amount + "]发生异常!"); isQuery = false; this.SAOBEI_QRCodeType = ""; this.SAOBEI_OrderId = ""; UpdateSaomaTicket(outTradeNo, this.SAOBEI_OrderId, this.SAOBEI_PAYTIME); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "查不到支付状态,请使用手工核销功能...")); } return new Tuple(isQuery, orderId, payAmount); } 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 }; //发送结果通知 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "查询支付结果超时")); LOGGER.Warn("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this._orderObject.TradeNo); var dialog = new DialogForm("支付结果", "没有查询到支付结果,系统无法确认本单已经支付", MessageBoxIcon.Warning, MessageBoxButtons.RetryCancel); if (DialogResult.Retry == dialog.ShowDialog()) { LOGGER.Warn("收银员手动选择重新查询一次结果,订单号<{0}>", this._orderObject.TradeNo); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "等待确认扣款状态")); this.initValue = 10; this.timeout = 60; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { OnPayCodeCheckClick(null, null); LOGGER.Warn("收银员手动放弃结果确认,订单号<{0}>", this._orderObject.TradeNo); //清理支付码 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 = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); 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(); //更新付款状态 lock (_lock) { if (!isPay) { isPay = true; } else { return; } } this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "扫呗支付成功")); //构建支付方式 this.AddSAOBEIPayType(saobeiPayment.Item3); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "扫呗支付付款成功"); //微信支付更新核销状态 //UpdateSaoMa(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 { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "查询结果:" + saobeiPayment.Item2)); } } 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(); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, saobeiPayment.Item2)); } } catch (Exception ex) { LOGGER.Error(ex, "银联商务支付付款结果查询发生异常"); } } private void AddSAOBEIPayType(SaobeiQueryResult queryParam) { if (queryParam != null && "SUCCESS".Equals(queryParam.Trade_state)) { //构建支付方式 PayItem item = OrderUtils.ToPayItem(this.CurrentPayMode); //租户ID item.TenantId = Global.Instance.Authc.TenantId; //订单号 item.OrderId = this._orderObject.Id; //订单编号 item.TradeNo = this._orderObject.TradeNo; //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); item.OutTradeNo = outTradeNo; //实收金额 item.PaidAmount = Convert.ToDecimal(StringUtils.GetDecimal(queryParam.Total_fee) / 100); //找零金额 item.ChangeAmount = Convert.ToDecimal(0.00); //已收金额,真正意义上实际收款金额 item.Amount = item.PaidAmount; item.CardNo = ""; item.TradeVoucherNo = queryParam.Out_trade_no;//利楚唯一订单号 item.Memo = this._payChannel.ToString(); item.Subscribe = string.Empty; item.PayChannel = this._payChannel; //支付状态 item.Status = (int)OrderPaymentStatus.已付款; item.StatusDesc = string.Format("{0}", queryParam.Trade_state); //将支付宝支付压入支付清单 this._orderObject.Pays.Add(item); //刷新界面数据 this.billSummary1.Refresh(this._orderObject); if (Global.Instance.GlobalConfigBoolValue(ConfigConstant.CONFIG_CASHIER_ISPAYVOICE)) Task.Factory.StartNew(() => { switch (item.No) { case "04"://支付宝 Voice.Pay.PayVoicePlay.PlayReceiveMoney(Voice.PayTypeEnum.Alipay, item.PaidAmount); break; case "05"://微信 Voice.Pay.PayVoicePlay.PlayReceiveMoney(Voice.PayTypeEnum.WeiXinPay, item.PaidAmount); break; } }); } } private bool VerifySAOBEIPay(string payCode, PayMode payMode) { if (string.IsNullOrEmpty(payCode)) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "付款码非法...")); return false; } var parameter = payMode.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() : ""; if (string.IsNullOrEmpty(merchant_no) || string.IsNullOrEmpty(terminal_id) || string.IsNullOrEmpty(signKey) || string.IsNullOrEmpty(gatewayUrl)) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "扫呗支付参数配置不完整...")); return false; } return true; } #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 override void Clear() { base.Clear(); this.txtPayCode.Text = string.Empty; this.txtPayCode.Enabled = true; this._orderObject = null; this._payChannel = PayChannelEnum.无; if (this.timer != null) { this.timer.Stop(); this.timer = null; LOGGER.Info("释放查询任务"); } if (!this.lastPayed) { //发送支付失败,重新生成订单号事件 MsgEvent.Send(Constant.ORDER_PAYMENT_ERROR_GENERATENO, ""); } } private void OnPayCodeCheckClick(object sender, EventArgs e) { //打开提示界面 var form = new AllinPayCheckForm(this._orderObject, this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount, true); form.ShowDialog(); } #region subin 2023-06-20 通联支付 private bool VerifyAllinPay(string payCode, PayMode payMode) { if (string.IsNullOrEmpty(payCode)) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "付款码非法...")); return false; } var parameter = payMode.Body; //通联支付参数 string appId = parameter.ContainsKey("appId") ? parameter["appId"].ToString() : ""; string appKey = parameter.ContainsKey("appKey") ? parameter["appKey"].ToString() : ""; string url = parameter.ContainsKey("gatewayUrl") ? parameter["gatewayUrl"].ToString() : ""; var payuserid = parameter.ContainsKey("payuserid") ? (parameter["payuserid"] != null ? parameter["payuserid"].ToString() : "") : ""; //string bizUserId = parameter.ContainsKey("bizUserId") ? parameter["bizUserId"].ToString() : ""; var vspCusid = parameter.ContainsKey("vspCusid") ? (parameter["vspCusid"] != null ? parameter["vspCusid"].ToString() : "") : ""; if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(appKey) || string.IsNullOrEmpty(url) || string.IsNullOrEmpty(payuserid)) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "通联支付参数配置不完整...")); if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(appKey) || string.IsNullOrEmpty(url)) { //公共参数 LOGGER.Warn("通联支付公共参数配置不完整"); } if (string.IsNullOrEmpty(payuserid) || string.IsNullOrEmpty(vspCusid)) { //公共参数 LOGGER.Warn("通联支付业务参数配置不完整"); } return false; } //if (string.IsNullOrEmpty(payuserid)) //{ // MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "通联支付参数未配置门店付款会员号...")); // return false; //} return true; } private Tuple VerifyOrderAllinPay() { using (var _db = Global.Instance.OpenDataBase) { var _ticket = _db.FirstOrDefault(string.Format("where orderNo = '{0}_{1}'", this._orderObject.StoreNo, this._orderObject.TradeNo)); if (_ticket == null) { return new Tuple(false, "无需核销"); } if (_ticket.PayStatus == 1) { if (!string.IsNullOrEmpty(_ticket.SerialNo)) { var orderDetail = new OrderDetail { reqsn = _ticket.OrderNo, trxid = _ticket.SerialNo, status = _ticket.OrderStatus, amount = (int)_ticket.Money * 100, }; //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "通联支付付款成功"); //构建支付方式,播放支付语音 AddAllinPayType(orderDetail); //清理支付码 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(); return new Tuple(true, "通联支付付款成功"); } return new Tuple(false, "支付异常,请联系管理员"); } if (_ticket.Money != this._orderObject.ReceivableAmount - this._orderObject.MalingAmount) { return new Tuple(false, "金额不相等,该核销数据无效"); } var payParam = this.CurrentPayMode.Body; AllinpayLib.AppId = payParam.ContainsKey("appId") ? payParam["appId"].ToString() : ""; AllinpayLib.AppKey = payParam.ContainsKey("appKey") ? payParam["appKey"].ToString() : ""; AllinpayLib.Url = payParam.ContainsKey("gatewayUrl") ? payParam["gatewayUrl"].ToString() : ""; var info = new GetOrderDetailModel() { reqsn = this._orderObject.TradeNo, }; var param = new GetOrderDetailParamInfo { bizContent = JsonUtils.Serialize(info) }; var response = AllinpayHelper.GetOrderDetail(param); if (!response.IsSuccess) { //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, response.ShowUserMsg)); //LOGGER.Warn("订单号<{0}>支付查询异常:{1}", this._orderObject.TradeNo, response.ShowUserMsg); LOGGER.Warn("订单[{0}]通联支付查询,网络通信错误:{1}", _orderObject.TradeNo, response.ShowUserMsg); return new Tuple(false, "支付查询异常"); } var _data = JsonUtils.Deserialize(response.ResultInfo.data); var _statusDesc = "进行中"; switch (_data.status) { case "1": _statusDesc = "未支付"; break; case "3": _statusDesc = "交易失败"; break; case "4": _statusDesc = "交易成功"; break; case "5": _statusDesc = "交易成功-发生退款"; break; case "6": _statusDesc = "关闭"; break; case "99": _statusDesc = "进行中"; break; } if (_statusDesc.Equals("交易成功")) { this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "通联支付付款成功")); //构建支付方式,播放支付语音 AddAllinPayType(_data); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "通联支付付款成功"); //清理支付码 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(); return new Tuple(true, "通联支付付款成功"); } return new Tuple(false, "支付异常:" + _statusDesc); } } private void AddAllinPayType(OrderDetail queryParam) { if (queryParam != null && "4".Equals(queryParam.status)) { //构建支付方式 PayItem item = OrderUtils.ToPayItem(this.CurrentPayMode); //租户ID item.TenantId = Global.Instance.Authc.TenantId; //订单号 item.OrderId = this._orderObject.Id; //订单编号 item.TradeNo = this._orderObject.TradeNo; //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); item.OutTradeNo = outTradeNo; //实收金额 item.PaidAmount = Convert.ToDecimal(StringUtils.GetDecimal(queryParam.amount) / 100); //找零金额 item.ChangeAmount = Convert.ToDecimal(0.00); //已收金额,真正意义上实际收款金额 item.Amount = item.PaidAmount; //通联扣款实收手续费,单位:分 item.Ext2 = ((decimal)queryParam.fee) / 100 + ""; item.CardNo = ""; item.TradeVoucherNo = queryParam.trxid;//通联唯一订单号 item.Memo = this._payChannel.ToString(); item.Subscribe = string.Empty; item.PayChannel = this._payChannel; //支付状态 item.Status = (int)OrderPaymentStatus.已付款; item.StatusDesc = string.Format("{0}", queryParam.status); //将通联支付压入支付清单 this._orderObject.Pays.Add(item); //刷新界面数据 this.billSummary1.Refresh(this._orderObject); if (Global.Instance.GlobalConfigBoolValue(ConfigConstant.CONFIG_CASHIER_ISPAYVOICE)) { Task.Factory.StartNew(() => { Voice.Pay.PayVoicePlay.PlayReceiveMoney(Voice.PayTypeEnum.AllinPay, item.PaidAmount); }); } } } private void PayChannel_Allin() { bool isQuery = false; var allinPay_OrderId = ""; //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); //string outTradeNo = this._orderObject.TradeNo; var _amount = this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount; var _recieverList = new List(); var applyParam = new AgentCollectApplyParamInfo(); var isResquest = false; try { var payParam = this.CurrentPayMode.Body; //AllinpayLib.AppId = payParam.ContainsKey("appId") ? payParam["appId"].ToString() : ""; //AllinpayLib.AppKey = payParam.ContainsKey("appKey") ? payParam["appKey"].ToString() : ""; //AllinpayLib.Url = payParam.ContainsKey("gatewayUrl") ? payParam["gatewayUrl"].ToString() : ""; var _vspCusid = payParam.ContainsKey("vspCusid") ? payParam["vspCusid"].ToString() : ""; var _payuserid = payParam.ContainsKey("payuserid") ? payParam["payuserid"].ToString() : ""; var _bizUserId = payParam.ContainsKey("bizUserId") ? payParam["bizUserId"].ToString() : ""; //decimal _bizUserAmount = 0; #region subin 分账变更内容 if (this._orderObject.OrderCount > 0) { //1.20230917 由单账号收退款后端统一分账改为多账号收退款前端分账 //ZHTQY_OUT16890697512466994 大同市平城区开闻快餐店 _recieverList.Add(new ApplyReciever { bizUserId = _bizUserId, amount = Convert.ToInt32(_amount * 100) }); #region 20230920 注销,由多账号收退款前端分账改为单账号收退款后端统一分账 //2.20230920 注销,由多账号收退款前端分账改为单账号收退款后端统一分账 //using (var db = Global.Instance.OpenDataBase) //{ // var productIdList = this._orderObject.Items.Select(item => item.ProductId).Distinct(); // var productIds = string.Join(",", productIdList); // StringBuilder sqlBuld = new StringBuilder(); // sqlBuld.Append("SELECT ssa.bizUserId,sfa.goodId FROM pos_split_shop_account ssa "); // sqlBuld.Append("LEFT JOIN pos_split_food_account sfa ON sfa.shopId=ssa.id "); // sqlBuld.Append("WHERE sfa.goodId IN ('{0}'); "); // string sql = string.Format(sqlBuld.ToString(), productIds.Replace(",", "','")); // var orderSubStoreDetail = db.Query(sql).ToList(); // var bizUseIdLst = orderSubStoreDetail.Count() > 0 ? orderSubStoreDetail.Select(item => item.BizUserId).Distinct().ToList() : new List(); // if (bizUseIdLst.Count() == 0) // { // LOGGER.Warn("订单[{0}]通联支付[{1}]分支付异常:收款方列表为空", _orderObject.TradeNo, Convert.ToInt32(_amount * 100)); // MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, string.Format("{0}", "收款方列表为空"))); // } // foreach (var item in bizUseIdLst) // { // var goodLst = orderSubStoreDetail.Where(m => m.BizUserId == item).ToList().Select(m => m.GoodId); // var goodIds = string.Join(",", goodLst); // var total = this._orderObject.Items.Where(m => goodIds.Contains(m.ProductId)).Sum(m => m.TotalAmonut); // _bizUserAmount += total; // _recieverList.Add(new ApplyReciever { bizUserId = item, amount = Convert.ToInt32(total * 100) }); // } //} #endregion } #endregion this.PayStep2.Value = this.PayStep2.Maximum / 3; //托管代收 var applyInfo = new AgentCollectApplyModel { reqsn = this._orderObject.TradeNo, payuserid = _payuserid, vspCusid = _vspCusid, payuseridtype = "", paytype = "CODEPAY_VSP_ORG", amount = Convert.ToInt32(_amount * 100), fee = 0, frontUrl = "", backUrl = "", limit_pay = "no_credit", source = "2", authcode = this.txtPayCode.Text, consumer_ip = "10.40.8.35", remark = "POSV代付", recieverList = JsonUtils.Serialize(_recieverList) }; applyParam.bizContent = JsonUtils.Serialize(applyInfo); //请求之前,先把支付时间更新到扫码支付表,防止软件假死、或者卡死导致核销不了 allinPay_OrderId = ""; UpdateSaomaTicket(outTradeNo, allinPay_OrderId, applyParam.timestamp); var _response = AllinpayHelper.AgentCollectApply(applyParam); if (_response.IsSuccess) { isResquest = true; this.lastPayed = true; this.PayStep2.Value = this.PayStep2.Maximum; // 支付结果需要查询 isQuery = true; var _data = JsonUtils.Deserialize(_response.ResultInfo.data); allinPay_OrderId = _data.orderNo; UpdateSaomaTicket(outTradeNo, allinPay_OrderId, applyParam.timestamp); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "等待确认扣款结果...")); } else { isResquest = true; this.lastPayed = false; this.PayStep2.Value = this.PayStep2.Maximum; LOGGER.Warn("订单[{0}]通联支付[{1}]分,支付错误:{2}", _orderObject.TradeNo, Convert.ToInt32(_amount * 100), _response.LogMsg); isQuery = false; allinPay_OrderId = ""; UpdateSaomaTicket(outTradeNo, allinPay_OrderId, applyParam.timestamp); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, string.Format("{0}", _response.ShowUserMsg))); this.lastPayed = false; //清理支付码 this.txtPayCode.Text = string.Empty; //允许扫码框输入 this.txtPayCode.Enabled = true; this.txtPayCode.Text = string.Empty; this.txtPayCode.Focus(); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "查询结果:" + _response.ShowUserMsg)); } } catch (Exception ex) { LOGGER.Error(ex, "订单[" + outTradeNo + "]通联支付[" + Convert.ToInt32(_amount * 100) + "]分,支付发生异常!"); isQuery = false; allinPay_OrderId = ""; UpdateSaomaTicket(outTradeNo, allinPay_OrderId, applyParam.timestamp); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "查不到支付状态,请使用手工核销功能...")); if (isResquest) { this.lastPayed = false; } } //return new Tuple(isQuery, outTradeNo, (decimal)_amount * 100); if (isQuery) { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "正在确认扣款状态")); this.initValue = 10; this.timeout = 90; 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 void QueryPayChannel_Allin() { //进度条最大值 int maximum = this.PayStep3.Maximum; this.PayStep3.Value = (initValue++); //判断是否超时,如果超时终止计时器,界面反馈信息 if (initValue % this.PayStep3.Maximum == 0) { //计时器停止 this.timer.Stop(); //发送结果通知 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "查询支付结果超时")); LOGGER.Warn("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this._orderObject.TradeNo); var dialog = new DialogForm("支付结果", "没有查询到支付结果,系统无法确认本单已经支付", MessageBoxIcon.Warning, MessageBoxButtons.RetryCancel); if (DialogResult.Retry == dialog.ShowDialog()) { LOGGER.Warn("收银员手动选择重新查询一次结果,订单号<{0}>", this._orderObject.TradeNo); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "等待确认扣款状态")); this.initValue = 10; this.timeout = 90; this.txtPayCode.Enabled = false; //启动定时器 this.timer.Start(); } else { OnPayCodeCheckClick(null, null); LOGGER.Warn("收银员手动放弃结果确认,订单号<{0}>", this._orderObject.TradeNo); //清理支付码 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.QueryAllinPayResult(); } } private void QueryAllinPayResult() { try { var payParam = this.CurrentPayMode.Body; AllinpayLib.AppId = payParam.ContainsKey("appId") ? payParam["appId"].ToString() : ""; AllinpayLib.AppKey = payParam.ContainsKey("appKey") ? payParam["appKey"].ToString() : ""; AllinpayLib.Url = payParam.ContainsKey("gatewayUrl") ? payParam["gatewayUrl"].ToString() : ""; //商户订单号 string outTradeNo = string.Format("{0}_{1}", this._orderObject.StoreNo, this._orderObject.TradeNo); //string outTradeNo = this._orderObject.TradeNo; var info = new GetOrderDetailModel() { reqsn = this._orderObject.TradeNo, }; var param = new GetOrderDetailParamInfo { bizContent = JsonUtils.Serialize(info) }; var _response = AllinpayHelper.GetOrderDetail(param); if (!_response.IsSuccess) { //明确失败,结束查询 //计时器停止 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(); //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, _response.ShowUserMsg)); LOGGER.Warn("订单[{0}]通联支付查询,错误:{0}", _orderObject.TradeNo, _response.ShowUserMsg); } else { var _data = JsonUtils.Deserialize(_response.ResultInfo.data); var _statusDesc = "进行中"; switch (_data.status) { case "1": _statusDesc = "未支付"; break; case "3": _statusDesc = "交易失败"; break; case "4": _statusDesc = "交易成功"; break; case "5": _statusDesc = "交易成功-发生退款"; break; case "6": _statusDesc = "关闭"; break; case "99": _statusDesc = "进行中"; break; } if ("4".Equals(_data.status)) { //计时器停止 this.timer.Stop(); //更新付款状态 lock (_lock) { if (!isPay) { isPay = true; } else { return; } } this.PayStep3.Value = this.PayStep3.Maximum; //发送消息通知显示文本 MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(true, "通联支付成功")); //构建支付方式,播放支付语音 AddAllinPayType(_data); //发送自动完成结账事件 MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "通联支付付款成功"); //清理支付码 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 if ("3".Equals(_data.status)) { //计时器停止 this.timer.Stop(); this.lastPayed = false; //清理支付码 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(); MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "查询结果:" + _statusDesc)); } else { MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple(false, "查询结果:" + _statusDesc)); } } } catch (Exception ex) { LOGGER.Error(ex, "通联支付结果查询发生异常"); } } #endregion } }