|
|
|
@@ -1,11 +1,13 @@ |
|
|
|
using Microsoft.AspNetCore.Mvc; |
|
|
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
|
|
|
using Microsoft.Extensions.Configuration; |
|
|
|
using Microsoft.Extensions.Options; |
|
|
|
using Microsoft.Extensions.Caching.Memory; |
|
|
|
using Altob.NtuInvoiceGateway.Models; |
|
|
|
using System.Text; |
|
|
|
using System.Text.Json; |
|
|
|
using System.Linq; |
|
|
|
using System.Globalization; |
|
|
|
|
|
|
|
namespace Altob.NtuInvoiceGateway.Pages; |
|
|
|
|
|
|
|
@@ -16,8 +18,8 @@ public class InvoiceModel : PageModel |
|
|
|
private readonly IHttpClientFactory _httpClientFactory; |
|
|
|
private readonly IMemoryCache _memoryCache; |
|
|
|
private readonly CompanyInfo _companyInfo; |
|
|
|
private readonly InvoiceApiOptions _invoiceApiOptions; |
|
|
|
private readonly DonateCodeApiOptions _donateCodeApiOptions; |
|
|
|
private readonly EndpointApiOptions _endpointApiOptions; |
|
|
|
private readonly bool _debugMode; |
|
|
|
private const string ServiceName = "NtuInvoiceGateway"; |
|
|
|
private const string DonateCodeCacheKey = "DonateCodeList"; |
|
|
|
private const string InvoiceDataTempKey = "InvoiceFormData"; |
|
|
|
@@ -27,15 +29,15 @@ public class InvoiceModel : PageModel |
|
|
|
IHttpClientFactory httpClientFactory, |
|
|
|
IMemoryCache memoryCache, |
|
|
|
IOptions<CompanyInfo> companyInfo, |
|
|
|
IOptions<InvoiceApiOptions> invoiceApiOptions, |
|
|
|
IOptions<DonateCodeApiOptions> donateCodeApiOptions) |
|
|
|
IOptions<EndpointApiOptions> endpointApiOptions, |
|
|
|
IConfiguration configuration) |
|
|
|
{ |
|
|
|
_logger = logger; |
|
|
|
_httpClientFactory = httpClientFactory; |
|
|
|
_memoryCache = memoryCache; |
|
|
|
_companyInfo = companyInfo.Value; |
|
|
|
_invoiceApiOptions = invoiceApiOptions.Value; |
|
|
|
_donateCodeApiOptions = donateCodeApiOptions.Value; |
|
|
|
_endpointApiOptions = endpointApiOptions.Value; |
|
|
|
_debugMode = configuration.GetValue<bool>("DebugMode"); |
|
|
|
} |
|
|
|
|
|
|
|
[BindProperty(SupportsGet = true)] |
|
|
|
@@ -81,17 +83,17 @@ public class InvoiceModel : PageModel |
|
|
|
} |
|
|
|
|
|
|
|
// Cache 中沒有資料,從 API 取得 |
|
|
|
if (string.IsNullOrWhiteSpace(_donateCodeApiOptions.Endpoint)) |
|
|
|
if (string.IsNullOrWhiteSpace(_endpointApiOptions.DonateCodeApi)) |
|
|
|
{ |
|
|
|
_logger.LogError("{ServiceName} - {ActionName} DonateCode API endpoint is not configured", ServiceName, actionName); |
|
|
|
return new JsonResult(new List<DonateGroup>()) { StatusCode = 500 }; |
|
|
|
} |
|
|
|
|
|
|
|
_logger.LogInformation("{ServiceName} - {ActionName} fetching donate codes from API: {Endpoint}", |
|
|
|
ServiceName, actionName, _donateCodeApiOptions.Endpoint); |
|
|
|
ServiceName, actionName, _endpointApiOptions.DonateCodeApi); |
|
|
|
|
|
|
|
var httpClient = _httpClientFactory.CreateClient(); |
|
|
|
var response = await httpClient.GetAsync(_donateCodeApiOptions.Endpoint); |
|
|
|
var response = await httpClient.GetAsync(_endpointApiOptions.DonateCodeApi); |
|
|
|
|
|
|
|
if (!response.IsSuccessStatusCode) |
|
|
|
{ |
|
|
|
@@ -176,7 +178,7 @@ public class InvoiceModel : PageModel |
|
|
|
// 顯示表單讓用戶填寫 |
|
|
|
return Page(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task<IActionResult> OnPostToEndPointAsync() |
|
|
|
{ |
|
|
|
NormalizeInvoiceData(); |
|
|
|
@@ -235,7 +237,7 @@ public class InvoiceModel : PageModel |
|
|
|
return Page(); |
|
|
|
} |
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(_invoiceApiOptions.Endpoint)) |
|
|
|
if (string.IsNullOrWhiteSpace(_endpointApiOptions.InvoiceApi)) |
|
|
|
{ |
|
|
|
ErrorMessage = "未設定外部發票 API 的位址"; |
|
|
|
_logger.LogError("{ServiceName} - {ActionName} Invoice API endpoint is not configured", ServiceName, actionName); |
|
|
|
@@ -261,6 +263,11 @@ public class InvoiceModel : PageModel |
|
|
|
// "loveCode": "" |
|
|
|
// } |
|
|
|
var httpClient = _httpClientFactory.CreateClient(); |
|
|
|
|
|
|
|
if (_debugMode) |
|
|
|
{ |
|
|
|
await PostPaymentNotifyForDebugAsync(httpClient, actionName); |
|
|
|
} |
|
|
|
var requestBody = JsonSerializer.Serialize(InvoiceData, new JsonSerializerOptions |
|
|
|
{ |
|
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase |
|
|
|
@@ -270,7 +277,7 @@ public class InvoiceModel : PageModel |
|
|
|
|
|
|
|
var content = new StringContent(requestBody, Encoding.UTF8, "application/json"); |
|
|
|
|
|
|
|
var response = await httpClient.PostAsync(_invoiceApiOptions.Endpoint, content); |
|
|
|
var response = await httpClient.PostAsync(_endpointApiOptions.InvoiceApi, content); |
|
|
|
|
|
|
|
var responseContent = await response.Content.ReadAsStringAsync(); |
|
|
|
_logger.LogInformation("{ServiceName} - {ActionName} received API response status {StatusCode} body: {ResponseBody}", |
|
|
|
@@ -318,23 +325,76 @@ public class InvoiceModel : PageModel |
|
|
|
return Page(); |
|
|
|
} |
|
|
|
|
|
|
|
private async Task PostPaymentNotifyForDebugAsync(HttpClient httpClient, string actionName) |
|
|
|
{ |
|
|
|
if (string.IsNullOrWhiteSpace(_endpointApiOptions.PaymentNotifyApi)) |
|
|
|
{ |
|
|
|
_logger.LogWarning("{ServiceName} - {ActionName} DebugMode enabled but PaymentNotify API endpoint is not configured", |
|
|
|
ServiceName, actionName); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
var licensePlate = string.IsNullOrWhiteSpace(InvoiceData.CarPlateNum) ? "9M1234" : InvoiceData.CarPlateNum; |
|
|
|
var parkingArea = string.IsNullOrWhiteSpace(InvoiceData.LocationID) ? "1" : InvoiceData.LocationID; |
|
|
|
var orderId = string.IsNullOrWhiteSpace(InvoiceData.OrderID) |
|
|
|
? $"Order{DateTime.UtcNow:yyyyMMddHHmmss}" |
|
|
|
: InvoiceData.OrderID; |
|
|
|
|
|
|
|
var amount = 0m; |
|
|
|
var rawAmount = InvoiceData.TransAmount?.Trim(); |
|
|
|
if (!string.IsNullOrWhiteSpace(rawAmount)) |
|
|
|
{ |
|
|
|
if (!decimal.TryParse(rawAmount, NumberStyles.Any, CultureInfo.InvariantCulture, out amount) && |
|
|
|
!decimal.TryParse(rawAmount, NumberStyles.Any, CultureInfo.CurrentCulture, out amount)) |
|
|
|
{ |
|
|
|
_logger.LogWarning("{ServiceName} - {ActionName} unable to parse TransAmount {TransAmount}, using 0 for debug PaymentNotify", |
|
|
|
ServiceName, actionName, InvoiceData.TransAmount); |
|
|
|
amount = 0m; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var paymentNotifyPayload = new |
|
|
|
{ |
|
|
|
licensePlate, |
|
|
|
parkingArea, |
|
|
|
orderId, |
|
|
|
amount |
|
|
|
}; |
|
|
|
var payloadJson = JsonSerializer.Serialize(paymentNotifyPayload); |
|
|
|
_logger.LogInformation("{ServiceName} - {ActionName} sending debug PaymentNotify payload: {Payload}", |
|
|
|
ServiceName, actionName, payloadJson); |
|
|
|
|
|
|
|
using var content = new StringContent(payloadJson, Encoding.UTF8, "application/json"); |
|
|
|
var response = await httpClient.PostAsync(_endpointApiOptions.PaymentNotifyApi, content); |
|
|
|
var responseContent = await response.Content.ReadAsStringAsync(); |
|
|
|
_logger.LogInformation("{ServiceName} - {ActionName} debug PaymentNotify response status {StatusCode} body: {ResponseBody}", |
|
|
|
ServiceName, actionName, response.StatusCode, responseContent); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
_logger.LogWarning(ex, "{ServiceName} - {ActionName} failed to POST debug PaymentNotify but continuing", |
|
|
|
ServiceName, actionName); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void NormalizeInvoiceData() |
|
|
|
{ |
|
|
|
InvoiceData ??= new InvoiceRequest(); |
|
|
|
|
|
|
|
InvoiceData.Identifier = InvoiceData.Identifier ?? string.Empty; |
|
|
|
InvoiceData.TransDateTime = InvoiceData.TransDateTime ?? string.Empty; |
|
|
|
InvoiceData.TransAmount = InvoiceData.TransAmount ?? string.Empty; |
|
|
|
InvoiceData.DeviceID = InvoiceData.DeviceID ?? string.Empty; |
|
|
|
InvoiceData.LocationID = InvoiceData.LocationID ?? string.Empty; |
|
|
|
InvoiceData.CarPlateNum = InvoiceData.CarPlateNum ?? string.Empty; |
|
|
|
InvoiceData.OrderID = InvoiceData.OrderID ?? string.Empty; |
|
|
|
InvoiceData.TaxType = InvoiceData.TaxType ?? string.Empty; |
|
|
|
|
|
|
|
InvoiceData.Email = InvoiceData.Email ?? string.Empty; |
|
|
|
InvoiceData.CarrierID = InvoiceData.CarrierID ?? string.Empty; |
|
|
|
InvoiceData.BuyerIdentifier = InvoiceData.BuyerIdentifier ?? string.Empty; |
|
|
|
InvoiceData.LoveCode = InvoiceData.LoveCode ?? string.Empty; |
|
|
|
// InvoiceData.Identifier = InvoiceData.Identifier ?? string.Empty; |
|
|
|
// InvoiceData.TransDateTime = InvoiceData.TransDateTime ?? string.Empty; |
|
|
|
// InvoiceData.TransAmount = InvoiceData.TransAmount ?? string.Empty; |
|
|
|
// InvoiceData.DeviceID = InvoiceData.DeviceID ?? string.Empty; |
|
|
|
// InvoiceData.LocationID = InvoiceData.LocationID ?? string.Empty; |
|
|
|
// InvoiceData.CarPlateNum = InvoiceData.CarPlateNum ?? string.Empty; |
|
|
|
// InvoiceData.OrderID = InvoiceData.OrderID ?? string.Empty; |
|
|
|
// InvoiceData.TaxType = InvoiceData.TaxType ?? string.Empty; |
|
|
|
// |
|
|
|
// InvoiceData.Email = InvoiceData.Email ?? string.Empty; |
|
|
|
// InvoiceData.CarrierID = InvoiceData.CarrierID ?? string.Empty; |
|
|
|
// InvoiceData.BuyerIdentifier = InvoiceData.BuyerIdentifier ?? string.Empty; |
|
|
|
// InvoiceData.LoveCode = InvoiceData.LoveCode ?? string.Empty; |
|
|
|
} |
|
|
|
|
|
|
|
private void RestoreDisplayValuesFromTempData() |
|
|
|
|