public void InsertStripeEvent(String customerId, String jsonString) { if (customerId == null) { return; } var context = new Models.ApplicationDbContext(); var user = context.Users.Where(u => u.StripeCustomerId == customerId).FirstOrDefault(); if (user == null) { return; } var stripeEventRecord = new StripeEvent { Date = DateTime.Now, Json = jsonString, User = user }; context.StripeEvents.Add(stripeEventRecord); context.SaveChanges(); }
public ActionResult Index() { Stream req = Request.InputStream; req.Seek(0, SeekOrigin.Begin); string json = new StreamReader(req).ReadToEnd(); StripeEvent stripeEvent = null; try { stripeEvent = StripeEventUtility.ParseEvent(json); } catch (Exception ex) { Log.Error().Exception(ex).Message("Unable to parse incoming event.").Report(b => b.AddObject(json, "Event")).Write(); return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Unable to parse incoming event")); } if (stripeEvent == null) { Log.Warn().Message("Null stripe event.").Write(); return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Incoming event empty")); } _stripeEventHandler.HandleEvent(stripeEvent); return(new HttpStatusCodeResult(HttpStatusCode.OK)); }
public override string ProcessRequest(Order order, HttpRequest request, IDictionary <string, string> settings) { string response = ""; try { order.MustNotBeNull("order"); request.MustNotBeNull("request"); settings.MustNotBeNull("settings"); // If in test mode, write out the form data to a text file if (settings.ContainsKey("mode") && settings["mode"] == "test") { LogRequest <Stripe>(request, logPostData: true); } //Stripe supports webhooks StripeEvent stripeEvent = GetStripeEvent(request); StripeCharge charge = Mapper <StripeCharge> .MapFromJson(stripeEvent.Data.Object.ToString()); if (stripeEvent.Type.StartsWith("charge.")) { PaymentState paymentState = GetPaymentState(charge); if (order.TransactionInformation.PaymentState != paymentState) { order.TransactionInformation.TransactionId = charge.Id; order.TransactionInformation.PaymentState = paymentState; order.Save(); } } } catch (Exception exp) { LoggingService.Instance.Error <Stripe>("Stripe(" + order.CartNumber + ") - ProcessRequest", exp); } return(response); }
public void TestProcessEventSynchronously() { var e = new StripeEvent { LiveMode = true, Type = "charge.succeeded", Created = DateTime.Now.AddDays(-1), Data = new StripeEventData { Object = JObject.FromObject(new StripeCharge { Id = "9876" }) } }; var expectedResponse = new StripeEventResponseDTO(); _stripeEventService.Setup(mocked => mocked.ProcessStripeEvent(e)).Returns(expectedResponse); var result = _fixture.ProcessStripeEvent(e); Assert.IsInstanceOf <RestHttpActionResult <StripeEventResponseDTO> >(result); Assert.AreEqual(HttpStatusCode.OK, ((RestHttpActionResult <StripeEventResponseDTO>)result).StatusCode); var dto = ((RestHttpActionResult <StripeEventResponseDTO>)result).Content; Assert.IsNotNull(dto); Assert.AreSame(expectedResponse, dto); _stripeEventService.VerifyAll(); _messageQueueFactory.VerifyAll(); _messageFactory.VerifyAll(); }
protected StripeEvent GetStripeEvent(HttpRequest request) { StripeEvent stripeEvent = null; if (HttpContext.Current.Items["TC_StripeEvent"] != null) { stripeEvent = (StripeEvent)HttpContext.Current.Items["TC_StripeEvent"]; } else { try { if (request.InputStream.CanSeek) { request.InputStream.Seek(0, SeekOrigin.Begin); } using (StreamReader reader = new StreamReader(request.InputStream)) { stripeEvent = StripeEventUtility.ParseEvent(reader.ReadToEnd()); HttpContext.Current.Items["TC_StripeEvent"] = stripeEvent; } } catch { } } return(stripeEvent); }
public override string GetCartNumber(HttpRequest request, IDictionary <string, string> settings) { string cartNumber = ""; try { request.MustNotBeNull("request"); settings.MustNotBeNull("settings"); // If in test mode, write out the form data to a text file if (settings.ContainsKey("mode") && settings["mode"] == "test") { LogRequest <Stripe>(request, logPostData: true); } StripeEvent stripeEvent = GetStripeEvent(request); // We are only interested in charge events if (stripeEvent != null && stripeEvent.Type.StartsWith("charge.")) { StripeCharge stripeCharge = Mapper <StripeCharge> .MapFromJson(stripeEvent.Data.Object.ToString()); cartNumber = stripeCharge.Description; } else { HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.BadRequest; } } catch (Exception exp) { LoggingService.Instance.Error <Stripe>("Stripe - Get cart number", exp); } return(cartNumber); }
private static StripeEvent VerifyEventSentFromStripe(StripeEvent stripeEvent) { var eventService = new StripeEventService(); stripeEvent = eventService.Get(stripeEvent.Id); return(stripeEvent); }
public void TestTransferPaidNoChargesFound() { var e = new StripeEvent { LiveMode = true, Type = "transfer.paid", Created = DateTime.Now.AddDays(-1), Data = new StripeEventData { Object = JObject.FromObject(new StripeTransfer { Id = "tx9876", }) } }; _donationService.Setup(mocked => mocked.GetDepositByProcessorTransferId("tx9876")).Returns((DepositDTO)null); _paymentProcessorService.Setup(mocked => mocked.GetChargesForTransfer("tx9876")).Returns(new List <StripeCharge>()); var result = _fixture.ProcessStripeEvent(e); Assert.IsNotNull(_fixture.ProcessStripeEvent(e)); Assert.IsInstanceOf <TransferPaidResponseDTO>(result); var tp = (TransferPaidResponseDTO)result; Assert.AreEqual(0, tp.TotalTransactionCount); Assert.AreEqual(0, tp.SuccessfulUpdates.Count); Assert.AreEqual(0, tp.FailedUpdates.Count); _paymentProcessorService.VerifyAll(); _donationService.VerifyAll(); }
/// <summary> /// Stores id of event to signify that the event has /// already been processed. /// </summary> /// <param name="stripeEvent"></param> public void InsertProcessedEvent(StripeEvent stripeEvent) { var p = new PaymentStripeEvent { EventId = stripeEvent.Id, }; _paymentStripeEventRepository.Insert(p); }
public ActionResult Index() { Stream request = Request.InputStream; request.Seek(0, SeekOrigin.Begin); string json = new StreamReader(request).ReadToEnd(); StripeEvent stripeEvent = null; try { stripeEvent = StripeEventUtility.ParseEvent(json); } catch (Exception e) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, string.Format("Unable to parse incoming event. The following error occured: {0}", e.Message))); } if (stripeEvent == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Incoming event empty")); } var emailService = new Services.EmailService(); switch (stripeEvent.Type) { case StripeEvents.ChargeRefunded: var charge = Mapper <StripeCharge> .MapFromJson(stripeEvent.Data.Object.ToString()); emailService.SendRefundEmail(charge); break; case StripeEvents.CustomerSubscriptionTrialWillEnd: var subscription = Mapper <StripeSubscription> .MapFromJson(stripeEvent.Data.Object.ToString()); emailService.SendTrialEndEmail(subscription); break; case StripeEvents.InvoicePaymentSucceeded: StripeInvoice invoice = Mapper <StripeInvoice> .MapFromJson(stripeEvent.Data.Object.ToString()); var customer = StripeCustomerService.Get(invoice.CustomerId); var user = UserManager.FindByEmail(customer.Email); user.ActiveUntil = user.ActiveUntil.AddMonths(1); UserManager.Update(user); emailService.SendSubscriptionPaymentReceiptEmail(invoice, customer); break; default: break; } return(new HttpStatusCodeResult(HttpStatusCode.OK)); }
public void ProcessEvent(StripeEvent stripeEvent) { // process event //balance.available //charge.dispute.created //charge.dispute.closed //charge.dispute.updated // charge.refund.updated }
public ActionResult Index() { // MVC3/4: Since Content-Type is application/json in HTTP POST from Stripe // we need to pull POST body from request stream directly Stream req = Request.InputStream; req.Seek(0, System.IO.SeekOrigin.Begin); string json = new StreamReader(req).ReadToEnd(); StripeEvent stripeEvent = null; WebhookEntities entity = new WebhookEntities(); entity.Logs.Add(new Log() { Info = "Webhook Received" }); entity.SaveChanges(); try { // as in header, you need https://github.com/jaymedavis/stripe.net // it's a great library that should have been offered by Stripe directly stripeEvent = StripeEventUtility.ParseEvent(json); } catch (Exception ex) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Unable to parse incoming event")); } if (stripeEvent == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Incoming event empty")); } entity.StripeWebhooks.Add(new StripeWebhook() { EventKey = stripeEvent.Id, EventType = stripeEvent.Type }); entity.SaveChanges(); switch (stripeEvent.Type) { case "charge.refunded": // do work break; case "customer.subscription.updated": case "customer.subscription.deleted": case "customer.subscription.created": // do work break; } return(new HttpStatusCodeResult(HttpStatusCode.OK)); }
public void RecordFailedEvent(StripeEvent stripeEvent, StripeEventResponseDTO stripeEventResponse) { try { _donationService.CreatePaymentProcessorEventError(stripeEvent, stripeEventResponse); } catch (Exception e) { _logger.Error("Error writing event to failure log", e); } }
public void it_should_validate_with_right_data() { // A timestamp within the default tolerance of 300 seconds int ReasonablyCloseTime = fixture.EventTimestamp + 120; ConstructedEvent = StripeEventUtility.ConstructEvent(fixture.StripeJson, fixture.StripeSignature, fixture.StripeSecret, ReasonablyCloseTime); ConstructedEvent.Should().NotBeNull(); ConstructedEvent.Request.Id.Should().Be("req_FAKE"); ConstructedEvent.Request.IdempotencyKey.Should().Be("placeholder"); ConstructedEvent.Account.Should().Be("acct_CONNECT"); }
public void TestProcessStripeEventNoMatchingEventHandler() { var e = new StripeEvent { LiveMode = true, Type = "not.this.one" }; Assert.IsNull(_fixture.ProcessStripeEvent(e)); _paymentProcessorService.VerifyAll(); _donationService.VerifyAll(); }
public IHttpActionResult ProcessStripeEvent([FromBody] StripeEvent stripeEvent) { if (stripeEvent == null || !ModelState.IsValid) { if (_logger.IsDebugEnabled) { _logger.Debug("Received invalid Stripe event " + stripeEvent); } return(BadRequest(ModelState)); } _logger.Debug("Received Stripe Event " + stripeEvent.Type); if (_liveMode != stripeEvent.LiveMode) { _logger.Debug("Dropping Stripe Event " + stripeEvent.Type + " because LiveMode was " + stripeEvent.LiveMode); return(Ok()); } StripeEventResponseDTO response = null; try { if (_asynchronous) { _logger.Debug("Enqueueing Stripe event " + stripeEvent.Type + " because AsynchronousProcessingMode was true"); var message = _messageFactory.CreateMessage(stripeEvent); _eventQueue.Send(message, MessageQueueTransactionType.None); response = new StripeEventResponseDTO { Message = "Queued event for asynchronous processing" }; } else { _logger.Debug("Processing Stripe event " + stripeEvent.Type + " because AsynchronousProcessingMode was false"); response = _stripeEventService.ProcessStripeEvent(stripeEvent); } } catch (Exception e) { var msg = "Unexpected error processing Stripe Event " + stripeEvent.Type; _logger.Error(msg, e); var responseDto = new StripeEventResponseDTO() { Exception = new ApplicationException(msg, e), Message = msg }; return(RestHttpActionResult <StripeEventResponseDTO> .ServerError(responseDto)); } return(response == null ? Ok() : (IHttpActionResult)RestHttpActionResult <StripeEventResponseDTO> .Ok(response)); }
public async static Task <HttpResponseMessage> HandleStripeEvent(StripeEvent stripeEvent, FortnoxClient fortnoxClient) { if (stripeEvent.Type == StripeEvents.CustomerCreated) { return(await fortnoxClient.HandleCustomerCreatedAsync(Mapper <StripeCustomer> .MapFromJson((String)stripeEvent.Data.Object.ToString()))); } else if (stripeEvent.Type == StripeEvents.InvoiceCreated) { return(await fortnoxClient.HandleInvoiceCreatedAsync(Mapper <StripeInvoice> .MapFromJson((String)stripeEvent.Data.Object.ToString()))); } throw new NotImplementedException($"No handler for {stripeEvent.Type}"); }
public virtual async Task <bool> RegisterEvent(Event stripeEvent, string description) { var newEvent = new StripeEvent { Id = stripeEvent.Id, Description = description }; StripeEvent eventSaved = await eventsBL.Save(newEvent, processInfo); if (eventSaved != null) { return(true); } return(false); }
public void ProcessRequest(HttpContext context) { try { Logs.LogsInsertAction("Stripe subscription attempted"); var json = new StreamReader(context.Request.InputStream).ReadToEnd(); var stripeEvent = StripeEventUtility.ParseEvent(json); switch (stripeEvent.Type) { case StripeEvents.InvoicePaymentSucceeded: // all of the types available are listed in StripeEvents // parse first call StripeInvoice insecureStripeInvoice = Stripe.Mapper <StripeInvoice> .MapFromJson(stripeEvent.Data.Object.ToString()); // just get id and retreive from stripe to prevent spoofing var eventService = new StripeEventService(); StripeRequestOptions requestOptions = new StripeRequestOptions(); requestOptions.ApiKey = Constants.StripeSecretKey; // can't be called more than once (webhooks can send multiple times) requestOptions.IdempotencyKey = stripeEvent.Id; StripeEvent response = eventService.Get(stripeEvent.Id, requestOptions); StripeInvoice stripeInvoice = Stripe.Mapper <StripeInvoice> .MapFromJson(response.Data.Object.ToString()); if (stripeInvoice.Paid) { using (var db = new UniversalGymEntities()) { var user = db.Users.SingleOrDefault(s => s.StripeUrl == stripeInvoice.CustomerId); int charge = stripeInvoice.Total; new creditAdd(db).AddCredit(user, null, charge, charge); Logs.LogsInsertAction( "Stripe subscription successful: " + stripeInvoice.Total + " added to " + user.Email); } } break; } } catch (Exception exception) { Logs.LogsInsertError(exception); } }
public void TestProcessStripeEventLiveModeMismatch() { var e = new StripeEvent { LiveMode = false }; var result = _fixture.ProcessStripeEvent(e); Assert.IsInstanceOf <OkResult>(result); _stripeEventService.VerifyAll(); _messageQueueFactory.VerifyAll(); _messageFactory.VerifyAll(); }
public void it_should_validate_with_right_data() { // Override the event utility to prevent it from looking at UTC now and use a fixed valid timestamp in the past StripeEventUtility.EpochUtcNowOverride = 1493329524; ConstructedEvent = StripeEventUtility.ConstructEvent(fixture.StripeJson, fixture.StripeSignature, fixture.StripeSecret); ConstructedEvent.Should().NotBeNull(); ConstructedEvent.Request.Id.Should().Be("req_FAKE"); ConstructedEvent.Request.IdempotencyKey.Should().Be("placeholder"); ConstructedEvent.Account.Should().Be("acct_CONNECT"); // Clean up to prevent unexpected behaviour in other facts StripeEventUtility.EpochUtcNowOverride = null; }
public Task <DomainEvent> GetAsync(DomainEvent e) { return(Task.Run(() => { try { StripeEvent eventObject = _service.Get(e.Id); return Task.FromResult(_mapper.Map <StripeEvent, DomainEvent>(eventObject)); } catch (StripeException ex) { throw new BillingException(string.Format("Failed to get billing event data by id {0}: {1}", e.Id, ex)); } })); }
public void TestInvoicePaymentFailedNoCancel() { const string processorId = "cus_123"; const string id = "9876"; const string subscriptionId = "sub_123"; const string chargeId = "ch_2468"; const int recurringGiftId = 123456; var e = new StripeEvent { LiveMode = true, Type = "invoice.payment_failed", Created = DateTime.Now.AddDays(-1), Data = new StripeEventData { Object = JObject.FromObject(new StripeInvoice() { Id = id, Customer = processorId, Charge = chargeId, Subscription = subscriptionId }) } }; var gift = new MpCreateDonationDistDto { Frequency = 1, RecurringGiftId = recurringGiftId, StripeCustomerId = processorId }; var charge = new StripeCharge { Id = chargeId, FailureMessage = "Your card was declined.", FailureCode = "card_declined" }; _paymentProcessorService.Setup(m => m.GetCharge(It.IsAny <string>())).Returns(charge); _mpDonorService.Setup(mocked => mocked.ProcessRecurringGiftDecline(subscriptionId, "card_declined: Your card was declined.")); _mpDonorService.Setup(mocked => mocked.GetRecurringGiftForSubscription(subscriptionId, "")).Returns(gift); Assert.IsNull(_fixture.ProcessStripeEvent(e)); _fixture.ProcessStripeEvent(e); _mpDonorService.VerifyAll(); }
public StripeEventResponseDTO ProcessStripeEvent(StripeEvent stripeEvent) { StripeEventResponseDTO response = null; try { switch (stripeEvent.Type) { case "charge.succeeded": ChargeSucceeded(stripeEvent.Created, ParseStripeEvent <StripeCharge>(stripeEvent.Data)); break; case "charge.failed": ChargeFailed(stripeEvent.Created, ParseStripeEvent <StripeCharge>(stripeEvent.Data)); break; case "transfer.paid": response = TransferPaid(stripeEvent.Created, ParseStripeEvent <StripeTransfer>(stripeEvent.Data)); break; case "invoice.payment_succeeded": InvoicePaymentSucceeded(stripeEvent.Created, ParseStripeEvent <StripeInvoice>(stripeEvent.Data)); break; case "invoice.payment_failed": InvoicePaymentFailed(stripeEvent.Created, ParseStripeEvent <StripeInvoice>(stripeEvent.Data)); break; default: _logger.Debug("Ignoring event " + stripeEvent.Type); break; } if (response?.Exception != null) { RecordFailedEvent(stripeEvent, response); } } catch (Exception e) { response = new StripeEventResponseDTO { Exception = new ApplicationException("Problem processing Stripe event", e) }; RecordFailedEvent(stripeEvent, response); throw; } return(response); }
public when_constructing_an_event() { StripeJson = new StreamReader( typeof(when_constructing_an_event).GetTypeInfo().Assembly.GetManifestResourceStream("Stripe.Tests.XUnit.events.event.json"), Encoding.UTF8 ).ReadToEnd(); // this throws an error because the tolerance was higher than allowed // ConstructedEvent = StripeEventUtility.ConstructEvent(StripeJson, StripeSignature, StripeSecret); // override the event utility from looking at utc now to 300 seconds in front of the timestamp in the header StripeEventUtility.EpochUtcNowOverride = 1493329524; ConstructedEvent = StripeEventUtility.ConstructEvent(StripeJson, StripeSignature, StripeSecret); // this throws an error that the signature doesn't match one in the headers //ConstructedEventBadJson = StripeEventUtility.ConstructEvent(StripeJson + "/n", StripeSignature, StripeSecret); }
public void TestChargeFailedBankAccountError() { var e = new StripeEvent { LiveMode = true, Type = "charge.failed", Created = DateTime.Now.AddDays(-1), Data = new StripeEventData { Object = JObject.FromObject(new StripeCharge { Id = "9876", FailureCode = "invalid_routing_number", FailureMessage = "description from stripe", Source = new StripeSource() { Object = "bank_account" }, Refunds = new StripeList <StripeRefund> { Data = new List <StripeRefund> { new StripeRefund { Id = "re999" } } } }) } }; var stripeRefund = new StripeRefundData(); _donationService.Setup(mocked => mocked.UpdateDonationStatus("9876", 777, e.Created, "invalid_routing_number: description from stripe")).Returns(123); _donationService.Setup(mocked => mocked.ProcessDeclineEmail("9876")); _paymentProcessorService.Setup(mocked => mocked.GetRefund("re999")).Returns(stripeRefund); _donationService.Setup(mocked => mocked.CreateDonationForBankAccountErrorRefund(It.Is <StripeRefund>(r => r.Data != null && r.Data.Any() && r.Data[0] == stripeRefund))) .Returns(123); Assert.IsNull(_fixture.ProcessStripeEvent(e)); _paymentProcessorService.VerifyAll(); _donationService.VerifyAll(); }
public IActionResult Stripe(string id, string @event, string notificationId, StripeEvent data) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } _logger.LogInformation( 0, $"{nameof(StripeController)} / '{{ReceiverId}}' received a '{{EventType}}' notification (event " + "'{EventName}').", id, data.EventType, @event); _logger.LogInformation( 1, "Data created at '{Created}' and contains Notification ID '{Id}' / '{NotificationId}', Live mode " + "'{DetailsLiveMode}', and Request ID '{RequestId}'.", data.Created, data.Id, notificationId, data.LiveMode, data.Request); var details = data.Data.Object; var created = DateTimeOffset.FromUnixTimeMilliseconds( details.Value <long>(StripeConstants.CreatedPropertyName)); _logger.LogInformation( 2, "Event detail created at '{DetailsCreated}' and contains {PropertyCount} properties, including " + "Account '{Account}', Id '{DetailsId}', Live mode '{DetailsLiveMode}', and Name '{Name}'.", created, details.Count, details.Value <string>("account"), details.Value <string>("id"), details.Value <string>(StripeConstants.LiveModePropertyName), details.Value <string>("name")); return(Ok()); }
public async Task <IActionResult> Stripe([FromBody] StripeEvent stripeEvent) { var result = new StripeBaseCommand(); try { switch (stripeEvent.Type) { case StripeEvents.ChargeRefunded: StripeRefundModel refund = StripeEventUtility.ParseEventDataItem <StripeRefundModel>(stripeEvent.Data.Object); await _stripeSvc.RefundPayment(refund.id, refund.metadata.AccountNumber, refund.amount_refunded); break; case StripeEvents.CustomerSubscriptionUpdated: break; case StripeEvents.InvoicePaymentFailed: // Invoice is sent and payment results in failure. //Undo Payment break; } } catch (StripeException ex) { var message = $"Unhandled {nameof(StripeException)} caught in {nameof(WebhookController)}.{nameof(Stripe)}. StripeEvent.Type: {stripeEvent.Type}"; _logger.Error(ex, message); result.Logs.Add(message); //await SendWebHookErrorEmail($"[Stripe Webhook Stripe Exception ({_env.EnvironmentName})]", stripeEvent, ex); } catch (Exception ex) { var message = $"Unhandled Exception caught in {nameof(WebhookController)}.{nameof(Stripe)}. StripeEvent.Type: {stripeEvent.Type}"; _logger.Error(ex, message); result.Logs.Add(message); //await SendWebHookErrorEmail($"[Stripe Webhook System Exception ({_env.EnvironmentName})]", stripeEvent, ex); } return(Ok(JsonNet.Serialize(new { result.Logs }, prettyPrint: true))); }
public void TestChargeSucceeded() { var e = new StripeEvent { LiveMode = true, Type = "charge.succeeded", Created = DateTime.Now.AddDays(-1), Data = new StripeEventData { Object = JObject.FromObject(new StripeCharge { Id = "9876" }) } }; _donationService.Setup(mocked => mocked.UpdateDonationStatus("9876", 888, e.Created, null)).Returns(123); Assert.IsNull(_fixture.ProcessStripeEvent(e)); _paymentProcessorService.VerifyAll(); _donationService.VerifyAll(); }
public override Task ExecuteAsync(string generator, WebHookHandlerContext context) { // For more information about Stripe WebHook payloads, please see // 'https://stripe.com/docs/webhooks' StripeEvent entry = context.GetDataOrDefault <StripeEvent>(); // We can trace to see what is going on. Trace.WriteLine(entry.ToString()); // Switch over the event types if you want to switch (entry.EventType) { default: // Information can be returned in a plain text response context.Response = context.Request.CreateResponse(); context.Response.Content = new StringContent(string.Format("Hello {0} event!", entry.EventType)); break; } return(Task.FromResult(true)); }