private MerchantWithdrawal CancelWithdrawal(MerchantWithdrawal fromWithdraw)
        {
            fromWithdraw.Status        = TransactionStatus.Cancelled;
            fromWithdraw.TransactionId = Guid.NewGuid().ToString("N");
            fromWithdraw.SelfPlatform  = true;//平台内提币

            using (var scope = new TransactionScope())
            {
                fromWithdraw = new MerchantWithdrawalDAC().Create(fromWithdraw);

                var fromWithdrawFee = new MerchantWithdrawalFee
                {
                    Amount       = fromWithdraw.Amount,
                    Fee          = 0,
                    Timestamp    = DateTime.UtcNow,
                    WithdrawalId = fromWithdraw.Id
                };

                new MerchantWithdrawalFeeDAC().Create(fromWithdrawFee);

                scope.Complete();
            }

            MerchantMSMQ.PubMerchantWithdrawReject(fromWithdraw.Id, 0);

            return(fromWithdraw);
        }
        private MerchantWithdrawal WithdrawalToOutside(MerchantWallet fromWallet, MerchantWithdrawal fromWithdraw, Cryptocurrency cryptocurrency,
                                                       MerchantAccount account, decimal amount, decimal fee, string address, string tag, string clientIP)
        {
            var actualAmount = amount - fee;

            ILog _logger = LogManager.GetLogger("LogicError");

            using (var scope = new TransactionScope())
            {
                try
                {
                    fromWithdraw.Status = TransactionStatus.UnSubmit;
                    fromWithdraw        = new MerchantWithdrawalDAC().Create(fromWithdraw);
                    var fromWithdrawFee = new MerchantWithdrawalFee
                    {
                        Amount       = amount,
                        Fee          = fee,
                        Timestamp    = DateTime.UtcNow,
                        WithdrawalId = fromWithdraw.Id
                    };
                    new MerchantWithdrawalFeeDAC().Create(fromWithdrawFee);
                    new MerchantWalletDAC().Freeze(fromWallet.Id, amount);

                    //var requestInfo = new FiiiFinanceAgent().TryCreateWithdraw(requestModel);

                    //new MerchantWithdrawalDAC().UpdateTransactionId(fromWithdraw.Id, requestInfo.RequestID,
                    //    requestInfo.TransactionId);

                    scope.Complete();
                }
                catch (CommonException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    _logger.Info($"Withdraw ApplyWithdrawal faild.WithdrawID:{fromWithdraw.Id},OrderNo:{fromWithdraw.OrderNo}.request Parameter - . Error message:{ex.Message}");
                    throw;
                }
            }
            var requestModel = new CreateWithdrawModel
            {
                AccountID        = account.Id,
                AccountType      = AccountTypeEnum.Merchant,
                CryptoName       = cryptocurrency.Code,
                ReceivingAddress = address,
                DestinationTag   = tag,
                Amount           = actualAmount,
                IPAddress        = clientIP,
                TransactionFee   = fee,
                WithdrawalId     = fromWithdraw.Id
            };

            RabbitMQSender.SendMessage("WithdrawSubmit", requestModel);

            return(fromWithdraw);
        }
示例#3
0
        public override Withdraw GetByRequestId(Guid accountId, long walletId, long withdrawRequestId)
        {
            var baseWithdraw = new MerchantWithdrawalDAC().GetByRequestId(accountId, walletId, withdrawRequestId);

            if (baseWithdraw == null)
            {
                return(null);
            }
            return(new Withdraw
            {
                Id = baseWithdraw.Id,
                Amount = baseWithdraw.Amount,
                Status = baseWithdraw.Status,
                TransactionId = baseWithdraw.TransactionId
            });
        }
        public WithdrawalConditionInfo GetWithdrawalInfo(Guid accountId, int cryptoId)
        {
            var result = new WithdrawalConditionInfo();

            var profileAgent = new MerchantProfileAgent();
            var profile      = profileAgent.GetMerchantProfile(accountId);
            var crypto       = new CryptocurrencyDAC().GetById(cryptoId);

            result.NeedTag = crypto.NeedTag;

            var wallet = new MerchantWalletDAC().GetByAccountId(accountId, cryptoId) ?? GenerateWallet(accountId, cryptoId, crypto.Code);

            //余额
            result.Balance = wallet.Balance.ToString(crypto.DecimalPlace);

            int level = profile.L2VerifyStatus == VerifyStatus.Certified ? 2 : profile.L1VerifyStatus == VerifyStatus.Certified ? 1 : 0;

            var masterSetting = GetMerchantWithdrawalMasterSettingWithCrypto(crypto, level);

            //最小提币量
            result.MinWithdrawalAmount = masterSetting.ToOutsideMinAmount.ToString(CultureInfo.InvariantCulture);
            // to fiiipay min withdraw amount
            result.ToFiiiPayMinWithdrawalAmount = masterSetting.ToUserMinAmount.ToString(CultureInfo.InvariantCulture);
            //手续费率
            result.HandleFeeTier = (crypto.Withdrawal_Tier ?? 0).ToString(CultureInfo.InvariantCulture);
            result.HandleFee     = (crypto.Withdrawal_Fee ?? 0).ToString(CultureInfo.InvariantCulture);
            result.DecimalPlace  = crypto.DecimalPlace;
            //限额
            result.VerifyLevel   = level;
            result.PerTxLimit    = masterSetting.PerTxLimit.ToString(crypto.DecimalPlace);
            result.PerDayLimit   = masterSetting.PerDayLimit.ToString(crypto.DecimalPlace);
            result.PerMonthLimit = masterSetting.PerMonthLimit.ToString(crypto.DecimalPlace);
            var     dac               = new MerchantWithdrawalDAC();
            var     today             = DateTime.UtcNow.Date;
            decimal dailyWithdrawal   = dac.DailyWithdrawal(accountId, cryptoId, today);
            decimal monthlyWithdrawal = dac.MonthlyWithdrawal(accountId, cryptoId, new DateTime(today.Year, today.Month, 1));
            decimal dayUsable         = masterSetting.PerDayLimit - dailyWithdrawal;
            decimal monthUsable       = masterSetting.PerMonthLimit - monthlyWithdrawal;

            dayUsable = Math.Min(dayUsable, monthUsable);

            result.PerDayUsable   = (dayUsable < 0 ? 0 : dayUsable).ToString(crypto.DecimalPlace);
            result.PerMonthUsable = (monthUsable < 0 ? 0 : monthUsable).ToString(crypto.DecimalPlace);

            return(result);
        }
示例#5
0
        public MerchantWithdrawalDTO WithdrawalDetail(Guid accountId, long withdrawalId)
        {
            var dac     = new MerchantWithdrawalDAC();
            var account = new MerchantAccountDAC().GetById(accountId);
            var data    = dac.GetById(accountId, withdrawalId);

            if (data == null)
            {
                return(null);
            }

            var crypto = new CryptocurrencyDAC().GetById(data.CryptoId);
            var result = new MerchantWithdrawalDTO
            {
                TransactionType   = TransactionType.Withdrawal,
                TransactionStatus = data.Status == TransactionStatus.UnSubmit ? TransactionStatus.Pending : data.Status,
                Address           = data.Address,
                Tag            = data.Tag,
                NeedTag        = crypto.NeedTag,
                Amount         = (data.Amount - data.WithdrawalFee).ToString(crypto.DecimalPlace),
                Timestamp      = data.Timestamp.ToUnixTime(),
                OrderNo        = data.OrderNo,
                TransactionFee = data.WithdrawalFee.ToString(crypto.DecimalPlace),
                CryptoCode     = crypto.Code,
                SelfPlatform   = data.SelfPlatform,
                TransactionId  = data.SelfPlatform ? "-" : data.TransactionId ?? "-",
                Remark         = data.Remark,
                AvatarId       = account.Photo
            };

            bool showCheckTime = crypto.Code != "XRP";

            if (showCheckTime && !data.SelfPlatform &&
                result.TransactionStatus == TransactionStatus.Pending &&
                data.RequestId.HasValue)
            {
                var statusInfo = new FiiiFinanceAgent().GetStatus(data.RequestId.Value);
                result.CheckTime     = $"{statusInfo.TotalConfirmation}/{statusInfo.MinRequiredConfirmation}";
                result.TransactionId = statusInfo.TransactionID;
            }

            return(result);
        }
        public void PushWithdrawReject(long id)
        {
            var withdraw = new MerchantWithdrawalDAC().GetById(id);
            var wallet   = new MerchantWalletDAC().GetById(withdraw.MerchantWalletId);
            var crypto   = new CryptocurrencyDAC().GetById(wallet.CryptoId);

            var regId       = RedisHelper.StringGet($"{FiiiPOS_APP_Notice_MerchantId}:{withdraw.MerchantAccountId}");
            var lang        = RedisHelper.StringGet(REDIS_LANGUAGE_DBINDEX, $"{FiiiPOS_APP_Language_MerchantId}:{withdraw.MerchantAccountId}") ?? "en";
            var titleKey    = "WithdrawalRejectTitle";
            var subTitleKey = "WithdrawalRejectSubTitle";
            var title       = ResourceHelper.FiiiPos.GetFormatResource(titleKey, lang, crypto.Code);
            var subTitle    = ResourceHelper.FiiiPos.GetResource(subTitleKey, lang);

            string noticeId = "";

            //写MongoDB [提币失败]
            MessagesComponent.AddMessage(withdraw.MerchantAccountId, UserType.Merchant, id.ToString(), FiiiPayPushType.TYPE_WITHDRAWAL_Reject, titleKey, subTitleKey, crypto.Code, title, subTitle, out noticeId);

            RegPush(FiiiPayPushType.TYPE_WITHDRAWAL_Reject, new List <string> {
                regId
            }, id, title, subTitle, noticeId);
            LogHelper.Info($"--------{lang}------{title}----------{subTitle}");
        }
示例#7
0
        public List <MerchantWithdrawalDTO> WithdrawalStatement(Guid accountId, int pageIndex, int pageSize)
        {
            var dac        = new MerchantWithdrawalDAC();
            var list       = dac.GetByMerchantAccountId(accountId, pageIndex, pageSize);
            var cryptoList = new CryptocurrencyDAC().GetAll();

            return(list.Select(e =>
            {
                var crypto = cryptoList.FirstOrDefault(c => c.Id == e.CryptoId);
                return new MerchantWithdrawalDTO
                {
                    Id = e.Id,
                    TransactionType = TransactionType.Withdrawal,
                    TransactionStatus = e.Status == TransactionStatus.UnSubmit ? TransactionStatus.Pending : e.Status,
                    Address = e.Address,
                    Amount = (e.Amount - e.WithdrawalFee).ToString(crypto?.DecimalPlace ?? 0),
                    Timestamp = e.Timestamp.ToUnixTime(),
                    OrderNo = e.OrderNo,
                    TransactionFee = e.WithdrawalFee.ToString(CultureInfo.InvariantCulture),
                    CryptoCode = crypto?.Code
                };
            }).ToList());
        }
示例#8
0
        public void SubmitWithdrawal(CreateWithdrawModel model)
        {
            if (model.AccountType == AccountTypeEnum.Merchant)
            {
                var withdrawalDAC = new MerchantWithdrawalDAC();
                var withdrawal    = withdrawalDAC.GetById(model.WithdrawalId);
                if (withdrawal == null || withdrawal.Status != Entities.Enums.TransactionStatus.UnSubmit)
                {
                    LogHelper.Info("Invalid withdrawal id or invalid withdrawal status");
                    return;
                }

                var agent = new FiiiFinanceAgent();

                try
                {
                    var requestInfo = agent.CreateWithdraw(model);

                    if (requestInfo.Code == 0)
                    {
                        withdrawalDAC.WithdrawalSubmited(model.WithdrawalId, requestInfo.RequestID,
                                                         requestInfo.TransactionId);
                    }
                    else if (requestInfo.Code == 20002 || requestInfo.Code == 300001)
                    {
                        var merchantWalletDac = new MerchantWalletDAC();
                        var merchantWallet    = merchantWalletDac.GetById(withdrawal.MerchantWalletId);
                        using (var scope = new TransactionScope())
                        {
                            try
                            {
                                withdrawalDAC.RejectById(withdrawal.Id, "Invalid address");
                                merchantWalletDac.Unfreeze(merchantWallet.Id, withdrawal.Amount);
                                new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                                {
                                    WalletId  = merchantWallet.Id,
                                    Action    = UserWalletStatementAction.Withdrawal,
                                    Amount    = withdrawal.Amount,
                                    Balance   = merchantWallet.Balance + withdrawal.Amount,
                                    Timestamp = DateTime.UtcNow
                                });
                                scope.Complete();
                            }
                            catch (Exception exception)
                            {
                                _log.Error(exception);
                            }
                        }
                    }
                    else
                    {
                        RabbitMQSender.SendMessage("WithdrawSubmit_Delay", model);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error($"UpdateTransactionId erorr, message:{JsonConvert.SerializeObject(model)}", ex);

                    RabbitMQSender.SendMessage("WithdrawSubmit_Delay", model);
                }
            }
            else if (model.AccountType == AccountTypeEnum.User)
            {
                var withdrawalDAC = new UserWithdrawalDAC();
                var withdrawal    = withdrawalDAC.GetById(model.WithdrawalId);
                if (withdrawal == null || withdrawal.Status != Entities.Enums.TransactionStatus.UnSubmit)
                {
                    LogHelper.Info("Invalid withdrawal id or invalid withdrawal status");
                    return;
                }

                var agent = new FiiiFinanceAgent();

                try
                {
                    var requestInfo = agent.CreateWithdraw(model);

                    if (requestInfo.Code == 0)
                    {
                        withdrawalDAC.WithdrawalSubmited(model.WithdrawalId, requestInfo.RequestID, requestInfo.TransactionId);
                    }
                    else if (requestInfo.Code == 20002 || requestInfo.Code == 300001)
                    {
                        var userWalletDac = new UserWalletDAC();
                        var userWallet    = userWalletDac.GetById(withdrawal.UserWalletId);
                        using (TransactionScope scope = new TransactionScope())
                        {
                            try
                            {
                                withdrawalDAC.RejectById(withdrawal.Id, "Invalid address");
                                userWalletDac.Unfreeze(withdrawal.UserWalletId, withdrawal.Amount);

                                new UserWalletStatementDAC().Insert(new Entities.UserWalletStatement
                                {
                                    WalletId      = userWallet.Id,
                                    Action        = Entities.UserWalletStatementAction.Withdrawal,
                                    Amount        = withdrawal.Amount,
                                    Balance       = userWallet.Balance + withdrawal.Amount,
                                    FrozenAmount  = -withdrawal.Amount,
                                    FrozenBalance = userWallet.FrozenBalance - withdrawal.Amount,
                                    Timestamp     = DateTime.UtcNow
                                });

                                scope.Complete();
                            }
                            catch (Exception exception)
                            {
                                _log.Error(exception);
                            }
                        }
                    }
                    else
                    {
                        RabbitMQSender.SendMessage("WithdrawSubmit_Delay", model);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error($"UpdateTransactionId erorr, message:{JsonConvert.SerializeObject(model)}", ex);
                    RabbitMQSender.SendMessage("WithdrawSubmit_Delay", model);
                }
            }
            else
            {
                LogHelper.Info("Invalid AccountType");
            }
        }
        //private MerchantWithdrawal WithdrawalToMerchantAccount(MerchantWallet fromWallet, MerchantWithdrawal fromWithdraw, MerchantWallet toWallet)
        //{
        //    MerchantDeposit deposit = null;
        //    using (var scope = new TransactionScope())
        //    {
        //        //提币
        //        fromWithdraw.Status = TransactionStatus.Confirmed;
        //        fromWithdraw.TransactionId = toWallet.MerchantAccountId.ToString("N");
        //        fromWithdraw.SelfPlatform = true;//平台内提币
        //        fromWithdraw = new MerchantWithdrawalDAC().Create(fromWithdraw);

        //        var fromWithdrawFee = new MerchantWithdrawalFee
        //        {
        //            Amount = fromWithdraw.Amount,
        //            Timestamp = DateTime.UtcNow,
        //            Fee = fromWithdraw.Amount * WithdrawalMasterSetting.ToMerchantHandleFeeTier,
        //            WithdrawalId = fromWithdraw.Id
        //        };
        //        new MerchantWithdrawalFeeDAC().Create(fromWithdrawFee);

        //        new MerchantWalletDAC().Decrease(fromWallet.Id, fromWithdraw.Amount);

        //        new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
        //        {
        //            WalletId = fromWallet.Id,
        //            Action = MerchantWalletStatementAction.Withdrawal,
        //            Amount = -fromWithdraw.Amount,
        //            Balance = fromWallet.Balance - fromWithdraw.Amount,
        //            Timestamp = DateTime.UtcNow
        //        });


        //        //充币
        //        var amount = fromWithdraw.Amount - fromWithdrawFee.Fee;
        //        if (amount <= 0)
        //        {
        //            throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.到账数量不能为零或者负数);
        //        }

        //        deposit = new MerchantDepositDAC().Insert(new MerchantDeposit
        //        {
        //            MerchantAccountId = toWallet.MerchantAccountId,
        //            MerchantWalletId = toWallet.Id,
        //            FromAddress = fromWallet.Address,
        //            ToAddress = toWallet.Address,
        //            Amount = fromWithdraw.Amount - fromWithdrawFee.Fee,
        //            Status = TransactionStatus.Confirmed,
        //            Timestamp = DateTime.UtcNow,
        //            OrderNo = CreateOrderno(),
        //            TransactionId = fromWallet.MerchantAccountId.ToString("N"),
        //            SelfPlatform = true
        //        });
        //        new MerchantWalletDAC().Increase(toWallet.Id, amount);
        //        new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
        //        {
        //            WalletId = toWallet.Id,
        //            Action = MerchantWalletStatementAction.Deposit,
        //            Amount = amount,
        //            Balance = toWallet.Balance + amount,
        //            Timestamp = DateTime.UtcNow
        //        });


        //        scope.Complete();
        //    }

        //    var withdrawId = fromWithdraw.Id;
        //    var depositId = deposit.Id;

        //    var t1 = Task.Run(() => new FiiiPOSPushComponent().PushWithdrawCompleted(withdrawId));
        //    var t2 = Task.Run(() => new FiiiPOSPushComponent().PushDeposit(depositId));
        //    Task.WaitAll(t1, t2);

        //    return fromWithdraw;
        //}

        private MerchantWithdrawal WithdrawalToUserAccount(MerchantWallet fromWallet, MerchantWithdrawal fromWithdraw,
                                                           UserWallet toWallet, decimal fee)
        {
            UserDeposit deposit;

            using (var scope = new TransactionScope())
            {
                //提币
                fromWithdraw.Status        = TransactionStatus.Confirmed;
                fromWithdraw.TransactionId = toWallet.UserAccountId.ToString("N");
                fromWithdraw.SelfPlatform  = true;//平台内提币
                fromWithdraw = new MerchantWithdrawalDAC().Create(fromWithdraw);

                var fromWithdrawFee = new MerchantWithdrawalFee
                {
                    Amount       = fromWithdraw.Amount,
                    Timestamp    = DateTime.UtcNow,
                    Fee          = fee,
                    WithdrawalId = fromWithdraw.Id
                };
                new MerchantWithdrawalFeeDAC().Create(fromWithdrawFee);

                new MerchantWalletDAC().Decrease(fromWallet.Id, fromWithdraw.Amount);

                new MerchantWalletStatementDAC().Insert(new MerchantWalletStatement
                {
                    WalletId  = fromWallet.Id,
                    Action    = MerchantWalletStatementAction.Withdrawal,
                    Amount    = -fromWithdraw.Amount,
                    Balance   = fromWallet.Balance - fromWithdraw.Amount,
                    Timestamp = DateTime.UtcNow
                });

                //充币
                var amount = fromWithdraw.Amount - fromWithdrawFee.Fee;
                new UserWalletDAC().Increase(toWallet.Id, amount);
                new UserWalletStatementDAC().Insert(new UserWalletStatement
                {
                    WalletId      = toWallet.Id,
                    Action        = UserWalletStatementAction.Deposit,
                    Amount        = amount,
                    Balance       = toWallet.Balance + amount,
                    FrozenAmount  = 0,
                    FrozenBalance = toWallet.FrozenBalance,
                    Timestamp     = DateTime.UtcNow
                });

                deposit = new UserDepositDAC().Insert(new UserDeposit
                {
                    UserAccountId = toWallet.UserAccountId,
                    UserWalletId  = toWallet.Id,
                    FromAddress   = fromWallet.Address,
                    FromTag       = fromWallet.Tag,
                    ToAddress     = toWallet.Address,
                    ToTag         = toWallet.Tag,
                    Amount        = amount,
                    Status        = TransactionStatus.Confirmed,
                    Timestamp     = DateTime.UtcNow,
                    OrderNo       = NumberGenerator.GenerateUnixOrderNo(),
                    TransactionId = fromWallet.MerchantAccountId.ToString("N"),
                    SelfPlatform  = true,
                    CryptoCode    = toWallet.CryptoCode
                });

                new UserTransactionDAC().Insert(new UserTransaction
                {
                    Id         = Guid.NewGuid(),
                    AccountId  = toWallet.UserAccountId,
                    CryptoId   = toWallet.CryptoId,
                    CryptoCode = toWallet.CryptoCode,
                    Type       = UserTransactionType.Deposit,
                    DetailId   = deposit.Id.ToString(),
                    Status     = (byte)deposit.Status,
                    Timestamp  = deposit.Timestamp,
                    Amount     = amount,
                    OrderNo    = deposit.OrderNo
                });

                scope.Complete();
            }

            var withdrawId = fromWithdraw.Id;
            var depositId  = deposit.Id;

            MerchantMSMQ.PubMerchantWithdrawCompleted(withdrawId, 0);
            MerchantMSMQ.PubUserDeposit(depositId, 0);

            return(fromWithdraw);
        }
        public MerchantWithdrawal Withdrawal(Guid accountId, decimal amount, int cryptoId, string address, string tag, string clientIP)
        {
            SecurityVerify.Verify <WithdrawVerify>(new CustomVerifier("MerchantWithdraw"), SystemPlatform.FiiiPOS, accountId.ToString(), (model) =>
            {
                return(model.PinVerified && model.CombinedVerified);
            });

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

            CryptoAddressValidation.ValidateAddress(cryptocurrency.Code, address);

            if (!string.IsNullOrEmpty(tag))
            {
                CryptoAddressValidation.ValidateTag(cryptocurrency.Code, tag);
            }

            var account = new MerchantAccountDAC().GetById(accountId);

            if (!new ProfileComponent().ValidateLv1(accountId))
            {
                throw new CommonException(ReasonCode.NOT_VERIFY_LV1, Resources.需要Lv1认证才能使用相关功能);
            }

            if (!account.IsAllowWithdrawal)
            {
                throw new CommonException(ReasonCode.Not_Allow_Withdrawal, Resources.禁止提币);
            }

            if (!cryptocurrency.Status.HasFlag(CryptoStatus.Withdrawal))
            {
                throw new CommonException(ReasonCode.CURRENCY_FORBIDDEN, Resources.CurrencyForbidden);
            }

            if (cryptocurrency.Enable == (byte)CurrencyStatus.Forbidden)
            {
                throw new CommonException(ReasonCode.CURRENCY_FORBIDDEN, Resources.CurrencyForbidden);
            }

            var fromWallet = new MerchantWalletDAC().GetByAccountId(accountId, cryptoId);

            if (fromWallet == null)
            {
                throw new CommonException(ReasonCode.Not_Allow_Withdrawal, Resources.禁止提币);
            }

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

            var profileAgent = new MerchantProfileAgent();
            var profile      = profileAgent.GetMerchantProfile(accountId);

            int level = profile.L2VerifyStatus == VerifyStatus.Certified ? 2 : profile.L1VerifyStatus == VerifyStatus.Certified ? 1 : 0;

            var masterSetting = GetMerchantWithdrawalMasterSettingWithCrypto(cryptocurrency, level);

            if (amount > masterSetting.PerTxLimit)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.能高于单次提币量);
            }
            var     dac             = new MerchantWithdrawalDAC();
            var     today           = DateTime.UtcNow.Date;
            decimal dailyWithdrawal = dac.DailyWithdrawal(accountId, cryptoId, today);

            if (amount > masterSetting.PerDayLimit - dailyWithdrawal)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.今日提币达到限额);
            }
            decimal monthlyWithdrawal = dac.MonthlyWithdrawal(accountId, cryptoId, new DateTime(today.Year, today.Month, 1));

            if (amount > masterSetting.PerMonthLimit - monthlyWithdrawal)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.本月提币达到限额);
            }

            var fromWithdraw = new MerchantWithdrawal
            {
                MerchantAccountId = accountId,
                MerchantWalletId  = fromWallet.Id,
                Address           = address,
                Tag        = tag,
                Amount     = amount,
                Status     = TransactionStatus.UnSubmit,
                Timestamp  = DateTime.UtcNow,
                OrderNo    = NumberGenerator.GenerateUnixOrderNo(),
                CryptoId   = fromWallet.CryptoId,
                CryptoCode = fromWallet.CryptoCode
            };

            var merchantWalletDac = new MerchantWalletDAC();
            var userWalletDac     = new UserWalletDAC();

            //是否是商户地址
            var toMerchantWallet = merchantWalletDac.GetByAddress(address, cryptocurrency.NeedTag ? tag : null);

            if (toMerchantWallet != null)
            {
                //if (toMerchantWallet.CryptoId != cryptoId)
                //    throw new CommonException(10000, string.Format(Resources.提币地址不是有效的地址, cryptocurrency.Code));
                //if (toMerchantWallet.MerchantAccountId == accountId)
                //    throw new CommonException(ReasonCode.CANNOT_TRANSFER_TO_YOURSELF, Resources.提币地址不能是自己账户的地址);
                //return WithdrawalToMerchantAccount(fromWallet, fromWithdraw, toMerchantWallet);
                // 042018
                throw new CommonException(ReasonCode.CAN_NOT_WITHDRAW_TO_FiiiPOS, Resources.FiiiPOSCantWithdrawToFiiiPOS);
            }

            //是否是用户地址
            var toUserWallet = userWalletDac.GetByAddressAndCrypto(cryptoId, address, cryptocurrency.NeedTag ? tag : null);

            if (toUserWallet != null)
            {
                if (toUserWallet.CryptoId != cryptoId)
                {
                    throw new CommonException(ReasonCode.GENERAL_ERROR, FiiiPay.Framework.Component.Properties.GeneralResources.EMInvalidAddress);
                }

                if (amount < masterSetting.ToUserMinAmount)
                {
                    throw new CommonException(10000, Resources.能低于最低提币量);
                }

                var fee = (fromWithdraw.Amount * masterSetting.ToUserHandleFeeTier).ToSpecificDecimal(cryptocurrency.DecimalPlace);
                if (amount <= fee)
                {
                    throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.到账数量不能为零或者负数);
                }

                return(WithdrawalToUserAccount(fromWallet, fromWithdraw, toUserWallet, fee));
            }

            //平台内提币如果tag不对,创建一条失败记录
            if (cryptocurrency.NeedTag && (userWalletDac.IsUserWalletAddress(address) || merchantWalletDac.IsMerchantWalletAddress(address)))
            {
                return(CancelWithdrawal(fromWithdraw));
            }

            //如果都不是,提币到场外
            if (amount < masterSetting.ToOutsideMinAmount)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.能低于最低提币量);
            }

            var baseFee  = cryptocurrency.Withdrawal_Fee ?? 0;
            var tier     = cryptocurrency.Withdrawal_Tier ?? 0;
            var fee1     = (amount * tier).ToSpecificDecimal(cryptocurrency.DecimalPlace);
            var totalFee = baseFee + fee1;

            if (amount <= totalFee)
            {
                throw new CommonException(ReasonCode.GENERAL_ERROR, Resources.到账数量不能为零或者负数);
            }

            return(WithdrawalToOutside(fromWallet, fromWithdraw, cryptocurrency, account, amount, totalFee, address, tag, clientIP));
        }