public AmazonPayApiData ParseNotification(HttpRequestBase request) { string json = null; using (var reader = new StreamReader(request.InputStream)) { json = reader.ReadToEnd(); } var parser = new OffAmazonPaymentsNotifications.NotificationsParser(); var message = parser.ParseRawMessage(request.Headers, json); var data = new AmazonPayApiData() { MessageType = message.NotificationType.ToString(), MessageId = ((OffAmazonPaymentsNotifications.IpnNotificationMetadata)message.NotificationMetadata).NotificationReferenceId }; if (message.NotificationType == OffAmazonPaymentsNotifications.NotificationType.AuthorizationNotification) { var details = ((OffAmazonPaymentsNotifications.AuthorizationNotification)message).AuthorizationDetails; data.AuthorizationId = details.AmazonAuthorizationId; data.CaptureId = details.IdList.SafeGet(0); data.ReferenceId = details.AuthorizationReferenceId; data.CaptureNow = details.CaptureNow; data.Creation = details.CreationTimestamp; if (details.AuthorizationFee != null) data.Fee = new AmazonPayApiPrice(details.AuthorizationFee.Amount, details.AuthorizationFee.CurrencyCode); if (details.AuthorizationAmount != null) data.AuthorizedAmount = new AmazonPayApiPrice(details.AuthorizationAmount.Amount, details.AuthorizationAmount.CurrencyCode); if (details.CapturedAmount != null) data.CapturedAmount = new AmazonPayApiPrice(details.CapturedAmount.Amount, details.CapturedAmount.CurrencyCode); if (details.ExpirationTimestampSpecified) data.Expiration = details.ExpirationTimestamp; if (details.AuthorizationStatus != null) { data.ReasonCode = details.AuthorizationStatus.ReasonCode; data.ReasonDescription = details.AuthorizationStatus.ReasonDescription; data.State = details.AuthorizationStatus.State; data.StateLastUpdate = details.AuthorizationStatus.LastUpdateTimestamp; } } else if (message.NotificationType == OffAmazonPaymentsNotifications.NotificationType.CaptureNotification) { var details = ((OffAmazonPaymentsNotifications.CaptureNotification)message).CaptureDetails; data.CaptureId = details.AmazonCaptureId; data.ReferenceId = details.CaptureReferenceId; data.Creation = details.CreationTimestamp; if (details.CaptureFee != null) data.Fee = new AmazonPayApiPrice(details.CaptureFee.Amount, details.CaptureFee.CurrencyCode); if (details.CaptureAmount != null) data.CapturedAmount = new AmazonPayApiPrice(details.CaptureAmount.Amount, details.CaptureAmount.CurrencyCode); if (details.RefundedAmount != null) data.RefundedAmount = new AmazonPayApiPrice(details.RefundedAmount.Amount, details.RefundedAmount.CurrencyCode); if (details.CaptureStatus != null) { data.ReasonCode = details.CaptureStatus.ReasonCode; data.ReasonDescription = details.CaptureStatus.ReasonDescription; data.State = details.CaptureStatus.State; data.StateLastUpdate = details.CaptureStatus.LastUpdateTimestamp; } } else if (message.NotificationType == OffAmazonPaymentsNotifications.NotificationType.RefundNotification) { var details = ((OffAmazonPaymentsNotifications.RefundNotification)message).RefundDetails; data.RefundId = details.AmazonRefundId; data.ReferenceId = details.RefundReferenceId; data.Creation = details.CreationTimestamp; if (details.FeeRefunded != null) data.Fee = new AmazonPayApiPrice(details.FeeRefunded.Amount, details.FeeRefunded.CurrencyCode); if (details.RefundAmount != null) data.RefundedAmount = new AmazonPayApiPrice(details.RefundAmount.Amount, details.RefundAmount.CurrencyCode); if (details.RefundStatus != null) { data.ReasonCode = details.RefundStatus.ReasonCode; data.ReasonDescription = details.RefundStatus.ReasonDescription; data.State = details.RefundStatus.State; data.StateLastUpdate = details.RefundStatus.LastUpdateTimestamp; } } return data; }
public string ToInfoString(AmazonPayApiData data) { var sb = new StringBuilder(); try { string[] strings = _localizationService.GetResource("Plugins.Payments.AmazonPay.MessageStrings").SplitSafe(";"); string state = data.State.Grow(data.ReasonCode, " "); if (data.ReasonDescription.HasValue()) state = "{0} ({1})".FormatWith(state, data.ReasonDescription); sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.MessageTyp), data.MessageType.NaIfEmpty())); sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.State), state)); var stateDate = _dateTimeHelper.ConvertToUserTime(data.StateLastUpdate, DateTimeKind.Utc); sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.StateUpdate), stateDate.ToString())); sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.MessageId), data.MessageId.NaIfEmpty())); if (data.AuthorizationId.HasValue()) sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.AuthorizationID), data.AuthorizationId)); if (data.CaptureId.HasValue()) sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.CaptureID), data.CaptureId)); if (data.RefundId.HasValue()) sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.RefundID), data.RefundId)); sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.ReferenceID), data.ReferenceId.NaIfEmpty())); if (data.Fee != null && data.Fee.Amount != 0.0) { bool isSigned = (data.MessageType.IsCaseInsensitiveEqual("RefundNotification") || data.MessageType.IsCaseInsensitiveEqual("GetRefundDetails")); sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.Fee), (isSigned ? "-" : "") + data.Fee.ToString())); } if (data.AuthorizedAmount != null && data.AuthorizedAmount.Amount != 0.0) sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.AuthorizedAmount), data.AuthorizedAmount.ToString())); if (data.CapturedAmount != null && data.CapturedAmount.Amount != 0.0) sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.CapturedAmount), data.CapturedAmount.ToString())); if (data.RefundedAmount != null && data.RefundedAmount.Amount != 0.0) sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.RefundedAmount), data.RefundedAmount.ToString())); if (data.CaptureNow.HasValue) sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.CaptureNow), data.CaptureNow.Value.ToString())); var creationDate = _dateTimeHelper.ConvertToUserTime(data.Creation, DateTimeKind.Utc); sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.Creation), creationDate.ToString())); if (data.Expiration.HasValue) { var expirationDate = _dateTimeHelper.ConvertToUserTime(data.Expiration.Value, DateTimeKind.Utc); sb.AppendLine("{0}: {1}".FormatWith(strings.SafeGet((int)AmazonPayMessage.Expiration), expirationDate.ToString())); } } catch (Exception exc) { exc.Dump(); } return sb.ToString(); }
public AuthorizationDetails GetAuthorizationDetails(AmazonPayClient client, string authorizationId, out AmazonPayApiData data) { data = new AmazonPayApiData(); AuthorizationDetails details = null; var request = new GetAuthorizationDetailsRequest(); request.SellerId = client.Settings.SellerId; request.AmazonAuthorizationId = authorizationId; var response = client.Service.GetAuthorizationDetails(request); if (response.IsSetGetAuthorizationDetailsResult()) { var result = response.GetAuthorizationDetailsResult; if (result != null && result.IsSetAuthorizationDetails()) details = result.AuthorizationDetails; } try { data.MessageType = "GetAuthorizationDetails"; if (response.IsSetResponseMetadata() && response.ResponseMetadata.IsSetRequestId()) data.MessageId = response.ResponseMetadata.RequestId; if (details != null) { if (details.IsSetAmazonAuthorizationId()) data.AuthorizationId = details.AmazonAuthorizationId; if (details.IsSetAuthorizationReferenceId()) data.ReferenceId = details.AuthorizationReferenceId; if (details.IsSetIdList() && details.IdList.IsSetmember()) data.CaptureId = (details.IdList.member != null && details.IdList.member.Count > 0 ? details.IdList.member[0] : null); if (details.IsSetAuthorizationFee()) data.Fee = new AmazonPayApiPrice(details.AuthorizationFee.Amount, details.AuthorizationFee.CurrencyCode); if (details.IsSetAuthorizationAmount()) data.AuthorizedAmount = new AmazonPayApiPrice(details.AuthorizationAmount.Amount, details.AuthorizationAmount.CurrencyCode); if (details.IsSetCapturedAmount()) data.CapturedAmount = new AmazonPayApiPrice(details.CapturedAmount.Amount, details.CapturedAmount.CurrencyCode); if (details.IsSetCaptureNow()) data.CaptureNow = details.CaptureNow; if (details.IsSetCreationTimestamp()) data.Creation = details.CreationTimestamp; if (details.IsSetExpirationTimestamp()) data.Expiration = details.ExpirationTimestamp; if (details.IsSetAuthorizationStatus()) { data.ReasonCode = details.AuthorizationStatus.ReasonCode; data.ReasonDescription = details.AuthorizationStatus.ReasonDescription; data.State = details.AuthorizationStatus.State.ToString(); data.StateLastUpdate = details.AuthorizationStatus.LastUpdateTimestamp; } } } catch (Exception exc) { exc.Dump(); } return details; }
public RefundDetails GetRefundDetails(AmazonPayClient client, string refundId, out AmazonPayApiData data) { data = new AmazonPayApiData(); RefundDetails details = null; var request = new GetRefundDetailsRequest(); request.SellerId = client.Settings.SellerId; request.AmazonRefundId = refundId; var response = client.Service.GetRefundDetails(request); if (response != null && response.IsSetGetRefundDetailsResult()) { var result = response.GetRefundDetailsResult; if (result != null && result.IsSetRefundDetails()) details = result.RefundDetails; } try { data.MessageType = "GetRefundDetails"; if (response.IsSetResponseMetadata() && response.ResponseMetadata.IsSetRequestId()) data.MessageId = response.ResponseMetadata.RequestId; if (details != null) { if (details.IsSetAmazonRefundId()) data.RefundId = details.AmazonRefundId; if (details.IsSetRefundReferenceId()) data.ReferenceId = details.RefundReferenceId; if (details.IsSetFeeRefunded()) data.Fee = new AmazonPayApiPrice(details.FeeRefunded.Amount, details.FeeRefunded.CurrencyCode); if (details.IsSetRefundAmount()) data.RefundedAmount = new AmazonPayApiPrice(details.RefundAmount.Amount, details.RefundAmount.CurrencyCode); if (details.IsSetCreationTimestamp()) data.Creation = details.CreationTimestamp; if (details.IsSetRefundStatus()) { data.ReasonCode = details.RefundStatus.ReasonCode; data.ReasonDescription = details.RefundStatus.ReasonDescription; data.State = details.RefundStatus.State.ToString(); data.StateLastUpdate = details.RefundStatus.LastUpdateTimestamp; } } } catch (Exception exc) { exc.Dump(); } return details; }
public void DataPollingTaskProcess() { try { // ignore cancelled and completed (paid and shipped) orders. ignore old orders too. var data = new AmazonPayApiData(); int pollingMaxOrderCreationDays = _services.Settings.GetSettingByKey<int>("AmazonPaySettings.PollingMaxOrderCreationDays", 31); var isTooOld = DateTime.UtcNow.AddDays(-(pollingMaxOrderCreationDays)); var query = from x in _orderRepository.Table where x.PaymentMethodSystemName == AmazonPayCore.SystemName && x.CreatedOnUtc > isTooOld && !x.Deleted && x.OrderStatusId < (int)OrderStatus.Complete && x.PaymentStatusId != (int)PaymentStatus.Voided orderby x.Id descending select x; var orders = query.ToList(); //"- start polling {0} orders".FormatWith(orders.Count).Dump(); foreach (var order in orders) { try { var client = new AmazonPayClient(_services.Settings.LoadSetting<AmazonPaySettings>(order.StoreId)); if (client.Settings.DataFetching == AmazonPayDataFetchingType.Polling) { if (order.AuthorizationTransactionId.HasValue()) { var details = _api.GetAuthorizationDetails(client, order.AuthorizationTransactionId, out data); ProcessAuthorizationResult(client, order, data, details); } if (order.CaptureTransactionId.HasValue()) { if (_orderProcessingService.CanMarkOrderAsPaid(order) || _orderProcessingService.CanVoidOffline(order) || _orderProcessingService.CanRefundOffline(order) || _orderProcessingService.CanPartiallyRefundOffline(order, 0.01M)) { var details = _api.GetCaptureDetails(client, order.CaptureTransactionId, out data); ProcessCaptureResult(client, order, data); if (_orderProcessingService.CanRefundOffline(order) || _orderProcessingService.CanPartiallyRefundOffline(order, 0.01M)) { // note status polling: we cannot use GetRefundDetails to reflect refund(s) made at Amazon seller central cause we // do not have any refund-id and there is no api endpoint that serves them. so we only can process CaptureDetails.RefundedAmount. ProcessRefundResult(client, order, data); } } } } } catch (OffAmazonPaymentsServiceException exc) { LogAmazonError(exc); } catch (Exception exc) { LogError(exc); } } } catch (OffAmazonPaymentsServiceException exc) { LogAmazonError(exc); } catch (Exception exc) { LogError(exc); } }
private void ProcessRefundResult(AmazonPayClient client, Order order, AmazonPayApiData data) { if (data.State.IsCaseInsensitiveEqual("Pending")) return; if (data.RefundedAmount != null && data.RefundedAmount.Amount != 0.0) // totally refunded amount { // we could only process it once cause otherwise order.RefundedAmount would getting wrong. if (order.RefundedAmount == decimal.Zero) { decimal refundAmount = Convert.ToDecimal(data.RefundedAmount.Amount); decimal receivable = order.OrderTotal - refundAmount; if (receivable <= decimal.Zero) { if (_orderProcessingService.CanRefundOffline(order)) { _orderProcessingService.RefundOffline(order); if (client.Settings.DataFetching == AmazonPayDataFetchingType.Polling) AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); } } else { if (_orderProcessingService.CanPartiallyRefundOffline(order, refundAmount)) { _orderProcessingService.PartiallyRefundOffline(order, refundAmount); if (client.Settings.DataFetching == AmazonPayDataFetchingType.Polling) AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); } } } } if (client.Settings.DataFetching == AmazonPayDataFetchingType.Ipn) AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); }
private void ProcessCaptureResult(AmazonPayClient client, Order order, AmazonPayApiData data) { if (data.State.IsCaseInsensitiveEqual("Pending")) return; string newResult = data.State.Grow(data.ReasonCode, " "); if (data.State.IsCaseInsensitiveEqual("Completed") && _orderProcessingService.CanMarkOrderAsPaid(order)) { _orderProcessingService.MarkOrderAsPaid(order); CloseOrderReference(client.Settings, order); } else if (data.State.IsCaseInsensitiveEqual("Declined") && _orderProcessingService.CanVoidOffline(order)) { if (!GetAuthorizationState(client, order.AuthorizationTransactionId).IsCaseInsensitiveEqual("Open")) { _orderProcessingService.VoidOffline(order); } } if (!newResult.IsCaseInsensitiveEqual(order.CaptureTransactionResult)) { order.CaptureTransactionResult = newResult; _orderService.UpdateOrder(order); AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); } }
private void ProcessAuthorizationResult(AmazonPayClient client, Order order, AmazonPayApiData data, OffAmazonPaymentsService.Model.AuthorizationDetails details) { string formattedAddress; var orderAttribute = DeserializeOrderAttribute(order); if (!orderAttribute.IsBillingAddressApplied) { if (_api.FulfillBillingAddress(client.Settings, order, details, out formattedAddress)) { AddOrderNote(client.Settings, order, AmazonPayOrderNote.BillingAddressApplied, formattedAddress); orderAttribute.IsBillingAddressApplied = true; SerializeOrderAttribute(orderAttribute, order); } else if (formattedAddress.HasValue()) { AddOrderNote(client.Settings, order, AmazonPayOrderNote.BillingAddressCountryNotAllowed, formattedAddress); orderAttribute.IsBillingAddressApplied = true; SerializeOrderAttribute(orderAttribute, order); } } if (data.State.IsCaseInsensitiveEqual("Pending")) return; string newResult = data.State.Grow(data.ReasonCode, " "); if (_orderProcessingService.CanMarkOrderAsAuthorized(order)) { _orderProcessingService.MarkAsAuthorized(order); } if (data.State.IsCaseInsensitiveEqual("Closed") && data.ReasonCode.IsCaseInsensitiveEqual("OrderReferenceCanceled") && _orderProcessingService.CanVoidOffline(order)) { _orderProcessingService.VoidOffline(order); // cancelation at amazon seller central } if (!newResult.IsCaseInsensitiveEqual(order.AuthorizationTransactionResult)) { order.AuthorizationTransactionResult = newResult; if (order.CaptureTransactionId.IsNullOrEmpty() && data.CaptureId.HasValue()) order.CaptureTransactionId = data.CaptureId; // captured at amazon seller central _orderService.UpdateOrder(order); AddOrderNote(client.Settings, order, AmazonPayOrderNote.AmazonMessageProcessed, _api.ToInfoString(data)); } }
private Order FindOrder(AmazonPayApiData data) { Order order = null; string errorId = null; if (data.MessageType.IsCaseInsensitiveEqual("AuthorizationNotification")) { if ((order = _orderService.GetOrderByPaymentAuthorization(AmazonPayCore.SystemName, data.AuthorizationId)) == null) errorId = "AuthorizationId {0}".FormatWith(data.AuthorizationId); } else if (data.MessageType.IsCaseInsensitiveEqual("CaptureNotification")) { if ((order = _orderService.GetOrderByPaymentCapture(AmazonPayCore.SystemName, data.CaptureId)) == null) order = _orderRepository.GetOrderByAmazonId(data.AnyAmazonId); if (order == null) errorId = "CaptureId {0}".FormatWith(data.CaptureId); } else if (data.MessageType.IsCaseInsensitiveEqual("RefundNotification")) { var attribute = _genericAttributeService.GetAttributes(AmazonPayCore.AmazonPayRefundIdKey, "Order") .Where(x => x.Value == data.RefundId) .FirstOrDefault(); if (attribute == null || (order = _orderService.GetOrderById(attribute.EntityId)) == null) order = _orderRepository.GetOrderByAmazonId(data.AnyAmazonId); if (order == null) errorId = "RefundId {0}".FormatWith(data.RefundId); } if (errorId.HasValue()) Logger.InsertLog(LogLevel.Warning, T("Plugins.Payments.AmazonPay.OrderNotFound", errorId), ""); return order; }