public PreDepositOM PreDeposit(UserAccount user, int cryptoId)
        {
            var dac    = new UserWalletDAC();
            var wallet = dac.GetByAccountId(user.Id, cryptoId) ?? new UserWalletComponent().GenerateWallet(user.Id, cryptoId);
            var coin   = new CryptocurrencyDAC().GetById(cryptoId);

            if (string.IsNullOrEmpty(wallet.Address))
            {
                var agent       = new FiiiFinanceAgent();
                var addressInfo = agent.CreateWallet(coin.Code, user.Id, AccountTypeEnum.User, user.Email, user.Cellphone);
                if (string.IsNullOrWhiteSpace(addressInfo.Address))
                {
                    throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.FailedGenerateAddress);
                }

                wallet.Address = addressInfo.Address;
                wallet.Tag     = addressInfo.DestinationTag;

                dac.UploadAddress(wallet.Id, wallet.Address, wallet.Tag);
            }

            return(new PreDepositOM
            {
                Address = wallet.Address,
                Tag = wallet.Tag,
                Code = coin.Code,
                NeedTag = coin.NeedTag
            });
        }
        public void Refund(long id)
        {
            var redPocket = _redPocketDac.GetById(id);

            if (redPocket == null)
            {
                _log.Error($"Red pocket is not found. {id}");
                return;
            }

            if (redPocket.RemainCount > 0)
            {
                var userWalletDAC          = new UserWalletDAC();
                var userWalletStatementDAC = new UserWalletStatementDAC();
                var userTransactionDAC     = new UserTransactionDAC();

                var wallet = userWalletDAC.GetByAccountId(redPocket.AccountId, redPocket.CryptoId);
                if (wallet == null)
                {
                    _log.Error($"Wallet exception. {redPocket.AccountId} RedPocketId={id}");
                    return;
                }

                using (var scope = new TransactionScope())
                {
                    userWalletDAC.Increase(wallet.Id, redPocket.Balance);
                    userWalletStatementDAC.Insert(new UserWalletStatement
                    {
                        WalletId      = wallet.Id,
                        Balance       = wallet.Balance + redPocket.Balance,
                        Amount        = redPocket.Balance,
                        FrozenAmount  = 0,
                        FrozenBalance = wallet.FrozenBalance,
                        Action        = "Refund Red Pocket",
                        Timestamp     = DateTime.UtcNow
                    });

                    _refundDac.Insert(new RedPocketRefund
                    {
                        Id        = redPocket.Id,
                        Amount    = redPocket.Balance,
                        OrderNo   = _identity.StringId(),
                        Timestamp = DateTime.UtcNow
                    });

                    _redPocketDac.UpdateStatus(redPocket.Id, redPocket.RemainCount == redPocket.Count ? RedPocketStatus.FullRefund : RedPocketStatus.Refund);

                    userTransactionDAC.UpdateStatus(UserTransactionType.PushRedPocket, redPocket.Id.ToString(), redPocket.AccountId, (byte)RedPocketStatus.Refund);

                    scope.Complete();
                }
            }
        }
Example #3
0
        public bool BillerRefund(string orderNo)
        {
            var orderDac = new BillerOrderDAC();
            var order    = FiiiPayDB.DB.Queryable <BillerOrders>().Where(t => t.OrderNo.Equals(orderNo)).First();

            if (order == null)
            {
                throw new CommonException(10000, "Order does not exist!");
            }

            var merchantWalletDAC = new MerchantWalletDAC();
            var userWalletDAC     = new UserWalletDAC();

            var userWallet = userWalletDAC.GetByAccountId(order.AccountId, order.CryptoId);

            if (userWallet == null)
            {
                throw new CommonException(10001, "A currency that is not supported by the user");
            }
            using (var scope = new TransactionScope())
            {
                userWalletDAC.Increase(order.AccountId, order.CryptoId, order.CryptoAmount);
                new UserWalletStatementDAC().Insert(new UserWalletStatement
                {
                    WalletId  = userWallet.Id,
                    Action    = "REFUND",
                    Amount    = order.CryptoAmount,
                    Balance   = userWallet.Balance + order.CryptoAmount,
                    Timestamp = DateTime.UtcNow,
                    Remark    = $"Refund from billerorder({order.OrderNo})"
                });

                order.Status = BillerOrderStatus.Fail;
                orderDac.UpdateStatus(order);

                new RefundDAC().Insert(new Refund
                {
                    OrderId   = order.Id,
                    Status    = RefundStatus.Completed,
                    Timestamp = DateTime.UtcNow
                });
                scope.Complete();
            }
            return(true);
        }
Example #4
0
        public string FiiiPayTransferInto(UserAccount account, Cryptocurrency coin, decimal amount)
        {
            var walletDac = new UserWalletDAC();
            var wallet    = walletDac.GetByAccountId(account.Id, coin.Id);
            UserExTransferOrder order;

            using (var scope = new TransactionScope())
            {
                if (wallet == null)
                {
                    wallet = new UserWalletComponent().GenerateWallet(account.Id, coin.Id);
                }

                walletDac.Increase(wallet.Id, amount);

                order = new UserExTransferOrder
                {
                    Timestamp  = DateTime.UtcNow,
                    OrderNo    = CreateOrderNo(),
                    OrderType  = ExTransferType.FromEx,
                    AccountId  = account.Id,
                    WalletId   = wallet.Id,
                    CryptoId   = coin.Id,
                    CryptoCode = coin.Code,
                    Amount     = amount,
                    Status     = 1,
                    Remark     = null,
                    ExId       = null
                };

                new UserExTransferOrderDAC().Create(order);

                scope.Complete();
            }

            try
            {
                FiiiEXTransferMSMQ.PubUserTransferFromEx(order.Id, 0);
            }
            catch (Exception ex)
            {
                LogHelper.Info("PubUserTransferFromEx - error", ex);
            }
            return(order.OrderNo);
        }
Example #5
0
        public TransferFiiiExConditionOM FiiiPayTransferFiiiExCondition(UserAccount account, int cryptoId)
        {
            var crypto    = new CryptocurrencyDAC().GetById(cryptoId);
            var walletDac = new UserWalletDAC();
            var wallet    = walletDac.GetByAccountId(account.Id, crypto.Id);

            var fiiiExBalance = this.FiiiExBalance(FiiiType.FiiiPay, account.Id, crypto);

            var minQuantity =
                (1M / (decimal)Math.Pow(10, crypto.DecimalPlace)).ToString(crypto.DecimalPlace);

            return(new TransferFiiiExConditionOM
            {
                Balance = (wallet?.Balance ?? 0M).ToString(crypto.DecimalPlace),
                MinQuantity = minQuantity,
                FiiiExBalance = fiiiExBalance.ToString(crypto.DecimalPlace),
                FiiiExMinQuantity = minQuantity
            });
        }
Example #6
0
        public void DistributeRewards(FiiiPayRewardMessage message, int fiiicoinId)
        {
            MerchantAccountDAC maDAC = new MerchantAccountDAC();
            var merchant             = maDAC.GetByUsername(message.Account);

            if (merchant == null)
            {
                throw new CommonException(10000, $"无效的商家名:{message.Account}");
            }

            InviteRecord invitor = GetInvitor(merchant.Id);

            if (invitor == null)
            {
                throw new CommonException(10000, "没有邀请人");
            }

            var invitedList = new InviteRecordDAC().GetFiiiPosRecordsByInvitorId(invitor.InviterAccountId, InviteType.Fiiipos);
            var rewardRate  = GetRewardPercentage(invitedList == null ? 0 : invitedList.Count);

            if (rewardRate == 0)
            {
                throw new CommonException(10000, "没有达到奖励条件");
            }

            decimal t            = (decimal)Math.Pow(10, -8);
            long    nTotalReward = (long)Math.Floor(message.Reward * rewardRate);

            if (nTotalReward == 0)
            {
                throw new CommonException(10000, "奖励金额为0");
            }
            decimal  rewardAmount = nTotalReward * t;
            DateTime dtNow        = DateTime.UtcNow;

            if (message.CurrentDate > 0)
            {
                dtNow = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(message.CurrentDate);
            }
            var distributeRecord = new RewardDistributeRecords
            {
                UserAccountId     = invitor.InviterAccountId,
                MerchantAccountId = merchant.Id,
                SN             = message.SN,
                OriginalReward = message.Reward,
                Percentage     = rewardRate,
                ActualReward   = rewardAmount,
                Timestamp      = dtNow
            };

            long    profitId;
            decimal oldBalance    = 0;
            var     invitorWallet = uwDAC.GetByAccountId(invitor.InviterAccountId, fiiicoinId);

            using (var scope = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 1, 30)))
            {
                if (invitorWallet == null)
                {
                    invitorWallet = CreateWallet(invitor.InviterAccountId, fiiicoinId, rewardAmount);
                }
                else
                {
                    oldBalance = invitorWallet.Balance;
                    uwDAC.Increase(invitorWallet.Id, rewardAmount);
                }

                var profitDetail = new ProfitDetail
                {
                    InvitationId = invitor.Id,
                    CryptoAmount = rewardAmount,
                    AccountId    = invitor.InviterAccountId,
                    Status       = InviteStatusType.IssuedActive,
                    Type         = ProfitType.InvitePiiiPos,
                    OrderNo      = CreateOrderno(),
                    Timestamp    = dtNow,
                    CryptoId     = invitorWallet.CryptoId,
                    CryptoCode   = "FIII"
                };
                profitId = pfDAC.Insert(profitDetail);

                uwsDAC.Insert(new UserWalletStatement
                {
                    WalletId      = invitorWallet.Id,
                    Action        = UserWalletStatementAction.Reward,
                    Amount        = rewardAmount,
                    Balance       = oldBalance + rewardAmount,
                    FrozenAmount  = 0,
                    FrozenBalance = invitorWallet.FrozenBalance,
                    Timestamp     = dtNow
                });

                transDAC.Insert(new UserTransaction
                {
                    AccountId    = invitor.InviterAccountId,
                    Amount       = rewardAmount,
                    CryptoCode   = "FIII",
                    CryptoId     = fiiicoinId,
                    DetailId     = profitId.ToString(),
                    Id           = Guid.NewGuid(),
                    MerchantName = string.Empty,
                    OrderNo      = profitDetail.OrderNo,
                    Status       = 2,
                    Timestamp    = dtNow,
                    Type         = UserTransactionType.Profit
                });

                distributeRecord.ProfitId = profitId;
                rdrDAC.Insert(distributeRecord);

                scope.Complete();
            }

            if (profitId > 0)
            {
                try
                {
                    MessagePushService.PubUserInviteSuccessed(profitId, 0);
                }
                catch (Exception ex)
                {
                    throw new CommonException(10000, ex.Message);
                }
            }
        }
Example #7
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);
            }
        }
Example #8
0
        public TransferResult Transfer(InvestorAccount account, int countryId, string cellphone, decimal amount, string pinToken)
        {
            new SecurityVerification(SystemPlatform.FiiiCoinWork).VerifyToken(pinToken, SecurityMethod.Pin);

            CountryDAC     countryDac     = new CountryDAC();
            UserAccountDAC userAccountDac = new UserAccountDAC();
            Country        country        = countryDac.GetById(countryId);

            if (country == null)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, R.AccountNotExist);
            }
            UserAccount userAccount = userAccountDac.GetByCountryIdAndCellphone(countryId, cellphone);

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

            InvestorAccountDAC accountDac = new InvestorAccountDAC();

            if (account.Balance < amount)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, R.余额不足);
            }

            UserWalletDAC userWalletDac = new UserWalletDAC();

            UserWallet userWallet = userWalletDac.GetByAccountId(userAccount.Id, FiiiCoinUtility.Cryptocurrency.Id);

            InvestorOrder investorOrder;
            UserDeposit   userDeposit;

            using (var scope = new TransactionScope())
            {
                if (userWallet == null)
                {
                    userWallet = new UserWalletComponent().GenerateWallet(userAccount.Id, FiiiCoinUtility.Cryptocurrency.Id);
                }
                accountDac.Decrease(account.Id, amount);
                investorOrder = new InvestorOrderDAC().Insert(new InvestorOrder
                {
                    Id                 = Guid.NewGuid(),
                    OrderNo            = CreateOrderNo(),
                    TransactionType    = InvestorTransactionType.Transfer,
                    Status             = 1,
                    InverstorAccountId = account.Id,
                    UserAccountId      = userAccount.Id,
                    CryptoId           = FiiiCoinUtility.Cryptocurrency.Id,
                    CryptoAmount       = amount,
                    Timestamp          = DateTime.UtcNow
                });
                new InvestorWalletStatementDAC().Insert(new InvestorWalletStatement
                {
                    Id           = Guid.NewGuid(),
                    InvestorId   = account.Id,
                    TagAccountId = userAccount.Id,
                    Action       = InvestorTransactionType.Transfer,
                    Amount       = -amount,
                    Balance      = account.Balance - amount,
                    Timestamp    = DateTime.UtcNow
                });
                // 2018-06-26: new rules IncreaseFrozen -> Increase
                userWalletDac.Increase(userWallet.Id, amount);
                userDeposit = new UserDepositDAC().Insert(new UserDeposit
                {
                    UserAccountId = userAccount.Id,
                    UserWalletId  = userWallet.Id,
                    FromAddress   = null,
                    FromTag       = null,
                    ToAddress     = null,
                    ToTag         = null,
                    Amount        = amount,
                    Status        = TransactionStatus.Confirmed,
                    Timestamp     = DateTime.UtcNow,
                    OrderNo       = CreateOrderNo(),
                    TransactionId = account.Id.ToString(),
                    SelfPlatform  = true,
                    RequestId     = null
                });


                scope.Complete();
            }

            InvestorMSMQ.PubUserDeposit(userDeposit.Id, 0);

            return(new TransferResult
            {
                OrderId = investorOrder.Id,
                OrderNo = investorOrder.OrderNo,
                TargetAccount = GetMaskedCellphone(country.PhoneCode, userAccount.Cellphone),
                Timestamp = DateTime.UtcNow.ToUnixTime()
            });
        }
Example #9
0
        public bool Refund(string orderNo)
        {
            var orderDac = new OrderDAC();

            var order = orderDac.GetByOrderNo(orderNo);

            if (order == null)
            {
                throw new CommonException(10000, "Order does not exist!");
            }

            if (order.Status != OrderStatus.Completed)
            {
                throw new CommonException(10001, "Order state exception!");
            }

            if (DateTime.UtcNow.AddDays(-3000) > order.PaymentTime)
            {
                throw new CommonException(10000, "Orders cannot be refundable for more than three days!");
            }

            var merchantWalletDAC = new MerchantWalletDAC();
            var userWalletDAC     = new UserWalletDAC();

            var merchantWallet = merchantWalletDAC.GetByAccountId(order.MerchantAccountId, order.CryptoId);

            if (merchantWallet == null)
            {
                throw new CommonException(10001, "The currency that the merchant does not support!");
            }

            if (merchantWallet.Balance < order.ActualCryptoAmount)
            {
                throw new CommonException(10001, "Not sufficient funds!");
            }

            var userWallet = userWalletDAC.GetByAccountId(order.UserAccountId.Value, order.CryptoId);

            if (userWallet == null)
            {
                throw new CommonException(10001, "A currency that is not supported by the user");
            }

            var merchantAccount = new MerchantAccountDAC().GetById(order.MerchantAccountId);

            var orderWithdrawalFee = new OrderWithdrawalFeeDAC().GetByOrderId(order.Id);

            if (orderWithdrawalFee != null)
            {
                var merchantOrderWithdrawalFeeWallet = merchantWalletDAC.GetByAccountId(order.MerchantAccountId, orderWithdrawalFee.CryptoId);
                using (var scope = new TransactionScope())
                {
                    merchantWalletDAC.Decrease(order.MerchantAccountId, order.CryptoId, order.ActualCryptoAmount);
                    new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                    {
                        WalletId  = merchantWallet.Id,
                        Action    = "REFUND",
                        Amount    = -order.ActualCryptoAmount,
                        Balance   = merchantWallet.Balance - order.ActualCryptoAmount,
                        Timestamp = DateTime.UtcNow,
                        Remark    = $"Refund to order({order.OrderNo})"
                    });

                    merchantWalletDAC.Increase(order.MerchantAccountId, orderWithdrawalFee.CryptoId, orderWithdrawalFee.Amount);
                    new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                    {
                        WalletId  = merchantOrderWithdrawalFeeWallet.Id,
                        Action    = "REFUND",
                        Amount    = orderWithdrawalFee.Amount,
                        Balance   = merchantWallet.Balance - orderWithdrawalFee.Amount,
                        Timestamp = DateTime.UtcNow,
                        Remark    = $"Refund to order({order.OrderNo})"
                    });

                    userWalletDAC.Increase(order.UserAccountId.Value, order.CryptoId, order.CryptoAmount);
                    new UserWalletStatementDAC().Insert(new UserWalletStatement
                    {
                        WalletId      = userWallet.Id,
                        Action        = "REFUND",
                        Amount        = order.CryptoAmount,
                        Balance       = userWallet.Balance + order.CryptoAmount,
                        FrozenAmount  = 0,
                        FrozenBalance = userWallet.FrozenBalance,
                        Timestamp     = DateTime.UtcNow,
                        Remark        = $"Refund from order({order.OrderNo})"
                    });

                    order.Status    = OrderStatus.Refunded;
                    order.Timestamp = DateTime.UtcNow;
                    orderDac.UpdateStatus(order);

                    new UserTransactionDAC().Insert(new UserTransaction
                    {
                        Id           = Guid.NewGuid(),
                        AccountId    = order.UserAccountId.Value,
                        CryptoId     = userWallet.CryptoId,
                        CryptoCode   = userWallet.CryptoCode,
                        Type         = UserTransactionType.Refund,
                        DetailId     = order.Id.ToString(),
                        Status       = (byte)order.Status,
                        Timestamp    = DateTime.UtcNow,
                        Amount       = order.CryptoAmount,
                        OrderNo      = order.OrderNo,
                        MerchantName = merchantAccount?.MerchantName
                    });

                    new RefundDAC().Insert(new Refund
                    {
                        OrderId   = order.Id,
                        Status    = RefundStatus.Completed,
                        Timestamp = DateTime.UtcNow
                    });

                    scope.Complete();
                }
            }
            else
            {
                using (var scope = new TransactionScope())
                {
                    merchantWalletDAC.Decrease(order.MerchantAccountId, order.CryptoId, order.ActualCryptoAmount);
                    new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                    {
                        WalletId  = merchantWallet.Id,
                        Action    = "REFUND",
                        Amount    = -order.ActualCryptoAmount,
                        Balance   = merchantWallet.Balance - order.ActualCryptoAmount,
                        Timestamp = DateTime.UtcNow,
                        Remark    = $"Refund to order({order.OrderNo})"
                    });

                    userWalletDAC.Increase(order.UserAccountId.Value, order.CryptoId, order.CryptoAmount);
                    new UserWalletStatementDAC().Insert(new UserWalletStatement
                    {
                        WalletId      = userWallet.Id,
                        Action        = "REFUND",
                        Amount        = order.CryptoAmount,
                        Balance       = userWallet.Balance + order.CryptoAmount,
                        FrozenAmount  = 0,
                        FrozenBalance = userWallet.FrozenBalance,
                        Timestamp     = DateTime.UtcNow,
                        Remark        = $"Refund from order({order.OrderNo})"
                    });

                    order.Status = OrderStatus.Refunded;
                    //order.Timestamp = DateTime.UtcNow;
                    orderDac.UpdateStatus(order);

                    new UserTransactionDAC().Insert(new UserTransaction
                    {
                        Id           = Guid.NewGuid(),
                        AccountId    = order.UserAccountId.Value,
                        CryptoId     = userWallet.CryptoId,
                        CryptoCode   = userWallet.CryptoCode,
                        Type         = UserTransactionType.Refund,
                        DetailId     = order.Id.ToString(),
                        Status       = (byte)order.Status,
                        Timestamp    = DateTime.UtcNow,
                        Amount       = order.CryptoAmount,
                        OrderNo      = order.OrderNo,
                        MerchantName = merchantAccount?.MerchantName
                    });

                    new RefundDAC().Insert(new Refund
                    {
                        OrderId   = order.Id,
                        Status    = RefundStatus.Completed,
                        Timestamp = DateTime.UtcNow
                    });

                    scope.Complete();
                }
            }
            return(true);
        }
Example #10
0
        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 #11
0
        public void Refund(Guid accountId, string orderNo, string pinToken)
        {
            var merchantAccountDAC = new MerchantAccountDAC();
            var merchantAccount    = merchantAccountDAC.GetById(accountId);

            if (merchantAccount == null)
            {
                return;
            }

            new SecurityVerification(SystemPlatform.FiiiPOS).VerifyToken(merchantAccount.Id, pinToken, SecurityMethod.Pin);
            var orderDac = new OrderDAC();

            var order = orderDac.GetByOrderNo(orderNo);

            if (order == null)
            {
                throw new CommonException(10000, Resources.订单不存在);
            }

            if (merchantAccount.Id != order.MerchantAccountId)
            {
                return;
            }

            if (order.Status != OrderStatus.Completed)
            {
                throw new CommonException(10000, Resources.订单状态异常);
            }

            if (DateTime.UtcNow.AddDays(-3) > order.PaymentTime.Value)
            {
                throw new CommonException(10000, Resources.订单超过三天不能退款);
            }

            var merchantWalletDAC = new MerchantWalletDAC();
            var userWalletDAC     = new UserWalletDAC();

            var merchantWallet = merchantWalletDAC.GetByAccountId(order.MerchantAccountId, order.CryptoId);

            if (merchantWallet == null)
            {
                throw new CommonException(10000, Resources.商户不支持的币种);
            }

            if (merchantWallet.Balance < order.ActualCryptoAmount)
            {
                throw new CommonException(10000, Resources.余额不足);
            }

            var userWallet = userWalletDAC.GetByAccountId(order.UserAccountId.Value, order.CryptoId);

            if (userWallet == null)
            {
                throw new CommonException(10000, Resources.用户不支持的币种);
            }
            var orderWithdrawalFee = new OrderWithdrawalFeeDAC().GetByOrderId(order.Id);

            if (orderWithdrawalFee != null && orderWithdrawalFee.Amount > 0)
            {
                var merchantOrderWithdrawalFeeWallet = merchantWalletDAC.GetByAccountId(order.MerchantAccountId, orderWithdrawalFee.CryptoId);
                using (var scope = new TransactionScope())
                {
                    merchantWalletDAC.Decrease(merchantAccount.Id, order.CryptoId, order.ActualCryptoAmount);
                    new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                    {
                        WalletId  = merchantWallet.Id,
                        Action    = "REFUND",
                        Amount    = -order.ActualCryptoAmount,
                        Balance   = merchantWallet.Balance - order.ActualCryptoAmount,
                        Timestamp = DateTime.UtcNow,
                        Remark    = $"Refund to order({order.OrderNo})"
                    });

                    merchantWalletDAC.Increase(merchantAccount.Id, orderWithdrawalFee.CryptoId, orderWithdrawalFee.Amount);
                    new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                    {
                        WalletId  = merchantOrderWithdrawalFeeWallet.Id,
                        Action    = "REFUND",
                        Amount    = orderWithdrawalFee.Amount,
                        Balance   = merchantWallet.Balance - orderWithdrawalFee.Amount,
                        Timestamp = DateTime.UtcNow,
                        Remark    = $"Refund to order({order.OrderNo})"
                    });

                    userWalletDAC.Increase(order.UserAccountId.Value, order.CryptoId, order.CryptoAmount);
                    new UserWalletStatementDAC().Insert(new UserWalletStatement
                    {
                        WalletId  = userWallet.Id,
                        Action    = "REFUND",
                        Amount    = order.CryptoAmount,
                        Balance   = userWallet.Balance + order.CryptoAmount,
                        Timestamp = DateTime.UtcNow,
                        Remark    = $"Refund from order({order.OrderNo})"
                    });

                    order.Status    = OrderStatus.Refunded;
                    order.Timestamp = DateTime.UtcNow;
                    orderDac.UpdateStatus(order);

                    new RefundDAC().Insert(new Refund
                    {
                        OrderId   = order.Id,
                        Status    = RefundStatus.Completed,
                        Timestamp = DateTime.UtcNow
                    });

                    scope.Complete();
                }
            }
            else
            {
                using (var scope = new TransactionScope())
                {
                    merchantWalletDAC.Decrease(merchantAccount.Id, order.CryptoId, order.ActualCryptoAmount);
                    new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                    {
                        WalletId  = merchantWallet.Id,
                        Action    = "REFUND",
                        Amount    = -order.ActualCryptoAmount,
                        Balance   = merchantWallet.Balance - order.ActualCryptoAmount,
                        Timestamp = DateTime.UtcNow,
                        Remark    = $"Refund to order({order.OrderNo})"
                    });

                    userWalletDAC.Increase(order.UserAccountId.Value, order.CryptoId, order.CryptoAmount);
                    new UserWalletStatementDAC().Insert(new UserWalletStatement
                    {
                        WalletId  = userWallet.Id,
                        Action    = "REFUND",
                        Amount    = order.CryptoAmount,
                        Balance   = userWallet.Balance + order.CryptoAmount,
                        Timestamp = DateTime.UtcNow,
                        Remark    = $"Refund from order({order.OrderNo})"
                    });

                    order.Status = OrderStatus.Refunded;
                    //order.Timestamp = DateTime.UtcNow;
                    orderDac.UpdateStatus(order);

                    new RefundDAC().Insert(new Refund
                    {
                        OrderId   = order.Id,
                        Status    = RefundStatus.Completed,
                        Timestamp = DateTime.UtcNow
                    });

                    scope.Complete();
                }
            }

            MerchantMSMQ.PubRefundOrder(order.OrderNo, 0);
        }
Example #12
0
        /// <summary>
        /// 订单退款
        /// </summary>
        /// <param name="merchantId"></param>
        /// <param name="orderNo"></param>
        /// <param name="pin"></param>
        /// <returns>-1=账号不存在 -2=PIN码错误 -3=订单不存在 -4=商家账户不对 -5=订单状态不符合要求 -6=商家不支持的币种 -7=商家金额不够 -8=用户钱包不支持币种 -9=回滚 -10=日期超过3天</returns>
        public int RefundOrder(Guid merchantId, string orderNo, string pin)
        {
            OrderDAC orderDac = new OrderDAC();

            MerchantAccount merchantAccount = new MerchantAccountDAC().GetById(merchantId);

            if (merchantAccount == null)
            {
                throw new CommonException(ReasonCode.FiiiPosReasonCode.ACCOUNT_NOT_EXISTS, "账号不存在");
            }

            if (!PasswordHasher.VerifyHashedPassword(merchantAccount.PIN, pin))
            {
                throw new CommonException(ReasonCode.PIN_ERROR, "PIN码错误");   //Wrong PIN enterred
            }
            Order order = orderDac.GetByOrderNo(orderNo);

            if (order == null)
            {
                throw new CommonException(ReasonCode.FiiiPosReasonCode.ORDERNO_NOT_EXISTS, "找不到该订单"); //The order not exist
            }
            if (merchantAccount.Id != order.MerchantAccountId)
            {
                throw new CommonException(ReasonCode.FiiiPosReasonCode.ORDERNO_NOTBE_ACCOUNT, "不是该用户的订单");
            }

            if (order.Status != OrderStatus.Completed)
            {
                throw new CommonException(ReasonCode.FiiiPosReasonCode.ORDER_COMPLETED, "订单已完成,不能退款");  //Wrong order status.
            }
            if (DateTime.UtcNow.AddDays(-3) > order.PaymentTime.Value)
            {
                throw new CommonException(ReasonCode.FiiiPosReasonCode.EMAIL_CODE_EXPIRE, "订单支付已超过3天,不能退款");//订单超过3天
            }
            var merchantWalletDAC = new MerchantWalletDAC();
            var userWalletDAC     = new UserWalletDAC();

            var merchantWallet = merchantWalletDAC.GetByAccountId(order.MerchantAccountId, order.CryptoId);

            if (merchantWallet == null)
            {
                throw new CommonException(ReasonCode.FiiiPosReasonCode.REFUND_MERCHANT_WALLET_NOT_EXISTS, "找不到该商家的钱包"); //Merchant account not support this cryptocurrency
            }
            if (merchantWallet.Balance < order.ActualCryptoAmount)
            {
                throw new CommonException(ReasonCode.FiiiPosReasonCode.REFUND_BALANCE_LOW, "余额不足,无法退款");  //Balance not enough
            }
            var userWallet = userWalletDAC.GetByAccountId(order.UserAccountId.Value, order.CryptoId);

            if (userWallet == null)
            {
                throw new CommonException(ReasonCode.FiiiPosReasonCode.REFUND_USER_WALLET_NOT_EXISTS, "找不到订单用户的钱包");  //User account not support this cryptocurrency
            }
            int result = -9;

            using (var scope = new TransactionScope())
            {
                merchantWalletDAC.Decrease(merchantAccount.Id, order.CryptoId, order.ActualCryptoAmount);
                new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                {
                    WalletId  = merchantWallet.Id,
                    Action    = "REFUND",
                    Amount    = -order.ActualCryptoAmount,
                    Balance   = merchantWallet.Balance - order.ActualCryptoAmount,
                    Timestamp = DateTime.UtcNow,
                    Remark    = $"Refund to order({order.OrderNo})"
                });

                userWalletDAC.Increase(order.UserAccountId.Value, order.CryptoId, order.CryptoAmount);
                new UserWalletStatementDAC().Insert(new UserWalletStatement
                {
                    WalletId  = userWallet.Id,
                    Action    = "REFUND",
                    Amount    = order.CryptoAmount,
                    Balance   = userWallet.Balance + order.CryptoAmount,
                    Timestamp = DateTime.UtcNow,
                    Remark    = $"Refund from order({order.OrderNo})"
                });

                order.Status = OrderStatus.Refunded;

                orderDac.UpdateStatus(order);

                new RefundDAC().Insert(new Refund
                {
                    OrderId   = order.Id,
                    Status    = RefundStatus.Completed,
                    Timestamp = DateTime.UtcNow
                });

                result = 1;
                scope.Complete();
            }

            if (result > 0) //发送退款通知
            {
                RabbitMQSender.SendMessage("RefundOrder", order.OrderNo);
            }

            return(result);
        }
Example #13
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 #14
0
        public void DistributeRewards(FiiiPayRewardMessage message, DateTime dt)
        {
            if (fiiicoinId == 0)
            {
                var fiiicoin = new CryptocurrencyDAC().GetByCode("FIII");
                fiiicoinId = fiiicoin.Id;
            }
            MerchantAccountDAC maDAC = new MerchantAccountDAC();
            var merchant             = maDAC.GetByUsername(message.Account);

            if (merchant == null)
            {
                throw new CommonException(10000, $"无效的商家名:{message.Account}");
            }

            InviteRecord invitor = GetInvitor(merchant.Id);

            if (invitor == null)
            {
                throw new CommonException(10000, "没有邀请人");
            }

            var invitedList = new InviteRecordDAC().GetFiiiPosRecordsByInvitorId(invitor.InviterAccountId, InviteType.Fiiipos);
            var rewardRate  = GetRewardPercentage(invitedList == null ? 0 : invitedList.Count);

            if (rewardRate == 0)
            {
                throw new CommonException(10000, "没有达到奖励条件");
            }

            decimal t            = (decimal)Math.Pow(10, -8);
            long    nTotalReward = (long)Math.Floor(message.ActualReward * rewardRate);

            if (nTotalReward == 0)
            {
                throw new CommonException(10000, "奖励金额为0");
            }
            decimal rewardAmount     = nTotalReward * t;
            var     distributeRecord = new RewardDistributeRecords
            {
                UserAccountId     = invitor.InviterAccountId,
                MerchantAccountId = merchant.Id,
                SN             = message.SN,
                OriginalReward = message.ActualReward,
                Percentage     = rewardRate,
                ActualReward   = rewardAmount,
                Timestamp      = dt
            };

            long    profitId      = 0;
            decimal oldBalance    = 0;
            var     invitorWallet = uwDAC.GetByAccountId(invitor.InviterAccountId, fiiicoinId);

            using (var scope = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 1, 30)))
            {
                if (invitorWallet == null)
                {
                    invitorWallet = CreateWallet(invitor.InviterAccountId, fiiicoinId, rewardAmount);
                }
                else
                {
                    oldBalance = invitorWallet.Balance;
                    uwDAC.Increase(invitorWallet.Id, rewardAmount);
                }
                profitId = pfDAC.Insert(new ProfitDetail()
                {
                    InvitationId = invitor.Id,
                    CryptoAmount = rewardAmount,
                    AccountId    = invitor.InviterAccountId,
                    Status       = InviteStatusType.IssuedActive,
                    Type         = ProfitType.InvitePiiiPos,
                    OrderNo      = CreateOrderno(),
                    Timestamp    = dt,
                    CryptoId     = invitorWallet.CryptoId
                });
                uwsDAC.Insert(new UserWalletStatement
                {
                    WalletId      = invitorWallet.Id,
                    Action        = UserWalletStatementAction.Reward,
                    Amount        = rewardAmount,
                    Balance       = oldBalance + rewardAmount,
                    FrozenAmount  = 0,
                    FrozenBalance = invitorWallet.FrozenBalance,
                    Timestamp     = dt,
                    Remark        = "System"
                });

                distributeRecord.ProfitId = profitId;
                rdrDAC.Insert(distributeRecord);

                new TempDataDAC().MessageComplated(message.Id);

                scope.Complete();
            }
        }