123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- using static JiaZhiQuan.Common.Models.MallGoodsModel.RefundModel;
- using System.Data;
- using System.Threading.Tasks;
- using Wicture.DbRESTFul.Infrastructure.Repository;
- using JiaZhiQuan.Common.JuheAPI.HuiFu;
- using System.Runtime.CompilerServices;
- using System;
- using JiaZhiQuan.Common.Models.PO;
- using JiaZhiQuan.Common.Models.VO.UE;
- using JiaZhiQuan.Common.Config;
- using MailKit;
- using Elasticsearch.Net;
- using Newtonsoft.Json;
- using System.Collections.Generic;
- using Wicture.DbRESTFul;
- using System.Net.Http.Headers;
- using NPOI.SS.UserModel;
- using JiaZhiQuan.Common.Response;
- namespace JiaZhiQuan.Common {
- public partial class RepositoryExtension {
- #region 账户逻辑
- //插入支出锁定表
- public static async Task<InsertResult> AddUserExpend(this DbRESTFulRepository repository,
- UEUserExpend info, IDbConnection conn, IDbTransaction trans) {
- info.state = 1;
- var expend = await repository.QuerySingleOrDefaultAsync<UEUserExpend>(
- $@"select * from ue_user_expend where orgId=@orgId",
- new { info.orgId,info.expendType });
- if (expend == null) {
- return await repository.SimpleInsert("ue_user_expend", info, conn, trans);
- } else {
- var cnt= await repository.SimpleUpdate("ue_user_expend", new { info.expend,state=1 },
- new { info.orgId, info.expendType }, conn, trans);
- return new InsertResult { count= cnt.count };
- }
- }
- /// <summary>
- /// 查询用户支出中的数据
- /// </summary>
- /// <param name="repository"></param>
- /// <param name="userId"></param>
- /// <param name="expendType">支出类型(1,平台账户支出,2,价值币支出)</param>
- /// <param name="conn"></param>
- /// <param name="trans"></param>
- /// <returns></returns>
- public static async Task<int> UserExpending(this DbRESTFulRepository repository,
- long userId,int expendType,
- IDbConnection conn=null, IDbTransaction trans= null) {
- return await repository.QuerySingleOrDefaultAsync<int?>(
- @$"select sum(expend) expend from ue_user_expend
- where state in(1,3) and userId={userId} and expendType={expendType}", null, conn, trans)??0;
- }
- /// <summary>
- /// 更新支出为支出结束状态
- /// </summary>
- /// <param name="repository"></param>
- /// <param name="orgId"></param>
- /// <param name="expendType">1:平台账号,2:价值币</param>
- /// <param name="conn"></param>
- /// <param name="trans"></param>
- /// <returns></returns>
- public static async Task<OperateResult> UserExpendEnd(this DbRESTFulRepository repository,
- string orgId,int expendType, IDbConnection conn = null, IDbTransaction trans = null) {
- return await repository.SimpleUpdate("ue_user_expend", new {state=2 }, new { orgId, expendType });
- }
- public static async Task<OperateResult> UserExpendExcept(this DbRESTFulRepository repository,
- string orgId, int expendType, IDbConnection conn = null, IDbTransaction trans = null) {
- return await repository.SimpleUpdate("ue_user_expend", new { state = 3 }, new { orgId, expendType });
- }
- //插入平台流水表
- public static async Task<InsertResult> AddPlatformBill(this DbRESTFulRepository repository,
- UEPlatformBill info, IDbConnection conn, IDbTransaction trans) {
- return await repository.SimpleInsert("ue_platform_bill", info, conn, trans); ;
- }
- //插入个人钱包表
- public static async Task<InsertResult> AddWalletDetail(this DbRESTFulRepository repository,
- UEWalletDetail info, IDbConnection conn, IDbTransaction trans) {
- var oldWallet= await repository.QuerySingleOrDefaultAsync<dynamic>(
- $@"select id,balance from ue_wallet where userId=@userId",
- new { info.userId }, conn, trans);
- var oldBalance = oldWallet?.balance ?? 0;
- var wallet = new {
- info.userId,
- balance = (info.detailType == 1 ?
- info.amount : -info.amount) + oldBalance
- };
- if (wallet.balance < 0) {
- throw new Exception("平台账号资金不支持此操作");
- }
- info.balance = wallet.balance;
- var cnt =await repository.SimpleInsert("ue_wallet_detail",info,conn,trans);
- if(cnt.count>0 ) {
- if (oldWallet != null) {
- await repository.SimpleUpdate("ue_wallet", new { wallet.balance },
- new { oldWallet.id }, conn, trans);
- } else {
- await repository.SimpleInsert("ue_wallet",wallet,conn,trans);
- }
- }
- return cnt;
- }
- //查询个人钱包可用的钱
- public static async Task<int> QueryAccountAmount(this DbRESTFulRepository repository,
- long userId) {
- var exist = await repository.QuerySingleOrDefaultAsync<int>(
- $"select balance from ue_wallet where userId={userId}");
- var expending = await repository.UserExpending(userId, 1);
- var canUse = exist - expending;
- if (canUse < 0) {
- canUse = 0;
- }
- return canUse;
- }
- #endregion
- //汇付接口请求插入
- public static async Task<InsertResult> AddHuiFuReq(this DbRESTFulRepository repository,
- HuiFuReqBase info, IDbConnection conn=null, IDbTransaction trans = null) {
- return await repository.SimpleInsert("ue_huifu_req",
- new {
- info.reqId,
- info.orgId, reqType = (int)info.ReqType(),
- billEventType=info.eventType,dealResult=0,
- info.orderId,info.userId }, conn, trans);
- }
- #region 退款逻辑
- /// <summary>
- /// 发起退款
- /// </summary>
- /// <param name="repository"></param>
- /// <param name="order"></param>
- /// <param name="takeoutEarnest">是否扣除保证金</param>
- /// <param name="info">发起请求的基础信息,如 orderId,userId,eventType等</param>
- /// <returns></returns>
- public static async Task<dynamic> LaunchRefund(this DbRESTFulRepository repository,
- ConfigFromDb config, UEOrderHang order, bool? takeoutEarnest, HuiFuReqBase info) {
- //order.earnestMoneyRefunded==1 表示已支付保证金,其他状态表示未支付。
- //takeoutEarnest==false 表示要退保证金
- order = await repository.QuerySingleOrDefaultAsync<UEOrderHang>(
- $@"select * from ue_order_hang where orderId=@orderId", new { order.orderId});
- var hastEarnest = true;
- if (order.earnestAmount <= 0 ||
- order.earnestMoneyRefunded != 1) {
- takeoutEarnest = null;
- hastEarnest = false;
- }
- //仅退保证金
- var onlyEarnest = order.orderState == 5 && hastEarnest && takeoutEarnest == false;
- if(!onlyEarnest) {
- if (order.orderState != -1) {
- throw new Exception("订单状态不正常,不能退款");
- }
- }
- //仅退保证金
- var refundAmt = onlyEarnest ? order.earnestAmount :
- order.payAmount - (hastEarnest&&takeoutEarnest==true ? order.earnestAmount : 0);
- //更改保证金的状态为待退回 ,不扣除,是需要退回的
- if (takeoutEarnest == false && hastEarnest) {
- await repository.SimpleUpdate("ue_order_hang",
- new { earnestMoneyRefunded = 4 }, new { order.orderId, earnestMoneyRefunded = 1 });
- }
- if (refundAmt + order.refundAmount > order.payAmount) {
- throw new Exception("不支持此操作,退款金额大于支付金额");
- }
- if (refundAmt <= 0) {
- var baseResp=new HuiFuRespBase();
- baseResp.CopyBaseInfo(info);
- return await repository.RefundSuccess(baseResp, null,order) ;
- }
- //查询原先的支付信息。
- var payReqInfo = await repository.QuerySingleOrDefaultAsync<UEHuiFuReq>(
- $@"select * from ue_huifu_req where orderId=@orderId
- and billEventType=1 and reqType=1 and dealResult=1 ",new { order.orderId })??
- throw new Exception("不存在支付信息,无法申请退款");
- //生成请求参数
- var reqInfo = new HuiFuRefundInfo {
- ord_amt = refundAmt,
- org_req_date = payReqInfo.createAt.ToString("yyyyMMdd"),
- org_req_seq_id = payReqInfo.reqId
- };
- reqInfo.CopyBaseInfo(info);
-
- //发起汇付请求。
- var resp= await repository.HuiFuRequest<HuiFuRefundResp>(config, reqInfo);
- return resp;
- }
- public static async Task<dynamic> RefundCallback(this DbRESTFulRepository repository,
- HuiFuRespBase info,HuiFuRefundAsyncResp orgResp) {
- var rst = new { count = 0 };
- try {
- var exist = await repository.QuerySingleOrDefaultAsync<UEHuiFuReq>(
- @"select * from ue_huifu_req as r
- where r.reqId=@reqId limit 1",
- new { info.reqId });
- if (exist==null) {
- LoggerManager.Logger.Error($"存在退款回调伪造嫌疑 - 源id:{info.orgId}" +
- $" - extra:{JsonConvert.SerializeObject(info.extra)}");
- return rst;
- }
- info.orderId = exist.orderId.ToString();
- info.orgId = exist.orgId;
- using var conn = repository.ConnectionManager.GetConnection();
- conn.Open();
- var trans = conn.BeginTransaction();
- try {
- //更新流水表状态,因为同一个orgId可能会有多次请求,所以要更新reqId
- await repository.SimpleUpdate("ue_huifu_req", new {
- info.dealResult,
- info.hfSeqId
- }, new { info.reqId, dealResult = new List<int> { 0, 2, 3 } }, conn, trans);
-
- //退款成功,更新相关状态
- if (info.dealResult == 1) {
- await repository.RefundSuccess(info, orgResp,null, conn, trans);
- }
- trans.Commit();
- } catch (Exception ex) {
- trans.Rollback();
- throw;
- }
- } catch (Exception ex) {
- LoggerManager.Logger.Error("处理逻辑出错:" + ex.Message + ex.StackTrace);
- }
- return rst;
- }
- //退款成功操作
- public static async Task<bool> RefundSuccess(this DbRESTFulRepository repository,
- HuiFuRespBase info, HuiFuRefundAsyncResp orgResp, UEOrderHang saleOrder,
- IDbConnection conn = null, IDbTransaction trans = null) {
- var rst = new InsertResult() { count = 0 };
- //更新订单退款金额。
- var order = saleOrder ?? await repository.QuerySingleOrDefaultAsync<UEOrderHang>(
- $@"select * from ue_order_hang where orderId=@orderId ",
- new { info.orderId }) ?? throw new Exception("订单不存在");
- var now = DateTime.Now;
- //仅退保证金
- var onlyEarnest = order.orderState == 5 && order.earnestMoneyRefunded == 4;
- if (!onlyEarnest) {
- if (order.payPoints > 0) {
- //退回价值币
- var canPoints = order.payPoints;
- var count = await repository.QuerySingleOrDefaultAsync<int>(
- @$"update n_user_statistic set points=points+{canPoints}
- where userId={order.buyerId};select row_count() as count;",
- null, conn, trans);
- if (count > 0) {
- // 添加价值币变动记录
- await repository.QueryAsync<dynamic>(@$"insert into n_user_points_record
- (userId, points, `way`, extra, description, createAt, createAtDate)
- values({order.buyerId}, {canPoints}, 'UORDER', '{order.orderId}',
- '交易取消-订单{order.orderId}', now(), now())", null, conn, trans);
- }
- }
- //退回平台账户抵扣金额。
- if (order.accountDeductionAmount > 0) {
- //钱包金额增加
- var detail = new UEWalletDetail {
- detailId = Guid.NewGuid().ToString("N"),
- detailType = 1,//收入
- detailEvent = 11,
- orderId = order.orderId,
- amount = order.accountDeductionAmount.Value,
- payway = 1,
- userId = order.buyerId,
- createAt = now,
- };
- await repository.AddWalletDetail(detail, conn, trans);
- }
- }
- //添加平台流水
- var refundAmt = double.Parse(orgResp?.actual_ref_amt ?? "0") * 100;
- if (refundAmt > 0) {
- var bill = new UEPlatformBill {
- billId = Guid.NewGuid().ToString("N"),
- billType = 2,
- billEvent = onlyEarnest ? 20 : 21,
- orderId = order.orderId,
- amount = (int)refundAmt,
- payway = 1,
- userId = order.buyerId,
- createAt = now,
- };
- await repository.AddPlatformBill(bill, conn, trans);
- var cnt = await repository.SimpleUpdate("ue_order_hang",
- new {
- refundAmount = order.refundAmount + refundAmt
- },
- new { order.orderId }, conn, trans);
- }
- await repository.SimpleUpdate("ue_order_hang",
- new {
- earnestMoneyRefunded = 2
- },
- new { order.orderId, earnestMoneyRefunded = 4 }, conn, trans);
- return true;
- }
- #endregion
- /// <summary>
- /// 请求汇付接口
- /// </summary>
- /// <typeparam name="TResp"></typeparam>
- /// <param name="repository"></param>
- /// <param name="config"></param>
- /// <param name="info"></param>
- /// <param name="isOrgIdUnique">源id在记录表里是否唯一</param>
- /// <param name="conn"></param>
- /// <param name="trans"></param>
- /// <returns></returns>
- public static async Task<TResp> HuiFuRequest<TResp>(this DbRESTFulRepository repository,
- ConfigFromDb config, HuiFuReqBase info,bool isOrgIdUnique=false,
- IDbConnection conn=null,IDbTransaction trans = null) {
- info.InitNoticeUrl(config);
- HuiFuUtil.InitReqId(info);
- //插入请求记录
- if (isOrgIdUnique) {
- //查询库中的记录。
- var reqRecord = await repository.QuerySingleOrDefaultAsync<UEHuiFuReq>(
- $@"select orgId from ue_huifu_req where orgId=@orgId limit 1",
- new { info.orgId });
- if (reqRecord != null) {
- await repository.SimpleUpdate("ue_huifu_req", new { info.reqId },
- new { info.orgId });
- } else {
- await repository.AddHuiFuReq(info);
- }
- } else {
- await repository.AddHuiFuReq(info);
- }
- //插入请求内容
- await repository.SimpleInsert("ue_huifu_req_result", new {
- info.reqId,
- reqInfo = JsonConvert.SerializeObject(info),
- }, conn, trans);
- var resp = HuiFuUtil.Request<TResp>(config.HuiFuConfig,info);
- //状态要改成处理中,失败改成失败
- var dealResult = 3;
- if (resp == null) {
- dealResult = 2;
- } else {
- //请求成功,处理结果为处理中
- if(resp is HuiFuIndvResp indvResp&&
- !string.IsNullOrEmpty(indvResp.huifu_id)) {
- dealResult = 1;
- } else {
- dealResult = 3;
- }
-
- await repository.SimpleUpdate("ue_huifu_req_result",
- new { respInfo = JsonConvert.SerializeObject(resp) },
- new { info.reqId }, conn, trans);
- }
- //更新处理结果
- await repository.SimpleUpdate("ue_huifu_req", new { dealResult },
- new {
- dealResult = 0,
- info.reqId
- }, conn, trans);
- return resp;
- }
- public class UEUserExpend {
- /// <summary>
- /// 主键ID
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public int id { get; set; }
- /// <summary>
- /// 操作源id(如支付id,退款id,或提现id等)
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public string orgId { get; set; }
- /// <summary>
- /// 支出数量(货币单位是分,价值币单位是1价值币)
- /// </summary>
- public int expend { get; set; }
- /// <summary>
- /// 支出类型
- /// </summary>
- /// <remarks>
- /// 1,平台账户支出,2,价值币支出
- /// </remarks>
- public int expendType { get; set; }
- /// <summary>
- /// 支出状态
- /// </summary>
- /// <remarks>
- /// 1,支出中,2支出完成,默认1
- /// </remarks>
- public int state { get; set; }
- /// <summary>
- /// 用户id
- /// </summary>
- public long userId { get; set; }
- /// <summary>
- /// 创建时间
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public DateTime createAt { get; set; }
- /// <summary>
- /// 修改时间
- /// </summary>
- public DateTime? updateAt { get; set; }
- }
- public class UEHuiFuReq {
- /// <summary>
- /// 主键ID
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public int id { get; set; }
- /// <summary>
- /// 请求流水号(由原始id加前缀组成,reqType为1,前缀加P,2加I,3加O,4加C,5加R,6加RQ,后缀加随机4位,方便同样的orgId可以多次请求)
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public string reqId { get; set; }
- /// <summary>
- /// 原始id(如果是支付,就是支付id,如果是退款,就是退款id,如果没有,就为空)
- /// </summary>
- public string orgId { get; set; }
- /// <summary>
- /// 汇付流水号(全局流水号)
- /// </summary>
- public string hfSeqId { get; set; }
- /// <summary>
- /// 请求类型(1,聚合正扫,2,用户开户3,用户入驻4,用户提现5,取消订单退款6,取消订单退款查询)
- /// </summary>
- public sbyte reqType { get; set; }
- /// <summary>
- /// 处理结果(0待处理,1成功,2失败,3处理中)
- /// </summary>
- public sbyte dealResult { get; set; }
- /// <summary>
- /// 事件类型(0无,1,订单支付,2商品取回,仓储费支付,3订单取消退款,4,取货保证金退款,5,下单抵扣,6,提现)
- /// </summary>
- public sbyte billEventType { get; set; }
- /// <summary>
- /// 订单编号
- /// </summary>
- public long orderId { get; set; }
- /// <summary>
- /// 用户id
- /// </summary>
- public long userId { get; set; }
- /// <summary>
- /// 原交易流水号
- /// </summary>
- public string orgReqSeqId { get; set; }
- /// <summary>
- /// 创建时间
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public DateTime createAt { get; set; }
- }
- public class UEPlatformBill {
- /// <summary>
- /// 主键ID,流水编号
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public string billId { get; set; }
- /// <summary>
- /// 流水类型
- /// </summary>
- /// <remarks>
- /// 1: 收入,2: 支出
- /// 非空
- /// </remarks>
- public int billType { get; set; }
- /// <summary>
- /// 流水事件
- /// </summary>
- /// <remarks>
- /// 收入类型范围在[10-19],支出类型范围在[20-29]
- /// 例如:收入:10-订单收入,11-仓储费收入;支出:20-取货保证金退款,21-订单退款,22-提现
- /// </remarks>
- public int billEvent { get; set; }
- /// <summary>
- /// 订单编号
- /// </summary>
- public long? orderId { get; set; }
- /// <summary>
- /// 流水金额单位分
- /// </summary>
- public int amount { get; set; }
- /// <summary>
- /// 支付方式
- /// </summary>
- /// <remarks>
- /// 1: 支付宝,2: 银行卡
- /// </remarks>
- public int payway { get; set; }
- /// <summary>
- /// 用户id
- /// </summary>
- public long userId { get; set; }
- /// <summary>
- /// 创建时间
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public DateTime createAt { get; set; }
- /// <summary>
- /// 修改时间
- /// </summary>
- public DateTime? updateAt { get; set; }
- }
- public class UEWalletDetail {
- /// <summary>
- /// 主键ID,明细编号
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public string detailId { get; set; }
- /// <summary>
- /// 明细类型
- /// </summary>
- /// <remarks>
- /// 1: 收入,2: 支出
- /// 非空
- /// </remarks>
- public int detailType { get; set; }
- /// <summary>
- /// 流水事件
- /// </summary>
- /// <remarks>
- /// 收入类型范围在[10-19],支出类型范围在[20-29]
- /// 例如:收入:10-卖货收入,11-撤单退回,12-取货保证金退回;
- /// 支出:20-下单抵扣,21-提现
- /// </remarks>
- public int detailEvent { get; set; }
- /// <summary>
- /// 订单编号
- /// </summary>
- public long? orderId { get; set; }
- /// <summary>
- /// 流水金额 单位分
- /// </summary>
- public int amount { get; set; }
- /// <summary>
- /// 当前结存
- /// </summary>
- public int balance { get; set; }
- /// <summary>
- /// 支付方式
- /// </summary>
- /// <remarks>
- /// 1: 支付宝,2: 银行卡
- /// </remarks>
- public int payway { get; set; }
- /// <summary>
- /// 用户id
- /// </summary>
- public long userId { get; set; }
- /// <summary>
- /// 创建时间
- /// </summary>
- /// <remarks>
- /// 非空
- /// </remarks>
- public DateTime createAt { get; set; }
- /// <summary>
- /// 修改时间
- /// </summary>
- public DateTime? updateAt { get; set; }
- }
- }
- }
|