using CRM.Core.BLL.Application.B;
using CRM.Core.BLL.Wx;
using CRM.Core.DTO;
using CRM.Core.DTO.Bill;
using CRM.Core.Model.Entity;
using Csv;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using WX.CRM.Common;
namespace CRM.Core.BLL.Application.Bill
{
public class BillService
{
private static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
private Bill_Account_BL bill_Account_BL = new Bill_Account_BL();
public string UserName;
public BillService(string UserName)
{
this.UserName = UserName;
}
public retMsg ImportBillzip(string filename, Stream filestream)
{
retMsg retMsg = new retMsg() { result = true };
StringBuilder sb = new StringBuilder();
using (ZipArchive archive = new ZipArchive(filestream, ZipArchiveMode.Read, false, Encoding.Default))
{
foreach (var item in archive.Entries)
{
if (item.Length > 0)
{
var fname = item.Name;
var msg = ImportBill(fname, item.Open());
if (msg.result == false) retMsg.result = false;
sb.Append($"{fname}:{msg.retmsg}
");
}
}
}
retMsg.retmsg = sb.ToString();
return retMsg;
}
public retMsg ImportBill(string filename, Stream filestream)
{
retMsg retMsg = new retMsg() { result = true };
try
{
Stopwatch stopwatch = Stopwatch.StartNew();
List bill_Accounts = new List();
var file_ext = Path.GetExtension(filename).ToLower();
var name = Path.GetFileNameWithoutExtension(filename);
Logger.Info("开始解析");
if (file_ext.Equals(".zip"))
{
retMsg = ImportBillzip(filename, filestream);
return retMsg;
}
if (file_ext.Equals(".csv"))
{
if (name.Contains("微信交易账单"))
{
bill_Accounts = GetBillAccountsFromWX_Business(filestream);
}
else if (name.Contains("账务"))
{
bill_Accounts = GetBillAccountsFromAli_csv(filestream);
}
else
{
retMsg.result = false;
retMsg.retmsg = String.Format("csv文件未找到微信关键字:[微信交易账单]或支付宝关键字:[账务]");
return retMsg;
}
}
else if (file_ext.Equals(".xls") || file_ext.Equals(".xlsx"))
{
if (name.Contains("东高") || name.Contains("银行"))
{
bill_Accounts = GetBillAccountsFromBank(filestream, file_ext);
}
else
{
retMsg.result = false;
retMsg.retmsg = String.Format("excel文件未找到银行关键字:[东高],[银行]");
return retMsg;
}
}
else
{
retMsg.result = false;
retMsg.retmsg = String.Format("非法文件格式,请导入微信支付宝的csv格式或银行xlsx格式文件");
return retMsg;
}
Logger.Info("解析完成");
// bill_Account_BL.AddList(bill_Accounts);
bill_Account_BL.BulkInsertToMysql("Bill_Account", bill_Accounts);
Logger.Info("插入完成");
retMsg.retmsg = getbillsMsg(bill_Accounts);
stopwatch.Stop();
Logger.Info(string.Format("{0},耗时{1}", retMsg.retmsg, stopwatch.ElapsedMilliseconds));
}
catch (Exception ex)
{
retMsg.result = false;
retMsg.retmsg = String.Format("异常:{0}", ex.Message);
Logger.Error(ex);
}
return retMsg;
}
public string getbillsMsg(List bill_Accounts)
{
var paybill = bill_Accounts.Where(d => d.trade_type == Bill_TradeType_enum.Pay.ToString());
var refundbill = bill_Accounts.Where(d => d.trade_type == Bill_TradeType_enum.Refund.ToString());
var amount = paybill.Sum(d => d.trade_amount);
var feeamount = paybill.Sum(d => d.fee_amount);
var refundAmount = refundbill.Sum(d => d.trade_amount);
var feeRefundAmount = refundbill.Sum(d => d.fee_amount);
return string.Format("交易数:{0},交易金额:{1},退款金额:{2},手续费:{3}", bill_Accounts.Count, amount, refundAmount, feeamount - feeRefundAmount);
}
public Bill_Account FullBillAccount(Bill_Account bill_Account)
{
return bill_Account;
}
public List GetBillAccountsFromWX_Business(Stream filestream)
{
List result = new List();
foreach (var line in CsvReader.ReadFromStream(filestream))
{
//line.Raw=line.Raw.Replace("`", "");
if (line.ColumnCount != line.Headers.Count()) continue;
Bill_Account bill_Account = new Bill_Account()
{
mch = MCH_enum.Wxpay.ToString(),
mch_id = line["商户号"].TrimStart('`'),
trade_no = line["微信订单号"].TrimStart('`'),
out_trade_no = line["商户订单号"].TrimStart('`'),
trade_datetime = DateTime.Parse(line["交易时间"].TrimStart('`')),
out_mch = line["付款银行"].TrimStart('`'),
out_mchid = line["付款银行"].TrimStart('`'),
trade_info = line["商品名称"].TrimStart('`'),
payer_id = line["用户标识"].TrimStart('`'),
creat_id = UserName,
creat_datetime = DateTime.Now,
last_modify_time = DateTime.Now
};
var type = line["交易状态"].TrimStart('`');
if (type.Equals(WX_TradeType_enum.SUCCESS.ToString()))
{
bill_Account.trade_type = Bill_TradeType_enum.Pay.ToString();
bill_Account.trade_amount = decimal.Parse(line["应结订单金额"].TrimStart('`'));
bill_Account.fee_amount = decimal.Parse(line["手续费"].TrimStart('`'));
}
else if (type.Equals(WX_TradeType_enum.REFUND.ToString()))
{
bill_Account.trade_type = Bill_TradeType_enum.Refund.ToString();
bill_Account.trade_amount = decimal.Parse(line["退款金额"].TrimStart('`'));
bill_Account.fee_amount = Math.Abs(decimal.Parse(line["手续费"].TrimStart('`')));
bill_Account.trade_no = line["微信退款单号"].TrimStart('`');
bill_Account.out_trade_no = line["商户退款单号"].TrimStart('`');
bill_Account.main_trade_no = line["微信订单号"].TrimStart('`');
}
result.Add(bill_Account);
}
return result;
}
public List GetBillAccountsFromAli_xls(Stream filestream, string file_ext = "xls")
{
List result = new List();
IWorkbook workBook = null;
switch (file_ext)
{
case "xls":
workBook = new HSSFWorkbook(filestream);
break;
case "xlsx":
workBook = new XSSFWorkbook(filestream);
break;
default: throw new ArgumentException("非法后缀");
}
var sheet = workBook.GetSheetAt(0);
var row0 = sheet.GetRow(0);
var rownum = sheet.LastRowNum;
var title = row0.GetCell(0).StringCellValue;
var mch_id = "";
if (title.Contains("["))
{
mch_id = title.Split('[')[1].Trim(']');
}
for (int i = 2; i < rownum; i++)
{
var row = sheet.GetRow(i);
var s = row.Cells[1].RichStringCellValue;
}
foreach (var line in CsvReader.ReadFromStream(filestream))
{
//line.Raw=line.Raw.Replace("`", "");
if (line.ColumnCount != line.Headers.Count()) continue;
Bill_Account bill_Account = new Bill_Account()
{
mch = MCH_enum.Wxpay.ToString(),
mch_id = line["商户号"].TrimStart('`'),
trade_no = line["微信订单号"].TrimStart('`'),
out_trade_no = line["商户订单号"].TrimStart('`'),
trade_datetime = DateTime.Parse(line["交易时间"].TrimStart('`')),
out_mch = line["付款银行"].TrimStart('`'),
out_mchid = line["付款银行"].TrimStart('`'),
trade_info = line["商品名称"].TrimStart('`'),
payer_id = line["用户标识"].TrimStart('`'),
creat_id = UserName,
creat_datetime = DateTime.Now,
last_modify_time = DateTime.Now
};
var type = line["交易状态"].TrimStart('`');
if (type.Equals(WX_TradeType_enum.SUCCESS.ToString()))
{
bill_Account.trade_type = Bill_TradeType_enum.Pay.ToString();
bill_Account.trade_amount = decimal.Parse(line["应结订单金额"].TrimStart('`'));
bill_Account.fee_amount = decimal.Parse(line["手续费"].TrimStart('`'));
}
else if (type.Equals(WX_TradeType_enum.REFUND.ToString()))
{
bill_Account.trade_type = Bill_TradeType_enum.Refund.ToString();
bill_Account.trade_amount = decimal.Parse(line["退款金额"].TrimStart('`'));
bill_Account.fee_amount = Math.Abs(decimal.Parse(line["手续费"].TrimStart('`')));
bill_Account.trade_no = line["微信退款单号"].TrimStart('`');
bill_Account.out_trade_no = line["商户退款单号"].TrimStart('`');
bill_Account.main_trade_no = line["微信订单号"].TrimStart('`');
}
else
{
continue;
}
result.Add(bill_Account);
}
return result;
}
public List GetBillAccountsFromAli_csv(Stream filestream)
{
List result = new List();
List FeeRefundList = new List();
Dictionary Feekvs = new Dictionary();
List RefundList = new List();
string csv = new StreamReader(filestream, Encoding.GetEncoding("GB2312")).ReadToEnd();
var top = csv.Substring(1, csv.IndexOf('\n'));
var mch_id = "";
if (top.Contains("["))
{
mch_id = top.Split('[')[1].Trim('\n').Trim(']');
}
foreach (var line in CsvReader.ReadFromText(csv))
{
//line.Raw=line.Raw.Replace("`", "");
if (line.ColumnCount != line.Headers.Count()) continue;
Bill_Account bill_Account = new Bill_Account()
{
mch = MCH_enum.Alipay.ToString(),
mch_id = mch_id,
trade_no = line["支付宝交易号"],
out_trade_no = line["商户订单号"],
trade_datetime = DateTime.Parse(line["入账时间"]),
out_mch = line["支付渠道"],
out_mchid = line["支付渠道"],
trade_info = line["商品名称"],
payer_name = line["对方名称"],
payer_id = line["对方账户"],
creat_id = UserName,
creat_datetime = DateTime.Now,
last_modify_time = DateTime.Now
};
var type = line["账务类型"].TrimStart('`');
var sr = line["收入(+元)"].Trim();
if (type.Contains("在线支付") || (type.Contains("转账") && !string.IsNullOrEmpty(sr)))
{
bill_Account.trade_type = Bill_TradeType_enum.Pay.ToString();
bill_Account.trade_amount = decimal.Parse(line["收入(+元)"]);
bill_Account.fee_amount = decimal.Parse(line["服务费(元)"]);
}
else if (type.Contains("退款") || type.Contains("转账"))
{
bill_Account.trade_type = Bill_TradeType_enum.Refund.ToString();
bill_Account.trade_amount = decimal.Parse(line["支出(-元)"]);
bill_Account.fee_amount = Math.Abs(decimal.Parse(line["服务费(元)"]));
bill_Account.trade_no = line["支付宝流水号"];
bill_Account.main_trade_no = line["支付宝交易号"];
bill_Account.refund_info = line["备注"];
RefundList.Add(bill_Account);
continue;
}
else if (type.Contains("退费"))
{
bill_Account.trade_amount = decimal.Parse(line["收入(+元)"]);
FeeRefundList.Add(bill_Account);
continue;
}
else if (type.Contains("收费"))
{
bill_Account.trade_amount = decimal.Parse(line["支出(-元)"]);
Feekvs.Add(bill_Account.trade_no, bill_Account.trade_amount);
continue;
}
else
{
continue;
}
result.Add(bill_Account);
}
//更新手续费为收费
foreach (var item in result)
{
var fee = 0m;
if (Feekvs.TryGetValue(item.trade_no, out fee))
{
item.fee_amount = fee;
}
}
var rkv = RefundList.ToDictionary(d => d.main_trade_no, d => d);
foreach (var fee in FeeRefundList)
{
rkv[fee.trade_no].fee_amount = fee.trade_amount;
}
result.AddRange(rkv.Values.ToList());
return result;
}
public List GetBillAccountsFromBank(Stream filestream, string file_ext = "xls")
{
List result = new List();
IWorkbook workBook = null;
switch (file_ext)
{
case ".xls":
workBook = new HSSFWorkbook(filestream);
break;
case ".xlsx":
workBook = new XSSFWorkbook(filestream);
break;
default: throw new ArgumentException("非法后缀");
}
var sheet = workBook.GetSheetAt(0);
var row0 = sheet.GetRow(0);
var rownum = sheet.LastRowNum;
for (int i = 1; i <= rownum; i++)
{
try
{
var row = sheet.GetRow(i);
if (row == null)
break;
var s = row.Cells[1].RichStringCellValue;
if (string.IsNullOrEmpty(s.String)) continue;
Bill_Account bill_Account = new Bill_Account()
{
mch = MCH_enum.Bank.ToString(),
mch_id = row.Cells[0].StringCellValue,
trade_no = row.Cells[11].StringCellValue,
out_trade_no = "",
trade_datetime = DateTime.ParseExact(String.Format("{0}{1}", row.Cells[3].StringCellValue, row.Cells[4].StringCellValue), "yyyyMMddHHmmss", CultureInfo.InvariantCulture),
out_mch = row.Cells[22].StringCellValue,
out_mchid = row.Cells[20].StringCellValue,
trade_info = row.Cells[10].StringCellValue,
payer_name = row.Cells[19].StringCellValue,
payer_id = row.Cells[19].StringCellValue,
creat_id = UserName,
creat_datetime = DateTime.Now,
last_modify_time = DateTime.Now
};
var type = row.Cells[6].StringCellValue;
//if (type.Contains("提回对公户收款")|| type.Contains("IBPS对公提回贷记"))
if (row.Cells[7].NumericCellValue == 0)
{
bill_Account.trade_type = Bill_TradeType_enum.Pay.ToString();
bill_Account.trade_amount = Convert.ToDecimal(row.Cells[8].NumericCellValue);
}
else if (row.Cells[8].NumericCellValue == 0)
{
bill_Account.trade_type = Bill_TradeType_enum.Refund.ToString();
bill_Account.trade_amount = Convert.ToDecimal(row.Cells[7].NumericCellValue);
bill_Account.refund_info = row.Cells[10].StringCellValue;
}
else
{
continue;
}
result.Add(bill_Account);
}
catch (Exception ex)
{
Logger.Error($"异常行:{i}", ex);
throw (new Exception($"异常行:{i}", ex));
}
}
return result;
}
public List billAccountChecks(List bill_Accounts)
{
List checks = new List();
if (bill_Accounts.Count == 0) return checks;
WX_SzzyOrderDeposit_BL _orderDeposit = new WX_SzzyOrderDeposit_BL();
var bills = bill_Accounts.Where(d => d.trade_type.Equals(Bill_TradeType_enum.Pay.ToString())).ToList();
var mintime = bills.Min(d => d.trade_datetime).Date;
var maxtime = bills.Max(d => d.trade_datetime).Date.AddDays(1);
var where = PredicateExtensionses.True();
where = where.And(p => p.auditstatus == 1);
where = where.And(p => p.paydate >= mintime && p.paydate < maxtime);
var depositList = _orderDeposit.GetList(where).ToList();
var depositKVs = new ConcurrentDictionary();
var depositKVsError = new ConcurrentDictionary();
foreach (var item in depositList)
{
if (!depositKVs.TryAdd(item.payno, item))
{
depositKVsError.TryAdd(item.payno, item);
}
}
foreach (var item in bills)
{
var billcheck = new BillDto.BillAccountCheck()
{
mch = item.mch,
mch_id = item.mch_id,
trade_no = item.trade_no,
out_trade_no = item.out_trade_no,
trade_datetime = item.trade_datetime,
trade_type = item.trade_type,
trade_amount = item.trade_amount,
fee_amount = item.fee_amount,
out_mch = item.out_mch,
payer_name = item.payer_name,
payer_id = item.payer_id,
out_mchid = item.out_mchid,
trade_info = item.trade_info,
};
//微信支付宝识别订单号
if (item.mch.Equals(MCH_enum.Wxpay.ToString()) || item.mch.Equals(MCH_enum.Alipay.ToString()))
{
WX_SzzyOrderDeposit wX_SzzyOrderDeposit = null;
if (depositKVs.TryRemove(item.trade_no, out wX_SzzyOrderDeposit))
{
billcheck.id = wX_SzzyOrderDeposit.id;
billcheck.resid = wX_SzzyOrderDeposit.resid;
billcheck.paytypename = wX_SzzyOrderDeposit.paytypename;
billcheck.paydate = wX_SzzyOrderDeposit.paydate;
billcheck.payprice = wX_SzzyOrderDeposit.payprice;
billcheck.payname = wX_SzzyOrderDeposit.payname;
billcheck.payno = wX_SzzyOrderDeposit.payno;
if (billcheck.payprice == billcheck.trade_amount)
{
billcheck.checkStatus = Bill_CheckStatus.Success.ToString();
billcheck.checkResult = "成功";
}
else
{
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "金额不对";
}
if (depositKVsError.ContainsKey(item.trade_no))
{
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "此流水号重复";
}
}
else
{
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "账单未匹配";
}
}
//银行
if (item.mch.Equals(MCH_enum.Bank.ToString()))
{
var deposits = depositKVs.Values.ToList();
var deposit = deposits.Where(d => d.payname.Equals(item.payer_name) && d.paydate == item.trade_datetime.Date && d.payprice == item.trade_amount).ToList();
if (deposit.Count == 0)
{
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "账单未匹配";
}
else
{
var wX_SzzyOrderDeposit = deposit.FirstOrDefault();
billcheck.id = wX_SzzyOrderDeposit.id;
billcheck.resid = wX_SzzyOrderDeposit.resid;
billcheck.paytypename = wX_SzzyOrderDeposit.paytypename;
billcheck.paydate = wX_SzzyOrderDeposit.paydate;
billcheck.payprice = wX_SzzyOrderDeposit.payprice;
billcheck.payname = wX_SzzyOrderDeposit.payname;
billcheck.payno = wX_SzzyOrderDeposit.payno;
if (deposit.Count == 1)
{
billcheck.checkStatus = Bill_CheckStatus.Success.ToString();
billcheck.checkResult = "成功";
}
else
{
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "有同用户,同日,同金额多笔交易";
}
}
}
checks.Add(billcheck);
}
//剩余到账未匹配
var somedeposits = depositKVs.Values.ToList();
List depositIds = checks.Select(d => d.id).ToList();
var NoChcek = somedeposits.Where(d => !depositIds.Contains(d.id)).ToList();
foreach (var wX_SzzyOrderDeposit in NoChcek)
{
var billcheck = new BillDto.BillAccountCheck();
billcheck.id = wX_SzzyOrderDeposit.id;
billcheck.resid = wX_SzzyOrderDeposit.resid;
billcheck.paytypename = wX_SzzyOrderDeposit.paytypename;
billcheck.paydate = wX_SzzyOrderDeposit.paydate;
billcheck.payprice = wX_SzzyOrderDeposit.payprice;
billcheck.payname = wX_SzzyOrderDeposit.payname;
billcheck.payno = wX_SzzyOrderDeposit.payno;
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "到账未匹配";
checks.Add(billcheck);
}
return checks;
}
public List billAccountRefundChecks(List bill_Accounts)
{
List checks = new List();
if (bill_Accounts.Count == 0) return checks;
WX_SzzyOrderRefund_BL wX_SzzyOrderRefund_BL = new WX_SzzyOrderRefund_BL();
var bills = bill_Accounts.Where(d => d.trade_type.Equals(Bill_TradeType_enum.Refund.ToString())).ToList();
var mintime = bills.Min(d => d.trade_datetime).Date;
var maxtime = bills.Max(d => d.trade_datetime).Date.AddDays(1);
var where = PredicateExtensionses.True();
where = where.And(p => p.auditstatus == 1);
where = where.And(p => p.refunddate >= mintime && p.refunddate < maxtime);
where = where.And(p => p.isacturalrefund == 1);
var refundList = wX_SzzyOrderRefund_BL.GetList(where).ToList();
foreach (var item in bills)
{
var billcheck = new BillDto.BillRefundCheck()
{
mch = item.mch,
mch_id = item.mch_id,
trade_no = item.trade_no,
out_trade_no = item.out_trade_no,
trade_datetime = item.trade_datetime,
trade_type = item.trade_type,
trade_amount = item.trade_amount,
fee_amount = item.fee_amount,
payer_name = item.payer_name,
payer_id = item.payer_id,
out_mchid = item.out_mchid,
trade_info = item.trade_info,
refund_info = item.refund_info,
main_trade_no = item.main_trade_no
};
var refundordierids = billcheck.refund_info.Replace("退款", "").Replace("转账", "")
.Replace("+", ",").Replace("/", ",").Replace(" ", ",")
.Replace("、", ",").Replace(",", ",").Trim();
billcheck.refund_orderids = refundordierids;
var orderids_str = refundordierids.Split(',');
List otderids = new List();
foreach (var orderidstr in orderids_str)
{
var orderid = 0;
if (Int32.TryParse(orderidstr, out orderid))
{
otderids.Add(orderid);
}
}
int refundtype = 5;
switch (item.mch)
{
case "Alipay":
refundtype = 1;
break;
case "Wxpay":
refundtype = 5;
break;
case "Bank":
refundtype = 3;
break;
default:
break;
}
var refunds = refundList.Where(d => otderids.Contains(d.orderid) && d.refundtype == refundtype).ToList();
if (refunds.Count == 0)
{
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "没有找到订单号";
checks.Add(billcheck);
}
var refundprice = refunds.Sum(d => d.refundprice);
var trade_amount = billcheck.trade_amount;
foreach (var refund in refunds)
{
billcheck.id = Convert.ToInt32(refund.id);
billcheck.orderid = refund.orderid;
billcheck.refundprice = refund.refundprice;
billcheck.username = refund.username;
billcheck.refundtypename = refund.refundtypename;
billcheck.refunddate = refund.refunddate;
billcheck.auditorname = refund.auditorname;
billcheck.audittime = refund.audittime;
if (trade_amount == refundprice)
{
billcheck.checkStatus = Bill_CheckStatus.Success.ToString();
billcheck.checkResult = "成功";
checks.Add(billcheck);
billcheck = new BillDto.BillRefundCheck();
}
else
{
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "金额不对";
checks.Add(billcheck);
billcheck = new BillDto.BillRefundCheck();
}
}
}
//剩余退款未匹配
List checkids = checks.Select(d => d.id).ToList();
var NoChcek = refundList.Where(d => !checkids.Contains(Convert.ToInt32(d.id))).ToList();
foreach (var refund in NoChcek)
{
var billcheck = new BillDto.BillRefundCheck();
billcheck.id = Convert.ToInt32(refund.id);
billcheck.orderid = refund.orderid;
billcheck.refundprice = refund.refundprice;
billcheck.username = refund.username;
billcheck.refundtypename = refund.refundtypename;
billcheck.refunddate = refund.refunddate;
billcheck.auditorname = refund.auditorname;
billcheck.audittime = refund.audittime;
billcheck.checkStatus = Bill_CheckStatus.Fail.ToString();
billcheck.checkResult = "退款未匹配";
checks.Add(billcheck);
}
return checks;
}
public enum MCH_enum
{ Wxpay, Alipay, Bank }
public enum WX_TradeType_enum
{ SUCCESS, REFUND }
public enum Bill_TradeType_enum
{ Pay, Refund }
public enum Bill_CheckStatus
{ Success, Fail }
}
}