using Ant.Core.Utils;
using Ant.Core.WebApi.Enum;
using Ant.Core.WebApi.Model;
using Aop.Api.Util;
using Central.Control.WebApi.Config;
using Central.Control.WebApi.DbEntity;
using Central.Control.WebApi.EFDbContext;
using Central.Control.WebApi.Enum;
using Central.Control.WebApi.Log4net;
using Central.Control.WebApi.Models.Request;
using Central.Control.WebApi.Models.Response;
using Central.Control.WebApi.Service.Interface;
using Com.Alipay;
using Com.Alipay.Business;
using Com.Alipay.Domain;
using Com.Alipay.Model;
using F2FPayDll.Domain;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;

namespace Central.Control.WebApi.Service
{
    /// <summary>
    /// 
    /// </summary>
    public class OrderService: IOrderService
    {
        IAlipayTradeService serviceClient = F2FBiz.CreateClientInstance(AliPayConfig.serverUrl, AliPayConfig.appId, AliPayConfig.merchant_private_key, AliPayConfig.version,
                           AliPayConfig.sign_type, AliPayConfig.alipay_public_key, AliPayConfig.charset);

        /// <summary>
        /// 支付宝回写地址
        /// </summary>
        public readonly static string aliNotifyUrl = ConfigurationManager.AppSettings["aliNotifyUrl"].ToString();
        /// <summary>
        /// 支付中间页地址
        /// </summary>
        public readonly static string payRedirectUrl = ConfigurationManager.AppSettings["payredirecturl"].ToString();

        private readonly IDbContext _dbContent;
        private readonly IUserService _userService;
        private readonly ILog4NetHelper _log4NetHelper;
        private readonly IYWLogService _ywLogService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbContent"></param>
        /// <param name="userService"></param>
        /// <param name="log4NetHelper"></param>
        /// <param name="ywLogService"></param>
        public OrderService(
            IDbContext dbContent,
            IUserService userService,
            ILog4NetHelper log4NetHelper,
            IYWLogService ywLogService)
        {
            _dbContent = dbContent;
            _userService = userService;
            _log4NetHelper = log4NetHelper;
            _ywLogService = ywLogService;
        }

        /// <summary>
        /// 下单
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        public ApiResult<OrderResponseDto> Order(OrderRequestDto req)
        {
            #region 1、验证参数
            if (req == null
                || string.IsNullOrWhiteSpace(req.ProductId)
                || req.Count <= 0)
            {
                return new ApiResult<OrderResponseDto>(ApiStatusCode.InvalidParameter, "请求参数不正确");
            }
            #endregion

            #region 2、验证相应数据和库存
            var productInfo = (from p in _dbContent.Set<YW_Product>().Where(p => p.IsDelete == 0 && p.Sale == Enum.SaleEnum.On)
                           join dp in _dbContent.Set<YW_DeviceProduct>().Where(p => p.IsDelete == 0) on p.Id equals dp.ProductId
                           where p.Id == req.ProductId
                           select new {
                               Product = p,
                               DeviceProduct = dp
                           }).FirstOrDefault();
            if (productInfo == null)
            {
                return new ApiResult<OrderResponseDto>(ApiStatusCode.RecordNotFound, "未找到下单的商品");
            }
            #endregion

            #region 3、包装盒库存验证

            var session = _userService.GetLoginSession();
            // 修改
            var devicePacking = _dbContent.Set<YW_DevicePacking>().FirstOrDefault(p => p.IsDelete == 0 && p.DeviceId == session.UserId);
            if (devicePacking == null)
            {
                return new ApiResult<OrderResponseDto>(ApiStatusCode.Forbidden, "当前机器未放置或者未设置打包盒包,请联系工作人员添加包装盒");
            }
            // int orderCount = req.OrderInfo.Sum(p => p.Count);
            int packingCount = devicePacking.Stock * devicePacking.Capacity;
            if (packingCount < req.Count)
            {
                return new ApiResult<OrderResponseDto>(ApiStatusCode.Forbidden, "包装盒库存不足,请联系工作人员添加包装盒");
            }

            // 计算使用的包装盒数量(减包装盒库存)
            var exceptStock = req.Count / devicePacking.Capacity;
            var yushu = req.Count % devicePacking.Capacity;
            if (yushu > 0)
            {
                exceptStock++;
            }
            // 扣库存
            devicePacking.Stock -= exceptStock;

            #endregion

            #region 4、商品库存验证
            var orderId = IdGenerator.NewId();

            if (productInfo.DeviceProduct.Stock < req.Count)
            {
                return new ApiResult<OrderResponseDto>(ApiStatusCode.Forbidden, $"{productInfo.Product.Name}库存不足,请修改后重新下单");
            }

            // 扣库存
            var deviceProduct = productInfo.DeviceProduct;
            deviceProduct.Stock -= req.Count;

            #endregion

            #region 5、下单
            YW_Order order = new YW_Order()
            {
                Id = orderId,
                Name = productInfo.Product.Name,
                DeviceId = session.UserId,
                Price = deviceProduct.Price * req.Count,
                PayStatus = PayStatusEnum.UnPay,
                OrderStatus = OrderStatusEnum.UnPay,
                // PaySerialId = Snowflake.Instance().GetId().ToString(), // 支付流水号,支付完成会回写
                CreateBY = session.UserId
            };

            // orderDetails
            var orderDetails = new YW_OrderDetails()
            {
                Id = IdGenerator.NewId(),
                OrderId = orderId,
                ProductId = productInfo.Product.Id,
                Name = productInfo.Product.Name,
                Code = productInfo.Product.Code,
                Img = productInfo.Product.Img,
                Info = productInfo.Product.Info,
                Price = productInfo.DeviceProduct.Price,
                BuyingPrice = productInfo.Product.BuyingPrice,
                Count = req.Count,
                CreateBY = session.UserId
            };

            YW_OrderProcess orderProcess = new YW_OrderProcess()
            {
                Id = IdGenerator.NewId(),
                OrderId = order.Id,
                DeviceId = session.UserId,
                CurrentOrderStatus = OrderStatusEnum.UnPay,
                Message = "下单成功",
                CreateBY = session.UserId
            };
            #endregion

            #region 6、存库
            _dbContent.Set<YW_Order>().Add(order);
            _dbContent.Set<YW_OrderProcess>().Add(orderProcess);
            _dbContent.Set<YW_OrderDetails>().Add(orderDetails);

            // 数据库执行 库存已经改过了,会自动保存
            _dbContent.SaveChanges();
            #endregion

            // 写入订单日志
            _ywLogService.WriteOrderLog(order.Id, "下单", "下单成功", session.UserId);

            return new ApiResult<OrderResponseDto>(new OrderResponseDto()
            {
                OrderId = order.Id,
                Price = order.Price,
                QrCode = string.Format(payRedirectUrl, order.Id)
            });
        }

        /// <summary>
        /// 获取待烧烤的商品列表
        /// <summary>
        /// <returns></returns>
        public ApiResult<List<QueueOrderResponseDto>> GetQueueOrders()
        {
            var session = _userService.GetLoginSession();
            var orders = _dbContent.Set<YW_Order>()
                                    .Where(p => p.IsDelete == 0
                                                && p.PayStatus == PayStatusEnum.Paid
                                                && p.OrderStatus == OrderStatusEnum.Paid
                                                && p.DeviceId == session.UserId)
                                    .OrderBy(p => p.CreateDT).ToList();
            var orderIds = orders.Select(p => p.Id).ToList();
            var orderDetails = _dbContent.Set<YW_OrderDetails>().Where(p => p.IsDelete == 0 && orderIds.Contains(p.OrderId)).ToList();

            List<QueueOrderResponseDto> result = new List<QueueOrderResponseDto>();
            orders.ForEach(item =>
            {
                var currentOrderDetails = orderDetails.FirstOrDefault(p => p.ProductId == item.Id);

                var img = string.Empty;
                if (!string.IsNullOrWhiteSpace(currentOrderDetails?.Img))
                {
                    img = $"{ProductService.ImagePrefix}{currentOrderDetails.Img}";
                }
                QueueOrderResponseDto resultItem = new QueueOrderResponseDto()
                {
                    OrderId = item.Id,
                    TotalPrice = item.Price,
                    Name = item.Name,
                    Code = currentOrderDetails?.Code,
                    Img = img,
                    Price = currentOrderDetails?.Price ?? 0,
                    Count = currentOrderDetails?.Count ?? 0
                };

                result.Add(resultItem);
            });
            return new ApiResult<List<QueueOrderResponseDto>>(result);
        }

        /// <summary>
        /// 取消未支付订单
        /// </summary>
        /// <returns></returns>
        public ApiResult CancelUnPayOrder(string orderId)
        {            
            var session = _userService.GetLoginSession();
            var order = _dbContent.Set<YW_Order>().FirstOrDefault(p => p.IsDelete == 0 && p.Id == orderId && p.DeviceId == session.UserId);
            if (order == null)
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "取消的订单不存在");
            }
            if (order.PayStatus != PayStatusEnum.UnPay && order.OrderStatus != OrderStatusEnum.UnPay)
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "当前订单不是未支付状态,不能取消");
            }
            order.PayStatus = PayStatusEnum.Cancel;
            order.OrderStatus = OrderStatusEnum.Cancel;
            _dbContent.SaveChanges();
            return new ApiResult();
        }

        /// <summary>
        /// 回写流程状态
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        public ApiResult OrderProcess(OrderProcessRequestDto req)
        {
            if (req == null)
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "请求参数不正确");
            }
            var order = _dbContent.Set<YW_Order>().FirstOrDefault(p => p.Id == req.OrderId);
            if (order == null)
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "未找到相应订单");
            }
            if (order.PayStatus != PayStatusEnum.Paid)
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "未支付订单不能回写流程");
            }
            if (order.OrderStatus == OrderStatusEnum.UnPay
                || order.OrderStatus == OrderStatusEnum.Cancel)
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "未支付或已取消订单不能回写流程");
            }
            var session = _userService.GetLoginSession();
            // 修改订单状态
            order.OrderStatus = req.OrderStatus;
            // 记录订单流程
            YW_OrderProcess orderProcess = new YW_OrderProcess()
            {
                Id = IdGenerator.NewId(),
                OrderId = req.OrderId,
                DeviceId = session.UserId,
                CurrentOrderStatus = req.OrderStatus,
                Message = req.Message,
                CreateBY = session.UserId
            };
            _dbContent.Set<YW_OrderProcess>().Add(orderProcess);
            _dbContent.SaveChanges();

            // 写入订单日志
            _ywLogService.WriteOrderLog(order.Id, "流程回写", $"回写流程状态{req.OrderStatus.ToString()}", session.UserId);

            return new ApiResult();
        }

        /// <summary>
        /// 获取支付宝支付链接
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public string AliPayProcess(string id)
        {
            // 1、先查询订单是否存在
            var order = _dbContent.Set<YW_Order>().FirstOrDefault(p => p.IsDelete == 0 && p.Id == id);
            if (order == null)
            {
                return "http://api.rgtech.ltd/html/ordernotexist.html";
            }
            string result = "http://api.rgtech.ltd/html/error.html";

            // 查询订单详情
            var orderDetails = _dbContent.Set<YW_OrderDetails>().Where(p => p.IsDelete == 0 && p.OrderId == order.Id).ToList();

            #region 拼写支付宝支付参数

            AlipayTradePrecreateContentBuilder builder = new AlipayTradePrecreateContentBuilder();
            //收款账号
            builder.seller_id = AliPayConfig.pid;
            //订单编号
            builder.out_trade_no = order.Id;
            //订单总金额
            builder.total_amount = order.Price.ToString();
            //参与优惠计算的金额
            //builder.discountable_amount = "";
            //不参与优惠计算的金额
            //builder.undiscountable_amount = "";
            //订单名称
            builder.subject = order.Name;
            //自定义超时时间
            builder.timeout_express = "10m";
            //订单描述
            builder.body = "";
            //门店编号,很重要的参数,可以用作之后的营销
            builder.store_id = order.DeviceId;
            //操作员编号,很重要的参数,可以用作之后的营销
            //builder.operator_id = "test";

            //传入商品信息详情
            List<GoodsInfo> gList = orderDetails?.Select(od => new GoodsInfo()
            {
                goods_id = od.Id,
                goods_name = od.Name,
                price = od.Price.ToString(),
                quantity = od.Count.ToString()
            }).ToList() ?? new List<GoodsInfo>();
            builder.goods_detail = gList;

            //系统商接入可以填此参数用作返佣
            //ExtendParams exParam = new ExtendParams();
            //exParam.sysServiceProviderId = "20880000000000";
            //builder.extendParams = exParam;

            #endregion



            //如果需要接收扫码支付异步通知,那么请把下面两行注释代替本行。
            //推荐使用轮询撤销机制,不推荐使用异步通知,避免单边账问题发生。
            //AlipayF2FPrecreateResult precreateResult = new AlipayF2FPrecreateResult();
            AlipayF2FPrecreateResult precreateResult = serviceClient.tradePrecreate(builder, aliNotifyUrl);//商户接收异步通知的地址,采用异步回写通知

            switch (precreateResult.Status)
            {
                case ResultEnum.SUCCESS:
                    result = precreateResult.response.QrCode;
                    break;
                case ResultEnum.FAILED:
                case ResultEnum.UNKNOWN:
                default:
                    // 请求失败,记录日志
                    _log4NetHelper.Error($"[AliPayProcess]-tradePrecreate失败:{JsonConvert.SerializeObject(precreateResult)}");
                    break;
            }
            return result;
        }

        /// <summary>
        /// 支付宝支付回写(已测试好,勿动)
        /// </summary>
        /// <returns></returns>
        public string AliPayNotify()
        {
            _log4NetHelper.Info("[AliPayNotify]-start");
            SortedDictionary<string, string> sPara = GetRequestPost();
            _log4NetHelper.Info("[AliPayNotify]-[原始请求参数]-" + JsonConvert.SerializeObject(sPara));
            
            Notify aliNotify = new Notify(AliPayConfig.charset, AliPayConfig.sign_type, AliPayConfig.pid, AliPayConfig.mapiUrl, AliPayConfig.alipay_public_key);

            string notifyId = HttpContext.Current.Request.Form["notify_id"];
            string sign = HttpContext.Current.Request.Form["sign"];
            _log4NetHelper.Info($"[AliPayNotify]-[基础参数]-notify_id:{notifyId};sign{sign}");

            //对异步通知进行验签
            bool verifyResult = aliNotify.Verify(sPara, notifyId, sign);
            if (verifyResult && CheckParams()) //验签成功 && 关键业务参数校验成功
            {
                _log4NetHelper.Info("[AliPayNotify]-验签成功");

                string paySerialId = HttpContext.Current.Request.Form["trade_no"] ?? string.Empty;
                string outTradeNo = HttpContext.Current.Request.Form["out_trade_no"] ?? string.Empty;
                string payResponse = JsonConvert.SerializeObject(sPara);

                // 写入支付日志-里面有trycatch
                _ywLogService.WritePayCallLog(paySerialId, outTradeNo, PayWayEnum.AliPay, payResponse);

                PayStatusEnum payStatus = PayStatusEnum.Fail;
                if (HttpContext.Current.Request.Form["trade_status"] == "TRADE_SUCCESS")
                {
                    payStatus = PayStatusEnum.Paid;
                }

                PayWriteBackRequestDto payWriteBack = new PayWriteBackRequestDto()
                {
                    PaySerialId = paySerialId,
                    OrderId = outTradeNo,
                    PayStatus = payStatus,
                    PayWay = PayWayEnum.AliPay,
                    BuyerId = HttpContext.Current.Request.Form["buyer_id"] ?? string.Empty,
                    BuyAccount = HttpContext.Current.Request.Form["buyer_logon_id"] ?? string.Empty,
                    SellerId = HttpContext.Current.Request.Form["seller_id"] ?? string.Empty,
                    SellAccount = HttpContext.Current.Request.Form["seller_email"] ?? string.Empty,
                    TotalAmount = ConvertHelper.ToDecimal(HttpContext.Current.Request.Form["total_amount"]),
                    PayAmount = ConvertHelper.ToDecimal(HttpContext.Current.Request.Form["buyer_pay_amount"]),
                    PayTime = ConvertHelper.ToDateTime(HttpContext.Current.Request.Form["gmt_payment"]),
                    PayResponse = payResponse
                };
                // 回写到实际表中
                var result = PayWriteBack(payWriteBack);
                if (!result.IsSuccess)
                {
                    // 失败了
                    _log4NetHelper.Info($"[AliPayNotify]-[支付回写验证失败]-{result.Message}");
                    return "false";
                }
                return "sucess";
            }
            else
            {
                _log4NetHelper.Info("[AliPayNotify]-验签失败!!!");
                return "false";
            }
        }

        /// <summary>
        /// 申请退款
        /// </summary>
        /// <returns></returns>
        public ApiResult OrderRefund(string orderId)
        {
            var order = _dbContent.Set<YW_Order>().FirstOrDefault(p => p.IsDelete == 0 && p.Id == orderId);

            if (order.PayStatus != PayStatusEnum.RefundApply)
            {
                // 订单状态不可退款
                return new ApiResult(ApiStatusCode.InvalidParameter, "当前订单状态不可退款");
            }
            ApiResult result = null;
            switch (order.PayWay)
            {
                case PayWayEnum.WeChatPay:
                    result = new ApiResult(ApiStatusCode.Forbidden, "微信支付暂未接入,无法发起退款");
                    break;
                case PayWayEnum.AliPay:
                    // 支付宝退款
                    result = AliPayRefund(order.Id, order.PaySerialId, order.Price, "客户发起退款");
                    break;
                default:
                    result = new ApiResult(ApiStatusCode.Forbidden, "未知支付方式,无法在线自动退款");
                    break;
            }

            if (result.IsSuccess)
            {
                // 修改订单状态
                order.PayStatus = PayStatusEnum.Refunding;
                order.OrderStatus = OrderStatusEnum.Cancel;
                order.ModifyDT = DateTime.Now;
                order.ModifyBY = "用户申请";
                _dbContent.SaveChanges();
                // 写入订单流程记录
                _ywLogService.WriteOrderProcess(order.Id, order.DeviceId, OrderStatusEnum.Cancel, "申请退款", "用户申请");
            }
            return result;
        }

        /// <summary>
        /// 轮询查询退款信息,并更新订单的退款记录
        /// </summary>
        /// <returns></returns>
        public ApiResult OrderRefundLoop()
        {
            // 1、查询出所有退款中的订单
            // 2、请求支付宝退款接口查询是否已退款成功
            // 3、退款成功或失败时,回写到订单中
            var modifyDt = DateTime.Now.AddMinutes(-2);// 查询2分钟以前的订单,因为退款需要一定时间,马上查询会返回失败
            var order = _dbContent.Set<YW_Order>().Where(p => p.IsDelete == 0 && p.PayStatus == PayStatusEnum.RefundApply && p.ModifyDT < modifyDt).OrderBy(p => p.ModifyDT).FirstOrDefault();
            if (order == null)
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "无退款中订单");
            }
            // 更新modifydt以便下次捞取别的订单
            order.ModifyDT = DateTime.Now;

            ApiResult result = null;
            switch (order.PayWay)
            {
                case PayWayEnum.WeChatPay:
                    result = new ApiResult(ApiStatusCode.Forbidden, "微信支付暂未接入,无法进行查询");
                    break;
                case PayWayEnum.AliPay:
                    // 查询支付宝退款
                    result = AliPayRefundQuery(order.Id, order.PaySerialId, order.DeviceId);
                    break;
                default:
                    result = new ApiResult(ApiStatusCode.Forbidden, "未知支付方式,无法进行查询");
                    break;
            }

            if (result.IsSuccess)
            {
                // 修改订单状态
                order.PayStatus = PayStatusEnum.Refunded;
                order.OrderStatus = OrderStatusEnum.Cancel;
                order.ModifyDT = DateTime.Now;
                order.ModifyBY = "用户申请";
                // 写入订单流程记录
                _ywLogService.WriteOrderProcess(order.Id, order.DeviceId, OrderStatusEnum.Cancel, "退款成功", "用户申请");
            }
            else
            {
                // 退款失败,将订单更新成错误,并记录订单日志
                order.PayStatus = PayStatusEnum.Fail;
                order.OrderStatus = OrderStatusEnum.Cancel;
                order.ModifyDT = DateTime.Now;
                order.ModifyBY = "用户申请";
                // 写入订单日志
                _ywLogService.WriteOrderLog(order.Id, "订单退款失败", result.Message, "用户申请");
            }
            _dbContent.SaveChanges();
            return result;
        }

        #region privatemethods

        /// <summary>
        /// 支付回写(回写到实际表中)
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        private ApiResult PayWriteBack(PayWriteBackRequestDto req)
        {
            if (req == null
                || string.IsNullOrWhiteSpace(req.PaySerialId))
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "请求参数不正确");
            }
            var order = _dbContent.Set<YW_Order>().FirstOrDefault(p => p.Id == req.OrderId);
            if (order == null)
            {
                return new ApiResult(ApiStatusCode.InvalidParameter, "未找到相应订单");
            }
            if (order.Price != req.TotalAmount)
            {
                // 写入订单日志
                string msg = $"回写总金额与订单金额不匹配,订单号{order.Id};订单价格{order.Price};支付流水号{req.PaySerialId};支付订单总金额{req.TotalAmount}";
                _ywLogService.WriteOrderLog(order.Id, "支付回写", msg, req.PayWay.ToString());
                return new ApiResult(ApiStatusCode.InvalidParameter, msg);
            }
            if (order.Price != req.PayAmount)
            {
                // 写入订单日志
                string msg = $"回写支付金额与订单金额不匹配,订单号{order.Id};订单价格{order.Price};支付流水号{req.PaySerialId};支付订单已付金额{req.PayAmount}";
                _ywLogService.WriteOrderLog(order.Id, "支付回写", msg, req.PayWay.ToString());
                return new ApiResult(ApiStatusCode.InvalidParameter, msg);
            }
            var status = GetStatusByPayWriteBack(req.PayStatus);
            // 修改订单状态
            order.PayStatus = status.Item1;
            order.OrderStatus = status.Item2;
            order.PaySerialId = req.PaySerialId;
            // 记录订单支付流程
            YW_PayCall payCall = new YW_PayCall()
            {
                Id = IdGenerator.NewId(),
                OrderId = req.OrderId,
                PayStatus = status.Item1,
                PaySerialId = req.PaySerialId,
                PayWay = req.PayWay,
                BuyerId = req.BuyerId,
                BuyAccount = req.BuyAccount,
                SellerId = req.SellerId,
                SellAccount = req.SellAccount,
                PayAmount = req.PayAmount,
                PayTime = req.PayTime,
                PayResponse = req.PayResponse,
                CreateBY = req.BuyAccount
            };
            _dbContent.Set<YW_PayCall>().Add(payCall);

            // 写入订单流程信息
            _ywLogService.WriteOrderProcess(req.OrderId, order.DeviceId, order.OrderStatus, "订单回写成功", "支付回写");

            _dbContent.SaveChanges();

            // 记录订单日志
            _ywLogService.WriteOrderLog(order.Id, "支付回写", "回写成功", req.PayWay.ToString());

            return new ApiResult();
        }

        /// <summary>
        /// 支付宝退款
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="paySerialId"></param>
        /// <param name="refundAmount"></param>
        /// <param name="refundReason"></param>
        /// <returns></returns>
        private ApiResult AliPayRefund(string orderId,string paySerialId,decimal refundAmount, string refundReason)
        {
            AlipayTradeRefundContentBuilder builder = new AlipayTradeRefundContentBuilder()
            {
                trade_no = paySerialId,
                out_trade_no = orderId,
                refund_amount = refundAmount.ToString(),
                out_request_no = string.Empty,
                refund_reason = refundReason,
            };
            ApiResult result = null;
            // 支付宝退款
            _log4NetHelper.Error($"[AliPayRefund]-tradeRefund-start:request:{JsonConvert.SerializeObject(builder)}");
            AlipayF2FRefundResult refundResult = serviceClient.tradeRefund(builder);
            _log4NetHelper.Error($"[AliPayRefund]-tradeRefund-end:request:{JsonConvert.SerializeObject(refundResult)}");

            switch (refundResult.Status)
            {
                case ResultEnum.SUCCESS:
                    // 退款成功-记录日志
                    _ywLogService.WriteOrderLog(orderId, "申请退款", $"申请退款成功:退款金额{refundResult.response?.SendBackFee}", "用户申请");
                    result = new ApiResult();
                    break;
                default:
                    result = new ApiResult(ApiStatusCode.InternalServerError, "请求支付宝退款失败" + refundResult.response?.SubMsg);
                    // 退款失败-记录订单日志
                    _ywLogService.WriteOrderLog(orderId, "申请退款", $"申请退款失败:{refundResult.response?.SubMsg}", "用户申请");
                    // 请求失败,记录log4net日志
                    _log4NetHelper.Error($"[AliPayRefund]-tradeRefund失败:request:{JsonConvert.SerializeObject(builder)};response:{JsonConvert.SerializeObject(refundResult)}");
                    break;
            }
            return result;
        }

        /// <summary>
        /// 支付宝退款查询
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="paySerialId"></param>
        /// <param name="deviceId"></param>
        /// <returns></returns>
        private ApiResult AliPayRefundQuery(string orderId, string paySerialId, string deviceId)
        {
            var builder = new AlipayTradeFastpayRefundQueryContentBuilder()
            {
                trade_no = paySerialId,
                out_trade_no = orderId,
                out_request_no = deviceId
            };
            ApiResult result = null;
            // 支付宝退款
            _log4NetHelper.Error($"[AliPayRefund]-AliPayRefundQuery-start:request:{JsonConvert.SerializeObject(builder)}");
            var refundQueryResult = serviceClient.tradeFastpayRefundQuery(builder);
            _log4NetHelper.Error($"[AliPayRefund]-AliPayRefundQuery-end:request:{JsonConvert.SerializeObject(refundQueryResult)}");

            switch (refundQueryResult.Status)
            {
                case ResultEnum.SUCCESS:
                    string content = "成功";
                    if (refundQueryResult.response.RefundStatus == "REFUND_SUCCESS")
                    {
                        // 退款成功
                        result = new ApiResult();
                        content = $"退款成功:退款金额{refundQueryResult.response?.RefundAmount}";
                    }
                    else
                    {
                        // 退款失败
                        result = new ApiResult(ApiStatusCode.InternalServerError, "请求支付宝退款失败" + refundQueryResult.response?.SubMsg);
                        content = $"退款失败:{refundQueryResult.response?.SubMsg}";
                    }
                    // 记录订单日志
                    _ywLogService.WriteOrderLog(orderId, "退款查询", content, "用户申请");
                    break;
                default:
                    result = new ApiResult(ApiStatusCode.InternalServerError, "请求支付宝退款失败" + refundQueryResult.response?.SubMsg);
                    // 退款失败-记录订单日志
                    _ywLogService.WriteOrderLog(orderId, "退款查询", $"退款失败:{refundQueryResult.response?.SubMsg}", "用户申请");
                    // 请求失败,记录log4net日志
                    _log4NetHelper.Error($"[AliPayRefund]-AliPayRefundQuery失败:request:{JsonConvert.SerializeObject(builder)};response:{JsonConvert.SerializeObject(refundQueryResult)}");
                    break;
            }
            return result;
        }

        /// <summary>
        /// 支付测试
        /// </summary>
        /// <returns></returns>
        public ApiResult<AlipayF2FPrecreateResult> PayTest()
        {

            AlipayTradePrecreateContentBuilder builder = BuildPrecreateContent();
            string out_trade_no = builder.out_trade_no;

            //如果需要接收扫码支付异步通知,那么请把下面两行注释代替本行。
            //推荐使用轮询撤销机制,不推荐使用异步通知,避免单边账问题发生。
            // AlipayF2FPrecreateResult precreateResult = serviceClient.tradePrecreate(builder);
            string notify_url = aliNotifyUrl;  //商户接收异步通知的地址
            AlipayF2FPrecreateResult precreateResult = serviceClient.tradePrecreate(builder, notify_url);

            //以下返回结果的处理供参考。
            //payResponse.QrCode即二维码对于的链接
            //将链接用二维码工具生成二维码打印出来,顾客可以用支付宝钱包扫码支付。
            string result = "";


            return new ApiResult<AlipayF2FPrecreateResult>(precreateResult);
            //switch (precreateResult.Status)
            //{
            //    case ResultEnum.SUCCESS:
            //        DoWaitProcess(precreateResult);
            //        txtRCCode.Text = precreateResult.response.QrCode;
            //        break;
            //    case ResultEnum.FAILED:
            //        result = precreateResult.response.Body;
            //        Response.Redirect("result.aspx?Text=" + result);
            //        break;

            //    case ResultEnum.UNKNOWN:
            //        if (precreateResult.response == null)
            //        {
            //            result = "配置或网络异常,请检查后重试";
            //        }
            //        else
            //        {
            //            result = "系统异常,请更新外部订单后重新发起请求";
            //        }
            //        Response.Redirect("result.aspx?Text=" + result);
            //        break;
            //}


        }

        /// <summary>
        /// 构造支付请求数据
        /// </summary>
        /// <returns>请求数据集</returns>
        private AlipayTradePrecreateContentBuilder BuildPrecreateContent()
        {
            AlipayTradePrecreateContentBuilder builder = new AlipayTradePrecreateContentBuilder();
            //收款账号
            builder.seller_id = AliPayConfig.pid;
            //订单编号-----------------------
            builder.out_trade_no = DateTime.Now.ToString("yyyyMMddHHmmss") + "0000" + (new Random()).Next(1, 10000).ToString();
            //订单总金额-----------------------------
            builder.total_amount = "0.02";
            //参与优惠计算的金额
            //builder.discountable_amount = "";
            //不参与优惠计算的金额
            //builder.undiscountable_amount = "";
            //订单名称-------------------------------
            builder.subject = "smj_webapi测试订单";
            //自定义超时时间
            builder.timeout_express = "5m";
            //订单描述
            builder.body = "";
            //门店编号,很重要的参数,可以用作之后的营销--------------------
            builder.store_id = "test store id";
            //操作员编号,很重要的参数,可以用作之后的营销---------------------
            builder.operator_id = "test";

            //传入商品信息详情
            List<GoodsInfo> gList = new List<GoodsInfo>();
            GoodsInfo goods = new GoodsInfo();
            goods.goods_id = "goods id";
            goods.goods_name = "goods name";
            goods.price = "0.02";
            goods.quantity = "1";
            gList.Add(goods);
            builder.goods_detail = gList;

            //系统商接入可以填此参数用作返佣
            //ExtendParams exParam = new ExtendParams();
            //exParam.sysServiceProviderId = "20880000000000";
            //builder.extendParams = exParam;

            return builder;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="payStatus"></param>
        /// <returns></returns>
        private Tuple<PayStatusEnum, OrderStatusEnum> GetStatusByPayWriteBack(PayStatusEnum payStatus)
        {
            // 临时:payStatus 0失败,1成功
            OrderStatusEnum orderStatus = OrderStatusEnum.UnPay;
            switch (payStatus)
            {
                case  PayStatusEnum.Paid:// 成功
                    orderStatus = OrderStatusEnum.Paid;
                    break;
                default:// 失败
                    break;
            }

            return new Tuple<PayStatusEnum, OrderStatusEnum>(payStatus, orderStatus);
        }

        /// <summary>
        /// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组
        /// </summary>
        /// <returns>request回来的信息组成的数组</returns>
        private SortedDictionary<string, string> GetRequestPost()
        {
            int i = 0;
            SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
            NameValueCollection coll;
            //Load Form variables into NameValueCollection variable.
            coll = HttpContext.Current.Request.Form;

            // Get names of all forms into a string array.
            String[] requestItem = coll.AllKeys;

            for (i = 0; i < requestItem.Length; i++)
            {
                sArray.Add(requestItem[i], HttpContext.Current.Request.Form[requestItem[i]]);
            }

            return sArray;
        }

        /// <summary>
        /// 对支付宝异步通知的关键参数进行校验
        /// </summary>
        /// <returns></returns>
        private bool CheckParams()
        {
            bool ret = true;

            //获得调用方的appid;
            //如果是非授权模式,appid是商户的appid;如果是授权模式(token调用),appid是系统商的appid
            string app_id = HttpContext.Current.Request.Form["app_id"];
            if (app_id != AliPayConfig.appId)
            {
                ret = false;
                _log4NetHelper.Info($"[支付回写][appid认证失败]:request_appid:{app_id};sys_appid:{AliPayConfig.appId}");
            }
            return ret;
        }

        #endregion

    }
}