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 Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Web;
namespace Central.Control.WebApi.Service
{
///
///
///
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);
///
/// 支付宝回写地址
///
public readonly static string aliNotifyUrl = ConfigurationManager.AppSettings["aliNotifyUrl"].ToString();
private readonly IDbContext _dbContent;
private readonly IUserService _userService;
private readonly ILog4NetHelper _log4NetHelper;
///
///
///
///
///
///
public OrderService(
IDbContext dbContent,
IUserService userService,
ILog4NetHelper log4NetHelper)
{
_dbContent = dbContent;
_userService = userService;
_log4NetHelper = log4NetHelper;
}
///
/// 下单
///
///
///
public ApiResult Order(OrderRequestDto req)
{
#region 1、验证参数
if (req == null
|| req.OrderInfo == null
|| req.OrderInfo.Count() == 0)
{
return new ApiResult(ApiStatusCode.InvalidParameter, "请求参数不正确");
}
#endregion
#region 2、验证相应数据和库存
var productIds = req.OrderInfo.Select(p => p.ProductId).ToList();
var products = _dbContent.Set().Where(p => p.IsDelete == 0 && p.Sale == Enum.SaleEnum.On && productIds.Contains(p.Id)).ToList();
if (products.Count() <= 0)
{
return new ApiResult(ApiStatusCode.RecordNotFound, "未找到下单的商品");
}
#endregion
#region 3、包装盒库存验证
var session = _userService.GetLoginSession();
// 修改
var devicePackings = _dbContent.Set().Where(p => p.IsDelete == 0 && p.DeviceId == session.UserId).ToList();
if (devicePackings == null || devicePackings.Count() == 0)
{
return new ApiResult(ApiStatusCode.Forbidden, "包装盒库存不足,请联系工作人员添加包装盒");
}
int orderCount = req.OrderInfo.Sum(p => p.Count);
int packingCount = devicePackings.Sum(p => p.Stock * p.Capacity);
if (packingCount < orderCount)
{
return new ApiResult(ApiStatusCode.Forbidden, "包装盒库存不足,请联系工作人员添加包装盒");
}
// 计算使用的包装盒数量(减包装盒库存)
var orderCountIndex = orderCount;
foreach (var devicePacking in devicePackings)
{
if (orderCountIndex <= 0)
{
break;// 数量为0了,则直接跳出循环
}
int currentPackingStock = devicePacking.Stock;
for (int i = 0; i < currentPackingStock; i++)
{
// 循环库存
if (orderCountIndex <= 0)
{
break;// 数量为0了,则直接跳出循环
}
orderCountIndex = orderCountIndex - devicePacking.Capacity;
devicePacking.Stock--;// 减库存
}
}
#endregion
#region 4、商品库存验证
var orderId = IdGenerator.NewId();
List orderDetailAdds = new List();
List orderProcessAdds = new List();
foreach (var o in req.OrderInfo)
{
var currentProduct = products.FirstOrDefault(p => p.Id == o.ProductId);
if (currentProduct == null)
{
return new ApiResult(ApiStatusCode.RecordNotFound, $"{o.ProductId}商品不存在");
}
if (currentProduct.Stock < o.Count)
{
return new ApiResult(ApiStatusCode.Forbidden, $"{currentProduct.Name}商品库存不足,请修改后重新下单");
}
// 扣库存
currentProduct.Stock = currentProduct.Stock - o.Count;
// orderDetails
orderDetailAdds.Add(new YW_OrderDetails()
{
Id = IdGenerator.NewId(),
OrderId = orderId,
ProductId = currentProduct.Id,
Name = currentProduct.Name,
Code = currentProduct.Code,
Img = currentProduct.Img,
Info = currentProduct.Info,
Price = currentProduct.Price,
BuyingPrice = currentProduct.BuyingPrice,
Count = o.Count,
CreateBY = session.UserId
});
}
#endregion
#region 5、下单
YW_Order order = new YW_Order()
{
Id = orderId,
DeviceId = session.UserId,
Price = orderDetailAdds.Sum(p => p.Price * p.Count),
PayStatus = PayStatusEnum.UnPay,
OrderStatus = OrderStatusEnum.UnPay,
// PaySerialId = Snowflake.Instance().GetId().ToString(), // 支付流水号,支付完成会回写
CreateBY = session.UserId
};
YW_OrderProcess orderProcess = new YW_OrderProcess()
{
Id = IdGenerator.NewId(),
OrderId = order.Id,
DeviceId = session.UserId,
CurrentOrderStatus = OrderStatusEnum.UnPay,
Message = "下单成功",
CreateBY = session.Id
};
#endregion
#region 6、存库
_dbContent.Set().Add(order);
_dbContent.Set().Add(orderProcess);
_dbContent.Set().AddRange(orderDetailAdds);
// 数据库执行 库存已经改过了,会自动保存
_dbContent.SaveChanges();
#endregion
#region 5、支付宝支付--目前直接入支付宝支付测试,后期需要替换成中间页面
#endregion
return new ApiResult(new OrderResponseDto()
{
OrderId = order.Id,
Price = order.Price
});
}
///
/// 获取待烧烤的商品列表
///
///
public ApiResult> GetQueueOrders()
{
var orders = _dbContent.Set()
.Where(p => p.IsDelete == 0
&& p.PayStatus == PayStatusEnum.Paid
&& p.OrderStatus == OrderStatusEnum.Paid)
.OrderBy(p => p.CreateDT).ToList();
var orderIds = orders.Select(p => p.Id).ToList();
var orderDetails = _dbContent.Set().Where(p => p.IsDelete == 0 && orderIds.Contains(p.OrderId)).ToList();
List result = new List();
orders.ForEach(item => {
QueueOrderResponseDto resultItem = new QueueOrderResponseDto()
{
OrderId = item.Id,
Price = item.Price,
OrderDetails = orderDetails
.Where(p => p.OrderId == item.Id)
.Select(p => SafeClone.Trans(p))
.ToList()
};
resultItem.OrderDetails?.ForEach(p => p.Img = $"{ProductService.ImagePrefix}{p.Img}");
result.Add(resultItem);
});
return new ApiResult>(result);
}
///
/// 回写流程状态
///
///
///
public ApiResult OrderProcess(OrderProcessRequestDto req)
{
if (req == null)
{
return new ApiResult(ApiStatusCode.InvalidParameter, "请求参数不正确");
}
var order = _dbContent.Set().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 seesion = _userService.GetLoginSession();
// 修改订单状态
order.OrderStatus = req.OrderStatus;
// 记录订单流程
YW_OrderProcess orderProcess = new YW_OrderProcess()
{
Id = IdGenerator.NewId(),
OrderId = req.OrderId,
DeviceId = seesion.UserId,
CurrentOrderStatus = req.OrderStatus,
Message = req.Message,
CreateBY = seesion.UserId
};
_dbContent.Set().Add(orderProcess);
_dbContent.SaveChanges();
return new ApiResult();
}
///
/// 支付宝回写
///
///
public string AliPayNotify()
{
_log4NetHelper.Info("[AliPayNotify]-start");
SortedDictionary 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]-验签成功");
PayStatusEnum payStatus = PayStatusEnum.Fail;
if (HttpContext.Current.Request.Form["trade_status"] == "TRADE_SUCCESS")
{
payStatus = PayStatusEnum.Paid;
}
PayWriteBackRequestDto payWriteBack = new PayWriteBackRequestDto()
{
PaySerialId = HttpContext.Current.Request.Form["trade_no"] ?? string.Empty,
OrderId = HttpContext.Current.Request.Form["out_trade_no"] ?? string.Empty,
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 = JsonConvert.SerializeObject(sPara)
};
// 回写到实际表中
var result = PayWriteBack(payWriteBack);
if (!result.IsSuccess)
{
// 失败了
_log4NetHelper.Info($"[AliPayNotify]-[支付回写验证失败]-{result.Message}");
return "false";
}
return "sucess";
}
else
{
_log4NetHelper.Info("[AliPayNotify]-验签失败!!!");
return "false";
}
}
///
/// 支付回写(雏形,需要根据实际需要接入支付宝或微信)
///
///
///
private ApiResult PayWriteBack(PayWriteBackRequestDto req)
{
if (req == null
|| string.IsNullOrWhiteSpace(req.PaySerialId))
{
return new ApiResult(ApiStatusCode.InvalidParameter, "请求参数不正确");
}
var order = _dbContent.Set().FirstOrDefault(p => p.Id == req.OrderId);
if (order == null)
{
return new ApiResult(ApiStatusCode.InvalidParameter, "未找到相应订单");
}
if (order.Price != req.TotalAmount)
{
// 需要写入订单日志------------------------
return new ApiResult(ApiStatusCode.InvalidParameter, $"回写总金额与订单金额不匹配,订单号{order.Id};订单价格{order.Price};支付流水号{req.PaySerialId};支付订单总金额{req.TotalAmount}");
}
if (order.Price != req.PayAmount)
{
// 需要写入订单日志------------------------
return new ApiResult(ApiStatusCode.InvalidParameter, $"回写支付金额与订单金额不匹配,订单号{order.Id};订单价格{order.Price};支付流水号{req.PaySerialId};支付订单已付金额{req.PayAmount}");
}
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().Add(payCall);
_dbContent.SaveChanges();
return new ApiResult();
}
///
/// 支付测试
///
///
public ApiResult 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(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;
//}
}
///
/// 构造支付请求数据
///
/// 请求数据集
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 gList = new List();
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;
}
///
///
///
///
///
private Tuple GetStatusByPayWriteBack(PayStatusEnum payStatus)
{
// 临时:payStatus 0失败,1成功
OrderStatusEnum orderStatus = OrderStatusEnum.UnPay;
switch (payStatus)
{
case PayStatusEnum.UnPay:// 成功
orderStatus = OrderStatusEnum.Paid;
break;
default:// 失败
break;
}
return new Tuple(payStatus, orderStatus);
}
///
/// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组
///
/// request回来的信息组成的数组
private SortedDictionary GetRequestPost()
{
int i = 0;
SortedDictionary sArray = new SortedDictionary();
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;
}
///
/// 对支付宝异步通知的关键参数进行校验
///
///
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;
}
}
}