|
|
|
|
using Aop.Api;
|
|
|
|
|
using Aop.Api.Request;
|
|
|
|
|
using Aop.Api.Response;
|
|
|
|
|
using POSV.Bill;
|
|
|
|
|
using POSV.Component;
|
|
|
|
|
using POSV.Entity;
|
|
|
|
|
using POSV.MessageEvent;
|
|
|
|
|
using POSV.PayApi;
|
|
|
|
|
using POSV.Payment.Saobei;
|
|
|
|
|
using POSV.Payment.Saobei.Parameter;
|
|
|
|
|
using POSV.Payment.Saobei.Result;
|
|
|
|
|
using POSV.ShoppingCart;
|
|
|
|
|
using POSV.Utils;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
|
|
|
|
namespace POSV.Business
|
|
|
|
|
{
|
|
|
|
|
public partial class MPayDialogForm : BusinessForm
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 支付支付通知,用于新版本食堂版,异步通知支付结果
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
public delegate void PayResultPush(OrderObject _data, string payCode,bool succeed, Exception exception);
|
|
|
|
|
|
|
|
|
|
public PayResultPush payResultPush = null;
|
|
|
|
|
|
|
|
|
|
/// <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;
|
|
|
|
|
|
|
|
|
|
private string SAOBEI_QRCodeType = "";
|
|
|
|
|
private string SAOBEI_PAYTIME = "";
|
|
|
|
|
private string SAOBEI_OrderId = "";
|
|
|
|
|
|
|
|
|
|
public static object _lock = new object();
|
|
|
|
|
|
|
|
|
|
public bool isPay = false;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 订单对象
|
|
|
|
|
/// </summary>
|
|
|
|
|
private OrderObject _orderObject = null;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 支付渠道
|
|
|
|
|
/// </summary>
|
|
|
|
|
private PayChannelEnum _payChannel = PayChannelEnum.原生支付;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public MPayDialogForm(OrderObject orderObject)
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
|
|
|
|
|
MsgEvent.RemoveListener(Constant.PAY_AUTO_EVENT_NOTIFY, FinishedEventNotify);
|
|
|
|
|
MsgEvent.Receive(Constant.PAY_AUTO_EVENT_NOTIFY, FinishedEventNotify);
|
|
|
|
|
|
|
|
|
|
this._orderObject = orderObject;
|
|
|
|
|
|
|
|
|
|
this.lblTips.Text = string.Format(this.lblTips.Tag.ToString(), this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount);
|
|
|
|
|
|
|
|
|
|
this.initValue = 10;
|
|
|
|
|
|
|
|
|
|
this.SAOBEI_QRCodeType = "";
|
|
|
|
|
this.SAOBEI_OrderId = "";
|
|
|
|
|
|
|
|
|
|
this.isPay = false;
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = "请扫描或输入支付码...";
|
|
|
|
|
|
|
|
|
|
this._orderObject = orderObject;
|
|
|
|
|
//初始化支付状态
|
|
|
|
|
this.isPay = false;
|
|
|
|
|
|
|
|
|
|
//微信支付不允许抹零
|
|
|
|
|
this._orderObject.MalingAmount = 0;
|
|
|
|
|
//微信支付不允许找零
|
|
|
|
|
this._orderObject.ChangeAmount = 0;
|
|
|
|
|
|
|
|
|
|
//将当前应收金额赋值
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
this.txtPayCode.SelectAll();
|
|
|
|
|
|
|
|
|
|
//支付结果查询的计时器
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void FinishedEventNotify(object sender, MsgEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
//整单状态
|
|
|
|
|
this._orderObject.OrderStatus = OrderStatus.已完成;
|
|
|
|
|
//整单支付状态
|
|
|
|
|
this._orderObject.PaymentStatus = OrderPaymentStatus.已付款;
|
|
|
|
|
//通知主界面结账成功
|
|
|
|
|
MsgEvent.Send(Constant.ORDER_PAYMENT_NOTIFY, this._orderObject);
|
|
|
|
|
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
|
|
|
|
|
//关闭界面
|
|
|
|
|
BillClose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnLoad(EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
base.OnLoad(e);
|
|
|
|
|
if (DesignMode) return;
|
|
|
|
|
|
|
|
|
|
SetStyle(ControlStyles.Selectable, true);
|
|
|
|
|
|
|
|
|
|
this.txtPayCode.Multiline = false;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
this.txtPayCode.SelectAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnTimerTick(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() => {
|
|
|
|
|
|
|
|
|
|
switch (this._payChannel)
|
|
|
|
|
{
|
|
|
|
|
case PayChannelEnum.原生支付:
|
|
|
|
|
{
|
|
|
|
|
QueryPayChannel_0();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case PayChannelEnum.扫呗支付:
|
|
|
|
|
{
|
|
|
|
|
QueryPayChannel_SAOBEI();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
LOGGER.Info("查询支付结果中....");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 操作是否验证通过
|
|
|
|
|
/// </summary>
|
|
|
|
|
private bool PaymentVerify = false;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 当前的支付方式
|
|
|
|
|
/// </summary>
|
|
|
|
|
private PayMode CurrentPayMode = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void OnKeyBoardTouchAfter(object sender, KeyboardExtEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
switch (e.KeyCode)
|
|
|
|
|
{
|
|
|
|
|
case "clear":
|
|
|
|
|
//如果当前焦点控件是输入框
|
|
|
|
|
if (this.ActiveControl is TextBox)
|
|
|
|
|
{
|
|
|
|
|
var activeControl = this.ActiveControl as TextBox;
|
|
|
|
|
activeControl.Text = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "close":
|
|
|
|
|
{
|
|
|
|
|
OnCloseClick(sender, EventArgs.Empty);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "accept":
|
|
|
|
|
//验证通过
|
|
|
|
|
if (this.PaymentVerify && this.CurrentPayMode != null)
|
|
|
|
|
{
|
|
|
|
|
this.OnAcceptButtonClick(new TransparentEventArgs(TransparentAction.Accept, e.KeyCode, this._orderObject));
|
|
|
|
|
//保存扫描支付单号
|
|
|
|
|
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_SAOBEI();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
this.Owner.Visible = false;
|
|
|
|
|
this.Visible = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "100":
|
|
|
|
|
{
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["1"]);
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["0"]);
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["0"]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "50":
|
|
|
|
|
{
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["5"]);
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["0"]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "20":
|
|
|
|
|
{
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["2"]);
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["0"]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "10":
|
|
|
|
|
{
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["1"]);
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["0"]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map[e.KeyCode]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnCloseClick(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
BillClose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void BillClose() {
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
|
|
|
|
|
this._orderObject = null;
|
|
|
|
|
|
|
|
|
|
this._payChannel = PayChannelEnum.无;
|
|
|
|
|
|
|
|
|
|
if (this.timer != null)
|
|
|
|
|
{
|
|
|
|
|
this.timer.Stop();
|
|
|
|
|
this.timer = null;
|
|
|
|
|
|
|
|
|
|
LOGGER.Info("释放查询任务");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.Owner != null)
|
|
|
|
|
{
|
|
|
|
|
this.Owner.Close();
|
|
|
|
|
}
|
|
|
|
|
this.Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnKeyboardBefore(object sender, KeyboardExtEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
this.PaymentVerify = false;
|
|
|
|
|
|
|
|
|
|
this.CurrentPayMode = null;
|
|
|
|
|
|
|
|
|
|
if (this._orderObject == null)
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "订单数据错误啦,请拍个照...";
|
|
|
|
|
|
|
|
|
|
this.PaymentVerify = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (this._orderObject.PaidAmount > 0)
|
|
|
|
|
{
|
|
|
|
|
//获取扫描码
|
|
|
|
|
var payCode = this.txtPayCode.Text.Trim();
|
|
|
|
|
if (string.IsNullOrEmpty(payCode))
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "请扫描或输入支付码...";
|
|
|
|
|
|
|
|
|
|
this.PaymentVerify = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.CurrentPayMode = GetPayMode(payCode);
|
|
|
|
|
|
|
|
|
|
if (this.CurrentPayMode == null)
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "支付码不合法或尚未适配...";
|
|
|
|
|
|
|
|
|
|
this.PaymentVerify = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "扫描" + this.CurrentPayMode.Name + "付款码...";
|
|
|
|
|
|
|
|
|
|
this.PaymentVerify = VerifyInputValue(payCode, this.CurrentPayMode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "付款金额非法...";
|
|
|
|
|
|
|
|
|
|
this.PaymentVerify = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region 验证付款码、支付参数是否正确
|
|
|
|
|
|
|
|
|
|
private bool VerifyWxPay(string payCode, PayMode payMode)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(payCode) || payCode.Length != 18)
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "微信付款码非法...";
|
|
|
|
|
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))
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "微信支付参数配置不完整...";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool VerifyAliPay(string payCode, PayMode payMode)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(payCode) || (payCode.Length < 16 || payCode.Length > 24))
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "支付宝付款码非法...";
|
|
|
|
|
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))
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "支付宝支付参数配置不完整...";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool VerifyInputValue(string payCode, PayMode payMode)
|
|
|
|
|
{
|
|
|
|
|
bool isVerify = false;
|
|
|
|
|
|
|
|
|
|
var parameter = payMode.Body;
|
|
|
|
|
if (parameter == null || parameter.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "尚未配置支付参数...";
|
|
|
|
|
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 "saobei":
|
|
|
|
|
{
|
|
|
|
|
this._payChannel = PayChannelEnum.扫呗支付;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "目前暂不支持该类型付款码...";
|
|
|
|
|
|
|
|
|
|
isVerify = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case PayChannelEnum.扫呗支付:
|
|
|
|
|
{
|
|
|
|
|
isVerify = VerifySAOBEIPay(payCode, payMode);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return isVerify;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 原生支付渠道
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 查询原生支付结果
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void QueryPayChannel_0()
|
|
|
|
|
{
|
|
|
|
|
//进度条最大值
|
|
|
|
|
int maximum = 70;
|
|
|
|
|
initValue = initValue + 1;
|
|
|
|
|
//判断是否超时,如果超时终止计时器,界面反馈信息
|
|
|
|
|
if (initValue % maximum == 0)
|
|
|
|
|
{
|
|
|
|
|
//计时器停止
|
|
|
|
|
this.timer.Stop();
|
|
|
|
|
|
|
|
|
|
//修改结果颜色
|
|
|
|
|
//this.PayStep3.ProgressColors = new Color[] { Color.Red , Color.Red };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//发送结果通知
|
|
|
|
|
this.labelMessage.Text = "查询支付结果超时";
|
|
|
|
|
|
|
|
|
|
LOGGER.Warn("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this._orderObject.TradeNo);
|
|
|
|
|
|
|
|
|
|
//回掉通知
|
|
|
|
|
if (this.payResultPush != null)
|
|
|
|
|
{
|
|
|
|
|
this.payResultPush(this._orderObject, this.txtPayCode.Text, false, new Exception("查询支付结果超时"));
|
|
|
|
|
return;//不在启用窗口提示
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dialog = new DialogForm("支付结果", "没有查询到支付结果,系统无法确认本单已经支付", MessageBoxIcon.Warning, MessageBoxButtons.RetryCancel);
|
|
|
|
|
if (DialogResult.Retry == dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Warn("收银员手动选择重新查询一次结果,订单号<{0}>", this._orderObject.TradeNo);
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = "等待确认扣款状态";
|
|
|
|
|
|
|
|
|
|
this.initValue = 10;
|
|
|
|
|
|
|
|
|
|
this.timeout = 60;
|
|
|
|
|
|
|
|
|
|
this.txtPayCode.Enabled = false;
|
|
|
|
|
this.billKeyboard1.LockCancel();
|
|
|
|
|
|
|
|
|
|
//启动定时器
|
|
|
|
|
this.timer.Start();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Warn("收银员手动放弃结果确认,订单号<{0}>", this._orderObject.TradeNo);
|
|
|
|
|
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
case "04":
|
|
|
|
|
{
|
|
|
|
|
var isQuery = AliPayResult();
|
|
|
|
|
|
|
|
|
|
if (isQuery)
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "正在确认扣款状态";
|
|
|
|
|
|
|
|
|
|
this.initValue = 10;
|
|
|
|
|
|
|
|
|
|
this.timeout = 60;
|
|
|
|
|
|
|
|
|
|
this.txtPayCode.Enabled = false;
|
|
|
|
|
this.billKeyboard1.LockCancel();
|
|
|
|
|
|
|
|
|
|
//启动定时器
|
|
|
|
|
this.timer.Start();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "05":
|
|
|
|
|
{
|
|
|
|
|
var isQuery = WxPayResult();
|
|
|
|
|
|
|
|
|
|
//需要查询支付结果的两种情况:1)支付提示扣款成功;2)支付结果未知
|
|
|
|
|
if (isQuery)
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "等待确认扣款状态";
|
|
|
|
|
|
|
|
|
|
this.initValue = 10;
|
|
|
|
|
|
|
|
|
|
this.timeout = 60;
|
|
|
|
|
|
|
|
|
|
this.txtPayCode.Enabled = false;
|
|
|
|
|
this.billKeyboard1.LockCancel();
|
|
|
|
|
|
|
|
|
|
//启动定时器
|
|
|
|
|
this.timer.Start();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
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;
|
|
|
|
|
this.billKeyboard1.LockCancel();
|
|
|
|
|
|
|
|
|
|
//发起微信扣款请求
|
|
|
|
|
this.labelMessage.Text = "发起微信扣款请求";
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
LOGGER.Info("订单[{0}]微信扣款返回结果:{1}", outTradeNo, JsonUtils.Serialize(result));
|
|
|
|
|
|
|
|
|
|
if ("SUCCESS".Equals(result.return_code))
|
|
|
|
|
{
|
|
|
|
|
if ("SUCCESS".Equals(result.result_code))
|
|
|
|
|
{
|
|
|
|
|
//需要直接确认结果,无需等待输入密码
|
|
|
|
|
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.labelMessage.Text = "网络超时,正在查询支付状态,请稍候...";
|
|
|
|
|
isQuery = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayErrCode.BANKERROR:
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "银行端超时,正在查询支付状态,请稍候...";
|
|
|
|
|
|
|
|
|
|
isQuery = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayErrCode.USERPAYING:
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "等待用户输入密码,请稍候...";
|
|
|
|
|
|
|
|
|
|
//需等待输入密码,需要确认结果
|
|
|
|
|
isQuery = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayErrCode.ORDERPAID:
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "订单号重复支付,请使用新订单";
|
|
|
|
|
|
|
|
|
|
isQuery = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayErrCode.AUTHCODEEXPIRE:
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = "二维码过期,请用户在微信上刷新后再试";
|
|
|
|
|
|
|
|
|
|
isQuery = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayErrCode.NOTENOUGH:
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "用户余额不足,请用户换卡支付";
|
|
|
|
|
|
|
|
|
|
isQuery = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayErrCode.NOTSUPORTCARD:
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "不支持当前支付,请用户换卡或绑新卡支付";
|
|
|
|
|
isQuery = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayErrCode.INVALID_REQUEST:
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (result.err_code_des == "201 商户订单号重复")
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "商户订单号重复,请消单后重新下单";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = result.err_code_des;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isQuery = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = result.err_code_des;
|
|
|
|
|
isQuery = false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Warn("订单[{0}]微信支付[{1}]分,微信支付网络通信错误:{0}", outTradeNo, totalFee, result.return_msg);
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = result.return_msg;
|
|
|
|
|
|
|
|
|
|
//Task.Factory.StartNew(new Action(() =>
|
|
|
|
|
//{
|
|
|
|
|
// Global.Instance.BugReport(new Exception("微信支付错误2" + JsonUtils.Serialize(result)));
|
|
|
|
|
//}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "微信支付发生异常,开始确认支付结果";
|
|
|
|
|
|
|
|
|
|
LOGGER.Error(ex, "微信支付发生异常");
|
|
|
|
|
|
|
|
|
|
//发起支付发生异常,为了避免客户已经收到请求,开始支付,这里进行补救查询
|
|
|
|
|
isQuery = true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.AddWxPayType(result);
|
|
|
|
|
//微信支付更新核销状态
|
|
|
|
|
//UpdateSaoMa(outTradeNo);
|
|
|
|
|
//发送自动完成结账事件
|
|
|
|
|
this.labelMessage.Text = "微信支付成功";
|
|
|
|
|
|
|
|
|
|
//整单状态
|
|
|
|
|
this._orderObject.OrderStatus = OrderStatus.已完成;
|
|
|
|
|
//整单支付状态
|
|
|
|
|
this._orderObject.PaymentStatus = OrderPaymentStatus.已付款;
|
|
|
|
|
//通知主界面结账成功
|
|
|
|
|
MsgEvent.Send(Constant.ORDER_PAYMENT_NOTIFY, this._orderObject);
|
|
|
|
|
|
|
|
|
|
//MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "微信支付成功");
|
|
|
|
|
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
|
|
|
|
|
//关闭界面
|
|
|
|
|
BillClose();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayTradeState.USERPAYING:
|
|
|
|
|
{
|
|
|
|
|
string message = string.Format("{0}:{1}秒", "请提示用户输入支付密码", --timeout);
|
|
|
|
|
this.labelMessage.Text = message;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case WxPayTradeState.NOTPAY:
|
|
|
|
|
case WxPayTradeState.PAYERROR:
|
|
|
|
|
{
|
|
|
|
|
//计时器停止
|
|
|
|
|
this.timer.Stop();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = "密码错误或未输入,请重新扫码";
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
string message = string.Format("{0}:{1}秒", result.trade_state_desc, --timeout);
|
|
|
|
|
this.labelMessage.Text = message;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (result.err_code == "ORDERNOTEXIST")
|
|
|
|
|
{
|
|
|
|
|
//计时器停止
|
|
|
|
|
this.timer.Stop();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = "微信:未收到该订单,请重新扫码";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string message = string.Format("正在确认微信扣款结果:{0}秒,{1}", --timeout, result.err_code_des);
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = message;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Warn("查询支付结果网络通信错误:{0}", result.return_msg);
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = 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);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#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;
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = "等待确认扣款结果...";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isQuery = false;
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = string.Format("{0}<{1}>", response.SubMsg, response.SubCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "支付宝付款发生异常");
|
|
|
|
|
|
|
|
|
|
if (ex.Message.Contains("私钥格式错误"))
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "支付宝私钥配置错误...";
|
|
|
|
|
|
|
|
|
|
isQuery = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "支付宝付款发生异常...";
|
|
|
|
|
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.AddAliPayType(response);
|
|
|
|
|
|
|
|
|
|
//发送自动完成结账事件
|
|
|
|
|
this.labelMessage.Text = "支付宝付款成功";
|
|
|
|
|
//整单状态
|
|
|
|
|
this._orderObject.OrderStatus = OrderStatus.已完成;
|
|
|
|
|
//整单支付状态
|
|
|
|
|
this._orderObject.PaymentStatus = OrderPaymentStatus.已付款;
|
|
|
|
|
//通知主界面结账成功
|
|
|
|
|
MsgEvent.Send(Constant.ORDER_PAYMENT_NOTIFY, this._orderObject);
|
|
|
|
|
|
|
|
|
|
if (this.payResultPush != null)
|
|
|
|
|
{
|
|
|
|
|
this.payResultPush(this._orderObject, this.txtPayCode.Text, true, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "支付宝付款成功");
|
|
|
|
|
//微信支付更新核销状态
|
|
|
|
|
//UpdateSaoMa(outTradeNo);
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//关闭界面
|
|
|
|
|
BillClose();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "WAIT_BUYER_PAY":
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "等待买家付款...";
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "等待买家付款...";
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 扫呗支付渠道
|
|
|
|
|
|
|
|
|
|
private void PayChannel_SAOBEI()
|
|
|
|
|
{
|
|
|
|
|
this.SAOBEI_QRCodeType = "";
|
|
|
|
|
this.SAOBEI_OrderId = "";
|
|
|
|
|
var saobeiPayResult = SAOBEIPayResult();
|
|
|
|
|
|
|
|
|
|
if (saobeiPayResult.Item1)
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "正在确认扣款状态";
|
|
|
|
|
|
|
|
|
|
this.initValue = 10;
|
|
|
|
|
|
|
|
|
|
this.timeout = 60;
|
|
|
|
|
|
|
|
|
|
this.txtPayCode.Enabled = false;
|
|
|
|
|
this.billKeyboard1.LockCancel();
|
|
|
|
|
|
|
|
|
|
//启动定时器
|
|
|
|
|
this.timer.Start();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.ToInt16(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";
|
|
|
|
|
}
|
|
|
|
|
this.SAOBEI_QRCodeType = request.Pay_type;
|
|
|
|
|
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);
|
|
|
|
|
this.labelMessage.Text = "等待确认扣款结果...";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isQuery = false;
|
|
|
|
|
this.SAOBEI_QRCodeType = "";
|
|
|
|
|
this.SAOBEI_OrderId = "";
|
|
|
|
|
UpdateSaomaTicket(outTradeNo, this.SAOBEI_OrderId, this.SAOBEI_PAYTIME);
|
|
|
|
|
this.labelMessage.Text = 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);
|
|
|
|
|
this.labelMessage.Text = "查不到支付状态,请使用手工核销功能...";
|
|
|
|
|
}
|
|
|
|
|
return new Tuple<bool, string, decimal>(isQuery, orderId, payAmount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void QueryPayChannel_SAOBEI()
|
|
|
|
|
{
|
|
|
|
|
//进度条最大值
|
|
|
|
|
int maximum = 70;
|
|
|
|
|
initValue = initValue + 1;
|
|
|
|
|
|
|
|
|
|
//判断是否超时,如果超时终止计时器,界面反馈信息
|
|
|
|
|
if (initValue % maximum == 0)
|
|
|
|
|
{
|
|
|
|
|
//计时器停止
|
|
|
|
|
this.timer.Stop();
|
|
|
|
|
//修改结果颜色
|
|
|
|
|
//this.PayStep3.ProgressColors = new Color[] { Color.Red , Color.Red };
|
|
|
|
|
|
|
|
|
|
//发送结果通知
|
|
|
|
|
this.labelMessage.Text = "查询支付结果超时";
|
|
|
|
|
|
|
|
|
|
LOGGER.Warn("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this._orderObject.TradeNo);
|
|
|
|
|
|
|
|
|
|
//回掉通知
|
|
|
|
|
if (this.payResultPush != null)
|
|
|
|
|
{
|
|
|
|
|
this.payResultPush(this._orderObject, this.txtPayCode.Text, false, new Exception(string.Format("查询支付结果超时,系统无法确认本单已经支付,订单号<{0}>", this._orderObject.TradeNo)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var dialog = new DialogForm("支付结果", "没有查询到支付结果,系统无法确认本单已经支付", MessageBoxIcon.Warning, MessageBoxButtons.RetryCancel);
|
|
|
|
|
if (DialogResult.Retry == dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Warn("收银员手动选择重新查询一次结果,订单号<{0}>", this._orderObject.TradeNo);
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = "等待确认扣款状态";
|
|
|
|
|
|
|
|
|
|
this.initValue = 10;
|
|
|
|
|
|
|
|
|
|
this.timeout = 60;
|
|
|
|
|
|
|
|
|
|
this.txtPayCode.Enabled = false;
|
|
|
|
|
this.billKeyboard1.LockCancel();
|
|
|
|
|
//启动定时器
|
|
|
|
|
this.timer.Start();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Warn("收银员手动放弃结果确认,订单号<{0}>", this._orderObject.TradeNo);
|
|
|
|
|
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
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.labelMessage.Text = "扫呗支付成功";
|
|
|
|
|
//构建支付方式
|
|
|
|
|
this.AddSAOBEIPayType(saobeiPayment.Item3);
|
|
|
|
|
//整单状态
|
|
|
|
|
this._orderObject.OrderStatus = OrderStatus.已完成;
|
|
|
|
|
//整单支付状态
|
|
|
|
|
this._orderObject.PaymentStatus = OrderPaymentStatus.已付款;
|
|
|
|
|
//通知主界面结账成功
|
|
|
|
|
MsgEvent.Send(Constant.ORDER_PAYMENT_NOTIFY, this._orderObject);
|
|
|
|
|
|
|
|
|
|
//回掉通知
|
|
|
|
|
if (this.payResultPush != null)
|
|
|
|
|
{
|
|
|
|
|
this.payResultPush(this._orderObject, this.txtPayCode.Text, true, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//发送自动完成结账事件
|
|
|
|
|
//MsgEvent.Send(Constant.PAY_AUTO_EVENT_NOTIFY, "扫呗支付付款成功");
|
|
|
|
|
//微信支付更新核销状态
|
|
|
|
|
//UpdateSaoMa(outTradeNo);
|
|
|
|
|
//清理支付码
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
|
|
|
|
|
//关闭界面
|
|
|
|
|
BillClose();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "查询结果:" + saobeiPayment.Item2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//明确失败,结束查询
|
|
|
|
|
//计时器停止
|
|
|
|
|
this.timer.Stop();
|
|
|
|
|
//允许扫码框输入
|
|
|
|
|
this.txtPayCode.Enabled = true;
|
|
|
|
|
this.billKeyboard1.UnLock();
|
|
|
|
|
this.txtPayCode.Text = string.Empty;
|
|
|
|
|
this.txtPayCode.Focus();
|
|
|
|
|
|
|
|
|
|
this.labelMessage.Text = saobeiPayment.Item2;
|
|
|
|
|
//回掉通知
|
|
|
|
|
if (this.payResultPush != null)
|
|
|
|
|
{
|
|
|
|
|
this.payResultPush(this._orderObject, this.txtPayCode.Text, false, new Exception(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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool VerifySAOBEIPay(string payCode, PayMode payMode)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(payCode))
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "付款码非法...";
|
|
|
|
|
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))
|
|
|
|
|
{
|
|
|
|
|
this.labelMessage.Text = "扫呗支付参数配置不完整...";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
private void OnPayCodeEnterClick(object sender, Component.EnterEventArg e)
|
|
|
|
|
{
|
|
|
|
|
this.OnKeyboardBefore(this.billKeyboard1, new KeyboardExtEventArgs("accept"));
|
|
|
|
|
|
|
|
|
|
if (this.PaymentVerify)
|
|
|
|
|
{
|
|
|
|
|
this.OnKeyBoardTouchAfter(this.billKeyboard1, new KeyboardExtEventArgs("accept"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnPayCodeValueChanged(object sender, Component.EnterEventArg e)
|
|
|
|
|
{
|
|
|
|
|
string inputString = e.Value;
|
|
|
|
|
if (!string.IsNullOrEmpty(inputString))
|
|
|
|
|
{
|
|
|
|
|
int intputLength = inputString.Length;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnPayCodeCheckClick(object sender, TouchEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
//打开提示界面
|
|
|
|
|
var form = new FastMPayChckForm(this._orderObject, this._orderObject.ReceivableAmount - this._orderObject.ReceivedAmount);
|
|
|
|
|
form.ShowDialog();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|