Sfoglia il codice sorgente

測試頁面

master
Joanne.Chuang 2 settimane fa
parent
commit
c5203067c9
7 ha cambiato i file con 194 aggiunte e 58 eliminazioni
  1. +15
    -1
      Altob.NtuInvoiceGateway/Pages/Invoice.cshtml
  2. +76
    -50
      Altob.NtuInvoiceGateway/Pages/Invoice.cshtml.cs
  3. +80
    -6
      Altob.NtuInvoiceGateway/Pages/TestPostInvoice.cshtml
  4. +14
    -0
      Altob.NtuInvoiceGateway/Pages/TestPostInvoice.cshtml.cs
  5. +3
    -1
      Altob.NtuInvoiceGateway/Program.cs
  6. +3
    -0
      Altob.NtuInvoiceGateway/appsettings.Development.json
  7. +3
    -0
      Altob.NtuInvoiceGateway/appsettings.json

+ 15
- 1
Altob.NtuInvoiceGateway/Pages/Invoice.cshtml Vedi File

@@ -54,7 +54,6 @@
<div asp-validation-summary="ModelOnly" class="text-danger mb-3"></div>

<!-- 隱藏欄位:系統傳入的資料 -->
<input type="hidden" asp-for="InvoiceData.Identifier" />
<input type="hidden" asp-for="InvoiceData.TransDateTime" />
<input type="hidden" asp-for="InvoiceData.TransAmount" />
<input type="hidden" asp-for="InvoiceData.DeviceID" />
@@ -63,6 +62,21 @@
<input type="hidden" asp-for="InvoiceData.OrderID" />
<input type="hidden" asp-for="InvoiceData.TaxType" />

@{
if (string.IsNullOrWhiteSpace(Model.InvoiceData.Identifier))
{
Model.InvoiceData.Identifier = Model.CompanyTaxId;
}
}

<div class="mb-3">
<label asp-for="InvoiceData.Identifier" class="form-label">開發票者統編</label>
<input asp-for="InvoiceData.Identifier"
class="form-control"
maxlength="8" />
<span asp-validation-for="InvoiceData.Identifier" class="text-danger"></span>
</div>

<div class="alert alert-info mb-4">
<strong>注意:</strong>以下三個選項只能填寫其中一個
</div>


+ 76
- 50
Altob.NtuInvoiceGateway/Pages/Invoice.cshtml.cs Vedi File

@@ -7,20 +7,24 @@ using System.Text.Json;

namespace Altob.NtuInvoiceGateway.Pages;

[IgnoreAntiforgeryToken] // 允許外部系統 POST JSON 請求
public class InvoiceModel : PageModel
{
private readonly ILogger<InvoiceModel> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private readonly CompanyInfo _companyInfo;
private readonly InvoiceApiOptions _invoiceApiOptions;

public InvoiceModel(
ILogger<InvoiceModel> logger,
IHttpClientFactory httpClientFactory,
IOptions<CompanyInfo> companyInfo)
IOptions<CompanyInfo> companyInfo,
IOptions<InvoiceApiOptions> invoiceApiOptions)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
_companyInfo = companyInfo.Value;
_invoiceApiOptions = invoiceApiOptions.Value;
}

[BindProperty]
@@ -35,55 +39,49 @@ public class InvoiceModel : PageModel
public string DisplayTransDateTime { get; set; } = string.Empty;
public string DisplayTransAmount { get; set; } = string.Empty;

public void OnGet(
string? identifier = null,
string? transDateTime = null,
string? transAmount = null,
string? deviceID = null,
string? email = null,
string? carrierID = null,
string? locationID = null,
string? carPlateNum = null,
string? orderID = null,
string? buyerIdentifier = null,
// string? loveCode = null,
string? taxType = null)
public void OnGet()
{
// 從查詢字串接收系統轉頁傳來的資料
if (!string.IsNullOrEmpty(identifier))
InvoiceData.Identifier = identifier;
if (!string.IsNullOrEmpty(transDateTime))
{
InvoiceData.TransDateTime = transDateTime;
DisplayTransDateTime = transDateTime;
}
if (!string.IsNullOrEmpty(transAmount))
{
InvoiceData.TransAmount = transAmount;
DisplayTransAmount = transAmount;
}
if (!string.IsNullOrEmpty(deviceID))
InvoiceData.DeviceID = deviceID;
if (!string.IsNullOrEmpty(email))
InvoiceData.Email = email;
if (!string.IsNullOrEmpty(carrierID))
InvoiceData.CarrierID = carrierID;
if (!string.IsNullOrEmpty(locationID))
InvoiceData.LocationID = locationID;
if (!string.IsNullOrEmpty(carPlateNum))
InvoiceData.CarPlateNum = carPlateNum;
if (!string.IsNullOrEmpty(orderID))
InvoiceData.OrderID = orderID;
if (!string.IsNullOrEmpty(buyerIdentifier))
InvoiceData.BuyerIdentifier = buyerIdentifier;
// if (!string.IsNullOrEmpty(loveCode))
// InvoiceData.LoveCode = loveCode;
if (!string.IsNullOrEmpty(taxType))
InvoiceData.TaxType = taxType;
// GET 方法保留為空,主要接收方式改為 POST JSON
}

public async Task<IActionResult> OnPostAsync()
{
// 檢查是否為 JSON 請求(外部系統轉頁)
if (Request.ContentType?.Contains("application/json") == true)
{
try
{
// 從 Request Body 讀取 JSON 資料
using var reader = new StreamReader(Request.Body);
var jsonContent = await reader.ReadToEndAsync();

var jsonData = JsonSerializer.Deserialize<InvoiceRequest>(jsonContent, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true
});

if (jsonData != null)
{
InvoiceData = jsonData;
DisplayTransDateTime = InvoiceData.TransDateTime;
DisplayTransAmount = InvoiceData.TransAmount;
ModelState.Clear(); // ensure Razor uses the JSON payload values

_logger.LogInformation("Received JSON redirect for OrderID: {OrderID}", InvoiceData.OrderID);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error parsing JSON request");
ErrorMessage = "接收轉頁資料時發生錯誤";
}

// 顯示表單讓用戶填寫
return Page();
}

// 處理表單提交
// 保留發票資訊顯示
DisplayTransDateTime = InvoiceData.TransDateTime;
DisplayTransAmount = InvoiceData.TransAmount;
@@ -117,26 +115,54 @@ public class InvoiceModel : PageModel
return Page();
}

if (string.IsNullOrWhiteSpace(_invoiceApiOptions.Endpoint))
{
ErrorMessage = "未設定外部發票 API 的位址";
_logger.LogError("Invoice API endpoint is not configured");
return Page();
}

try
{
// 呼叫 TODO API(這裡使用規格中的範例 API)
// http://192.168.110.72:22055/api/Intella/invoiceInfo
// {
// "identifier": "12345678",
// "transDateTime": "2026/01/08 12:00:00",
// "transAmount": "30",
// "deviceID": "test",
// "locationID": "1",
// "carPlateNum": "ABC1235",
// "orderID": "260109_1",
// "email": "",
// "carrierID": "/ab12345",
// "buyerIdentifier": "",
// "taxType": "1",
// "loveCode": ""
// }
var httpClient = _httpClientFactory.CreateClient();
var jsonContent = JsonSerializer.Serialize(InvoiceData, new JsonSerializerOptions
var requestBody = JsonSerializer.Serialize(InvoiceData, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});

var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
var content = new StringContent(requestBody, Encoding.UTF8, "application/json");

// TODO: 替換為實際的 API 端點
var response = await httpClient.PostAsync("YOUR_API_ENDPOINT_HERE", content);
var response = await httpClient.PostAsync(_invoiceApiOptions.Endpoint, content);

var responseContent = await response.Content.ReadAsStringAsync();
var apiResponse = JsonSerializer.Deserialize<InvoiceResponse>(responseContent, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
PropertyNameCaseInsensitive = true
});

if (!response.IsSuccessStatusCode)
{
ErrorMessage = $"提交失敗:{apiResponse?.msg ?? response.StatusCode.ToString()}";
_logger.LogWarning("Invoice submission failed with HTTP {StatusCode} for OrderID: {OrderID}", response.StatusCode, InvoiceData.OrderID);
return Page();
}

if (apiResponse?.msgCode == "0000")
{
SuccessMessage = "發票資訊提交成功!";


+ 80
- 6
Altob.NtuInvoiceGateway/Pages/TestPostInvoice.cshtml Vedi File

@@ -1,4 +1,5 @@
@page
@model TestPostInvoiceModel
@{
ViewData["Title"] = "POST 轉頁測試";
Layout = null;
@@ -25,12 +26,20 @@
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label">開發票者統編 (Identifier) *</label>
<input type="text" class="form-control" name="InvoiceData.Identifier" value="12345678" required>
<input type="text"
class="form-control"
name="InvoiceData.Identifier"
value="@(string.IsNullOrWhiteSpace(Model.CompanyTaxId) ? "" : Model.CompanyTaxId)"
required>
<small class="text-muted">8位數字</small>
</div>
<div class="col-md-6">
<label class="form-label">發票交易日期 (TransDateTime) *</label>
<input type="text" class="form-control" name="InvoiceData.TransDateTime" value="2024-01-15 14:30:00" required>
<input type="text"
class="form-control"
name="InvoiceData.TransDateTime"
value="@Model.CurrentTransDateTime"
required>
</div>
</div>

@@ -42,26 +51,26 @@
</div>
<div class="col-md-6">
<label class="form-label">設備代號 (DeviceID) *</label>
<input type="text" class="form-control" name="InvoiceData.DeviceID" value="DEVICE001" required>
<input type="text" class="form-control" name="InvoiceData.DeviceID" value="NtuInvoiceGateway" required>
</div>
</div>

<div class="row mb-3">
<div class="col-md-6">
<label class="form-label">停車場站代號 (LocationID) *</label>
<input type="text" class="form-control" name="InvoiceData.LocationID" value="A" maxlength="1" required>
<input type="text" class="form-control" name="InvoiceData.LocationID" value="1" maxlength="1" required>
<small class="text-muted">1個字元</small>
</div>
<div class="col-md-6">
<label class="form-label">車牌號碼 (CarPlateNum) *</label>
<input type="text" class="form-control" name="InvoiceData.CarPlateNum" value="ABC1234" required>
<input type="text" class="form-control" name="InvoiceData.CarPlateNum" value="9M1234" required>
</div>
</div>

<div class="row mb-3">
<div class="col-md-6">
<label class="form-label">訂單編號 (OrderID) *</label>
<input type="text" class="form-control" name="InvoiceData.OrderID" value="ORDER20240115001" required>
<input type="text" class="form-control" name="InvoiceData.OrderID" value="@Model.CurrentOrderNo" required>
</div>
<div class="col-md-6">
<label class="form-label">稅別 (TaxType) *</label>
@@ -114,6 +123,21 @@
</ul>
</div>

<hr class="my-4">

<div class="card border-primary">
<div class="card-header bg-primary text-white">
<h5>JSON POST 測試(符合規格要求)</h5>
</div>
<div class="card-body">
<p class="text-success"><strong>✓ 此方式符合英特拉規格:Method: POST, 資料格式: JSON</strong></p>
<button type="button" class="btn btn-primary btn-lg w-100" onclick="testJsonPost()">
發送 JSON POST 請求到發票頁面
</button>
<div id="jsonResult" class="mt-3"></div>
</div>
</div>

<hr>

<div class="card bg-light">
@@ -127,5 +151,55 @@
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
async function testJsonPost() {
const resultDiv = document.getElementById('jsonResult');
resultDiv.innerHTML = '<div class="alert alert-info">發送中...</div>';

const form = document.querySelector('form');
if (!form) {
resultDiv.innerHTML = '<div class="alert alert-danger">找不到表單元素</div>';
return;
}

const formData = new FormData(form);
const jsonData = {
identifier: formData.get('InvoiceData.Identifier')?.toString() ?? '',
transDateTime: formData.get('InvoiceData.TransDateTime')?.toString() ?? '',
transAmount: formData.get('InvoiceData.TransAmount')?.toString() ?? '',
deviceID: formData.get('InvoiceData.DeviceID')?.toString() ?? '',
email: formData.get('InvoiceData.Email')?.toString() ?? '',
carrierID: formData.get('InvoiceData.CarrierID')?.toString() ?? '',
locationID: formData.get('InvoiceData.LocationID')?.toString() ?? '',
carPlateNum: formData.get('InvoiceData.CarPlateNum')?.toString() ?? '',
orderID: formData.get('InvoiceData.OrderID')?.toString() ?? '',
buyerIdentifier: formData.get('InvoiceData.BuyerIdentifier')?.toString() ?? '',
loveCode: '',
taxType: formData.get('InvoiceData.TaxType')?.toString() ?? ''
};

try {
const response = await fetch('/Invoice', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(jsonData)
});

if (response.ok) {
// JSON POST 成功,直接顯示返回的 HTML 頁面
const html = await response.text();
document.open();
document.write(html);
document.close();
} else {
resultDiv.innerHTML = `<div class="alert alert-danger">請求失敗: ${response.status}</div>`;
}
} catch (error) {
resultDiv.innerHTML = `<div class="alert alert-danger">發生錯誤: ${error.message}</div>`;
}
}
</script>
</body>
</html>

+ 14
- 0
Altob.NtuInvoiceGateway/Pages/TestPostInvoice.cshtml.cs Vedi File

@@ -1,9 +1,23 @@
using System;
using Altob.NtuInvoiceGateway.Models;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;

namespace Altob.NtuInvoiceGateway.Pages;

public class TestPostInvoiceModel : PageModel
{
public string CompanyTaxId { get; }
public string CurrentTransDateTime { get; }
public string CurrentOrderNo { get; }

public TestPostInvoiceModel(IOptions<CompanyInfo> companyInfo)
{
CompanyTaxId = companyInfo.Value.TaxId;
CurrentTransDateTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
CurrentOrderNo = DateTime.Now.ToString("ORDERyyyyMMddHHmmssfff");
}

public void OnGet()
{
}


+ 3
- 1
Altob.NtuInvoiceGateway/Program.cs Vedi File

@@ -7,6 +7,8 @@ builder.Services.AddHttpClient();
// Configure company info
builder.Services.Configure<Altob.NtuInvoiceGateway.Models.CompanyInfo>(
builder.Configuration.GetSection("CompanyInfo"));
builder.Services.Configure<Altob.NtuInvoiceGateway.Models.InvoiceApiOptions>(
builder.Configuration.GetSection("InvoiceApi"));

var app = builder.Build();

@@ -28,4 +30,4 @@ app.MapStaticAssets();
app.MapRazorPages()
.WithStaticAssets();

app.Run();
app.Run();

+ 3
- 0
Altob.NtuInvoiceGateway/appsettings.Development.json Vedi File

@@ -5,5 +5,8 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"InvoiceApi": {
"Endpoint": "http://192.168.110.72:22055/api/Intella/invoiceInfo"
}
}

+ 3
- 0
Altob.NtuInvoiceGateway/appsettings.json Vedi File

@@ -9,5 +9,8 @@
"CompanyInfo": {
"Name": "國立台灣大學臨時停車場",
"TaxId": "18384226"
},
"InvoiceApi": {
"Endpoint": "http://192.168.110.72:22055/api/Intella/invoiceInfo"
}
}

Loading…
Annulla
Salva