Example #1
0
        public BillerPayOM Pay(UserAccount account, BillerPayIM im, ref int errorCode)
        {
            var coin = new CryptocurrencyDAC().GetById(im.CryptoId);

            if (!coin.Status.HasFlag(CryptoStatus.Biller) || coin.Enable == 0)
            {
                throw new CommonException(ReasonCode.CURRENCY_FORBIDDEN, MessageResources.CurrencyForbidden);
            }
            var result = PrePay(new BillerPrePayIM()
            {
                CountryId = im.CountryId, CryptoAmount = im.CryptoAmount, CryptoCode = im.CryptoCode,
                CryptoId  = im.CryptoId, FiatAmount = im.FiatAmount, FiatCurrency = im.FiatCurrency
            }).Status;

            if (result != 0)
            {
                errorCode = 10400 + result;
                return(null);
            }

            new SecurityComponent().VerifyPin(account, im.Pin);
            var cryptoCurrency = new CryptocurrencyDAC().GetById(im.CryptoId);

            if (cryptoCurrency?.Id == null)
            {
                throw new CommonException(ReasonCode.CRYPTO_NOT_EXISTS, "Error: Invalid Cryptocurrency");
            }
            var uwComponent = new UserWalletComponent();
            var userWallet  = uwComponent.GetUserWallet(account.Id, im.CryptoId);

            if (userWallet == null)
            {
                throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance);
            }
            if (userWallet.Balance < im.CryptoAmount)
            {
                throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance);
            }
            var uwDAC       = new UserWalletDAC();
            var uwsDAC      = new UserWalletStatementDAC();
            var boDAC       = new BillerOrderDAC();
            var billerOrder = new BillerOrder()
            {
                Id           = Guid.NewGuid(),
                BillerCode   = im.BillerCode,
                CryptoAmount = im.CryptoAmount,
                CryptoCode   = im.CryptoCode,
                CryptoId     = im.CryptoId,
                Discount     = im.CryptoCode.Equals("Fiii", StringComparison.InvariantCultureIgnoreCase)
                    ? decimal.Parse(new MasterSettingDAC().SelectByGroup("BillerMaxAmount").First(item =>
                                                                                                  item.Name.Equals("DiscountRate", StringComparison.CurrentCultureIgnoreCase)).Value)
                    : 0,
                ExchangeRate    = im.ExchangeRate,
                FiatAmount      = im.FiatAmount,
                FiatCurrency    = im.FiatCurrency,
                ReferenceNumber = im.ReferenceNumber,
                Tag             = im.Tag,
                Status          = BillerOrderStatus.Pending,
                Timestamp       = DateTime.UtcNow,
                AccountId       = account.Id,
                OrderNo         = IdentityHelper.OrderNo(),
                PayTime         = DateTime.UtcNow,
                CountryId       = im.CountryId
            };
            var address = new BillerAddressDAC().GetAllAddresses(account.Id).FirstOrDefault(item =>
                                                                                            item.BillerCode == im.BillerCode && im.ReferenceNumber == item.ReferenceNumber);

            billerOrder.Tag = address?.Tag;
            using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, new TimeSpan(0, 0, 1, 30)))
            {
                uwDAC.Decrease(userWallet.Id, billerOrder.CryptoAmount);
                uwsDAC.Insert(new UserWalletStatement
                {
                    WalletId      = userWallet.Id,
                    Action        = UserWalletStatementAction.Consume,
                    Amount        = -billerOrder.CryptoAmount,
                    Balance       = userWallet.Balance - billerOrder.CryptoAmount,
                    FrozenAmount  = 0,
                    FrozenBalance = userWallet.FrozenBalance,
                    Timestamp     = DateTime.UtcNow
                });

                boDAC.Insert(billerOrder);
                new UserTransactionDAC().Insert(new UserTransaction
                {
                    Id         = Guid.NewGuid(),
                    AccountId  = billerOrder.AccountId,
                    CryptoId   = cryptoCurrency.Id,
                    CryptoCode = cryptoCurrency.Code,
                    Type       = UserTransactionType.BillOrder,
                    DetailId   = billerOrder.Id.ToString(),
                    Status     = (byte)billerOrder.Status,
                    Timestamp  = billerOrder.Timestamp,
                    Amount     = billerOrder.CryptoAmount,
                    OrderNo    = billerOrder.OrderNo
                });
                scope.Complete();
            }

            return(new BillerPayOM()
            {
                CryptoAmount = billerOrder.CryptoAmount.ToString(), OrderNo = billerOrder.OrderNo,
                CryptoCode = billerOrder.CryptoCode, OrderId = billerOrder.Id,
                Timestamp = billerOrder.PayTime.ToUnixTime().ToString(),
                SaveAddress = address != null
            });
        }
Example #2
0
        //private readonly Dictionary<string, int> _notificationErrorCount = new Dictionary<string, int>();

        public void Payment(string message)
        {
            var orderModel = JsonConvert.DeserializeObject <MallPaymentOrder>(message);

            var userWalletDac      = new UserWalletDAC();
            var walletStatementDac = new UserWalletStatementDAC();
            var gatewayOrderDac    = new GatewayOrderDAC();
            var mallDac            = new MallPaymentOrderDAC();
            var cryptoDac          = new CryptocurrencyDAC();

            var extsis = gatewayOrderDac.GetByOrderNo(orderModel.OrderId);

            if (extsis != null && extsis.Status == GatewayOrderStatus.Completed)
            {
                _log.Info("Order message " + message + " hased Payment.");
                return;
            }

            var cryptoFiii = cryptoDac.GetByCode("FIII");
            var fiiiWallet = userWalletDac.GetByAccountId(orderModel.UserAccountId, cryptoFiii.Id);

            if (fiiiWallet.Balance < orderModel.CryptoAmount)
            {
                _log.ErrorFormat("message {0}, Insufficient balance", message);
            }

            try
            {
                var fiiiPrice      = GetMarketPrice("USD", "FIII");
                var fiiiFiatAmount = Math.Round(orderModel.CryptoAmount * fiiiPrice, 2);

                var trdeNo = NumberGenerator.GenerateUnixOrderNo();
                var id     = Guid.NewGuid();
                using (var scope = new TransactionScope())
                {
                    userWalletDac.Decrease(fiiiWallet.Id, orderModel.CryptoAmount);
                    walletStatementDac.Insert(new UserWalletStatement
                    {
                        WalletId      = fiiiWallet.Id,
                        Action        = UserWalletStatementAction.Consume,
                        Amount        = -orderModel.CryptoAmount,
                        Balance       = fiiiWallet.Balance - orderModel.CryptoAmount,
                        FrozenAmount  = 0,
                        FrozenBalance = fiiiWallet.FrozenBalance,
                        Timestamp     = DateTime.UtcNow
                    });

                    var gatewayFiiiOrder = new GatewayOrder
                    {
                        Id                 = id,
                        OrderNo            = orderModel.OrderId,
                        MerchantAccountId  = Guid.Empty,
                        MerchantName       = "FiiiShop",
                        CryptoId           = cryptoFiii.Id,
                        CryptoCode         = "FIII",
                        FiatAmount         = fiiiFiatAmount,
                        FiatCurrency       = "USD",
                        Status             = GatewayOrderStatus.Completed,
                        ExpiredTime        = DateTime.UtcNow.AddMinutes(30),
                        Markup             = 0M,
                        ExchangeRate       = fiiiPrice,
                        PaymentTime        = DateTime.UtcNow,
                        Timestamp          = DateTime.UtcNow,
                        UserAccountId      = orderModel.UserAccountId,
                        ActualCryptoAmount = orderModel.CryptoAmount,
                        ActualFiatAmount   = fiiiFiatAmount,
                        CryptoAmount       = orderModel.CryptoAmount,
                        TransactionFee     = 0,
                        Remark             = null,
                        TradeNo            = trdeNo
                    };
                    gatewayOrderDac.Insert(gatewayFiiiOrder);

                    mallDac.UpdateStatus(orderModel.Id, (byte)OrderStatus.Completed);
                    mallDac.UpdateTradeNo(orderModel.Id, trdeNo);

                    scope.Complete();
                }

                RabbitMQSender.SendMessage("ShopPayment", id);
                SendNotificationMessage(TradeType.Payment, orderModel.Id, orderModel.OrderId, trdeNo, "success");
            }
            catch (Exception exception)
            {
                //SendNotificationMessage(TradeType.Payment, orderModel.Id, orderModel.OrderId, string.Empty, "error");
                _log.Error("Payment error, exception : " + exception.Message);
            }
        }
        private GatewayOrder ExcutePay(GatewayOrderOM orderDetail, Guid id)
        {
            var cryptoCurrency = new CryptocurrencyDAC().GetByCode(orderDetail.Crypto);

            if (cryptoCurrency == null || cryptoCurrency?.Id == null)
            {
                throw new CommonException(CRYPTO_NOT_EXISTS, "Error: Invalid Cryptocurrency");
            }
            //var uwComponent = new UserWalletComponent();
            var userWallet = new UserWalletDAC().GetUserWallet(orderDetail.UserAccountId.Value, cryptoCurrency.Id);

            if (userWallet.Balance < orderDetail.ActualCryptoAmount)
            {
                throw new CommonException(INSUFFICIENT_BALANCE, Resources.余额不足);
            }
            var uwDAC  = new UserWalletDAC();
            var uwsDAC = new UserWalletStatementDAC();
            var goDAC  = new GatewayOrderDAC();

            bool needAddOrder = true;
            var  gatewayOrder = goDAC.GetByTradeNo(orderDetail.Id.ToString());

            if (gatewayOrder != null)
            {
                if (gatewayOrder.Status != GatewayOrderStatus.Pending)
                {
                    throw new CommonException(ORDER_HAD_COMPLETE, Resources.订单已完成或者已退款);
                }
                needAddOrder = false;
            }
            else
            {
                gatewayOrder = new Entities.GatewayOrder()
                {
                    OrderNo            = CreateOrderno(),
                    TradeNo            = orderDetail.Id.ToString(),
                    Id                 = id,
                    CryptoId           = cryptoCurrency.Id,
                    MerchantAccountId  = orderDetail.MerchantAccountId,
                    FiatAmount         = orderDetail.FiatAmount,
                    MerchantName       = orderDetail.MerchantName,
                    UserAccountId      = orderDetail.UserAccountId,
                    CryptoAmount       = orderDetail.CryptoAmount,
                    ActualCryptoAmount = orderDetail.ActualCryptoAmount,
                    FiatCurrency       = orderDetail.FiatCurrency,
                    Markup             = orderDetail.MarkupRate,
                    ActualFiatAmount   = orderDetail.ActualFiatAmount,
                    Status             = GatewayOrderStatus.Completed,
                    ExchangeRate       = orderDetail.ExchangeRate,
                    ExpiredTime        = orderDetail.ExpiredTime,
                    TransactionFee     = orderDetail.TransactionFee,
                    Timestamp          = DateTime.UtcNow,
                    PaymentTime        = DateTime.UtcNow,
                    Remark             = orderDetail.Remark
                };
            }

            using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, new TimeSpan(0, 0, 1, 30)))
            {
                if (needAddOrder)
                {
                    goDAC.Insert(gatewayOrder);
                }
                uwDAC.Decrease(userWallet.Id, orderDetail.ActualCryptoAmount);
                uwsDAC.Insert(new UserWalletStatement
                {
                    WalletId      = userWallet.Id,
                    Action        = UserWalletStatementAction.TansferOut,
                    Amount        = -orderDetail.ActualCryptoAmount,
                    Balance       = userWallet.Balance - orderDetail.ActualCryptoAmount,
                    FrozenAmount  = 0,
                    FrozenBalance = userWallet.FrozenBalance,
                    Timestamp     = DateTime.UtcNow
                });

                scope.Complete();
            }

            return(gatewayOrder);
        }
        public RedPocket Push(UserAccount userAccount, Guid accountId, int cryptoId, decimal amount, int count, string userPIN, string pin, string message = "")
        {
            if (userAccount.L1VerifyStatus != Entities.Enums.VerifyStatus.Certified)
            {
                throw new CommonException(ReasonCode.NOT_VERIFY_LV1, Resources.EMNeedLV1Verfied);
            }

            if (amount <= 0 || cryptoId <= 0)
            {
                throw new CommonException(Argument_Error, MessageResources.InvalidDataFormat);
            }
            if (count <= 0)
            {
                throw new CommonException(Argument_Error, MessageResources.InvalidDataFormat);
            }

            if (count > MaxCount)
            {
                throw new CommonException(Argument_Error, string.Format(MessageResources.RedPocket_MaxCount, MaxCount));
            }

            if (!string.IsNullOrWhiteSpace(message) && message.Length > 46)
            {
                throw new CommonException(Argument_Error, MessageResources.RedPocket_MaxMessage);
            }

            SecurityVerify.Verify(new PinVerifier(), SystemPlatform.FiiiPay, accountId.ToString(), userPIN, pin);

            var cryptoDAC = new CryptocurrencyDAC();
            var priceDAC  = new PriceInfoDAC();

            var crypto = cryptoDAC.GetById(cryptoId);

            if (crypto == null)
            {
                throw new SystemErrorException();
            }

            if (!crypto.Status.HasFlag(Foundation.Entities.Enum.CryptoStatus.RedPocket) || crypto.Enable == 0)
            {
                throw new CommonException(ReasonCode.CURRENCY_FORBIDDEN, MessageResources.CurrencyForbidden);
            }

            var min = crypto.DecimalPlace == 8 ? 0.00000001M : crypto.DecimalPlace == 6 ? 0.000001M : 0.00000001M;

            var minAmount = count * min;

            if (amount < minAmount)
            {
                throw new CommonException(Push_MinAmount, string.Format(MessageResources.RedPocket_MinAmount, minAmount, crypto.Code));
            }

            var price = priceDAC.GetPriceByName("USD", crypto.Code);

            var max       = crypto.DecimalPlace == 8 ? 999999999.999999999M : crypto.DecimalPlace == 6 ? 999999999.999999M : 999999999.999999999M;
            var maxAmount = Math.Round(MaxAmount / price, crypto.DecimalPlace);

            if (count > 1)
            {
                maxAmount = Math.Round(MaxAmount * count / price, crypto.DecimalPlace);
            }

            if (amount >= max || Math.Round(amount, crypto.DecimalPlace) > maxAmount)
            {
                throw new CommonException(Argument_Error, string.Format(MessageResources.RedPocket_MaxAmount, maxAmount, crypto.Code));
            }

            var userWalletDAC          = new UserWalletDAC();
            var redPocketDAC           = new RedPocketDAC();
            var userWalletStatementDAC = new UserWalletStatementDAC();
            var userTransactionDAC     = new UserTransactionDAC();

            var wallet = userWalletDAC.GetByAccountId(accountId, cryptoId);

            if (wallet == null || wallet.Balance < amount)
            {
                throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance);
            }

            var fiatAmount = price * amount;

            using (var scope = new TransactionScope())
            {
                try
                {
                    var redPocket = new RedPocket
                    {
                        AccountId      = accountId,
                        Status         = RedPocketStatus.Actived,
                        PassCode       = GeneralPassCode(),
                        CryptoCode     = crypto.Code,
                        Amount         = amount,
                        Balance        = amount,
                        Count          = count,
                        RemainCount    = count,
                        Message        = message,
                        Timestamp      = DateTime.UtcNow,
                        ExpirationDate = DateTime.UtcNow.AddMinutes(_expried),
                        CryptoId       = cryptoId,
                        OrderNo        = IdentityHelper.OrderNo(),
                        FiatAmount     = fiatAmount <= 0 ? 0M : Math.Round(fiatAmount, 8)
                    };

                    var redPocketId = redPocketDAC.Insert(redPocket);
                    userTransactionDAC.Insert(new UserTransaction
                    {
                        Id         = Guid.NewGuid(),
                        AccountId  = accountId,
                        CryptoId   = redPocket.CryptoId,
                        CryptoCode = redPocket.CryptoCode,
                        Type       = UserTransactionType.PushRedPocket,
                        DetailId   = redPocketId.ToString(),
                        Status     = (byte)redPocket.Status,
                        Timestamp  = redPocket.Timestamp,
                        Amount     = redPocket.Amount,
                        OrderNo    = redPocket.OrderNo
                    });

                    userWalletDAC.Decrease(wallet.Id, amount);
                    userWalletStatementDAC.Insert(new UserWalletStatement
                    {
                        WalletId      = wallet.Id,
                        Balance       = wallet.Balance - amount,
                        Amount        = 0 - amount,
                        FrozenAmount  = 0,
                        FrozenBalance = wallet.FrozenBalance,
                        Action        = "Push Red Pocket",
                        Timestamp     = DateTime.UtcNow
                    });

                    QueueHelper.DelaySender.Send("FiiiPay_RedPocket", redPocketId);

                    scope.Complete();

                    return(redPocket);
                }
                catch (Exception ex)
                {
                    _log.Error(ex);

                    throw new SystemErrorException();
                }
            }
        }
Example #5
0
        public TransferOM Transfer(UserAccount account, TransferIM im)
        {
            SecurityVerify.Verify(new PinVerifier(), SystemPlatform.FiiiPay, account.Id.ToString(), account.Pin, im.Pin);
            if (account.L1VerifyStatus != VerifyStatus.Certified)
            {
                throw new ApplicationException();
            }
            if (account.IsAllowTransfer.HasValue && !account.IsAllowTransfer.Value)
            {
                throw new CommonException(ReasonCode.TRANSFER_FORBIDDEN, MessageResources.TransferForbidden);
            }
            var toAccount = new UserAccountDAC().GetByCountryIdAndCellphone(im.ToCountryId, im.ToCellphone);

            if (toAccount == null)
            {
                throw new CommonException(ReasonCode.ACCOUNT_NOT_EXISTS, MessageResources.AccountNotExist);
            }
            if (toAccount.IsAllowTransfer.HasValue && !toAccount.IsAllowTransfer.Value)
            {
                throw new CommonException(ReasonCode.TRANSFER_FORBIDDEN, MessageResources.ToAccountTransferForbidden);
            }
            if (im.Amount >= Convert.ToDecimal(Math.Pow(10, 11)))
            {
                throw new CommonException(ReasonCode.TRANSFER_AMOUNT_OVERFLOW, MessageResources.TransferAmountOverflow);
            }
            var currency = new CryptocurrencyDAC().GetById(im.CoinId);

            if (!currency.Status.HasFlag(CryptoStatus.Transfer) || currency.Enable == 0)
            {
                throw new CommonException(ReasonCode.CURRENCY_FORBIDDEN, MessageResources.CurrencyForbidden);
            }
            if (im.Amount < (decimal)Math.Pow(10, -currency.DecimalPlace))
            {
                throw new CommonException(ReasonCode.TRANSFER_AMOUNT_OVERFLOW, MessageResources.TransferAmountTooSmall);
            }
            var decimalDigits = im.Amount.ToString().Length - im.Amount.ToString().IndexOf('.') - 1;

            if (decimalDigits > currency.DecimalPlace)
            {
                throw new CommonException(ReasonCode.TRANSFER_AMOUNT_OVERFLOW, MessageResources.TransferAmountOverflow);
            }

            if (account.Id == toAccount.Id)
            {
                throw new CommonException(ReasonCode.TRANSFER_TO_SELF, MessageResources.TransferToSelf);
            }

            var uwComponent = new UserWalletComponent();

            var toWallet = uwComponent.GetUserWallet(toAccount.Id, im.CoinId);

            if (toWallet == null)
            {
                toWallet = uwComponent.GenerateWallet(toAccount.Id, currency.Id);
            }

            var      country      = new CountryComponent().GetById(im.ToCountryId);
            DateTime dtCreateTime = DateTime.UtcNow;

            var fromWallet = uwComponent.GetUserWallet(account.Id, im.CoinId);

            if (fromWallet.Balance < im.Amount)
            {
                throw new CommonException(ReasonCode.TRANSFER_BALANCE_LOW, MessageResources.TransferBalanceLow);
            }

            UserTransfer transfer = new UserTransfer
            {
                Timestamp         = dtCreateTime,
                OrderNo           = CreateOrderno(),
                FromUserAccountId = account.Id,
                FromUserWalletId  = fromWallet.Id,
                CoinId            = currency.Id,
                CoinCode          = currency.Code,
                ToUserAccountId   = toAccount.Id,
                ToUserWalletId    = toWallet.Id,
                Amount            = im.Amount,
                Status            = (byte)TransactionStatus.Confirmed
            };

            var uwDAC  = new UserWalletDAC();
            var uwsDAC = new UserWalletStatementDAC();
            var utDAC  = new UserTransactionDAC();

            //var pushComponent = new FiiiPayPushComponent();
            using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, new TimeSpan(0, 0, 1, 30)))
            {
                transfer.Id = new UserTransferDAC().Insert(transfer);

                utDAC.Insert(new UserTransaction
                {
                    Id         = Guid.NewGuid(),
                    AccountId  = transfer.FromUserAccountId,
                    CryptoId   = transfer.CoinId,
                    CryptoCode = transfer.CoinCode,
                    Type       = UserTransactionType.TransferOut,
                    DetailId   = transfer.Id.ToString(),
                    Status     = transfer.Status,
                    Timestamp  = dtCreateTime,
                    Amount     = transfer.Amount,
                    OrderNo    = transfer.OrderNo
                });

                utDAC.Insert(new UserTransaction
                {
                    Id         = Guid.NewGuid(),
                    AccountId  = transfer.ToUserAccountId,
                    CryptoId   = transfer.CoinId,
                    CryptoCode = transfer.CoinCode,
                    Type       = UserTransactionType.TransferIn,
                    DetailId   = transfer.Id.ToString(),
                    Status     = transfer.Status,
                    Timestamp  = dtCreateTime,
                    Amount     = transfer.Amount,
                    OrderNo    = transfer.OrderNo
                });

                uwDAC.Decrease(fromWallet.Id, transfer.Amount);
                uwDAC.Increase(toWallet.Id, transfer.Amount);

                uwsDAC.Insert(new UserWalletStatement
                {
                    WalletId      = fromWallet.Id,
                    Action        = UserWalletStatementAction.TansferOut,
                    Amount        = -transfer.Amount,
                    Balance       = fromWallet.Balance - transfer.Amount,
                    FrozenAmount  = 0,
                    FrozenBalance = fromWallet.FrozenBalance,
                    Timestamp     = dtCreateTime
                });

                uwsDAC.Insert(new UserWalletStatement
                {
                    WalletId      = toWallet.Id,
                    Action        = UserWalletStatementAction.TansferIn,
                    Amount        = transfer.Amount,
                    Balance       = toWallet.Balance + transfer.Amount,
                    FrozenAmount  = 0,
                    FrozenBalance = toWallet.FrozenBalance,
                    Timestamp     = dtCreateTime
                });

                scope.Complete();
            }

            RabbitMQSender.SendMessage("UserTransferOutFiiiPay", transfer.Id);
            RabbitMQSender.SendMessage("UserTransferIntoFiiiPay", transfer.Id);
            //pushComponent.PushTransferOut(transfer.Id);
            //pushComponent.PushTransferInto(transfer.Id);

            return(new TransferOM
            {
                Timestamp = dtCreateTime.ToUnixTime().ToString(),
                TracingId = transfer.Id,
                TracingNo = transfer.OrderNo,
                AccountName = country.PhoneCode + " " + toAccount.Cellphone
            });
        }
        /// <summary>
        /// FiiiPay扫描第三方二维码支付
        /// </summary>
        /// <param name="code">二维码字符</param>
        /// <returns></returns>
        public GatewayOrderInfoOM Pay(GatewayPayIM im, UserAccount account)
        {
            new SecurityComponent().VerifyPin(account, im.Pin);

            var gatewayOrder = new GatewayOrderDAC().GetByOrderId(im.OrderId);

            if (gatewayOrder.Status != GatewayOrderStatus.Pending)
            {
                throw new CommonException(ReasonCode.ORDER_HAD_COMPLETE, MessageResources.OrderComplated);
            }
            var cryptoCurrency = new CryptocurrencyDAC().GetById(gatewayOrder.CryptoId);

            if (cryptoCurrency == null || cryptoCurrency?.Id == null)
            {
                throw new CommonException(ReasonCode.CRYPTO_NOT_EXISTS, "Error: Invalid Cryptocurrency");
            }
            var uwComponent = new UserWalletComponent();
            var userWallet  = uwComponent.GetUserWallet(gatewayOrder.UserAccountId.Value, gatewayOrder.CryptoId);

            if (userWallet == null)
            {
                throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance);
            }
            if (userWallet.Balance < gatewayOrder.CryptoAmount)
            {
                throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance);
            }
            var uwDAC  = new UserWalletDAC();
            var uwsDAC = new UserWalletStatementDAC();
            var goDAC  = new GatewayOrderDAC();

            using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, new TimeSpan(0, 0, 1, 30)))
            {
                uwDAC.Decrease(userWallet.Id, gatewayOrder.ActualCryptoAmount);
                uwsDAC.Insert(new UserWalletStatement
                {
                    WalletId      = userWallet.Id,
                    Action        = UserWalletStatementAction.TansferOut,
                    Amount        = -gatewayOrder.ActualCryptoAmount,
                    Balance       = userWallet.Balance - gatewayOrder.ActualCryptoAmount,
                    FrozenAmount  = 0,
                    FrozenBalance = userWallet.FrozenBalance,
                    Timestamp     = DateTime.UtcNow
                });
                gatewayOrder.Status      = GatewayOrderStatus.Completed;
                gatewayOrder.PaymentTime = DateTime.UtcNow;
                goDAC.Update(gatewayOrder);

                new UserTransactionDAC().Insert(new UserTransaction
                {
                    Id           = Guid.NewGuid(),
                    AccountId    = userWallet.UserAccountId,
                    CryptoId     = cryptoCurrency.Id,
                    CryptoCode   = cryptoCurrency.Code,
                    Type         = UserTransactionType.Order,
                    DetailId     = gatewayOrder.Id.ToString(),
                    Status       = (byte)gatewayOrder.Status,
                    Timestamp    = DateTime.UtcNow,
                    Amount       = gatewayOrder.CryptoAmount,
                    OrderNo      = gatewayOrder.OrderNo,
                    MerchantName = gatewayOrder.MerchantName
                });
                scope.Complete();
            }
            RabbitMQSender.SendMessage("FiiiPay_Gateway_PayCompleted", gatewayOrder.TradeNo);
            return(new GatewayOrderInfoOM()
            {
                Timestamp = gatewayOrder.PaymentTime?.ToUnixTime().ToString(),
                OrderId = gatewayOrder.Id,
                MerchantName = gatewayOrder.MerchantName,
                CryptoCode = cryptoCurrency.Code,
                ActurlCryptoAmount = gatewayOrder.ActualCryptoAmount
            });
        }
Example #7
0
        public TransferResult FiiiPayTransferToEx(UserAccount account, int cryptoId, decimal amount, string pin)
        {
            new SecurityComponent().VerifyPin(account, pin);

            var openAccountDac = new OpenAccountDAC();
            var openAccount    = openAccountDac.GetOpenAccount(FiiiType.FiiiPay, account.Id);

            if (openAccount == null)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, R.FiiiExAccountNotExist);
            }

            var crypto = new CryptocurrencyDAC().GetById(cryptoId);

            if (crypto == null)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, R.CurrencyForbidden);
            }

            var walletDac = new UserWalletDAC();
            var wallet    = walletDac.GetByAccountId(account.Id, crypto.Id);

            if (wallet.Balance < amount)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.余额不足);
            }
            //10091=参数不符合要求 10013=用户信息不存在 10020=币不存在 0=成功
            int result = FiiiExCoinIn(openAccount.OpenId, crypto.Code, amount, out string recordId);

            if (result != 0)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.划转到FiiiEx失败);
            }
            UserExTransferOrder order;

            using (var scope = new TransactionScope())
            {
                walletDac.Decrease(wallet.Id, amount);
                order = new UserExTransferOrder
                {
                    Timestamp  = DateTime.UtcNow,
                    OrderNo    = CreateOrderNo(),
                    OrderType  = ExTransferType.ToEx,
                    AccountId  = account.Id,
                    WalletId   = wallet.Id,
                    CryptoId   = crypto.Id,
                    CryptoCode = crypto.Code,
                    Amount     = amount,
                    Status     = 1,
                    Remark     = null,
                    ExId       = recordId
                };

                order = new UserExTransferOrderDAC().Create(order);
                scope.Complete();
            }

            try
            {
                FiiiEXTransferMSMQ.PubUserTransferToEx(order.Id, 0);
            }
            catch (Exception ex)
            {
                LogHelper.Info("PubUserTransferToEx - error", ex);
            }

            return(new TransferResult
            {
                Id = order.Id,
                Amount = order.Amount.ToString(crypto.DecimalPlace),
                OrderNo = order.OrderNo,
                Timestamp = order.Timestamp.ToUnixTime(),
                CryptoCode = crypto.Code
            });
        }
Example #8
0
        public async Task <PayOrderOM> PayAsync(UserAccount user, StoreOrderPayIM im)
        {
            #region 验证
            if (im.FiatAmount <= 0)
            {
                throw new ApplicationException();
            }
            SecurityVerify.Verify(new PinVerifier(), SystemPlatform.FiiiPay, user.Id.ToString(), user.Pin, im.Pin);
            if (!user.IsAllowExpense.HasValue || !user.IsAllowExpense.Value)
            {
                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 merchantInfo = new MerchantInformationDAC().GetById(im.MerchantInfoId);
            if (merchantInfo.Status != Status.Enabled || merchantInfo.VerifyStatus != VerifyStatus.Certified || merchantInfo.IsPublic != Status.Enabled)
            {
                throw new CommonException(ReasonCode.Not_Allow_AcceptPayment, MessageResources.MerchantExceptionTransClose);
            }
            if (!merchantInfo.IsAllowExpense)
            {
                throw new CommonException(ReasonCode.Not_Allow_AcceptPayment, MessageResources.MerchantReceiveNotAllowed);
            }
            if (merchantInfo.AccountType == AccountType.Merchant)
            {
                throw new ApplicationException();
            }

            var storeAccount = new UserAccountDAC().GetById(merchantInfo.MerchantAccountId);
            if (storeAccount.Id == user.Id)
            {
                throw new CommonException(ReasonCode.Not_Allow_AcceptPayment, MessageResources.PaytoSelf);
            }
            if (storeAccount == null || storeAccount.Status.Value != (byte)AccountStatus.Active)
            {
                throw new CommonException(ReasonCode.Not_Allow_AcceptPayment, MessageResources.MerchantFiiipayAbnormal);
            }

            var paySetting = await new StorePaySettingDAC().GetByCountryIdAsync(merchantInfo.CountryId);
            if (paySetting != null)
            {
                if (im.FiatAmount > paySetting.LimitAmount)
                {
                    throw new CommonException(ReasonCode.TRANSFER_AMOUNT_OVERFLOW, string.Format(MessageResources.TransferAmountOverflow, paySetting.LimitAmount, paySetting.FiatCurrency));
                }
            }
            #endregion

            var walletDAC     = new UserWalletDAC();
            var statementDAC  = new UserWalletStatementDAC();
            var storeOrderDAC = new StoreOrderDAC();
            var utDAC         = new UserTransactionDAC();

            #region 计算
            decimal markup       = merchantInfo.Markup;
            decimal feeRate      = merchantInfo.FeeRate;
            var     exchangeRate = new PriceInfoDAC().GetPriceByName(storeAccount.FiatCurrency, coin.Code);

            decimal failTotalAmount    = im.FiatAmount + (im.FiatAmount * markup).ToSpecificDecimal(4);
            decimal transactionFiatFee = (im.FiatAmount * feeRate).ToSpecificDecimal(4);
            decimal transactionFee     = (transactionFiatFee / exchangeRate).ToSpecificDecimal(coin.DecimalPlace);
            decimal cryptoAmount       = (failTotalAmount / exchangeRate).ToSpecificDecimal(coin.DecimalPlace);

            var fromWallet = walletDAC.GetUserWallet(user.Id, im.CoinId);
            if (fromWallet == null || fromWallet.Balance < cryptoAmount)
            {
                throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance);
            }

            var toWallet = walletDAC.GetUserWallet(storeAccount.Id, im.CoinId);
            if (toWallet == null)
            {
                toWallet = new UserWalletComponent().GenerateWallet(storeAccount.Id, im.CoinId);
            }
            #endregion

            #region entity
            DateTime   dtNow = DateTime.UtcNow;
            StoreOrder order = new StoreOrder
            {
                Id                 = Guid.NewGuid(),
                OrderNo            = IdentityHelper.OrderNo(),
                Timestamp          = dtNow,
                Status             = OrderStatus.Completed,
                MerchantInfoId     = merchantInfo.Id,
                MerchantInfoName   = merchantInfo.MerchantName,
                UserAccountId      = user.Id,
                CryptoId           = im.CoinId,
                CryptoCode         = coin.Code,
                CryptoAmount       = cryptoAmount,
                CryptoActualAmount = cryptoAmount - transactionFee,
                ExchangeRate       = exchangeRate,
                Markup             = markup,
                FiatCurrency       = storeAccount.FiatCurrency,
                FiatAmount         = im.FiatAmount,
                FiatActualAmount   = failTotalAmount,
                FeeRate            = feeRate,
                TransactionFee     = transactionFee,
                PaymentTime        = dtNow
            };
            UserWalletStatement fromStatement = new UserWalletStatement
            {
                WalletId      = fromWallet.Id,
                Action        = UserWalletStatementAction.StoreOrderOut,
                Amount        = -order.CryptoAmount,
                Balance       = fromWallet.Balance - order.CryptoAmount,
                FrozenAmount  = 0,
                FrozenBalance = fromWallet.FrozenBalance,
                Timestamp     = dtNow
            };
            UserWalletStatement toStatement = new UserWalletStatement
            {
                WalletId      = toWallet.Id,
                Action        = UserWalletStatementAction.StoreOrderIn,
                Amount        = order.CryptoActualAmount,
                Balance       = toWallet.Balance + order.CryptoActualAmount,
                FrozenAmount  = 0,
                FrozenBalance = toWallet.FrozenBalance,
                Timestamp     = dtNow
            };
            #endregion

            using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                await storeOrderDAC.CreateAsync(order);

                await utDAC.InsertAsync(new UserTransaction
                {
                    Id           = Guid.NewGuid(),
                    AccountId    = fromWallet.UserAccountId,
                    CryptoId     = order.CryptoId,
                    CryptoCode   = order.CryptoCode,
                    Type         = UserTransactionType.StoreOrderConsume,
                    DetailId     = order.Id.ToString(),
                    Status       = (byte)order.Status,
                    Timestamp    = order.PaymentTime.Value,
                    Amount       = order.CryptoAmount,
                    OrderNo      = order.OrderNo,
                    MerchantName = order.MerchantInfoName
                });

                await utDAC.InsertAsync(new UserTransaction
                {
                    Id           = Guid.NewGuid(),
                    AccountId    = toWallet.UserAccountId,
                    CryptoId     = order.CryptoId,
                    CryptoCode   = order.CryptoCode,
                    Type         = UserTransactionType.StoreOrderIncome,
                    DetailId     = order.Id.ToString(),
                    Status       = (byte)order.Status,
                    Timestamp    = order.Timestamp,
                    Amount       = order.CryptoActualAmount,
                    OrderNo      = order.OrderNo,
                    MerchantName = order.MerchantInfoName
                });

                walletDAC.Decrease(fromWallet.Id, order.CryptoAmount);
                walletDAC.Increase(toWallet.Id, order.CryptoActualAmount);
                statementDAC.Insert(fromStatement);
                statementDAC.Insert(toStatement);
                scope.Complete();
            }

            var pushObj = new { order.Id, order.UserAccountId, order.CryptoCode };

            RabbitMQSender.SendMessage("StoreOrderPayed", new { order.Id, MerchantInfoId = merchantInfo.MerchantAccountId, order.UserAccountId, order.CryptoCode });

            return(new PayOrderOM
            {
                Amount = order.CryptoAmount.ToString(coin.DecimalPlace),
                Currency = coin.Code,
                OrderId = order.Id.ToString(),
                OrderNo = order.OrderNo,
                Timestamp = dtNow.ToUnixTime().ToString()
            });
        }