public AddAddressOM AddAddress(UserAccount user, string address, string tag, string alias, int coinId) { var crypto = new CryptocurrencyDAC().GetById(coinId); CryptoAddressValidation.ValidateAddress(crypto.Code, address); if (!string.IsNullOrEmpty(tag)) { CryptoAddressValidation.ValidateTag(crypto.Code, tag); } var agent = new FiiiFinanceAgent(); try { if (!agent.ValidateAddress(crypto.Code, address)) { throw new CommonException(ReasonCode.GENERAL_ERROR, GeneralResources.EMInvalidAddress); } } catch (FiiiFinanceException ex) { if (ex.ReasonCode == 20002) { throw new CommonException(ReasonCode.GENERAL_ERROR, GeneralResources.EMInvalidAddress); } } var id = new CryptoAddressDAC().Insert(new CryptoAddress { AccountId = user.Id, AccountType = AccountType.User, Address = address, Tag = tag, Alias = alias, CryptoId = coinId, }); return(new AddAddressOM { Id = id }); }
public void AddAddress(Guid merchantAccountId, int cryptoId, string address, string tag, string remark) { var crypto = new CryptocurrencyDAC().GetById(cryptoId); CryptoAddressValidation.ValidateAddress(crypto.Code, address); if (!string.IsNullOrEmpty(tag)) { CryptoAddressValidation.ValidateTag(crypto.Code, tag); } //var merchant = new MerchantAccountDAC().GetById(merchantAccountId); try { if (!new FiiiFinanceAgent().ValidateAddress(crypto.Code, address)) { throw new CommonException(ReasonCode.GENERAL_ERROR, GeneralResources.EMInvalidAddress); } } catch (FiiiFinanceException ex) { if (ex.ReasonCode == 20002) { throw new CommonException(ReasonCode.GENERAL_ERROR, GeneralResources.EMInvalidAddress); } } var dac = new CryptoAddressDAC(); var entities = new CryptoAddress { AccountId = merchantAccountId, AccountType = AccountType.Merchant, CryptoId = cryptoId, Address = address, Tag = tag, Alias = remark }; dac.Insert(entities); }
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)); }
public WithdrawOM Withdraw(UserAccount user, WithdrawIM im, string clientIP) { SecurityVerify.Verify <WithdrawVerify>(new CustomVerifier("UserWithdraw"), SystemPlatform.FiiiPay, user.Id.ToString(), (model) => { return(model.PinVerified && model.CombinedVerified); }); if (user.L1VerifyStatus != VerifyStatus.Certified) { throw new CommonException(ReasonCode.NOT_VERIFY_LV1, Resources.EMNeedLV1Verfied); } var cryptocurrency = new CryptocurrencyDAC().GetById(im.CoinId); if (!cryptocurrency.Status.HasFlag(CryptoStatus.Withdrawal) || cryptocurrency.Enable == 0) { throw new CommonException(ReasonCode.CURRENCY_FORBIDDEN, MessageResources.CurrencyForbidden); } CryptoAddressValidation.ValidateAddress(cryptocurrency.Code, im.Address); if (!string.IsNullOrEmpty(im.Tag)) { CryptoAddressValidation.ValidateTag(cryptocurrency.Code, im.Tag); } //else if (cryptocurrency.NeedTag) //{ // throw new CommonException(ReasonCode.NEED_INPUT_TAG, GeneralResources.EMNeedInputTag); //} if (im.Amount <= 0) { throw new ApplicationException(MessageResources.AmountGreater); } var IsAllowWithdrawal = user.IsAllowWithdrawal ?? true; if (!IsAllowWithdrawal) { throw new CommonException(ReasonCode.Not_Allow_Withdrawal, MessageResources.WithdrawalDisabled); } var fromWallet = new UserWalletDAC().GetByAccountId(user.Id, im.CoinId); //var profile = new UserProfileAgent().GetUserProfile(user.Id); //标准化这个金额,防止超过8位 im.Amount = im.Amount.ToSpecificDecimal(cryptocurrency.DecimalPlace); var mastSettings = new MasterSettingDAC().SelectByGroup("UserWithdrawal"); var Withdrawal_PerTx_Limit_User_NotVerified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerTx_Limit_User_NotVerified").Value); var Withdrawal_PerDay_Limit_User_NotVerified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerDay_Limit_User_NotVerified").Value); var Withdrawal_PerMonth_Limit_User_NotVerified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerMonth_Limit_User_NotVerified").Value); var Withdrawal_PerTx_Limit_User_Lv1Verified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerTx_Limit_User_Lv1Verified").Value); var Withdrawal_PerDay_Limit_User_Lv1Verified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerDay_Limit_User_Lv1Verified").Value); var Withdrawal_PerMonth_Limit_User_Lv1Verified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerMonth_Limit_User_Lv1Verified").Value); var Withdrawal_PerTx_Limit_User_Lv2Verified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerTx_Limit_User_Lv2Verified").Value); var Withdrawal_PerDay_Limit_User_Lv2Verified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerDay_Limit_User_Lv2Verified").Value); var Withdrawal_PerMonth_Limit_User_Lv2Verified = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_PerMonth_Limit_User_Lv2Verified").Value); var MinAmount = Convert.ToDecimal(mastSettings.First(e => e.Name == "Withdrawal_MinAmount").Value); var merchantWalletDac = new MerchantWalletDAC(); var userWalletDac = new UserWalletDAC(); var isWithdrawToInside = (merchantWalletDac.IsMerchantWalletAddress(im.Address) || userWalletDac.IsUserWalletAddress(im.Address)); if (isWithdrawToInside) { MinAmount = Convert.ToDecimal(mastSettings.First(e => e.Name == "UserWithdrawal_ToUser_MinAmount").Value); } var exchangeRate = GetMarketPrice(user.CountryId, cryptocurrency.Code, "USD"); var _minAmount = (MinAmount / exchangeRate).ToSpecificDecimal(cryptocurrency.DecimalPlace); if (im.Amount < _minAmount) { throw new ApplicationException(MessageResources.MinWidrawalError); } var withdrawalDAC = new UserWithdrawalDAC(); var today = DateTime.UtcNow.Date; decimal dailyWithdrawal = withdrawalDAC.DailyWithdrawal(user.Id, im.CoinId, today); decimal monthlyWithdrawal = withdrawalDAC.MonthlyWithdrawal(user.Id, im.CoinId, new DateTime(today.Year, today.Month, 1)); var PerDayLimit = 0M; var PerMonthLimit = 0M; if (user.L1VerifyStatus == VerifyStatus.Certified && user.L2VerifyStatus == VerifyStatus.Certified) { PerDayLimit = Withdrawal_PerDay_Limit_User_Lv2Verified; PerMonthLimit = Withdrawal_PerMonth_Limit_User_Lv2Verified; } else if (user.L1VerifyStatus == VerifyStatus.Certified && user.L2VerifyStatus != VerifyStatus.Certified) { PerDayLimit = Withdrawal_PerDay_Limit_User_Lv1Verified; PerMonthLimit = Withdrawal_PerMonth_Limit_User_Lv1Verified; } else if (user.L1VerifyStatus != VerifyStatus.Certified && user.L2VerifyStatus != VerifyStatus.Certified) { PerDayLimit = Withdrawal_PerDay_Limit_User_NotVerified; PerMonthLimit = Withdrawal_PerMonth_Limit_User_NotVerified; } if ((PerDayLimit / exchangeRate - dailyWithdrawal).ToSpecificDecimal(cryptocurrency.DecimalPlace) < im.Amount) { throw new ApplicationException(MessageResources.TodayWidrawalLimit); } if ((PerMonthLimit / exchangeRate - monthlyWithdrawal).ToSpecificDecimal(cryptocurrency.DecimalPlace) < im.Amount) { throw new ApplicationException(MessageResources.MonthWithdrawalLimit); } var fromWithdraw = new UserWithdrawal { UserAccountId = user.Id, UserWalletId = fromWallet.Id, Address = im.Address, Tag = im.Tag, Amount = im.Amount, Status = TransactionStatus.UnSubmit, Timestamp = DateTime.UtcNow, OrderNo = IdentityHelper.OrderNo(), CryptoCode = fromWallet.CryptoCode, CryptoId = fromWallet.CryptoId }; //是否是商户地址 var toMerchantWallet = merchantWalletDac.GetByAddressAndCrypto(im.CoinId, im.Address, im.Tag); if (toMerchantWallet != null) { //if (toMerchantWallet.CryptoId != im.CoinId) // throw new CommonException(ReasonCode.GENERAL_ERROR, GeneralResources.EMInvalidAddress); //return WithdrawalToMerchantAccount(fromWallet, fromWithdraw, fromWithdrawFee, toMerchantWallet, cryptocurrency); //042018 throw new CommonException(ReasonCode.CAN_NOT_WITHDRAW_TO_FiiiPOS, MessageResources.FiiiPayCantWithdrawToFiiiPOS); } //是否是用户地址 var toUserWallet = userWalletDac.GetByAddressAndCrypto(im.CoinId, im.Address, im.Tag); if (toUserWallet != null) { if (toUserWallet.UserAccountId == user.Id) { throw new CommonException(ReasonCode.CANNOT_TRANSFER_TO_YOURSELF, MessageResources.WithdrawalToSelfError); } var toFiiiPayMinWithdrawAmount = GetToFiiiPayMinAmount(Convert.ToDecimal(mastSettings.First(e => e.Name == "UserWithdrawal_ToUser_MinAmount").Value), exchangeRate, cryptocurrency.DecimalPlace); if (im.Amount < toFiiiPayMinWithdrawAmount) { throw new CommonException(10000, MessageResources.MinWidrawalError); } return(WithdrawalToUserAccount(fromWallet, fromWithdraw, toUserWallet)); } var tier = cryptocurrency.Withdrawal_Tier ?? 0; var fee = im.Amount * tier + (cryptocurrency.Withdrawal_Fee ?? 0); fee = fee.ToSpecificDecimal(cryptocurrency.DecimalPlace); var actualAmount = im.Amount - fee; if (fromWallet.Balance < im.Amount) { throw new CommonException(ReasonCode.INSUFFICIENT_BALANCE, MessageResources.InsufficientBalance); } if (actualAmount <= 0) { throw new CommonException(ReasonCode.GENERAL_ERROR, MessageResources.ArrivalAmountError); } //地址是FiiiPay的地址,但tag找不到 if (cryptocurrency.NeedTag && isWithdrawToInside) { return(CancelWithdrawal(fromWithdraw)); } ILog _logger = LogManager.GetLogger("LogicError"); //如果都不是,向Finance申请提现 //var agent = new FiiiFinanceAgent(); var requestModel = new CreateWithdrawModel { AccountID = user.Id, AccountType = AccountTypeEnum.User, CryptoName = cryptocurrency.Code, ReceivingAddress = im.Address, DestinationTag = im.Tag, Amount = actualAmount, IPAddress = clientIP, TransactionFee = fee }; using (var scope = new TransactionScope()) { try { fromWithdraw.Id = withdrawalDAC.Create(fromWithdraw); var fromWithdrawFee = new UserWithdrawalFee { Amount = im.Amount, Fee = fee, Timestamp = DateTime.UtcNow, WithdrawalId = fromWithdraw.Id }; new UserTransactionDAC().Insert(new UserTransaction { Id = Guid.NewGuid(), AccountId = fromWithdraw.UserAccountId, CryptoId = fromWithdraw.CryptoId, CryptoCode = fromWithdraw.CryptoCode, Type = UserTransactionType.Withdrawal, DetailId = fromWithdraw.Id.ToString(), Status = (byte)fromWithdraw.Status, Timestamp = fromWithdraw.Timestamp, Amount = fromWithdraw.Amount, OrderNo = fromWithdraw.OrderNo }); new UserWithdrawalFeeDAC().Create(fromWithdrawFee); userWalletDac.Freeze(fromWallet.Id, im.Amount); new UserWalletStatementDAC().Insert(new UserWalletStatement { WalletId = fromWallet.Id, Action = UserWalletStatementAction.Withdrawal, Amount = 0 - im.Amount, Balance = fromWallet.Balance - im.Amount, FrozenAmount = im.Amount, FrozenBalance = fromWallet.FrozenBalance + im.Amount, Timestamp = DateTime.UtcNow }); requestModel.WithdrawalId = fromWithdraw.Id; Framework.Queue.RabbitMQSender.SendMessage("WithdrawSubmit", requestModel); scope.Complete(); } catch (CommonException) { throw; } catch (Exception ex) { _logger.Info($"Withdraw CreateWithdrawRequest faild.WithdrawID:{fromWithdraw.Id},OrderNo:{fromWithdraw.OrderNo}.request Parameter - {requestModel}. Error message:{ex.Message}"); throw; } } return(new WithdrawOM { OrderId = fromWithdraw.Id, OrderNo = fromWithdraw.OrderNo, Timestamp = fromWithdraw.Timestamp.ToUnixTime().ToString() }); }