예제 #1
0
        public void When(PaymentCompleted @event)
        {
            switch (State)
            {
            case OrderProcessState.OrderPlaced:
                State = OrderProcessState.PaymentCompleted;

                SendCommand(new DispatchOrder
                {
                    OrderId         = Id,
                    RestaurantId    = RestaurantId,
                    Items           = Items.ToList(),
                    Amount          = Amount,
                    DeliveryAddress = DeliveryAddress
                });
                break;

            // idempotence - same message sent twice
            case OrderProcessState.PaymentCompleted:
                break;

            default:
                throw new InvalidOperationException("Invalid state for this message");
            }
        }
        /// <summary>
        /// Add payment under the ticket using Glance Pay payment as an Omnivore 3rd Party Payment.
        /// </summary>
        /// <param name="ticketId">Ticket unique identifier</param>
        /// <param name="amountToPay">the amount in cents excluding tips to be paid</param>
        /// <param name="tipToPay">The amount of tips to be paid</param>
        /// <param name="tenderType">Identifier of party payment type. It changes depending on POS location.</param>
        /// <param name="typeName">Configurable name of tender type. 3rd_party for Omnivar virtual POS.</param>
        /// <returns>PaymentCompleted DTO</returns>
        public async Task <PaymentCompleted> AddPayment(string locationIdentifier, long transactionId, long ticketId,
                                                        int amountToPay, int tipToPay, string tenderType, string typeName)
        {
            Stopwatch watch;
            string    errorMessage = string.Empty;

#if DEBUG
            watch = Stopwatch.StartNew();
            Logger.LogTrace("RestClient creation.");
#endif

            string resource = string.Format("{0}/tickets/{1}/payments/", locationIdentifier, ticketId.ToString());

            RestClient restClient  = new RestClient(BASE_URI);
            var        restRequest = new RestRequest(resource, Method.POST);

            // Add HTTP Headers
            restRequest.AddHeader("Api-Key", OMNIVORE_API_KEY);
            restRequest.AddHeader("Content-Type", "application/json");

            //Add parameters to body as Json
            restRequest.AddJsonBody(new
            {
                amount      = amountToPay,
                tip         = tipToPay,
                tender_type = tenderType,
                type        = typeName
            });

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            Logger.LogTrace("Omnivore API call start.");
            IRestResponse asyncResp = await restClient.ExecuteTaskAsync(restRequest, cancellationTokenSource.Token);

            Logger.LogTrace("Omnivore API call end.");

            if (asyncResp == null)
            {
                throw new InternalServerErrorException("IRestResponse is null.");
            }

            PaymentCompleted paymentCompleted = null;
            RestResponse     response         = new RestResponse();
            response.Content = asyncResp.Content;
            JsonDeserializer deserializer = new JsonDeserializer();
            paymentCompleted            = deserializer.Deserialize <PaymentCompleted>(response);
            paymentCompleted.Successful = asyncResp.IsSuccessful;

#if DEBUG
            watch.Stop();
            var elapsedMs = watch.ElapsedMilliseconds;
            Logger.LogTrace(string.Format("AddPayment time: {0} msec.", elapsedMs.ToString()));
#endif
            Logger.LogDebug("Communicator: payment end");
            if (!paymentCompleted.Successful)
            {
                ThrowApiException(paymentCompleted);
            }
            return(paymentCompleted);
        }
        private void LogErrorMessage(PaymentCompleted paymentCompleted)
        {
            string errorMessage = paymentCompleted.ToErrorMessage();

            if (!string.IsNullOrEmpty(errorMessage))
            {
                Logger.LogError(errorMessage);
            }
        }
예제 #4
0
        public void Complete()
        {
            if (Status != PaymentStatus.Pending)
            {
                throw new InvalidOperationException($"Completing payment in '{Status}' status is not allowed.");
            }

            var @event = PaymentCompleted.Create(Id, DateTime.UtcNow);

            Enqueue(@event);
            Apply(@event);
        }
        public bool Handle(PaymentCompleted message)
        {
            var pm = _repository.Load(message.OrderId);

            if (pm == null)
            {
                throw new Exception("Could not locate Process Manager instance with id " + message.OrderId);
            }

            pm.When(message);
            _repository.Save(pm);

            return(true);
        }
예제 #6
0
 public void Handle(PaymentCompleted @event)
 {
     if (this.State == ProcessState.ReservationConfirmationReceived)
     {
         this.State = ProcessState.PaymentConfirmationReceived;
         this.AddCommand(new ConfirmOrder {
             OrderId = this.OrderId
         });
     }
     else
     {
         throw new InvalidOperationException("Cannot handle payment confirmation at this stage.");
     }
 }
예제 #7
0
 public Task HandleAsync(PaymentCompleted evnt)
 {
     return(TryUpdateRecordAsync(connection =>
     {
         return connection.UpdateAsync(new
         {
             State = (int)PaymentState.Completed,
             Version = evnt.Version
         }, new
         {
             Id = evnt.AggregateRootId,
             Version = evnt.Version - 1
         }, ConfigSettings.PaymentTable);
     }));
 }
 public void AddPayment(string ticketName, bool isPaid)
 {
     if (isPaid)
     {
         if (PaymentCompleted.MissingKey(ticketName))
         {
             PaymentCompleted[ticketName] = 0;
         }
         PaymentCompleted[ticketName]++;
     }
     else
     {
         PaymentPendingCount++;
     }
 }
예제 #9
0
        public void Complete()
        {
            if (this.State != PaymentStateType.Initiated)
            {
                throw new InvalidOperationException();
            }

            this.State = PaymentStateType.Completed;
            var completed = new PaymentCompleted
            {
                SourceId        = this.Payment.Id,
                PaymentSourceId = this.Payment.PaymentSourceId
            };

            this.AddEvent(completed);
        }
예제 #10
0
 public void Handle(PaymentCompleted @event)
 {
     using (var context = this._contextFactory.Invoke()) {
         var pm = context.Find(x => x.OrderId == @event.PaymentSourceId);
         if (pm != null)
         {
             pm.Handle(@event);
             context.Save(pm);
         }
         else
         {
             Trace.TraceError(
                 "Failed to locate the registration process manager handling the paid order with id {0}.",
                 @event.PaymentSourceId);
         }
     }
 }
        public void Handle(PaymentCompleted @event)
        {
            // TODO: should not skip the completed processes and try to re-acquire the reservation,
            // and if not possible due to not enough seats, move them to a "manual intervention" state.
            // This was not implemented but would be very important.
            var pInfo = repository.GetBy(x => x.OrderId == @event.PaymentSourceId).FirstOrDefault();

            if (pInfo != null)
            {
                var manager = new RegistrationProcessManager(pInfo);
                manager.Handle(@event);
                context.RegisterModified(manager.ProcessInfo);
                context.Commit();
            }
            else
            {
                Trace.TraceError("Failed to locate the registration process manager handling the paid order with id {0}.", @event.PaymentSourceId);
            }
        }
        public void Handle(PaymentCompleted @event)
        {
            using (var context = contextFactory.Invoke()) {
                // TODO: should not skip the completed processes and try to re-acquire the reservation,
                // and if not possible due to not enough seats, move them to a "manual intervention" state.
                // This was not implemented but would be very important.
                var pm = context.Find(x => x.OrderId == @event.PaymentSourceId);
                if (pm != null)
                {
                    pm.Handle(@event);

                    context.Save(pm);
                }
                else
                {
                    Trace.TraceError("Failed to locate the registration process manager handling the paid order with id {0}.", @event.PaymentSourceId);
                }
            }
        }
        /// <summary>
        /// Handle errors returned by Omnivore.
        /// <ex>{ "errors": [{"description": "Invalid payment type", "error": "invalid_input", "fields": ["$.type"]}]}</ex>
        /// <ex>{ "errors": [{"description": "Cannot make ticket payment because the ticket is closed.", "error": "ticket_closed"}]}</ex>
        /// </summary>
        /// <param name="paymentCompleted">DTO with payment result data.</param>
        private void ThrowApiException(PaymentCompleted paymentCompleted)
        {
            if (paymentCompleted.Successful)
            {
                return;
            }
            LogErrorMessage(paymentCompleted);
            ErrorSlug errorSlaug = paymentCompleted.Errors.Where(x => !string.IsNullOrEmpty(x.Error)).FirstOrDefault();

            if (errorSlaug == null)
            {
                throw new InternalServerErrorException("No error slug.");
            }

            HttpStatusCode statusCode   = errorSlaug.Error.ToHttpStatusCode();
            ApiException   apiException = statusCode.ToApiException(errorSlaug.Description);

            throw apiException;
        }
예제 #14
0
        public async Task <GSPRPaymentCallback> AddPaymentAsync(string locationIdentifier, long transactionId,
                                                                long ticketId, int amount, int tip, string tenderType, string type)
        {
            string generalErrorMessage = "Cannot add payment.";

            PaymentCompleted response = await communicator.AddPayment(locationIdentifier, transactionId, ticketId, amount, tip, tenderType, type);

            GSPRPaymentCallback calbackDto = new GSPRPaymentCallback()
            {
                TransactionID = transactionId,
                Success       = (response == null) ? false : response.Successful,
            };

            if (!calbackDto.Success)
            {
                logger.LogWarn(generalErrorMessage);
                calbackDto.ErrorMessage = generalErrorMessage;
            }

            return(calbackDto);
        }
예제 #15
0
 public void Consume(PaymentCompleted message)
 {
     Console.WriteLine("Payment completed.");
     State.PaymentCompleted = true;
     DeliverIfDone();
 }
예제 #16
0
        private void PaymentCompleted(PaymentCompleted message)
        {
            var order = Program.system.ActorOf(Props.Create(() => new EmailActor($"{OrderId}")));

            order.Tell(new SendEmailConfirmation());
        }
예제 #17
0
 private void RaiseCartPayedFor()
 {
     PaymentCompleted?.Invoke(this, new CartPayedForEventArgs(CartContents));
     Console.WriteLine("Transaction completed");
 }
예제 #18
0
 void MakePaymentButton_Click(object sender, EventArgs e)
 {
     PaymentCompleted.Invoke(this, new EventArgs());
 }
예제 #19
0
        private void Apply(PaymentCompleted @event)
        {
            Version++;

            Status = PaymentStatus.Completed;
        }