|
9 | 9 | using Microsoft.AspNetCore.Http; |
10 | 10 | using Microsoft.Extensions.Options; |
11 | 11 | using Parbad.Internal; |
| 12 | +using Parbad.Options; |
12 | 13 |
|
13 | | -namespace Parbad.Gateway.ParbadVirtual.MiddlewareInvoker |
| 14 | +namespace Parbad.Gateway.ParbadVirtual.MiddlewareInvoker; |
| 15 | + |
| 16 | +internal class ParbadVirtualGatewayMiddlewareInvoker : IParbadVirtualGatewayMiddlewareInvoker |
14 | 17 | { |
15 | | - internal class ParbadVirtualGatewayMiddlewareInvoker : IParbadVirtualGatewayMiddlewareInvoker |
| 18 | + private readonly HttpContext _httpContext; |
| 19 | + private readonly ParbadVirtualGatewayOptions _virtualGatewayOptions; |
| 20 | + private readonly ParbadOptions _options; |
| 21 | + |
| 22 | + public ParbadVirtualGatewayMiddlewareInvoker(IHttpContextAccessor httpContextAccessor, |
| 23 | + IOptions<ParbadVirtualGatewayOptions> virtualGatewayOptions, |
| 24 | + IOptions<ParbadOptions> options) |
16 | 25 | { |
17 | | - private readonly HttpContext _httpContext; |
18 | | - private readonly IOptions<ParbadVirtualGatewayOptions> _options; |
| 26 | + _httpContext = httpContextAccessor.HttpContext; |
| 27 | + _virtualGatewayOptions = virtualGatewayOptions.Value; |
| 28 | + _options = options.Value; |
| 29 | + } |
19 | 30 |
|
20 | | - public ParbadVirtualGatewayMiddlewareInvoker(IOptions<ParbadVirtualGatewayOptions> options, |
21 | | - IHttpContextAccessor httpContextAccessor) |
| 31 | + public async Task InvokeAsync() |
| 32 | + { |
| 33 | + if (_httpContext == null) |
22 | 34 | { |
23 | | - _options = options; |
24 | | - _httpContext = httpContextAccessor.HttpContext; |
| 35 | + throw new InvalidOperationException("HttpContext is null"); |
25 | 36 | } |
26 | 37 |
|
27 | | - public async Task InvokeAsync() |
| 38 | + if (_httpContext.Request.Query.ContainsKey("css")) |
28 | 39 | { |
29 | | - if (_httpContext == null) |
30 | | - { |
31 | | - throw new InvalidOperationException("HttpContext is null"); |
32 | | - } |
| 40 | + await HandleCss(_httpContext); |
33 | 41 |
|
34 | | - if (_httpContext.Request.Query.ContainsKey("css")) |
35 | | - { |
36 | | - await HandleCss(_httpContext); |
| 42 | + return; |
| 43 | + } |
37 | 44 |
|
38 | | - return; |
39 | | - } |
| 45 | + HttpResponseUtilities.AddNecessaryContents(_httpContext, "text/html"); |
40 | 46 |
|
41 | | - HttpResponseUtilities.AddNecessaryContents(_httpContext, "text/html"); |
| 47 | + var commandDetails = await GetCommandDetails(_httpContext); |
42 | 48 |
|
43 | | - var commandDetails = await GetCommandDetails(_httpContext); |
| 49 | + if (commandDetails == null) |
| 50 | + { |
| 51 | + await _httpContext.Response.WriteAsync("Parbad Virtual Gateway message: Invalid data is received."); |
44 | 52 |
|
45 | | - if (commandDetails == null) |
46 | | - { |
47 | | - await _httpContext.Response.WriteAsync("Parbad Virtual Gateway message: Invalid data is received."); |
| 53 | + return; |
| 54 | + } |
48 | 55 |
|
49 | | - return; |
50 | | - } |
| 56 | + var cssUrl = |
| 57 | + $"{_httpContext.Request.Scheme}://{_httpContext.Request.Host}{_httpContext.Request.PathBase}?css=true"; |
51 | 58 |
|
52 | | - var cssUrl = |
53 | | - $"{_httpContext.Request.Scheme}://{_httpContext.Request.Host}{_httpContext.Request.PathBase}?css=true"; |
| 59 | + var nonceProp = GetNonceProp(); |
54 | 60 |
|
55 | | - switch (commandDetails.CommandType) |
56 | | - { |
57 | | - case VirtualGatewayCommandType.Request: |
58 | | - await HandleRequestPage(_httpContext, commandDetails, cssUrl); |
| 61 | + switch (commandDetails.CommandType) |
| 62 | + { |
| 63 | + case VirtualGatewayCommandType.Request: |
| 64 | + await HandleRequestPage(_httpContext, commandDetails, cssUrl, nonceProp); |
59 | 65 |
|
60 | | - break; |
| 66 | + break; |
61 | 67 |
|
62 | | - case VirtualGatewayCommandType.Pay: |
63 | | - await HandleResultPage(_httpContext, commandDetails, cssUrl); |
| 68 | + case VirtualGatewayCommandType.Pay: |
| 69 | + await HandleResultPage(_httpContext, commandDetails, cssUrl, nonceProp); |
64 | 70 |
|
65 | | - break; |
| 71 | + break; |
66 | 72 |
|
67 | | - default: |
68 | | - await _httpContext.Response.WriteAsync("CommandType is not valid."); |
| 73 | + default: |
| 74 | + await _httpContext.Response.WriteAsync("CommandType is not valid."); |
69 | 75 |
|
70 | | - break; |
71 | | - } |
| 76 | + break; |
72 | 77 | } |
| 78 | + } |
73 | 79 |
|
74 | | - private async Task HandleCss(HttpContext httpContext) |
75 | | - { |
76 | | - HttpResponseUtilities.AddNecessaryContents(_httpContext, "text/css"); |
| 80 | + private async Task HandleCss(HttpContext httpContext) |
| 81 | + { |
| 82 | + HttpResponseUtilities.AddNecessaryContents(_httpContext, "text/css"); |
77 | 83 |
|
78 | | - var cssContent = await GetTemplate("ParbadVirtualGatewayStyles.css"); |
| 84 | + var cssContent = await GetTemplate("ParbadVirtualGatewayStyles.css"); |
79 | 85 |
|
80 | | - await httpContext.Response.WriteAsync(cssContent); |
81 | | - } |
| 86 | + await httpContext.Response.WriteAsync(cssContent); |
| 87 | + } |
82 | 88 |
|
83 | | - private async Task HandleRequestPage(HttpContext httpContext, |
84 | | - VirtualGatewayCommandDetails commandDetails, |
85 | | - string cssUrl) |
| 89 | + private async Task HandleRequestPage(HttpContext httpContext, |
| 90 | + VirtualGatewayCommandDetails commandDetails, |
| 91 | + string cssUrl, |
| 92 | + string nonceProp) |
| 93 | + { |
| 94 | + var template = await GetTemplate("VirtualGatewayRequestTemplate.html"); |
| 95 | + |
| 96 | + var html = template |
| 97 | + .Replace("#CssUrl#", cssUrl) |
| 98 | + .Replace("#nonce#", nonceProp) |
| 99 | + .Replace("#VirtualGatewayPath#", _virtualGatewayOptions.GatewayPath) |
| 100 | + .Replace("#TrackingNumber#", commandDetails.TrackingNumber.ToString()) |
| 101 | + .Replace("#Amount#", commandDetails.Amount.ToString()) |
| 102 | + .Replace("#DisplayAmount#", ((long)commandDetails.Amount).ToString("N0")) |
| 103 | + .Replace("#RedirectUrl#", commandDetails.RedirectUrl) |
| 104 | + .Replace("#YearNow#", DateTime.Now.Year.ToString()); |
| 105 | + |
| 106 | + await httpContext.Response.WriteAsync(html); |
| 107 | + } |
| 108 | + |
| 109 | + private static async Task HandleResultPage(HttpContext httpContext, |
| 110 | + VirtualGatewayCommandDetails commandDetails, |
| 111 | + string cssUrl, |
| 112 | + string nonceProp) |
| 113 | + { |
| 114 | + if (!httpContext.Request.Form.TryGetValue("isPaid", out var isPaid) || |
| 115 | + !bool.TryParse(isPaid, out var boolIsPaid)) |
86 | 116 | { |
87 | | - var template = await GetTemplate("VirtualGatewayRequestTemplate.html"); |
88 | | - |
89 | | - var html = template |
90 | | - .Replace("#CssUrl#", cssUrl) |
91 | | - .Replace("#VirtualGatewayPath#", _options.Value.GatewayPath) |
92 | | - .Replace("#TrackingNumber#", commandDetails.TrackingNumber.ToString()) |
93 | | - .Replace("#Amount#", commandDetails.Amount.ToString()) |
94 | | - .Replace("#DisplayAmount#", ((long)commandDetails.Amount).ToString("N0")) |
95 | | - .Replace("#RedirectUrl#", commandDetails.RedirectUrl) |
96 | | - .Replace("#YearNow#", DateTime.Now.Year.ToString()); |
97 | | - |
98 | | - await httpContext.Response.WriteAsync(html); |
| 117 | + await httpContext.Response.WriteAsync($"{nameof(isPaid)} field is not valid."); |
| 118 | + |
| 119 | + return; |
99 | 120 | } |
100 | 121 |
|
101 | | - private static async Task HandleResultPage(HttpContext httpContext, |
102 | | - VirtualGatewayCommandDetails commandDetails, |
103 | | - string cssUrl) |
| 122 | + var template = await GetTemplate("VirtualGatewayResultTemplate.html"); |
| 123 | + |
| 124 | + var html = template |
| 125 | + .Replace("#CssUrl#", cssUrl) |
| 126 | + .Replace("#nonce#", nonceProp) |
| 127 | + .Replace("#TrackingNumber#", commandDetails.TrackingNumber.ToString()) |
| 128 | + .Replace("#DisplayAmount#", ((long)commandDetails.Amount).ToString("N0")) |
| 129 | + .Replace("#TransactionCode#", boolIsPaid ? Guid.NewGuid().ToString("N") : string.Empty) |
| 130 | + .Replace("#RedirectUrl#", commandDetails.RedirectUrl) |
| 131 | + .Replace("#IsPaid#", isPaid.ToString().ToLower()) |
| 132 | + .Replace("#YearNow#", DateTime.Now.Year.ToString()) |
| 133 | + .Replace("#StatusText#", boolIsPaid ? "Paid" : "Cancelled"); |
| 134 | + |
| 135 | + await httpContext.Response.WriteAsync(html); |
| 136 | + } |
| 137 | + |
| 138 | + private static async Task<VirtualGatewayCommandDetails> GetCommandDetails(HttpContext httpContext) |
| 139 | + { |
| 140 | + if (!httpContext.Request.HasFormContentType) |
104 | 141 | { |
105 | | - if (!httpContext.Request.Form.TryGetValue("isPaid", out var isPaid) || |
106 | | - !bool.TryParse(isPaid, out var boolIsPaid)) |
107 | | - { |
108 | | - await httpContext.Response.WriteAsync($"{nameof(isPaid)} field is not valid."); |
109 | | - |
110 | | - return; |
111 | | - } |
112 | | - |
113 | | - var template = await GetTemplate("VirtualGatewayResultTemplate.html"); |
114 | | - |
115 | | - var html = template |
116 | | - .Replace("#CssUrl#", cssUrl) |
117 | | - .Replace("#TrackingNumber#", commandDetails.TrackingNumber.ToString()) |
118 | | - .Replace("#DisplayAmount#", ((long)commandDetails.Amount).ToString("N0")) |
119 | | - .Replace("#TransactionCode#", boolIsPaid ? Guid.NewGuid().ToString("N") : string.Empty) |
120 | | - .Replace("#RedirectUrl#", commandDetails.RedirectUrl) |
121 | | - .Replace("#IsPaid#", isPaid.ToString().ToLower()) |
122 | | - .Replace("#YearNow#", DateTime.Now.Year.ToString()) |
123 | | - .Replace("#StatusText#", boolIsPaid ? "Paid" : "Cancelled"); |
124 | | - |
125 | | - await httpContext.Response.WriteAsync(html); |
| 142 | + return null; |
126 | 143 | } |
127 | 144 |
|
128 | | - private static async Task<VirtualGatewayCommandDetails> GetCommandDetails(HttpContext httpContext) |
| 145 | + var form = await httpContext.Request.ReadFormAsync(); |
| 146 | + |
| 147 | + if (!Enum.TryParse(form["commandType"], out VirtualGatewayCommandType commandType)) |
129 | 148 | { |
130 | | - if (!httpContext.Request.HasFormContentType) |
131 | | - { |
132 | | - return null; |
133 | | - } |
134 | | - |
135 | | - var form = await httpContext.Request.ReadFormAsync(); |
136 | | - |
137 | | - if (!Enum.TryParse(form["commandType"], out VirtualGatewayCommandType commandType)) |
138 | | - { |
139 | | - commandType = VirtualGatewayCommandType.Request; |
140 | | - } |
141 | | - |
142 | | - if (!long.TryParse(form["trackingNumber"], out var trackingNumber) || |
143 | | - !form.TryGetValue("redirectUrl", out var redirectUrl) || |
144 | | - !Money.TryParse(form["amount"], out var amount)) |
145 | | - { |
146 | | - return null; |
147 | | - } |
148 | | - |
149 | | - return new VirtualGatewayCommandDetails(commandType, trackingNumber, amount, redirectUrl); |
| 149 | + commandType = VirtualGatewayCommandType.Request; |
150 | 150 | } |
151 | 151 |
|
152 | | - private static Task<string> GetTemplate(string templateName) |
| 152 | + if (!long.TryParse(form["trackingNumber"], out var trackingNumber) || |
| 153 | + !form.TryGetValue("redirectUrl", out var redirectUrl) || |
| 154 | + !Money.TryParse(form["amount"], out var amount)) |
153 | 155 | { |
154 | | - using var stream = typeof(ParbadVirtualGatewayOptions) |
155 | | - .GetTypeInfo() |
156 | | - .Assembly |
157 | | - .GetManifestResourceStream($"Parbad.Gateway.ParbadVirtual.{templateName}"); |
| 156 | + return null; |
| 157 | + } |
158 | 158 |
|
159 | | - var streamReader = new StreamReader(stream, Encoding.UTF8); |
| 159 | + return new VirtualGatewayCommandDetails(commandType, trackingNumber, amount, redirectUrl); |
| 160 | + } |
160 | 161 |
|
161 | | - return streamReader.ReadToEndAsync(); |
| 162 | + private static Task<string> GetTemplate(string templateName) |
| 163 | + { |
| 164 | + using var stream = typeof(ParbadVirtualGatewayOptions) |
| 165 | + .GetTypeInfo() |
| 166 | + .Assembly |
| 167 | + .GetManifestResourceStream($"Parbad.Gateway.ParbadVirtual.{templateName}"); |
| 168 | + |
| 169 | + var streamReader = new StreamReader(stream, Encoding.UTF8); |
| 170 | + |
| 171 | + return streamReader.ReadToEndAsync(); |
| 172 | + } |
| 173 | + |
| 174 | + private string GetNonceProp() |
| 175 | + { |
| 176 | + string nonceValue = null; |
| 177 | + |
| 178 | + if (_options.NonceFactory != null) |
| 179 | + { |
| 180 | + nonceValue = _options.NonceFactory(_httpContext); |
162 | 181 | } |
| 182 | + |
| 183 | + return string.IsNullOrWhiteSpace(nonceValue) ? null : $" nonce=\"{nonceValue}\""; |
163 | 184 | } |
164 | 185 | } |
0 commit comments