123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947 |
- 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.UserName);
- return new ApiResult<OrderResponseDto>(new OrderResponseDto()
- {
- OrderId = order.Id,
- Price = order.Price,
- QrCode = string.Format(payRedirectUrl, order.Id)
- });
- }
- /// <summary>
- /// 根据id获取商品信息
- /// </summary>
- /// <param name="orderId"></param>
- /// <returns></returns>
- public ApiResult<OrderInfoResponseDto> GetQueueOrder(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<OrderInfoResponseDto>(ApiStatusCode.InvalidParameter, "订单不存在");
- }
- OrderInfoResponseDto result = new OrderInfoResponseDto() {
- Id = order.Id,
- Name = order.Name,
- Price = order.Price,
- PayStatus = order.PayStatus,
- PaySerialId = order.PaySerialId,
- PayWay = order.PayWay
- };
- return new ApiResult<OrderInfoResponseDto>(result);
- }
- /// <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, "当前订单不是未支付状态,不能取消");
- }
- // 需要试试查询支付宝或者
- if (order.PayWay == PayWayEnum.AliPay)
- {
- var tradeQueryResult = serviceClient.tradeQuery(order.Id);
- if (tradeQueryResult.Status == ResultEnum.SUCCESS && tradeQueryResult.response.TradeStatus == "TRADE_SUCCESS")
- {
- // 已经支付成功
- 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";
- }
- if (order.PayStatus == PayStatusEnum.Cancel)
- {
- // 订单已取消,不能支付再次支付
- return "http://api.rgtech.ltd/html/ordercancel.html";
- }
- if (order.PayWay != PayWayEnum.UnKnow && order.PayWay != PayWayEnum.AliPay)
- {
- // 上次请求非支付宝支付、返回失败
- return "http://api.rgtech.ltd/html/errorpayway.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 = "2m";
- //订单描述
- 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:// 申请支付成功,写入订单支付方式(以便于其他人再次扫码使用不同支付方式)
- order.PayWay = PayWayEnum.AliPay;
- order.ModifyDT = DateTime.Now;
- _dbContent.SaveChanges();
- 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.Paid)
- {
- // 订单状态不可退款
- 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, order.Id, "客户发起退款");
- 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.Refunding && p.ModifyDT < modifyDt).OrderBy(p => p.ModifyDT).FirstOrDefault();
- if (order == null)
- {
- return new ApiResult(ApiStatusCode.InvalidParameter, "无退款中订单");
- }
- // 更新modifydt以便下次捞取别的订单
- order.ModifyDT = DateTime.Now;
- // 测试
- //var order = new YW_Order()
- //{
- // Id = "GBJUJCBWD3E26SIV",
- // PaySerialId = "2022040322001434260501434677",
- // DeviceId = string.Empty,// "cb8b354c-b713-4dd7-9752-a6f3217004a0",
- // PayWay = PayWayEnum.AliPay
- //};
- 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.Price);
- 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 out_request_no, string refundReason)
- {
- AlipayTradeRefundContentBuilder builder = new AlipayTradeRefundContentBuilder()
- {
- trade_no = paySerialId,
- out_trade_no = orderId,
- refund_amount = refundAmount.ToString(),
- out_request_no = out_request_no,
- 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="orderPrice"></param>
- /// <returns></returns>
- private ApiResult AliPayRefundQuery(string orderId, string paySerialId, decimal orderPrice)
- {
- var builder = new AlipayTradeFastpayRefundQueryContentBuilder()
- {
- trade_no = paySerialId,
- out_trade_no = orderId,
- out_request_no = orderId
- };
- ApiResult result = null;
- // 支付宝退款
- _log4NetHelper.Error($"[AliPayRefund]-AliPayRefundQuery-start:request:{JsonConvert.SerializeObject(builder)}");
- var refundQueryResult = serviceClient.tradeFastpayRefundQuery(builder);
- _log4NetHelper.Error($"[AliPayRefund]-AliPayRefundQuery-end:response:{JsonConvert.SerializeObject(refundQueryResult)}");
- switch (refundQueryResult.Status)
- {
- case ResultEnum.SUCCESS:
- string content = "成功";
- if (ConvertHelper.ToDecimal(refundQueryResult.response.RefundAmount) == orderPrice)
- {
- // 退款成功
- 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
- public AlipayF2FQueryResult tradeQuery(string orderId)
- {
- return serviceClient.tradeQuery(orderId);
- }
- }
- }
|