public void Handle(OrderStatusChanged @event) { if (@event.IsCompleted) { var order = _orderDao.FindById(@event.SourceId); var orderStatus = _orderDao.FindOrderStatusById(@event.SourceId); var pairingInfo = _orderDao.FindOrderPairingById(@event.SourceId); var account = _accountDao.FindById(order.AccountId); if (_serverSettings.GetPaymentSettings(order.CompanyKey).PaymentMode == PaymentMethod.RideLinqCmt) { // Check if card declined InitializeCmtServiceClient(); if (CmtErrorCodes.IsTerminalError(orderStatus.PairingError)) { // Terminal error, no need to react to paymentFailure. return; } var trip = _cmtTripInfoServiceHelper.CheckForTripEndErrors(pairingInfo.PairingToken); if (trip != null && trip.ErrorCode == CmtErrorCodes.CardDeclined) { _commandBus.Send(new ReactToPaymentFailure { AccountId = order.AccountId, OrderId = order.Id, IBSOrderId = order.IBSOrderId, CreditCardId = account.DefaultCreditCard.GetValueOrDefault(), TransactionId = orderStatus.OrderId.ToString().Split('-').FirstOrDefault(), // Use first part of GUID to display to user OverdueAmount = Convert.ToDecimal(@event.Fare + @event.Tax + @event.Tip + @event.Toll), TransactionDate = @event.EventDate }); return; } // Since RideLinqCmt payment is processed automatically by CMT, we have to charge booking fees separately _feeService.ChargeBookingFeesIfNecessary(orderStatus); } // If the user has decided not to pair (paying the ride in car instead), // we have to void the amount that was preauthorized if (_serverSettings.GetPaymentSettings(order.CompanyKey).PaymentMode != PaymentMethod.RideLinqCmt && (order.Settings.ChargeTypeId == ChargeTypes.CardOnFile.Id || order.Settings.ChargeTypeId == ChargeTypes.PayPal.Id) && (pairingInfo == null || pairingInfo.WasUnpaired) && !orderStatus.IsPrepaid) //prepaid order will never have a pairing info { // void the preauthorization to prevent misuse fees _paymentService.VoidPreAuthorization(order.CompanyKey, @event.SourceId); } } }
public PairingResponse Pair(string companyKey, Guid orderId, string cardToken, int autoTipPercentage) { try { if (_serverPaymentSettings.PaymentMode == PaymentMethod.RideLinqCmt) { // CMT RideLinq flow var orderStatusDetail = _orderDao.FindOrderStatusById(orderId); if (orderStatusDetail == null) { throw new Exception("Order not found"); } var pairingMethod = _serverPaymentSettings.CmtPaymentSettings.PairingMethod; if (pairingMethod == RideLinqPairingMethod.NotSet && companyKey.HasValueTrimmed()) { // we are on a company that wasn't migrated to the new pairing method setting, use the old one pairingMethod = _serverPaymentSettings.CmtPaymentSettings.UsePairingCode ? RideLinqPairingMethod.PairingCode : RideLinqPairingMethod.VehicleMedallion; } if (pairingMethod == RideLinqPairingMethod.PairingCode && !orderStatusDetail.RideLinqPairingCode.HasValue()) { // We haven't received the pairing code from IBS yet, set the ignore response false // so that the caller can exit without interpreting the response as a failure return(new PairingResponse { IgnoreResponse = true }); } _logger.LogMessage("Starting pairing with RideLinq for Order {0}", orderId); if (orderStatusDetail.IBSOrderId == null) { throw new Exception("Order has no IBSOrderId"); } // We need to extract the errorCode and resend it as a pairing response failed if necessary to prevent redoing a pairing after terminal error. var savedPairingErrorCode = CmtErrorCodes.ExtractTerminalError(orderStatusDetail.PairingError); if (savedPairingErrorCode.HasValue) { _logger.LogMessage("An attempt to pair order {0} after previous pairing ended in terminal error has been detected. Returning original pairing error {1}.", orderStatusDetail.OrderId, savedPairingErrorCode); return(new PairingResponse { IsSuccessful = false, ErrorCode = savedPairingErrorCode }); } var response = PairWithVehicleUsingRideLinq(pairingMethod, orderStatusDetail, cardToken, autoTipPercentage); if (response.ErrorCode.HasValue) { return(new PairingResponse { IsSuccessful = false, ErrorCode = response.ErrorCode }); } // send a command to save the pairing state for this order _commandBus.Send(new PairForPayment { OrderId = orderId, Medallion = response.Medallion, DriverId = response.DriverId.ToString(), PairingToken = response.PairingToken, PairingCode = response.PairingCode, TokenOfCardToBeUsedForPayment = cardToken, AutoTipPercentage = autoTipPercentage }); return(new PairingResponse { IsSuccessful = true, Message = "Success", PairingToken = response.PairingToken, PairingCode = response.PairingCode, Medallion = response.Medallion, TripId = response.TripId, DriverId = response.DriverId }); } else { // Normal CMT flow _pairingService.Pair(orderId, cardToken, autoTipPercentage); return(new PairingResponse { IsSuccessful = true, Message = "Success" }); } } catch (Exception e) { _logger.LogError(e); return(new PairingResponse { IsSuccessful = false, Message = e.Message, ErrorCode = CmtErrorCodes.UnableToPair }); } }
public void Handle(OrderStatusChanged @event) { if (@event.IsCompleted) { if (@event.Status.IsPrepaid) { // Send receipt for PrePaid // No tolls and surcharge for prepaid orders SendTripReceipt(@event.SourceId, Convert.ToDecimal(@event.Fare ?? 0), Convert.ToDecimal(@event.Tip ?? 0), Convert.ToDecimal(@event.Tax ?? 0)); } else { var order = _orderDao.FindById(@event.SourceId); var pairingInfo = _orderDao.FindOrderPairingById(@event.SourceId); var orderStatus = _orderDao.FindOrderStatusById(@event.SourceId); if (CmtErrorCodes.IsTerminalError(orderStatus.PairingError)) { return; } if (order.Settings.ChargeTypeId == ChargeTypes.PaymentInCar.Id) { // Send receipt for Pay in Car SendTripReceipt(@event.SourceId, Convert.ToDecimal(@event.Fare ?? 0), Convert.ToDecimal(@event.Tip ?? 0), Convert.ToDecimal(@event.Tax ?? 0), toll: Convert.ToDecimal(@event.Toll ?? 0), surcharge: Convert.ToDecimal(@event.Surcharge ?? 0)); } else if (pairingInfo != null && pairingInfo.DriverId.HasValue() && pairingInfo.Medallion.HasValue() && pairingInfo.PairingToken.HasValue()) { // Send receipt for CMTRideLinq InitializeCmtServiceClient(order.CompanyKey); var tripInfo = _cmtTripInfoServiceHelper.GetTripInfo(pairingInfo.PairingToken); if (tripInfo != null && !tripInfo.ErrorCode.HasValue && tripInfo.EndTime.HasValue) { var tollHistory = tripInfo.TollHistory != null ? tripInfo.TollHistory.Sum(p => p.TollAmount) : 0; var meterAmount = Math.Round(((double)tripInfo.Fare / 100), 2); var tollAmount = Math.Round(((double)tollHistory / 100), 2); var tipAmount = Math.Round(((double)tripInfo.Tip / 100), 2); var taxAmount = Math.Round(((double)tripInfo.Tax / 100), 2); var surchargeAmount = Math.Round(((double)tripInfo.Surcharge / 100), 2); var extraAmount = Math.Round(((double)tripInfo.Extra / 100), 2); var accessFee = Math.Round(((double)tripInfo.AccessFee / 100), 2); var fareAtAlternateRate = Math.Round(((double)tripInfo.FareAtAlternateRate / 100), 2); var tolls = new List <TollDetail>(); if (tripInfo.TollHistory != null) { tolls.AddRange(tripInfo.TollHistory.Select(toll => new TollDetail { TollName = toll.TollName, TollAmount = toll.TollAmount })); } SendTripReceipt(@event.SourceId, Convert.ToDecimal(meterAmount), Convert.ToDecimal(tipAmount), Convert.ToDecimal(taxAmount), extra: Convert.ToDecimal(extraAmount), toll: Convert.ToDecimal(tollAmount), surcharge: Convert.ToDecimal(surchargeAmount), cmtRideLinqFields: new SendReceipt.CmtRideLinqReceiptFields { DriverId = tripInfo.DriverId.ToString(), PickUpDateTime = tripInfo.StartTime, DropOffDateTime = tripInfo.EndTime, TripId = tripInfo.TripId, Distance = tripInfo.Distance, LastFour = tripInfo.LastFour, AccessFee = accessFee, FareAtAlternateRate = fareAtAlternateRate, RateAtTripEnd = tripInfo.RateAtTripEnd, RateAtTripStart = tripInfo.RateAtTripStart, Tolls = tolls.ToArray(), TipIncentive = order.TipIncentive ?? 0 }); } } } } }