| | | 1 | | using System; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | using System.Linq; |
| | | 4 | | using System.Threading.Tasks; |
| | | 5 | | using AutoMapper; |
| | | 6 | | using Microsoft.Extensions.Logging; |
| | | 7 | | using SVETA.Api.Data.DTO.Wallet; |
| | | 8 | | using SVETA.Api.Helpers; |
| | | 9 | | using SVETA.Api.Helpers.Authorize; |
| | | 10 | | using SVETA.Api.Services.Interfaces; |
| | | 11 | | using WinSolutions.Sveta.Common; |
| | | 12 | | using WinSolutions.Sveta.Server.Data.DataModel.Entities; |
| | | 13 | | using WinSolutions.Sveta.Server.Data.DataModel.Extensions; |
| | | 14 | | using WinSolutions.Sveta.Server.Data.DataModel.Kinds; |
| | | 15 | | using WinSolutions.Sveta.Server.Services.Interfaces; |
| | | 16 | | |
| | | 17 | | namespace SVETA.Api.Services.Implements |
| | | 18 | | { |
| | | 19 | | public class WalletPaymentService: IWalletPaymentService |
| | | 20 | | { |
| | | 21 | | private readonly ILogger<WalletPaymentService> _logger; |
| | | 22 | | private readonly IWalletHttpClient _walletHttpClient; |
| | | 23 | | private readonly IWalletService _walletService; |
| | | 24 | | private readonly IMovementService _movementService; |
| | | 25 | | private readonly IAuthenticationService _authUserService; |
| | | 26 | | private readonly IContragentService _contragentService; |
| | 86 | 27 | | private string vtbOk = "ok"; |
| | 86 | 28 | | private string invalidSms = "sms.sms_invalidcode"; |
| | | 29 | | |
| | 86 | 30 | | public WalletPaymentService(ILogger<WalletPaymentService> logger, |
| | 86 | 31 | | IAuthenticationService authUserService, |
| | 86 | 32 | | IWalletService walletService, |
| | 86 | 33 | | IMovementService movementService, |
| | 86 | 34 | | IContragentService contragentService, |
| | 86 | 35 | | IWalletHttpClient client) |
| | 86 | 36 | | { |
| | 86 | 37 | | _logger = logger; |
| | 86 | 38 | | _walletHttpClient = client; |
| | 86 | 39 | | _walletService = walletService; |
| | 86 | 40 | | _authUserService = authUserService; |
| | 86 | 41 | | _contragentService = contragentService; |
| | 86 | 42 | | _movementService = movementService; |
| | 86 | 43 | | } |
| | | 44 | | |
| | | 45 | | /// <summary> |
| | | 46 | | /// Возвращает информацию по кошельку |
| | | 47 | | /// </summary> |
| | | 48 | | /// <returns></returns> |
| | | 49 | | public async Task<WalletBalanceResponse> GetWalletInfo() |
| | 0 | 50 | | { |
| | 0 | 51 | | var contragent = await _contragentService.GetContragent(_authUserService.ContragentId) ?? |
| | 0 | 52 | | throw new ArgumentException($"Не найден контрагент #{_authUserService.ContragentId}"); |
| | 0 | 53 | | if (contragent.WalletId == default) |
| | 0 | 54 | | throw new ArgumentException($"Не прописан кошелек для контрагента #{contragent.Id}"); |
| | 0 | 55 | | var content = await _walletHttpClient.GetWalletBalance(contragent.WalletId); |
| | 0 | 56 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 57 | | throw new ArgumentException(content.Errdesc); |
| | 0 | 58 | | return content.Response; |
| | 0 | 59 | | } |
| | | 60 | | |
| | | 61 | | /// <summary> |
| | | 62 | | /// Возвращает информацию по кошельку для контрагента |
| | | 63 | | /// </summary> |
| | | 64 | | /// <param name="contragentId">Контрагент</param> |
| | | 65 | | /// <returns></returns> |
| | | 66 | | /// <exception cref="ArgumentException"></exception> |
| | | 67 | | public async Task<WalletBalanceResponse> GetWalletInfo(long contragentId) |
| | 0 | 68 | | { |
| | | 69 | | |
| | 0 | 70 | | var contragent = await _contragentService.GetContragent(contragentId) ?? |
| | 0 | 71 | | throw new ArgumentException($"Не найден контрагент #{_authUserService.ContragentId}"); |
| | 0 | 72 | | if (contragent.WalletId == default) |
| | 0 | 73 | | throw new ArgumentException($"Не прописан кошелек для контрагента #{contragent.Id}"); |
| | 0 | 74 | | var content = await _walletHttpClient.GetWalletBalance(contragent.WalletId); |
| | 0 | 75 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 76 | | throw new ArgumentException(content.Errdesc); |
| | 0 | 77 | | return content.Response; |
| | 0 | 78 | | } |
| | | 79 | | |
| | | 80 | | /// <summary> |
| | | 81 | | /// Проверяет доступность средств в кошельке на сумму |
| | | 82 | | /// </summary> |
| | | 83 | | /// <param name="sum"></param> |
| | | 84 | | /// <returns></returns> |
| | | 85 | | public async Task<WalletBalanceFreeResponse> GetWalletFreeBalance(long contragentId = 0, decimal sum = 0) |
| | 73 | 86 | | { |
| | 73 | 87 | | contragentId = contragentId != 0 ? contragentId : _authUserService.ContragentId; |
| | 73 | 88 | | var contragent = await _contragentService.GetContragent(contragentId) ?? |
| | 73 | 89 | | throw new ArgumentException($"Не найден контрагент #{contragentId}"); |
| | 73 | 90 | | if (contragent.WalletId == default) |
| | 0 | 91 | | throw new ArgumentException($"Не прописан кошелек для контрагента #{contragent.Id}"); |
| | 73 | 92 | | var content = await _walletHttpClient.GetFreeBalance(contragent.WalletId, sum); |
| | 73 | 93 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 94 | | { |
| | 0 | 95 | | _logger.LogError($"Ошибка получения баланса кошелька {contragent.WalletId}"); |
| | 0 | 96 | | throw new ArgumentException(content.Errdesc); |
| | | 97 | | } |
| | | 98 | | |
| | 73 | 99 | | var mapper = new MapperConfiguration(cfg => |
| | 146 | 100 | | cfg.CreateMap<WalletBalanceFreeVtbResponse, WalletBalanceFreeResponse>() |
| | 146 | 101 | | .ForMember(d => d.Id, e => |
| | 219 | 102 | | e.MapFrom(s => s.Acc_id))) |
| | 73 | 103 | | .CreateMapper(); |
| | 73 | 104 | | return mapper.Map<WalletBalanceFreeResponse>(content.Response); |
| | 73 | 105 | | } |
| | | 106 | | |
| | | 107 | | /// <summary> |
| | | 108 | | /// Создает транзакцию в втб |
| | | 109 | | /// </summary> |
| | | 110 | | /// <param name="movementId"></param> |
| | | 111 | | /// <returns></returns> |
| | | 112 | | public async Task CreateTransaction(long movementId) |
| | 0 | 113 | | { |
| | 0 | 114 | | Movement movement = await _movementService.GetMovementForItems(movementId) ?? |
| | 0 | 115 | | throw new ArgumentException($"Не найден документ #{movementId}"); |
| | | 116 | | |
| | 0 | 117 | | if (movement.Customer.Id != _authUserService.ContragentId && !_authUserService.IsUserPlatform()) //TODO: rem |
| | 0 | 118 | | throw new ForbidException(); |
| | | 119 | | |
| | 0 | 120 | | if (movement.MovementType.Id != (long)MovementKind.Shipment) |
| | 0 | 121 | | throw new ArgumentException($"Оплата возможна только для Отрузки"); |
| | | 122 | | |
| | 0 | 123 | | if (movement.MovementStatus.Id != (long)MovementsStatus.PaymentAwaiting) |
| | 0 | 124 | | throw new ArgumentException($"Оплата возможна только в статусе Ожидание оплаты"); |
| | | 125 | | |
| | 0 | 126 | | string buyerWalletId = movement.Customer.WalletId; |
| | 0 | 127 | | string sellerWaletId = movement.Supplier.WalletId; |
| | | 128 | | |
| | | 129 | | //Проверим что у всех участников прописаны кошельки в системе |
| | 0 | 130 | | var contragent = movement.Customer.WalletId == default ? movement.Customer : movement.Supplier.WalletId == d |
| | 0 | 131 | | if (contragent != null) |
| | 0 | 132 | | throw new ArgumentException($"Не прописан кошелек для контрагента #{contragent.Id}"); |
| | | 133 | | |
| | | 134 | | //Поищем транзакцию по этой заявке в статусе ожидание проверки смс, холдирование средств и подтверждена |
| | 0 | 135 | | long[] statuses = { (long)TransactionStatusKind.SmsWaited, (long)TransactionStatusKind.Holded, (long)Transac |
| | 0 | 136 | | foreach (var status in statuses) |
| | 0 | 137 | | { |
| | 0 | 138 | | var transaction = await _walletService.GetTransaction(movement.Id, status); |
| | 0 | 139 | | if (transaction != null) |
| | 0 | 140 | | { |
| | 0 | 141 | | switch (transaction.Status.Id) |
| | | 142 | | { |
| | | 143 | | case (long)TransactionStatusKind.SmsWaited: |
| | 0 | 144 | | { |
| | 0 | 145 | | DateTime time = transaction.ModificationDateTime ?? transaction.CreationDateTime; |
| | | 146 | | // если при добавлении 119 секунд получилось большая дата, то время жизни транзакции еще |
| | 0 | 147 | | if (time != DateTime.MinValue && time.AddSeconds(119) > DateTime.UtcNow) |
| | 0 | 148 | | { |
| | 0 | 149 | | return; |
| | | 150 | | } |
| | | 151 | | // код умер, да здравствует вновь запрошенный код |
| | 0 | 152 | | await RetrySms(movementId); |
| | 0 | 153 | | return; |
| | | 154 | | } |
| | | 155 | | case (long)TransactionStatusKind.Holded: |
| | 0 | 156 | | { |
| | 0 | 157 | | throw new ArgumentException($"Денежные средства по документу #{movement.Id} уже зарезерв |
| | | 158 | | } |
| | | 159 | | case (long)TransactionStatusKind.Confirmed: |
| | 0 | 160 | | { |
| | 0 | 161 | | throw new ArgumentException($"Денежные средства по документу #{movement.Id} уже зарезерв |
| | | 162 | | } |
| | 0 | 163 | | }; |
| | 0 | 164 | | } |
| | 0 | 165 | | } |
| | | 166 | | |
| | 0 | 167 | | var request = new WalletRequest |
| | 0 | 168 | | { |
| | 0 | 169 | | Tp = "distributor", |
| | 0 | 170 | | Model = new WalletRequestModel |
| | 0 | 171 | | { |
| | 0 | 172 | | Buyer = buyerWalletId, |
| | 0 | 173 | | Seller = sellerWaletId, |
| | 0 | 174 | | Sum = movement.PrepaimentSum, |
| | 0 | 175 | | Sum_distr = movement.Items.Sum(d => d.Price * d.Quantity), |
| | 0 | 176 | | Orderid = movement.DocumentNumber |
| | 0 | 177 | | } |
| | 0 | 178 | | }; |
| | 0 | 179 | | var content = await _walletHttpClient.CreateTransaction(movement.GUID, request); |
| | 0 | 180 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 181 | | throw new ArgumentException(content.Errdesc); |
| | 0 | 182 | | if (content.Response == null) |
| | 0 | 183 | | throw new ArgumentException($"Сервис ВТБК не вернул тело транзакции."); |
| | 0 | 184 | | var trStatus = await _walletService.GetTransactionStatus((long) TransactionStatusKind.SmsWaited); |
| | 0 | 185 | | await _walletService.CreateWalletTransaction(new WalletTransaction |
| | 0 | 186 | | { |
| | 0 | 187 | | Movement = movement, |
| | 0 | 188 | | Sum = request.Model.Sum, |
| | 0 | 189 | | TransactionId = content.Response.Id, |
| | 0 | 190 | | SmsId = content.Response.SmsId, |
| | 0 | 191 | | Status = trStatus |
| | 0 | 192 | | }); |
| | 0 | 193 | | } |
| | | 194 | | |
| | | 195 | | /// <summary> |
| | | 196 | | /// Совершает проверку введенной смс |
| | | 197 | | /// </summary> |
| | | 198 | | /// <param name="movementId"></param> |
| | | 199 | | /// <param name="code"></param> |
| | | 200 | | /// <returns></returns> |
| | | 201 | | public async Task CheckSms(long movementId, string code) |
| | 0 | 202 | | { |
| | 0 | 203 | | var transaction = (await _walletService.GetTransaction(movementId, (long)TransactionStatusKind.SmsWaited)) |
| | 0 | 204 | | ?? throw new ArgumentException($"Транзакция для #{movementId} в статусе ожидания проверки |
| | 0 | 205 | | if (transaction.Movement.Customer.Id != _authUserService.ContragentId && !_authUserService.IsUserPlatform()) |
| | 0 | 206 | | throw new ForbidException(); |
| | 0 | 207 | | DateTime time = transaction.ModificationDateTime ?? transaction.CreationDateTime; |
| | 0 | 208 | | if (time.AddSeconds(119) <= DateTime.UtcNow) |
| | 0 | 209 | | throw new SvetaException($"Время ожидания смс истекло. Запросите повторное смс", (int)ErrorCode.PaymentC |
| | | 210 | | |
| | 0 | 211 | | WalletCheckSmsRequest checkRequest = new WalletCheckSmsRequest |
| | 0 | 212 | | { |
| | 0 | 213 | | Action = "check_sms", |
| | 0 | 214 | | Id = transaction.TransactionId, |
| | 0 | 215 | | Smsid = transaction.SmsId, |
| | 0 | 216 | | Code = code |
| | 0 | 217 | | }; |
| | | 218 | | |
| | 0 | 219 | | var content = await _walletHttpClient.CheckSms(transaction.GUID, checkRequest); |
| | | 220 | | |
| | 0 | 221 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 222 | | { |
| | 0 | 223 | | if (content.Err.Equals(invalidSms, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 224 | | { |
| | 0 | 225 | | throw new SvetaException(content.Errdesc, (int)ErrorCode.PaymentCodeIncorrect); |
| | | 226 | | } |
| | | 227 | | else |
| | 0 | 228 | | { |
| | 0 | 229 | | throw new SvetaException(content.Errdesc, (int)ErrorCode.PaymentOtherError); |
| | | 230 | | } |
| | | 231 | | |
| | | 232 | | } |
| | | 233 | | |
| | | 234 | | //await _movementWorker.SetNextStatus(transaction.Movement.Id, MovementStatusKeys.payment); |
| | 0 | 235 | | await UpdateTransactionStatus(transaction, (long)TransactionStatusKind.Holded); |
| | 0 | 236 | | } |
| | | 237 | | |
| | | 238 | | /// <summary> |
| | | 239 | | /// Запрашивает повторное смс |
| | | 240 | | /// </summary> |
| | | 241 | | /// <param name="movementId"></param> |
| | | 242 | | /// <returns></returns> |
| | | 243 | | public async Task RetrySms(long movementId) |
| | 0 | 244 | | { |
| | 0 | 245 | | var transaction = (await _walletService.GetTransaction(movementId, (long)TransactionStatusKind.SmsWaited)) |
| | 0 | 246 | | ?? throw new ArgumentException($"Транзакция для #{movementId} в статусе ожидания проверки |
| | 0 | 247 | | if (transaction.Movement.Customer.Id != _authUserService.ContragentId && !_authUserService.IsUserPlatform()) |
| | 0 | 248 | | throw new ForbidException(); |
| | 0 | 249 | | WalletConfirmReqDTO request = new WalletConfirmReqDTO |
| | 0 | 250 | | { |
| | 0 | 251 | | Action = "retry_sms", |
| | 0 | 252 | | Id = transaction.TransactionId |
| | 0 | 253 | | }; |
| | 0 | 254 | | var content = await _walletHttpClient.RetrySms(transaction.GUID, request); |
| | 0 | 255 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 256 | | throw new ArgumentException(content.Errdesc); |
| | | 257 | | |
| | 0 | 258 | | transaction.SmsId = content.Response.Rp.Smsid; |
| | 0 | 259 | | await _walletService.Update(transaction); |
| | 0 | 260 | | } |
| | | 261 | | |
| | | 262 | | /// <summary> |
| | | 263 | | /// Подтверждает транзакцию |
| | | 264 | | /// </summary> |
| | | 265 | | /// <param name="movementId"></param> |
| | | 266 | | /// <returns></returns> |
| | | 267 | | public async Task ConfirmTransaction(long movementId) |
| | 0 | 268 | | { |
| | 0 | 269 | | var transaction = (await _walletService.GetTransaction(movementId, (long)TransactionStatusKind.Holded)) |
| | 0 | 270 | | ?? throw new ArgumentException($"Транзакция для документа #{movementId} со статусом Заморо |
| | | 271 | | |
| | 0 | 272 | | WalletConfirmReqDTO request = new WalletConfirmReqDTO |
| | 0 | 273 | | { |
| | 0 | 274 | | Action = "confirm", |
| | 0 | 275 | | Id = transaction.TransactionId |
| | 0 | 276 | | }; |
| | | 277 | | |
| | 0 | 278 | | var content = await _walletHttpClient.ConfirmTransaction(transaction.GUID, request); |
| | 0 | 279 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 280 | | throw new ArgumentException(content.Errdesc); |
| | | 281 | | |
| | 0 | 282 | | await UpdateTransactionStatus(transaction, (long)TransactionStatusKind.Confirmed); |
| | 0 | 283 | | } |
| | | 284 | | |
| | | 285 | | /// <summary> |
| | | 286 | | /// Отменяет транзакцию |
| | | 287 | | /// </summary> |
| | | 288 | | /// <param name="movementId"></param> |
| | | 289 | | /// <returns></returns> |
| | | 290 | | public async Task CancelTransaction(long movementId) |
| | 0 | 291 | | { |
| | 0 | 292 | | var transaction = (await _walletService.GetTransaction(movementId, (long)TransactionStatusKind.Holded)) |
| | 0 | 293 | | ?? throw new ArgumentException($"Транзакция для документа #{movementId} со статусом Заморо |
| | 0 | 294 | | WalletConfirmReqDTO request = new WalletConfirmReqDTO |
| | 0 | 295 | | { |
| | 0 | 296 | | Action = "cancel", |
| | 0 | 297 | | Id = transaction.TransactionId |
| | 0 | 298 | | }; |
| | | 299 | | |
| | 0 | 300 | | var content = await _walletHttpClient.CancelTransaction(transaction.GUID, request); |
| | 0 | 301 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 302 | | throw new ArgumentException(content.Errdesc); |
| | | 303 | | |
| | 0 | 304 | | await UpdateTransactionStatus(transaction, (long)TransactionStatusKind.Canceled); |
| | 0 | 305 | | } |
| | | 306 | | |
| | | 307 | | public async Task<WalletTransaction> GetTransaction(long movementId, TransactionStatusKind transactionStatus) => |
| | 29 | 308 | | await _walletService.GetTransaction(movementId, (long)transactionStatus); |
| | | 309 | | /// <summary> |
| | | 310 | | /// Изменяет сумму сделки по документу |
| | | 311 | | /// </summary> |
| | | 312 | | /// <param name="movementId"></param> |
| | | 313 | | /// <returns></returns> |
| | | 314 | | public async Task ChangeDealTransaction(long movementId) |
| | 0 | 315 | | { |
| | 0 | 316 | | Movement movement = await _movementService.GetMovementForItems(movementId) ?? |
| | 0 | 317 | | throw new ArgumentException($"Не найден документ #{movementId}"); |
| | 0 | 318 | | var transaction = (await _walletService.GetTransaction(movementId, (long)TransactionStatusKind.Holded)) |
| | 0 | 319 | | ?? throw new ArgumentException($"Транзакция для документа #{movementId} со статусом Заморо |
| | | 320 | | |
| | 0 | 321 | | WalletChangeDealRequestDto request = new WalletChangeDealRequestDto |
| | 0 | 322 | | { |
| | 0 | 323 | | Id = transaction.TransactionId, |
| | 0 | 324 | | Sum = movement.PrepaimentSum, |
| | 0 | 325 | | Sum_distr = movement.Items.Sum(d => d.Good.Prices.Actual(movement.Sender.Id).PriceNew * d.Quantity) |
| | 0 | 326 | | }; |
| | 0 | 327 | | var checkDealResult = await _walletHttpClient.CheckChangeDeal(transaction.GUID, request); |
| | 0 | 328 | | if (!checkDealResult.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 329 | | throw new ArgumentException(checkDealResult.Errdesc); |
| | 0 | 330 | | var content = await _walletHttpClient.ChangeDeal(transaction.GUID, request); |
| | 0 | 331 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 332 | | throw new ArgumentException(content.Errdesc); |
| | 0 | 333 | | transaction.Sum = movement.PrepaimentSum; |
| | 0 | 334 | | await UpdateTransactionStatus(transaction, (long)TransactionStatusKind.Holded); |
| | 0 | 335 | | } |
| | | 336 | | |
| | | 337 | | public async Task CheckChangeDealTransaction(long movementId) |
| | 0 | 338 | | { |
| | 0 | 339 | | Movement movement = await _movementService.GetMovement(movementId) ?? |
| | 0 | 340 | | throw new ArgumentException($"Не найден документ #{movementId}"); |
| | 0 | 341 | | var transaction = (await _walletService.GetTransaction(movement.Id, (long)TransactionStatusKind.Holded)) |
| | 0 | 342 | | ?? throw new ArgumentException($"Транзакция для документа #{movement.Id} со статусом Замор |
| | | 343 | | |
| | 0 | 344 | | WalletChangeDealRequestDto request = new WalletChangeDealRequestDto |
| | 0 | 345 | | { |
| | 0 | 346 | | Id = transaction.TransactionId, |
| | 0 | 347 | | Sum = movement.PrepaimentSum, |
| | 0 | 348 | | Sum_distr = movement.Items.Sum(d => d.Good.Prices.Actual(movement.Sender.Id).PriceNew * d.Quantity) |
| | 0 | 349 | | }; |
| | 0 | 350 | | var content = await _walletHttpClient.CheckChangeDeal(transaction.GUID, request); |
| | 0 | 351 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 352 | | throw new ArgumentException(content.Errdesc); |
| | 0 | 353 | | } |
| | | 354 | | |
| | | 355 | | /// <summary> |
| | | 356 | | /// Возвращает информацию о транзакции |
| | | 357 | | /// </summary> |
| | | 358 | | /// <param name="transactionId"></param> |
| | | 359 | | /// <returns></returns> |
| | | 360 | | public async Task<WalletTransactionHistory> GetTransactionInfo(string transactionId) |
| | 0 | 361 | | { |
| | 0 | 362 | | var content = await _walletHttpClient.GetTransactionInfo(transactionId); |
| | 0 | 363 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 364 | | throw new ArgumentException(content.Errdesc); |
| | | 365 | | |
| | 0 | 366 | | return content.Response; |
| | 0 | 367 | | } |
| | | 368 | | |
| | | 369 | | /// <summary> |
| | | 370 | | ///История транзакций за период по контрагенту |
| | | 371 | | /// </summary> |
| | | 372 | | /// <remarks>author: aabelentsov</remarks> |
| | | 373 | | /// <param name="typeRecord">тип записей - hold/record</param> |
| | | 374 | | /// <param name="active">1 - активный холд (если ничего не указано - выводится все) </param> |
| | | 375 | | /// <param name="status">статус транзакции (если ничего не указано - выводится все)</param> |
| | | 376 | | /// <param name="dateFrom">начальное время периода проводок</param> |
| | | 377 | | /// <param name="dateTo">конечное время периода проводок</param> |
| | | 378 | | /// <returns></returns> |
| | | 379 | | public async Task<List<WalletHistoryResponse>> GetAccountHistory(string typeRecord, int active, int status, Date |
| | 0 | 380 | | { |
| | 0 | 381 | | var contragent = await _contragentService.GetContragent(_authUserService.ContragentId) ?? |
| | 0 | 382 | | throw new ArgumentException($"Не найден контрагент #{_authUserService.ContragentId}"); |
| | 0 | 383 | | dateFrom = dateFrom == DateTime.MinValue ? DateTime.UtcNow.AddDays(-1) : dateFrom; |
| | 0 | 384 | | dateTo = dateTo == DateTime.MinValue ? DateTime.UtcNow.AddDays(1) : dateTo; |
| | | 385 | | |
| | 0 | 386 | | string onlyType = typeRecord?.ToUpper() switch |
| | 0 | 387 | | { |
| | 0 | 388 | | "HOLD" => "hold", |
| | 0 | 389 | | "RECORD" => "record", |
| | 0 | 390 | | _ => null |
| | 0 | 391 | | }; |
| | 0 | 392 | | var request = new WalletHistoryRequest |
| | 0 | 393 | | { |
| | 0 | 394 | | Periodbeg = dateFrom, |
| | 0 | 395 | | Periodend = dateTo, |
| | 0 | 396 | | Acc = contragent.WalletId, |
| | 0 | 397 | | Only = onlyType, |
| | 0 | 398 | | Active_hold = active == 1 ? active : (int?)null, |
| | 0 | 399 | | Status = status == 0 ? (int?)null : status, |
| | 0 | 400 | | Tp = null |
| | 0 | 401 | | }; |
| | 0 | 402 | | var content = await _walletHttpClient.GetTransactionHistory(request); |
| | 0 | 403 | | if (!content.Status.Equals(vtbOk, StringComparison.OrdinalIgnoreCase)) |
| | 0 | 404 | | throw new ArgumentException(content.Errdesc); |
| | 0 | 405 | | return content.Response ?? new List<WalletHistoryResponse>() { }; |
| | 0 | 406 | | } |
| | | 407 | | |
| | | 408 | | |
| | | 409 | | public async Task<bool> CheckNeedFallbackMoney(long movementId) |
| | | 410 | | { |
| | | 411 | | var transactionList = await _walletService.GetTransactions(movementId); |
| | | 412 | | if (transactionList.TotalCount == 0) return false; |
| | | 413 | | var transactions = transactionList.Result; |
| | 0 | 414 | | return transactions.Any(d => d.Status.Id == (long) TransactionStatusKind.Holded); |
| | | 415 | | } |
| | | 416 | | |
| | | 417 | | private async Task UpdateTransactionStatus(WalletTransaction transaction, long statusId) |
| | 0 | 418 | | { |
| | 0 | 419 | | var status = await _walletService.GetTransactionStatus(statusId); |
| | 0 | 420 | | transaction.Status = status; |
| | 0 | 421 | | await _walletService.Update(transaction); |
| | 0 | 422 | | } |
| | | 423 | | } |
| | | 424 | | |
| | | 425 | | public interface IWalletPaymentService |
| | | 426 | | { |
| | | 427 | | Task CreateTransaction(long movementId); |
| | | 428 | | Task<WalletBalanceResponse> GetWalletInfo(); |
| | | 429 | | Task<WalletBalanceResponse> GetWalletInfo(long contragentId); |
| | | 430 | | Task<WalletBalanceFreeResponse> GetWalletFreeBalance(long contragentId = 0, decimal sum = 0); |
| | | 431 | | Task CheckSms(long movementId, string code); |
| | | 432 | | Task RetrySms(long movementId); |
| | | 433 | | Task ConfirmTransaction(long movementId); |
| | | 434 | | Task CancelTransaction(long movementId); |
| | | 435 | | Task<WalletTransactionHistory> GetTransactionInfo(string transactionId); |
| | | 436 | | Task<List<WalletHistoryResponse>> GetAccountHistory(string typeRecord, int active, |
| | | 437 | | int status, DateTime dateFrom, DateTime dateTo); |
| | | 438 | | Task ChangeDealTransaction(long movementId); |
| | | 439 | | Task<bool> CheckNeedFallbackMoney(long movementId); |
| | | 440 | | Task<WalletTransaction> GetTransaction(long movementId, TransactionStatusKind transactionStatus); |
| | | 441 | | Task CheckChangeDealTransaction(long movementId); |
| | | 442 | | } |
| | | 443 | | } |