You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2960 lines
126 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
{
/// <summary>
/// PayStep3初始值
/// </summary>
private int initValue = 10;
/// <summary>
/// 是否等待用户输入支付密码
/// </summary>
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 = "<font size=\"+3\"><b> " + LangProxy.ToLang("等待扫描") + " </b></font><br/><font size=\"-1\"> " + LangProxy.ToLang("请扫描付款码") + " </font>";
PayStep2.Text = "<font size=\"+3\"><b>" + LangProxy.ToLang("发起扣款") + "</b></font><br/><font size=\"-1\">" + LangProxy.ToLang("发起扣款请求") + " </font>";
PayStep3.Text = "<font size=\"+3\"><b>" + LangProxy.ToLang("确认结果") + "</b></font><br/><font size=\"-1\">" + LangProxy.ToLang("确认扣款结果") + " </font>";
}
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;
}
}
/// <summary>
/// 订单对象
/// </summary>
private OrderObject _orderObject = null;
/// <summary>
/// 支付渠道
/// </summary>
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<bool, string>(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("查询支付结果中....");
}
/// <summary>
/// 操作是否验证通过
/// </summary>
private bool PaymentVerify = false;
/// <summary>
/// 当前的支付方式
/// </summary>
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<bool, string>(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<bool, string>(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<bool, string>(true, "支付码不合法..."));
this.PaymentVerify = false;
}
else
{
if (this.CurrentPayMode == null)
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(true, "支付码不合法或尚未适配..."));
this.PaymentVerify = false;
}
else
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(false, "扫描" + this.CurrentPayMode.Name + "付款码..."));
this.PaymentVerify = VerifyInputValue(payCode, this.CurrentPayMode);
}
}
#endregion
}
}
else
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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;
LOGGER.Info($"订单支付失败,重新生成订单号,原单号:[{Global.Instance.BusinessPlanLog.StoreNo}_{oldTradeNo}]==>新单号:[{Global.Instance.BusinessPlanLog.StoreNo}_{_orderObject.TradeNo}]......开始");
foreach (var item in this._orderObject.Items)
{
item.TradeNo = this._orderObject.TradeNo;
LOGGER.Info($"订单支付失败,原订单[{oldTradeNo}]商品<{item.ShortName}:{item.Id}>,重置订单号:{_orderObject.TradeNo}");
}
using (var db = Global.Instance.OpenDataBase)
{
//订单保存成功更新核销状态
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}]......pos_saoma_pay_ticket更新成功");
//发送支付失败,重新生成订单号事件
MsgEvent.Send(Constant.ORDER_PAYMENT_ERROR_GENERATENO, _orderObject.TradeNo);
}
LOGGER.Info($"订单支付失败,重新生成订单号,原单号:[{Global.Instance.BusinessPlanLog.StoreNo}_{oldTradeNo}]==>新单号:[{Global.Instance.BusinessPlanLog.StoreNo}_{_orderObject.TradeNo}]......更新成功");
}
else
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<bool, string>(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;
}
}
/// <summary>
/// 优先记录核销
/// </summary>
/// <param name="busNo"></param>
/// <param name="authCode"></param>
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<SaomaPayTicket>(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<SaomaPayTicket>(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;
}
/// <summary>
/// 根据扫描码适配支付方式
///
/// 支付宝授权码25~30开头的长度为16~24位的数字
///
/// 微信授权码 18位纯数字以10、11、12、13、14、15开头
///
/// </summary>
/// <param name="payCode"></param>
/// <returns></returns>
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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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 原生支付渠道
/// <summary>
/// 查询原生支付结果
/// </summary>
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<bool, string>(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<bool, string>(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;
}
}
}
/// <summary>
/// 原生支付
/// </summary>
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<bool, string>(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<bool, string>(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 原生微信支付
/// <summary>
/// 微信支付,返回是否确认查询结果
/// </summary>
/// <returns></returns>
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<bool, string>(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<bool, string>(true, "网络超时,正在查询支付状态,请稍候..."));
isQuery = true;
}
break;
case WxPayErrCode.BANKERROR:
{
this.PayStep2.Value = this.PayStep2.Maximum;
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(true, "银行端超时,正在查询支付状态,请稍候..."));
isQuery = true;
}
break;
case WxPayErrCode.USERPAYING:
{
this.PayStep2.Value = this.PayStep2.Maximum;
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(true, "等待用户输入密码,请稍候..."));
//需等待输入密码,需要确认结果
isQuery = true;
}
break;
case WxPayErrCode.ORDERPAID:
{
this.PayStep2.Value = this.PayStep2.Minimum;
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(true, "订单号重复支付,请使用新订单"));
isQuery = false;
}
break;
case WxPayErrCode.AUTHCODEEXPIRE:
{
this.PayStep2.Value = this.PayStep2.Minimum;
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(true, "二维码过期,请用户在微信上刷新后再试"));
isQuery = false;
}
break;
case WxPayErrCode.NOTENOUGH:
{
this.PayStep2.Value = this.PayStep2.Minimum;
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(true, "用户余额不足,请用户换卡支付"));
isQuery = false;
}
break;
case WxPayErrCode.NOTSUPORTCARD:
{
this.PayStep2.Value = this.PayStep2.Minimum;
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<bool, string>(true, "商户订单号重复,请消单后重新下单"));
}
else
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(true, result.err_code_des));
}
isQuery = false;
}
break;
default:
{
this.PayStep2.Value = this.PayStep2.Minimum;
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(true, "密码错误或未输入,请重新扫码"));
}
break;
default:
{
string message = string.Format("{0}:{1}秒", result.trade_state_desc, --timeout);
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<bool, string>(true, "微信:未收到该订单,请重新扫码"));
}
else
{
string message = string.Format("正在确认微信扣款结果:{0}秒,{1}", --timeout, result.err_code_des);
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(false, message));
}
}
}
else
{
LOGGER.Warn("查询支付结果网络通信错误:{0}", result.return_msg);
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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 原生支付宝
/// <summary>
/// 支付宝付款,返回是否确认查询结果
/// </summary>
/// <returns></returns>
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, object>();
//商户订单号
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<string, object>();
extend.Add("sys_service_provider_id", pid);
content.Add("extend_params", extend);
}
var goods = new List<Dictionary<string, object>>();
var details = new Dictionary<string, object>();
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<bool, string>(false, "等待确认扣款结果..."));
}
else
{
isQuery = false;
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<bool, string>(true, "支付宝私钥配置错误..."));
isQuery = false;
}
else
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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, object>();
//商户订单号
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<bool, string>(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<bool, string>(false, "等待买家付款..."));
}
break;
default:
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<bool, string>(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<bool, string>(false, _data.Item2));
this.txtPayCode.Enabled = true;
return;
}
//发送消息通知显示文本
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<PayItem>();
}
_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<bool, string>(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<bool, string>(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<bool, string>(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<SaomaPayTicket>(string.Format("where orderNo = '{0}_{1}'", this._orderObject.StoreNo, this._orderObject.TradeNo));
if (_ticket == null)
{
this.LOGGER.Info("在SaomaPayTicket 中查询不到相关数据");
return;
}
Dictionary<string, string> keys = new Dictionary<string, string>();
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<bool, string>(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<PayItem>();
}
_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<bool, string>(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<bool, string>(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<bool, string> VerifyOrderPay()
{
using (var _db = Global.Instance.OpenDataBase)
{
var _data = _db.FirstOrDefault<SaomaPayTicket>(string.Format("where orderNo = '{0}_{1}'", this._orderObject.StoreNo, this._orderObject.TradeNo));
if (_data == null)
{
return new Tuple<bool, string>(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<bool, string>(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<bool, string>(true, "");
}
return new Tuple<bool, string>(false, "支付异常,请联系管理员");
}
if (_data.Money != this._orderObject.ReceivableAmount - this._orderObject.MalingAmount)
{
return new Tuple<bool, string>(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<bool, string>(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<bool, string>(true, "");
}
}
return new Tuple<bool, string>(false, "");
}
}
private Tuple<bool, string, decimal> 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<bool, string>(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<bool, string>(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<bool, string>(false, "查不到支付状态,请使用手工核销功能..."));
}
return new Tuple<bool, string, decimal>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(true, "通联支付参数未配置门店付款会员号..."));
// return false;
//}
return true;
}
private Tuple<bool, string> VerifyOrderAllinPay()
{
using (var _db = Global.Instance.OpenDataBase)
{
var _ticket = _db.FirstOrDefault<SaomaPayTicket>(string.Format("where orderNo = '{0}_{1}'", this._orderObject.StoreNo, this._orderObject.TradeNo));
if (_ticket == null)
{
return new Tuple<bool, string>(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<bool, string>(true, "通联支付付款成功");
}
return new Tuple<bool, string>(false, "支付异常,请联系管理员");
}
if (_ticket.Money != this._orderObject.ReceivableAmount - this._orderObject.MalingAmount)
{
return new Tuple<bool, string>(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<bool, string>(false, response.ShowUserMsg));
//LOGGER.Warn("订单号<{0}>支付查询异常:{1}", this._orderObject.TradeNo, response.ShowUserMsg);
LOGGER.Warn("订单[{0}]通联支付查询,网络通信错误:{1}", _orderObject.TradeNo, response.ShowUserMsg);
return new Tuple<bool, string>(false, "支付查询异常");
}
var _data = JsonUtils.Deserialize<OrderDetail>(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<bool, string>(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<bool, string>(true, "通联支付付款成功");
}
return new Tuple<bool, string>(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<ApplyReciever>();
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<OrderSubStoreDetail>(sql).ToList();
// var bizUseIdLst = orderSubStoreDetail.Count() > 0 ? orderSubStoreDetail.Select(item => item.BizUserId).Distinct().ToList() : new List<string>();
// if (bizUseIdLst.Count() == 0)
// {
// LOGGER.Warn("订单[{0}]通联支付[{1}]分支付异常:收款方列表为空", _orderObject.TradeNo, Convert.ToInt32(_amount * 100));
// MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<AgentCollectApply>(_response.ResultInfo.data);
allinPay_OrderId = _data.orderNo;
UpdateSaomaTicket(outTradeNo, allinPay_OrderId, applyParam.timestamp);
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(false, "查不到支付状态,请使用手工核销功能..."));
if (isResquest)
{
this.lastPayed = false;
}
}
//return new Tuple<bool, string, decimal>(isQuery, outTradeNo, (decimal)_amount * 100);
if (isQuery)
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(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<bool, string>(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<bool, string>(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<bool, string>(false, _response.ShowUserMsg));
LOGGER.Warn("订单[{0}]通联支付查询,错误:{0}", _orderObject.TradeNo, _response.ShowUserMsg);
}
else
{
var _data = JsonUtils.Deserialize<OrderDetail>(_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<bool, string>(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<bool, string>(false, "查询结果:" + _statusDesc));
}
else
{
MsgEvent.Send(Constant.PAY_MESSAGE_EVENT_NOTIFY, new Tuple<bool, string>(false, "查询结果:" + _statusDesc));
}
}
}
catch (Exception ex)
{
LOGGER.Error(ex, "通联支付结果查询发生异常");
}
}
#endregion
}
}