WIP
This commit is contained in:
parent
586c6de020
commit
485bb9e4a9
@ -403,5 +403,6 @@ services:
|
|||||||
- IdentityUrl=http://10.0.75.1:5105
|
- IdentityUrl=http://10.0.75.1:5105
|
||||||
- CallBackUrl=http://localhost:5114
|
- CallBackUrl=http://localhost:5114
|
||||||
- WebhooksUrl=http://webhooks.api
|
- WebhooksUrl=http://webhooks.api
|
||||||
|
- SelfUrl=http://webhooks.client/
|
||||||
ports:
|
ports:
|
||||||
- "5114:80"
|
- "5114:80"
|
@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Webhooks.API.IntegrationEvents
|
||||||
|
{
|
||||||
|
public class OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent
|
||||||
|
{
|
||||||
|
public int OrderId { get; private set; }
|
||||||
|
public string OrderStatus { get; private set; }
|
||||||
|
public string BuyerName { get; private set; }
|
||||||
|
|
||||||
|
public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName)
|
||||||
|
{
|
||||||
|
OrderId = orderId;
|
||||||
|
OrderStatus = orderStatus;
|
||||||
|
BuyerName = buyerName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webhooks.API.Model;
|
||||||
|
using Webhooks.API.Services;
|
||||||
|
|
||||||
|
namespace Webhooks.API.IntegrationEvents
|
||||||
|
{
|
||||||
|
public class OrderStatusChangedToShippedIntegrationEventHandler : IIntegrationEventHandler<OrderStatusChangedToShippedIntegrationEvent>
|
||||||
|
{
|
||||||
|
private readonly IWebhooksRetriever _retriever;
|
||||||
|
private readonly IWebhooksSender _sender;
|
||||||
|
public OrderStatusChangedToShippedIntegrationEventHandler(IWebhooksRetriever retriever, IWebhooksSender sender )
|
||||||
|
{
|
||||||
|
_retriever = retriever;
|
||||||
|
_sender = sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(OrderStatusChangedToShippedIntegrationEvent @event)
|
||||||
|
{
|
||||||
|
var subscriptions = await _retriever.GetSubscriptionsOfType(WebhookType.OrderShipped);
|
||||||
|
|
||||||
|
var whook = new WebhookData(WebhookType.OrderShipped, @event);
|
||||||
|
await _sender.SendAll(subscriptions, whook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
src/Services/Webhooks/Webhooks.API/Model/WebhookData.cs
Normal file
26
src/Services/Webhooks/Webhooks.API/Model/WebhookData.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Webhooks.API.Model
|
||||||
|
{
|
||||||
|
public class WebhookData
|
||||||
|
{
|
||||||
|
public DateTime When { get; }
|
||||||
|
|
||||||
|
public string Payload { get; }
|
||||||
|
|
||||||
|
public string Type { get; }
|
||||||
|
|
||||||
|
public WebhookData(WebhookType hookType, object data)
|
||||||
|
{
|
||||||
|
When = DateTime.UtcNow;
|
||||||
|
Type = hookType.ToString();
|
||||||
|
Payload = JsonConvert.SerializeObject(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ namespace Webhooks.API.Model
|
|||||||
{
|
{
|
||||||
public enum WebhookType
|
public enum WebhookType
|
||||||
{
|
{
|
||||||
CatalogItemPriceChange = 1
|
CatalogItemPriceChange = 1,
|
||||||
|
OrderShipped = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webhooks.API.Model;
|
||||||
|
|
||||||
|
namespace Webhooks.API.Services
|
||||||
|
{
|
||||||
|
public interface IWebhooksRetriever
|
||||||
|
{
|
||||||
|
|
||||||
|
Task<IEnumerable<WebhookSubscription>> GetSubscriptionsOfType(WebhookType type);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webhooks.API.Model;
|
||||||
|
|
||||||
|
namespace Webhooks.API.Services
|
||||||
|
{
|
||||||
|
public interface IWebhooksSender
|
||||||
|
{
|
||||||
|
Task SendAll(IEnumerable<WebhookSubscription> receivers, WebhookData data);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webhooks.API.Infrastructure;
|
||||||
|
using Webhooks.API.Model;
|
||||||
|
|
||||||
|
namespace Webhooks.API.Services
|
||||||
|
{
|
||||||
|
public class WebhooksRetriever : IWebhooksRetriever
|
||||||
|
{
|
||||||
|
private readonly WebhooksContext _db;
|
||||||
|
public WebhooksRetriever(WebhooksContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
public async Task<IEnumerable<WebhookSubscription>> GetSubscriptionsOfType(WebhookType type)
|
||||||
|
{
|
||||||
|
var data = await _db.Subscriptions.Where(s => s.Type == type).ToListAsync();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Webhooks.API.Model;
|
||||||
|
|
||||||
|
namespace Webhooks.API.Services
|
||||||
|
{
|
||||||
|
public class WebhooksSender : IWebhooksSender
|
||||||
|
{
|
||||||
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
public WebhooksSender(IHttpClientFactory httpClientFactory, ILogger<WebhooksSender> logger)
|
||||||
|
{
|
||||||
|
_httpClientFactory = httpClientFactory;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendAll(IEnumerable<WebhookSubscription> receivers, WebhookData data)
|
||||||
|
{
|
||||||
|
var client = _httpClientFactory.CreateClient();
|
||||||
|
var json = JsonConvert.SerializeObject(data);
|
||||||
|
var tasks = receivers.Select(r => OnSendData(r, json, client));
|
||||||
|
await Task.WhenAll(tasks.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task OnSendData(WebhookSubscription subs, string jsonData, HttpClient client)
|
||||||
|
{
|
||||||
|
var request = new HttpRequestMessage()
|
||||||
|
{
|
||||||
|
RequestUri = new Uri(subs.DestUrl, UriKind.Absolute),
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
Content = new StringContent(jsonData, Encoding.UTF8, "application/json")
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(subs.Token))
|
||||||
|
{
|
||||||
|
request.Headers.Add("X-eshop-whtoken", subs.Token);
|
||||||
|
}
|
||||||
|
_logger.LogDebug($"Sending hook to {subs.DestUrl} of type {subs.Type.ToString()}");
|
||||||
|
return client.SendAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -61,7 +61,9 @@ namespace Webhooks.API
|
|||||||
.AddCustomAuthentication(Configuration)
|
.AddCustomAuthentication(Configuration)
|
||||||
.AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
|
.AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
|
||||||
.AddTransient<IIdentityService, IdentityService>()
|
.AddTransient<IIdentityService, IdentityService>()
|
||||||
.AddTransient<IGrantUrlTesterService, GrantUrlTesterService>();
|
.AddTransient<IGrantUrlTesterService, GrantUrlTesterService>()
|
||||||
|
.AddTransient<IWebhooksRetriever, WebhooksRetriever>()
|
||||||
|
.AddTransient<IWebhooksSender, WebhooksSender>();
|
||||||
|
|
||||||
var container = new ContainerBuilder();
|
var container = new ContainerBuilder();
|
||||||
container.Populate(services);
|
container.Populate(services);
|
||||||
@ -125,6 +127,7 @@ namespace Webhooks.API
|
|||||||
{
|
{
|
||||||
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
||||||
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
|
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
|
||||||
|
eventBus.Subscribe<OrderStatusChangedToShippedIntegrationEvent, OrderStatusChangedToShippedIntegrationEventHandler>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,19 +290,11 @@ namespace Webhooks.API
|
|||||||
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
|
|
||||||
//register delegating handlers
|
|
||||||
//services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
|
|
||||||
|
|
||||||
//InfinteTimeSpan -> See: https://github.com/aspnet/HttpClientFactory/issues/194
|
|
||||||
services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan);
|
services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan);
|
||||||
|
|
||||||
//add http client services
|
//add http client services
|
||||||
services.AddHttpClient("GrantClient")
|
services.AddHttpClient("GrantClient")
|
||||||
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
|
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
|
||||||
//.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
|
//.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/Web/WebhookClient/Extensions/ISessionExtensions.cs
Normal file
24
src/Web/WebhookClient/Extensions/ISessionExtensions.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Http
|
||||||
|
{
|
||||||
|
static class ISessionExtensions
|
||||||
|
{
|
||||||
|
public static void Set<T>(this ISession session, string key, T value)
|
||||||
|
{
|
||||||
|
session.SetString(key, JsonConvert.SerializeObject(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Get<T>(this ISession session, string key)
|
||||||
|
{
|
||||||
|
var value = session.GetString(key);
|
||||||
|
|
||||||
|
return value == null ? default(T) :
|
||||||
|
JsonConvert.DeserializeObject<T>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WebhookClient
|
||||||
|
{
|
||||||
|
public class HttpClientAuthorizationDelegatingHandler
|
||||||
|
: DelegatingHandler
|
||||||
|
{
|
||||||
|
private readonly IHttpContextAccessor _httpContextAccesor;
|
||||||
|
|
||||||
|
public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)
|
||||||
|
{
|
||||||
|
_httpContextAccesor = httpContextAccesor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var authorizationHeader = _httpContextAccesor.HttpContext
|
||||||
|
.Request.Headers["Authorization"];
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(authorizationHeader))
|
||||||
|
{
|
||||||
|
request.Headers.Add("Authorization", new List<string>() { authorizationHeader });
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = await GetToken();
|
||||||
|
|
||||||
|
if (token != null)
|
||||||
|
{
|
||||||
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await base.SendAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<string> GetToken()
|
||||||
|
{
|
||||||
|
const string ACCESS_TOKEN = "access_token";
|
||||||
|
|
||||||
|
return await _httpContextAccesor.HttpContext
|
||||||
|
.GetTokenAsync(ACCESS_TOKEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/Web/WebhookClient/Models/WebHookReceived.cs
Normal file
13
src/Web/WebhookClient/Models/WebHookReceived.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WebhookClient.Models
|
||||||
|
{
|
||||||
|
public class WebHookReceived
|
||||||
|
{
|
||||||
|
public DateTime When { get; set; }
|
||||||
|
public string Data { get; set; }
|
||||||
|
}
|
||||||
|
}
|
14
src/Web/WebhookClient/Models/WebhookResponse.cs
Normal file
14
src/Web/WebhookClient/Models/WebhookResponse.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WebhookClient.Models
|
||||||
|
{
|
||||||
|
public class WebhookResponse
|
||||||
|
{
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public string DestUrl { get; set; }
|
||||||
|
public string Token { get; set; }
|
||||||
|
}
|
||||||
|
}
|
15
src/Web/WebhookClient/Models/WebhookSubscriptionRequest.cs
Normal file
15
src/Web/WebhookClient/Models/WebhookSubscriptionRequest.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WebhookClient.Models
|
||||||
|
{
|
||||||
|
public class WebhookSubscriptionRequest
|
||||||
|
{
|
||||||
|
public string Url { get; set; }
|
||||||
|
public string Token { get; set; }
|
||||||
|
public string Event { get; set; }
|
||||||
|
public string GrantUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -7,13 +7,23 @@
|
|||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1 class="display-4">Welcome</h1>
|
<h1 class="display-4">Welcome</h1>
|
||||||
<p>eShopOnContainers - Webhook client</p>
|
<p>eShopOnContainers - Webhook client</p>
|
||||||
<a class="btn-primary btn" href="@Url.Action("SignIn","Account")>Login</a>
|
<a class="btn-primary btn" href="@Url.Action("SignIn","Account")">Login</a>
|
||||||
<p>Why I need to login? You only need to login <bold>to setup a new webhook</bold>.</p>
|
<p>Why I need to login? You only need to login <bold>to setup a new webhook</bold>.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (User.Identity.IsAuthenticated)
|
@if (User.Identity.IsAuthenticated)
|
||||||
{
|
{
|
||||||
<div class="row">
|
|
||||||
Your current Webhooks:
|
<div class="table">
|
||||||
|
<h3>Current webhooks invoked</h3>
|
||||||
|
<table class="table">
|
||||||
|
@foreach (var webhook in Model.WebHooksReceived)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>@webhook.When</td>
|
||||||
|
<td><pre>@webhook.Data</pre></td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,20 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using WebhookClient.Models;
|
||||||
|
|
||||||
namespace WebhookClient.Pages
|
namespace WebhookClient.Pages
|
||||||
{
|
{
|
||||||
|
|
||||||
public class IndexModel : PageModel
|
public class IndexModel : PageModel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public IEnumerable<WebHookReceived> WebHooksReceived { get; private set; }
|
||||||
|
|
||||||
public void OnGet()
|
public void OnGet()
|
||||||
{
|
{
|
||||||
|
WebHooksReceived = HttpContext.Session.Get<IEnumerable<WebHookReceived>>("webhooks.received") ?? Enumerable.Empty<WebHookReceived>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
src/Web/WebhookClient/Pages/RegisterWebhook.cshtml
Normal file
14
src/Web/WebhookClient/Pages/RegisterWebhook.cshtml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@page
|
||||||
|
@model WebhookClient.Pages.RegisterWebhookModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "RegisterWebhook";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h3>Register webhook</h3>
|
||||||
|
|
||||||
|
<p>This page registers the "OrderShipped" Webhook by sending a POST to webhooks.</p>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<p>Token: <input type="text" asp-for="Token" /></p>
|
||||||
|
<input type="submit" value="send" />
|
||||||
|
</form>
|
55
src/Web/WebhookClient/Pages/RegisterWebhook.cshtml.cs
Normal file
55
src/Web/WebhookClient/Pages/RegisterWebhook.cshtml.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Formatting;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using WebhookClient.Models;
|
||||||
|
|
||||||
|
namespace WebhookClient.Pages
|
||||||
|
{
|
||||||
|
|
||||||
|
public class RegisterWebhookModel : PageModel
|
||||||
|
{
|
||||||
|
private readonly Settings _settings;
|
||||||
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
|
|
||||||
|
[BindProperty] public string Token { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public RegisterWebhookModel(IOptions<Settings> settings, IHttpClientFactory httpClientFactory)
|
||||||
|
{
|
||||||
|
_settings = settings.Value;
|
||||||
|
_httpClientFactory = httpClientFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnGet()
|
||||||
|
{
|
||||||
|
Token = _settings.Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnPost()
|
||||||
|
{
|
||||||
|
var protocol = Request.IsHttps ? "https" : "http";
|
||||||
|
var selfurl = !string.IsNullOrEmpty(_settings.SelfUrl) ? _settings.SelfUrl : $"{protocol}://{Request.Host}/{Request.PathBase}";
|
||||||
|
var granturl = $"{selfurl}check";
|
||||||
|
var url = $"{selfurl}webhook";
|
||||||
|
var client = _httpClientFactory.CreateClient("GrantClient");
|
||||||
|
|
||||||
|
var payload = new WebhookSubscriptionRequest()
|
||||||
|
{
|
||||||
|
Event = "OrderShipped",
|
||||||
|
GrantUrl = granturl,
|
||||||
|
Url = url,
|
||||||
|
Token = Token
|
||||||
|
};
|
||||||
|
var response = await client.PostAsync<WebhookSubscriptionRequest>(_settings.WebhooksUrl + "/api/v1/webhooks", payload, new JsonMediaTypeFormatter());
|
||||||
|
|
||||||
|
RedirectToPage("Index");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/Web/WebhookClient/Pages/WebhooksList.cshtml
Normal file
28
src/Web/WebhookClient/Pages/WebhooksList.cshtml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
@page
|
||||||
|
@model WebhookClient.Pages.WebhooksListModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "WebhooksList";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1>List of Webhooks registered by user @User.Identity.Name</h1>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Date</th>
|
||||||
|
<th scope="col">Destination Url</th>
|
||||||
|
<th scope="col">Validation token</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
@foreach (var whr in Model.Webhooks)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>@whr.Date</td>
|
||||||
|
<td>@whr.DestUrl</td>
|
||||||
|
<td>@whr.Token</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
28
src/Web/WebhookClient/Pages/WebhooksList.cshtml.cs
Normal file
28
src/Web/WebhookClient/Pages/WebhooksList.cshtml.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
using WebhookClient.Models;
|
||||||
|
using WebhookClient.Services;
|
||||||
|
|
||||||
|
namespace WebhookClient.Pages
|
||||||
|
{
|
||||||
|
public class WebhooksListModel : PageModel
|
||||||
|
{
|
||||||
|
private readonly IWebhooksClient _webhooksClient;
|
||||||
|
|
||||||
|
public IEnumerable<WebhookResponse> Webhooks { get; private set; }
|
||||||
|
|
||||||
|
public WebhooksListModel(IWebhooksClient webhooksClient)
|
||||||
|
{
|
||||||
|
_webhooksClient = webhooksClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnGet()
|
||||||
|
{
|
||||||
|
Webhooks = await _webhooksClient.LoadWebhooks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/Web/WebhookClient/Services/IWebhooksClient.cs
Normal file
13
src/Web/WebhookClient/Services/IWebhooksClient.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using WebhookClient.Models;
|
||||||
|
|
||||||
|
namespace WebhookClient.Services
|
||||||
|
{
|
||||||
|
public interface IWebhooksClient
|
||||||
|
{
|
||||||
|
Task<IEnumerable<WebhookResponse>> LoadWebhooks();
|
||||||
|
}
|
||||||
|
}
|
29
src/Web/WebhookClient/Services/WebhooksClient.cs
Normal file
29
src/Web/WebhookClient/Services/WebhooksClient.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using WebhookClient.Models;
|
||||||
|
|
||||||
|
namespace WebhookClient.Services
|
||||||
|
{
|
||||||
|
public class WebhooksClient : IWebhooksClient
|
||||||
|
{
|
||||||
|
public async Task<IEnumerable<WebhookResponse>> LoadWebhooks()
|
||||||
|
{
|
||||||
|
return new[]{
|
||||||
|
new WebhookResponse()
|
||||||
|
{
|
||||||
|
Date = DateTime.Now,
|
||||||
|
DestUrl = "http://aaaaa.me",
|
||||||
|
Token = "3282832as2"
|
||||||
|
},
|
||||||
|
new WebhookResponse()
|
||||||
|
{
|
||||||
|
Date = DateTime.Now.Subtract(TimeSpan.FromSeconds(392)),
|
||||||
|
DestUrl = "http://bbbbb.me",
|
||||||
|
Token = "ds2"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/Web/WebhookClient/Settings.cs
Normal file
17
src/Web/WebhookClient/Settings.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WebhookClient
|
||||||
|
{
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public string Token { get; set; }
|
||||||
|
public string IdentityUrl { get; set; }
|
||||||
|
public string CallBackUrl { get; set; }
|
||||||
|
public string WebhooksUrl { get; set; }
|
||||||
|
public string SelfUrl { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,8 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Threading;
|
||||||
|
using WebhookClient.Services;
|
||||||
|
|
||||||
namespace WebhookClient
|
namespace WebhookClient
|
||||||
{
|
{
|
||||||
@ -25,7 +27,14 @@ namespace WebhookClient
|
|||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services
|
services
|
||||||
|
.AddSession(opt =>
|
||||||
|
{
|
||||||
|
opt.Cookie.Name = ".eShopWebhooks.Session";
|
||||||
|
})
|
||||||
|
.AddConfiguration(Configuration)
|
||||||
|
.AddHttpClientServices(Configuration)
|
||||||
.AddCustomAuthentication(Configuration)
|
.AddCustomAuthentication(Configuration)
|
||||||
|
.AddTransient<IWebhooksClient, WebhooksClient>()
|
||||||
.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +51,6 @@ namespace WebhookClient
|
|||||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
app.Map("/check", capp =>
|
app.Map("/check", capp =>
|
||||||
@ -69,14 +77,20 @@ namespace WebhookClient
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
app.UseSession();
|
||||||
app.UseMvcWithDefaultRoute();
|
app.UseMvcWithDefaultRoute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ServiceExtensions
|
static class ServiceExtensions
|
||||||
{
|
{
|
||||||
|
public static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
services.AddOptions();
|
||||||
|
services.Configure<Settings>(configuration);
|
||||||
|
return services;
|
||||||
|
}
|
||||||
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
var identityUrl = configuration.GetValue<string>("IdentityUrl");
|
var identityUrl = configuration.GetValue<string>("IdentityUrl");
|
||||||
@ -107,5 +121,19 @@ namespace WebhookClient
|
|||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
|
||||||
|
services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan);
|
||||||
|
|
||||||
|
//add http client services
|
||||||
|
services.AddHttpClient("GrantClient")
|
||||||
|
.SetHandlerLifetime(TimeSpan.FromMinutes(5))
|
||||||
|
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.0.2105168" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.0.2105168" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user