コード例 #1
0
 public ServiceResult <PayOrderOM> Pay(PayIM im)
 {
     return(new ServiceResult <PayOrderOM>
     {
         Data = new OrderComponent().Pay(this.GetUser(), im)
     });
 }
コード例 #2
0
ファイル: OrderComponent.cs プロジェクト: BryceStory/BS.FPApp
        /// <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()
            });
        }