public int Insert(OrderWithdrawalFee fee) { var sql = "INSERT INTO OrderWithdrawalFee (CryptoId, Amount, Timestamp, OrderId) VALUES (@CryptoId, @Amount, @Timestamp, @OrderId);SELECT SCOPE_IDENTITY()"; using (var con = ReadConnection()) { return(con.Query <int>(sql, new { fee.CryptoId, fee.Amount, fee.Timestamp, fee.OrderId }).FirstOrDefault()); } }
//private static readonly bool IsPushProduction = Convert.ToBoolean(ConfigurationManager.AppSettings.Get("PushProduction")); public PayOrderOM PayExistedOrder(UserAccount user, string orderNo, string pin) { new SecurityComponent().VerifyPin(user, pin); var isAllowExpense = user.IsAllowExpense ?? true; if (!isAllowExpense) { throw new CommonException(ReasonCode.Not_Allow_Expense, MessageResources.PaymentForbidden); } var order = RedisHelper.Get <RedisOrderDTO>($"fiiipos:order:{orderNo}"); RedisHelper.KeyDelete($"fiiipos:order:{orderNo}"); if (order == null) { throw new ApplicationException(MessageResources.OrderNotFound); } //if (new OrderDAC().GetByOrderNo(orderNo) != null) //{ // throw new ApplicationException(Resources.订单已完成或者已退款); //} if (order.UserId != Guid.Empty) { if (order.UserId != user.Id) { throw new ApplicationException(MessageResources.AccountNotMatch); } } var coin = new CryptocurrencyDAC().GetById(order.CryptoId); if (!coin.Status.HasFlag(CryptoStatus.Pay) || coin.Enable == 0) { throw new CommonException(ReasonCode.CURRENCY_FORBIDDEN, MessageResources.CurrencyForbidden); } var userWallet = new UserWalletDAC().GetByAccountId(user.Id, order.CryptoId); if (userWallet == null) { throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance); } var exchangeRate = GetExchangeRate(order.CountryId, order.FiatCurrency, coin); decimal fiatTotalAmount = (order.FiatAmount * (1 + order.Markup)).ToSpecificDecimal(4); decimal cryptoAmount = (fiatTotalAmount / exchangeRate).ToSpecificDecimal(coin.DecimalPlace); if (userWallet.Balance < cryptoAmount) { throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance); } var merchantAccount = new MerchantAccountDAC().GetById(order.MerchantGuid); if (!merchantAccount.IsAllowAcceptPayment || merchantAccount.Status == AccountStatus.Locked) { throw new CommonException(ReasonCode.Not_Allow_Withdrawal, MessageResources.MerchantExceptionTransClose); } var merchantWallet = new MerchantWalletDAC().GetByAccountId(order.MerchantGuid, order.CryptoId); if (merchantWallet == null || !merchantWallet.SupportReceipt) { throw new ApplicationException(MessageResources.MerchantNotSupperCrypto); } var country = new CountryComponent().GetById(merchantAccount.CountryId); var orderData = new Order { Id = Guid.NewGuid(), OrderNo = order.OrderNo, MerchantAccountId = merchantAccount.Id, CryptoId = coin.Id, CryptoCode = coin.Code, FiatAmount = order.FiatAmount, PaymentType = order.Type, FiatCurrency = order.FiatCurrency, Status = OrderStatus.Completed, ExpiredTime = DateTime.UtcNow.AddMinutes(30), Markup = merchantAccount.Markup, ExchangeRate = GetExchangeRate(merchantAccount.CountryId, order.FiatCurrency, coin), UnifiedExchangeRate = GetExchangeRate(merchantAccount.CountryId, country.FiatCurrency ?? "USD", coin), UnifiedFiatCurrency = country.FiatCurrency ?? "USD", MerchantIP = order.ClientIP, PaymentTime = DateTime.UtcNow, Timestamp = DateTime.UtcNow, UserAccountId = user.Id }; if (merchantAccount.WithdrawalFeeType != WithdrawalFeeType.FiiiCoin) { var calcModel = CalculateAmount(order.FiatAmount, merchantAccount.Markup, merchantAccount.Receivables_Tier, orderData.ExchangeRate, coin); orderData.ActualFiatAmount = calcModel.FiatTotalAmount; orderData.CryptoAmount = calcModel.CryptoAmount; orderData.TransactionFee = calcModel.TransactionFee; orderData.ActualCryptoAmount = calcModel.ActualCryptoAmount; var model = CalculateUnifiedAmount(orderData.CryptoAmount, orderData.ActualCryptoAmount, orderData.UnifiedExchangeRate); orderData.UnifiedFiatAmount = model.UnifiedFiatAmount; orderData.UnifiedActualFiatAmount = model.UnifiedActualFiatAmount; var orderWithdrawalFee = new OrderWithdrawalFee() { Timestamp = DateTime.UtcNow }; orderWithdrawalFee.CryptoId = orderData.CryptoId; orderWithdrawalFee.Amount = 0; Execute(orderWithdrawalFee); } else { var orderWithdrawalFee = CalculateOrderAmount(ref orderData, order, merchantAccount, coin); var wallet = new MerchantWalletDAC().GetByAccountId(merchantAccount.Id, new CryptocurrencyDAC().GetByCode("FIII").Id); if (orderWithdrawalFee.Amount != 0) { using (var scope = new TransactionScope()) { var dbOrder = new OrderDAC().Create(orderData); new UserTransactionDAC().Insert(new UserTransaction { Id = Guid.NewGuid(), AccountId = userWallet.UserAccountId, CryptoId = userWallet.CryptoId, CryptoCode = userWallet.CryptoCode, Type = UserTransactionType.Order, DetailId = dbOrder.Id.ToString(), Status = (byte)dbOrder.Status, Timestamp = dbOrder.Timestamp, Amount = dbOrder.CryptoAmount, OrderNo = dbOrder.OrderNo, MerchantName = merchantAccount.MerchantName }); orderWithdrawalFee.OrderId = dbOrder.Id; var id = new OrderWithdrawalFeeDAC().Insert(orderWithdrawalFee); new MerchantWalletDAC().Decrease(wallet.Id, orderWithdrawalFee.Amount); new MerchantWalletDAC().Increase(merchantWallet.Id, orderData.ActualCryptoAmount); new UserWalletDAC().Decrease(userWallet.Id, cryptoAmount); new UserWalletStatementDAC().Insert(new UserWalletStatement { Action = UserWalletStatementAction.Consume, Amount = orderData.CryptoAmount, Balance = userWallet.Balance - orderData.CryptoAmount, FrozenAmount = 0, FrozenBalance = userWallet.FrozenBalance, Remark = null, Timestamp = DateTime.UtcNow, WalletId = userWallet.Id }); new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement { Action = MerchantWalletStatementAction.Receipt, Amount = orderData.ActualCryptoAmount, Balance = merchantWallet.Balance + orderData.ActualCryptoAmount, Remark = null, Timestamp = DateTime.UtcNow, WalletId = merchantWallet.Id }); new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement { Action = MerchantWalletStatementAction.Withdrawal, Amount = orderWithdrawalFee.Amount, Balance = merchantWallet.Balance - orderData.ActualCryptoAmount, Remark = null, Timestamp = DateTime.UtcNow, WalletId = wallet.Id }); scope.Complete(); } } else { Execute(orderWithdrawalFee); } } void Execute(OrderWithdrawalFee orderWithdrawalFee) { using (var scope = new TransactionScope()) { var dbOrder = new OrderDAC().Create(orderData); new UserTransactionDAC().Insert(new UserTransaction { Id = Guid.NewGuid(), AccountId = userWallet.UserAccountId, CryptoId = userWallet.CryptoId, CryptoCode = userWallet.CryptoCode, Type = UserTransactionType.Order, DetailId = dbOrder.Id.ToString(), Status = (byte)dbOrder.Status, Timestamp = dbOrder.Timestamp, Amount = dbOrder.CryptoAmount, OrderNo = dbOrder.OrderNo, MerchantName = merchantAccount.MerchantName }); orderWithdrawalFee.OrderId = dbOrder.Id; var id = new OrderWithdrawalFeeDAC().Insert(orderWithdrawalFee); new UserWalletDAC().Decrease(userWallet.Id, cryptoAmount); new MerchantWalletDAC().Increase(merchantWallet.Id, orderData.ActualCryptoAmount); new UserWalletStatementDAC().Insert(new UserWalletStatement { Action = UserWalletStatementAction.Consume, Amount = orderData.CryptoAmount, Balance = userWallet.Balance - orderData.CryptoAmount, FrozenAmount = 0, FrozenBalance = userWallet.FrozenBalance, Remark = null, Timestamp = DateTime.UtcNow, WalletId = userWallet.Id }); new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement { Action = MerchantWalletStatementAction.Receipt, Amount = orderData.ActualCryptoAmount, Balance = merchantWallet.Balance + orderData.ActualCryptoAmount, Remark = null, Timestamp = DateTime.UtcNow, WalletId = merchantWallet.Id }); scope.Complete(); } } UserMSMQ.PubOrderPayed(orderData.Id, 0); //PushConsume(orderData.Id); UserMSMQ.PubConsumeOrder(orderData.Id); return(new PayOrderOM { Amount = orderData.CryptoAmount.ToString(coin.DecimalPlace), Currency = new CryptocurrencyDAC().GetById(order.CryptoId).Code, OrderId = orderData.Id.ToString(), OrderNo = orderData.OrderNo, Timestamp = orderData.PaymentTime?.ToUnixTime().ToString() }); }
/// <summary> /// 用户主动支付 /// </summary> /// <param name="user"></param> /// <param name="im"></param> /// <returns></returns> public PayOrderOM Pay(UserAccount user, PayIM im) { if (im.Amount <= 0) { throw new CommonException(ReasonCode.GENERAL_ERROR, MessageResources.AmountGreater); } new SecurityComponent().VerifyPin(user, im.Pin); var isAllowExpense = user.IsAllowExpense ?? true; if (!isAllowExpense) { throw new CommonException(ReasonCode.Not_Allow_Expense, MessageResources.PaymentForbidden); } var coin = new CryptocurrencyDAC().GetById(im.CoinId); if (!coin.Status.HasFlag(CryptoStatus.Pay) || coin.Enable == 0) { throw new CommonException(ReasonCode.CURRENCY_FORBIDDEN, MessageResources.CurrencyForbidden); } var merchantAccount = GetMerchantAccountByIdOrCode(im.MerchantId, im.MerchantCode); if (merchantAccount == null) { throw new CommonException(ReasonCode.INVALID_QRCODE, MessageResources.InvalidQRCode); } if (!merchantAccount.IsAllowAcceptPayment || merchantAccount.Status == AccountStatus.Locked) { throw new CommonException(ReasonCode.Not_Allow_AcceptPayment, MessageResources.MerchantExceptionTransClose); } var country = new CountryComponent().GetById(merchantAccount.CountryId); var orderData = new Order { Id = Guid.NewGuid(), OrderNo = IdentityHelper.OrderNo(), MerchantAccountId = merchantAccount.Id, CryptoId = coin.Id, CryptoCode = coin.Code, FiatAmount = im.Amount, PaymentType = im.PaymentType, FiatCurrency = merchantAccount.FiatCurrency, Status = OrderStatus.Completed, ExpiredTime = DateTime.UtcNow.AddMinutes(30), Markup = merchantAccount.Markup, ExchangeRate = GetExchangeRate(merchantAccount.CountryId, merchantAccount.FiatCurrency, coin), UnifiedExchangeRate = GetExchangeRate(merchantAccount.CountryId, country.FiatCurrency ?? "USD", coin), UnifiedFiatCurrency = country.FiatCurrency ?? "USD", MerchantIP = null, PaymentTime = DateTime.UtcNow, UserAccountId = user.Id, Timestamp = DateTime.UtcNow }; var order = Generate(merchantAccount, coin, country.FiatCurrency ?? "USD", im.Amount, im.PaymentType); order.UserAccountId = user.Id; var userWallet = new UserWalletDAC().GetByAccountId(user.Id, im.CoinId); if (userWallet.Balance < order.CryptoAmount) { throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance); } order.Status = OrderStatus.Completed; order.PaymentTime = DateTime.UtcNow; var merchantWallet = new MerchantWalletDAC().GetByAccountId(order.MerchantAccountId, order.CryptoId); if (merchantWallet == null || !merchantWallet.SupportReceipt) { throw new ApplicationException(MessageResources.MerchantNotSupperCrypto); } if (merchantAccount.WithdrawalFeeType != WithdrawalFeeType.FiiiCoin) { var calcModel = CalculateAmount(im.Amount, merchantAccount.Markup, merchantAccount.Receivables_Tier, orderData.ExchangeRate, coin); orderData.ActualFiatAmount = calcModel.FiatTotalAmount; orderData.CryptoAmount = calcModel.CryptoAmount; orderData.TransactionFee = calcModel.TransactionFee; orderData.ActualCryptoAmount = calcModel.ActualCryptoAmount; var model = CalculateUnifiedAmount(orderData.CryptoAmount, orderData.ActualCryptoAmount, orderData.UnifiedExchangeRate); orderData.UnifiedFiatAmount = model.UnifiedFiatAmount; orderData.UnifiedActualFiatAmount = model.UnifiedActualFiatAmount; var orderWithdrawalFee = new OrderWithdrawalFee { Timestamp = DateTime.UtcNow, CryptoId = orderData.CryptoId, Amount = 0 }; Execute(orderWithdrawalFee); } else { var orderWithdrawalFee = CalculateOrderAmount(ref orderData, new RedisOrderDTO() { CountryId = merchantAccount.CountryId, FiatAmount = im.Amount }, merchantAccount, coin); var wallet = new MerchantWalletDAC().GetByAccountId(merchantAccount.Id, new CryptocurrencyDAC().GetByCode("FIII").Id); if (orderWithdrawalFee.Amount != 0) { using (var scope = new TransactionScope()) { var dbOrder = new OrderDAC().Create(orderData); new UserTransactionDAC().Insert(new UserTransaction { Id = Guid.NewGuid(), AccountId = userWallet.UserAccountId, CryptoId = userWallet.CryptoId, CryptoCode = userWallet.CryptoCode, Type = UserTransactionType.Order, DetailId = dbOrder.Id.ToString(), Status = (byte)dbOrder.Status, Timestamp = dbOrder.Timestamp, Amount = dbOrder.CryptoAmount, OrderNo = dbOrder.OrderNo, MerchantName = merchantAccount.MerchantName }); orderWithdrawalFee.OrderId = dbOrder.Id; var id = new OrderWithdrawalFeeDAC().Insert(orderWithdrawalFee); new MerchantWalletDAC().Decrease(wallet.Id, orderWithdrawalFee.Amount); new MerchantWalletDAC().Increase(merchantWallet.Id, orderData.ActualCryptoAmount); new UserWalletDAC().Decrease(userWallet.Id, orderData.ActualCryptoAmount); new UserWalletStatementDAC().Insert(new UserWalletStatement { Action = UserWalletStatementAction.Consume, Amount = orderData.CryptoAmount, Balance = userWallet.Balance - orderData.CryptoAmount, FrozenAmount = 0, FrozenBalance = userWallet.FrozenBalance, Remark = null, Timestamp = DateTime.UtcNow, WalletId = userWallet.Id }); new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement { Action = MerchantWalletStatementAction.Receipt, Amount = orderData.ActualCryptoAmount, Balance = merchantWallet.Balance + orderData.ActualCryptoAmount, Remark = null, Timestamp = DateTime.UtcNow, WalletId = merchantWallet.Id }); new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement { Action = MerchantWalletStatementAction.Withdrawal, Amount = orderWithdrawalFee.Amount, Balance = merchantWallet.Balance - orderData.ActualCryptoAmount, Remark = null, Timestamp = DateTime.UtcNow, WalletId = wallet.Id }); scope.Complete(); } } else { Execute(orderWithdrawalFee); } } void Execute(OrderWithdrawalFee orderWithdrawalFee) { using (var scope = new TransactionScope()) { var dbOrder = new OrderDAC().Create(orderData); new UserTransactionDAC().Insert(new UserTransaction { Id = Guid.NewGuid(), AccountId = userWallet.UserAccountId, CryptoId = userWallet.CryptoId, CryptoCode = userWallet.CryptoCode, Type = UserTransactionType.Order, DetailId = dbOrder.Id.ToString(), Status = (byte)dbOrder.Status, Timestamp = dbOrder.Timestamp, Amount = dbOrder.CryptoAmount, OrderNo = dbOrder.OrderNo, MerchantName = merchantAccount.MerchantName }); orderWithdrawalFee.OrderId = dbOrder.Id; var id = new OrderWithdrawalFeeDAC().Insert(orderWithdrawalFee); new UserWalletDAC().Decrease(userWallet.Id, orderData.CryptoAmount); new MerchantWalletDAC().Increase(merchantWallet.Id, orderData.ActualCryptoAmount); new UserWalletStatementDAC().Insert(new UserWalletStatement { Action = UserWalletStatementAction.Consume, Amount = orderData.CryptoAmount, Balance = userWallet.Balance - orderData.CryptoAmount, FrozenAmount = 0, FrozenBalance = userWallet.FrozenBalance, Remark = null, Timestamp = DateTime.UtcNow, WalletId = userWallet.Id }); new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement { Action = MerchantWalletStatementAction.Receipt, Amount = orderData.ActualCryptoAmount, Balance = merchantWallet.Balance + orderData.ActualCryptoAmount, Remark = null, Timestamp = DateTime.UtcNow, WalletId = merchantWallet.Id }); scope.Complete(); } } UserMSMQ.PubOrderPayed(orderData.Id, 0); //PushConsume(order.Id); UserMSMQ.PubConsumeOrder(orderData.Id); return(new PayOrderOM { Amount = orderData.CryptoAmount.ToString(coin.DecimalPlace), Currency = new CryptocurrencyDAC().GetById(order.CryptoId).Code, OrderId = orderData.Id.ToString(), OrderNo = orderData.OrderNo, Timestamp = orderData.PaymentTime?.ToUnixTime().ToString() }); }
private OrderWithdrawalFee CalculateOrderAmount(ref Order order, RedisOrderDTO orderDto, MerchantAccount account, Cryptocurrency coin) { var orderWithdrawalFee = new OrderWithdrawalFee() { Timestamp = DateTime.UtcNow }; var wallet = new MerchantWalletDAC().GetByAccountId(account.Id, new CryptocurrencyDAC().GetByCode("FIII").Id); if (wallet == null || !wallet.SupportReceipt) { Excute(ref order); } else { var exchangeFiiiRate = GetExchangeRate(orderDto.CountryId, order.FiatCurrency, new CryptocurrencyDAC().GetById(wallet.CryptoId)); var fiiiCoin = new CryptocurrencyDAC().GetById(wallet.CryptoId); //var tempFiatActualAmount = orderDto.FiatAmount * (1 + account.Markup); var tempFiatActualAmount = orderDto.FiatAmount + (orderDto.FiatAmount * account.Markup).ToSpecificDecimal(4); var fiiiTransactionFee = ((orderDto.FiatAmount + orderDto.FiatAmount * account.Markup) * account.Receivables_Tier / exchangeFiiiRate) .ToSpecificDecimal( fiiiCoin.DecimalPlace); if (wallet.Balance < fiiiTransactionFee) { Excute(ref order); } else { orderWithdrawalFee.CryptoId = fiiiCoin.Id; orderWithdrawalFee.Amount = fiiiTransactionFee; order.ActualFiatAmount = tempFiatActualAmount.ToSpecificDecimal(4); order.CryptoAmount = ((orderDto.FiatAmount + orderDto.FiatAmount * account.Markup) / order.ExchangeRate).ToSpecificDecimal(coin.DecimalPlace); order.TransactionFee = 0; order.ActualCryptoAmount = order.CryptoAmount; var model = CalculateUnifiedAmount(order.CryptoAmount, order.ActualCryptoAmount, order.UnifiedExchangeRate); order.UnifiedFiatAmount = model.UnifiedFiatAmount; order.UnifiedActualFiatAmount = model.UnifiedActualFiatAmount; } } void Excute(ref Order inOrder) { var calcModel = CalculateAmount(orderDto.FiatAmount, account.Markup, account.Receivables_Tier, inOrder.ExchangeRate, coin); inOrder.ActualFiatAmount = calcModel.FiatTotalAmount; inOrder.CryptoAmount = calcModel.CryptoAmount; inOrder.TransactionFee = calcModel.TransactionFee; inOrder.ActualCryptoAmount = calcModel.ActualCryptoAmount; var model = CalculateUnifiedAmount(inOrder.CryptoAmount, inOrder.ActualCryptoAmount, inOrder.UnifiedExchangeRate); inOrder.UnifiedFiatAmount = model.UnifiedFiatAmount; inOrder.UnifiedActualFiatAmount = model.UnifiedActualFiatAmount; orderWithdrawalFee.CryptoId = inOrder.CryptoId; orderWithdrawalFee.Amount = 0; } return(orderWithdrawalFee); }