public async Task <IActionResult> GetDetailsAsync(string merchantId, string paymentRequestId) { try { IPaymentRequest paymentRequest = await _paymentRequestService.GetAsync(merchantId, paymentRequestId); if (paymentRequest == null) { return(NotFound(ErrorResponse.Create("Could not find payment request"))); } PaymentRequestRefund refundInfo = await _paymentRequestService.GetRefundInfoAsync(paymentRequest.WalletAddress); PaymentRequestDetailsModel model = await _paymentRequestDetailsBuilder.Build < PaymentRequestDetailsModel, PaymentRequestOrderModel, PaymentRequestTransactionModel, PaymentRequestRefundModel>(paymentRequest, refundInfo); return(Ok(model)); } catch (Exception ex) { await _log.WriteErrorAsync(nameof(GetDetailsAsync), new { MerchantId = merchantId, PaymentRequestId = paymentRequestId }.ToJson(), ex); throw; } }
public async Task <IActionResult> GetRefundData([Guid] string paymentRequestId) { try { PaymentRequestDetailsModel paymentRequestDetails = await _payInternalClient.GetPaymentRequestDetailsAsync(User.GetMerchantId(), paymentRequestId); if (!IsStatusValidForRefund(paymentRequestDetails.Status, paymentRequestDetails.ProcessingError)) { _log.Warning("Attempt to refund in incorrect status, details: " + paymentRequestDetails.ToJson()); return(BadRequest(ErrorResponse.Create(RefundErrorType.NotAllowedInStatus.ToString()))); } var paymentAsset = await _lykkeAssetsResolver.TryGetAssetAsync(paymentRequestDetails.PaymentAssetId); var refundData = new RefundDataResponse { PaymentAsset = Mapper.Map <AssetModel>(paymentAsset), SourceWalletAddresses = paymentRequestDetails.Transactions.SelectMany(x => x.SourceWalletAddresses).ToList(), Amount = paymentRequestDetails.Transactions.Sum(x => x.Amount) }; return(Ok(refundData)); } catch (Exception ex) { _log.ErrorWithDetails(ex, details: new { paymentRequestId }); return(BadRequest(ErrorResponse.Create(PayInvoicePortalApiErrorCodes.UnexpectedError))); } bool IsStatusValidForRefund(PaymentRequestStatus status, PaymentRequestProcessingError processingError) { var invoiceStatus = status.ToInvoiceStatus(processingError); switch (invoiceStatus) { case InvoiceStatus.Underpaid: case InvoiceStatus.Overpaid: case InvoiceStatus.LatePaid: return(true); default: return(false); } } }
public async Task <IActionResult> CreatePaymentRequest([FromBody] CreatePaymentRequestModel request) { if (string.IsNullOrWhiteSpace(request.SettlementAsset)) { return(BadRequest(PaymentErrorResponseModel.Create(PaymentErrorType.InvalidSettlementAsset))); } if (string.IsNullOrWhiteSpace(request.PaymentAsset)) { return(BadRequest(PaymentErrorResponseModel.Create(PaymentErrorType.InvalidPaymentAsset))); } try { var domainRequest = Mapper.Map <CreatePaymentRequest>(request, opt => opt.Items["MerchantId"] = _headersHelper.MerchantId); CreatePaymentResponse createResponse = await _paymentRequestService.CreatePaymentRequestAsync(domainRequest); PaymentRequestDetailsModel paymentRequestDetails = await _paymentRequestService.GetPaymentRequestDetailsAsync(_headersHelper.MerchantId, createResponse.Id); return(Ok(paymentRequestDetails.ToStatusApiModel())); } catch (InvalidSettlementAssetException ex) { _log.Error(ex, null, $"request: {request.ToJson()}"); return(BadRequest(PaymentErrorResponseModel.Create(PaymentErrorType.InvalidSettlementAsset))); } catch (InvalidPaymentAssetException ex) { _log.Error(ex, null, $"request: {request.ToJson()}"); return(BadRequest(PaymentErrorResponseModel.Create(PaymentErrorType.InvalidPaymentAsset))); } catch (Exception ex) { _log.Error(ex, null, $"request: {request.ToJson()}"); throw; } }
public async Task <IActionResult> GetDetailsAsync( [Required, RowKey] string merchantId, [Required, RowKey] string paymentRequestId) { IPaymentRequest paymentRequest = await _paymentRequestService.GetAsync(merchantId, paymentRequestId); if (paymentRequest == null) { return(NotFound(ErrorResponse.Create("Could not find payment request"))); } PaymentRequestRefund refundInfo = await _paymentRequestService.GetRefundInfoAsync(paymentRequest.WalletAddress); PaymentRequestDetailsModel model = await _paymentRequestDetailsBuilder.Build < PaymentRequestDetailsModel, PaymentRequestOrderModel, PaymentRequestTransactionModel, PaymentRequestRefundModel>(paymentRequest, refundInfo); return(Ok(model)); }
public async Task <IActionResult> Refund(string paymentRequestId, [FromQuery] string destinationAddress) { if (!paymentRequestId.IsValidPaymentRequestId()) { return(BadRequest(PaymentErrorResponseModel.Create(PaymentErrorType.InvalidPaymentId))); } try { PaymentRequestDetailsModel paymentRequestDetails = await _paymentRequestService.RefundAsync( new RefundRequest { MerchantId = _headersHelper.MerchantId, PaymentRequestId = paymentRequestId, DestinationAddress = destinationAddress }); return(Ok(paymentRequestDetails.ToStatusApiModel())); } catch (Exception ex) { _log.Error(ex, null, $@"request: { new { paymentRequestId, destinationAddress }.ToJson() }"); if (ex is PayInternal.Client.Exceptions.RefundErrorResponseException refundEx) { return(BadRequest(refundEx.ToErrorModel())); } return(BadRequest(PaymentErrorResponseModel.Create(PaymentErrorType.RefundIsNotAvailable))); } }
public static PaymentStatusResponseModel ToStatusApiModel(this PaymentRequestDetailsModel src) { PaymentStatusResponseModel response = new PaymentStatusResponseModel { Id = src.Id, PaymentAsset = src.PaymentAssetId, SettlementAsset = src.SettlementAssetId, OrderId = src.OrderId, PaymentRequest = new PaymentRequestResponseModel { Amount = src.Order?.PaymentAmount, Address = src.WalletAddress, CreatedAt = src.Timestamp.ToIsoDateTime(), ExchangeRate = src.Order?.ExchangeRate, ExpirationDt = src.DueDate.ToIsoDateTime(), Transactions = src.Transactions.Any() ? src.Transactions.Select(Mapper.Map <PaymentResponseTransactionModel>).ToList() : null } }; switch (src.Status) { case PaymentRequestStatus.New: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentRequestCreated; break; case PaymentRequestStatus.Confirmed: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentConfirmed; break; case PaymentRequestStatus.InProcess: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentInProgress; break; case PaymentRequestStatus.Cancelled: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentCancelled; break; case PaymentRequestStatus.Error: switch (src.ProcessingError) { case PaymentRequestProcessingError.PaymentAmountAbove: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentError; response.Error = new ErrorResponseModel { Code = PaymentRequestErrorPublicCodes.PaymentAmountAbove }; break; case PaymentRequestProcessingError.PaymentAmountBelow: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentError; response.Error = new ErrorResponseModel { Code = PaymentRequestErrorPublicCodes.PaymentAmountBelow }; break; case PaymentRequestProcessingError.PaymentExpired: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentError; response.Error = new ErrorResponseModel { Code = PaymentRequestErrorPublicCodes.PaymentExpired }; break; case PaymentRequestProcessingError.RefundNotConfirmed: response.PaymentStatus = PaymentRequestPublicStatuses.RefundError; response.RefundRequest = Mapper.Map <RefundRequestResponseModel>(src.Refund); response.Error = new ErrorResponseModel { Code = PaymentRequestErrorPublicCodes.TransactionNotConfirmed }; break; case PaymentRequestProcessingError.LatePaid: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentError; response.Error = new ErrorResponseModel { Code = PaymentRequestErrorPublicCodes.LatePaid }; break; case PaymentRequestProcessingError.UnknownPayment: response.PaymentStatus = PaymentRequestPublicStatuses.PaymentError; break; case PaymentRequestProcessingError.UnknownRefund: response.PaymentStatus = PaymentRequestPublicStatuses.RefundError; response.RefundRequest = Mapper.Map <RefundRequestResponseModel>(src.Refund); response.Error = new ErrorResponseModel { Code = PaymentRequestErrorPublicCodes.RefundIsNotAvailable }; break; default: throw new Exception("Unknown payment request error type"); } break; case PaymentRequestStatus.RefundInProgress: response.PaymentStatus = PaymentRequestPublicStatuses.RefundInProgress; response.RefundRequest = Mapper.Map <RefundRequestResponseModel>(src.Refund); break; case PaymentRequestStatus.Refunded: response.PaymentStatus = PaymentRequestPublicStatuses.RefundConfirmed; response.RefundRequest = Mapper.Map <RefundRequestResponseModel>(src.Refund); break; default: throw new Exception("Unknown payment request status"); } return(response); }