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.

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