| @@ -0,0 +1,11 @@ | |||||
| namespace Altob.NtuInvoiceGateway.Models; | |||||
| public class DonateGroup | |||||
| { | |||||
| public string DonateBan { get; set; } = string.Empty; | |||||
| public string DonateNm { get; set; } = string.Empty; | |||||
| public string DonateCode { get; set; } = string.Empty; | |||||
| public string DonateShortNm { get; set; } = string.Empty; | |||||
| public string HsnNm { get; set; } = string.Empty; | |||||
| public int Seq { get; set; } | |||||
| } | |||||
| @@ -0,0 +1,6 @@ | |||||
| namespace Altob.NtuInvoiceGateway.Models; | |||||
| public class DonateCodeApiOptions | |||||
| { | |||||
| public string Endpoint { get; set; } = string.Empty; | |||||
| } | |||||
| @@ -86,6 +86,10 @@ | |||||
| <label asp-for="InvoiceData.LoveCode" class="form-label">捐贈碼</label> | <label asp-for="InvoiceData.LoveCode" class="form-label">捐贈碼</label> | ||||
| <select asp-for="InvoiceData.LoveCode" class="form-control" id="loveCodeSelect"> | <select asp-for="InvoiceData.LoveCode" class="form-control" id="loveCodeSelect"> | ||||
| <option value="">請選擇捐贈機構</option> | <option value="">請選擇捐贈機構</option> | ||||
| @if (!string.IsNullOrEmpty(Model.InvoiceData.LoveCode)) | |||||
| { | |||||
| <option value="@Model.InvoiceData.LoveCode" selected>載入中... (@Model.InvoiceData.LoveCode)</option> | |||||
| } | |||||
| </select> | </select> | ||||
| <small class="form-text text-muted">選擇捐贈機構後即為捐贈發票</small> | <small class="form-text text-muted">選擇捐贈機構後即為捐贈發票</small> | ||||
| <span asp-validation-for="InvoiceData.LoveCode" class="text-danger"></span> | <span asp-validation-for="InvoiceData.LoveCode" class="text-danger"></span> | ||||
| @@ -120,6 +124,8 @@ | |||||
| document.addEventListener('DOMContentLoaded', function() { | document.addEventListener('DOMContentLoaded', function() { | ||||
| // 載入捐贈碼資料 | // 載入捐贈碼資料 | ||||
| const loveCodeSelect = $('#loveCodeSelect'); | const loveCodeSelect = $('#loveCodeSelect'); | ||||
| const selectedValue = loveCodeSelect.val(); // 保存送出失敗後返回的值 | |||||
| console.log('Initial loveCode value:', selectedValue); | |||||
| fetch('/Invoice?handler=DonateCodes') | fetch('/Invoice?handler=DonateCodes') | ||||
| .then(response => { | .then(response => { | ||||
| @@ -129,6 +135,10 @@ | |||||
| return response.json(); | return response.json(); | ||||
| }) | }) | ||||
| .then(data => { | .then(data => { | ||||
| // 移除臨時的"載入中"選項(除了第一個空值選項) | |||||
| loveCodeSelect.find('option:not(:first)').remove(); | |||||
| // 添加所有捐贈碼選項 | |||||
| data.forEach(item => { | data.forEach(item => { | ||||
| const optionText = `(${item.donateCode}) ${item.donateNm}`; | const optionText = `(${item.donateCode}) ${item.donateNm}`; | ||||
| const option = new Option(optionText, item.donateCode, false, false); | const option = new Option(optionText, item.donateCode, false, false); | ||||
| @@ -149,6 +159,12 @@ | |||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||
| // 恢復之前選擇的值 | |||||
| if (selectedValue) { | |||||
| loveCodeSelect.val(selectedValue).trigger('change'); | |||||
| console.log('Restored loveCode value:', selectedValue); | |||||
| } | |||||
| }) | }) | ||||
| .catch(error => { | .catch(error => { | ||||
| console.error('載入捐贈碼資料失敗:', error); | console.error('載入捐贈碼資料失敗:', error); | ||||
| @@ -37,7 +37,7 @@ public class InvoiceModel : PageModel | |||||
| _donateCodeApiOptions = donateCodeApiOptions.Value; | _donateCodeApiOptions = donateCodeApiOptions.Value; | ||||
| } | } | ||||
| [BindProperty] | |||||
| [BindProperty(SupportsGet = true)] | |||||
| public InvoiceRequest InvoiceData { get; set; } = new(); | public InvoiceRequest InvoiceData { get; set; } = new(); | ||||
| public string? ErrorMessage { get; set; } | public string? ErrorMessage { get; set; } | ||||
| @@ -53,7 +53,10 @@ public class InvoiceModel : PageModel | |||||
| public void OnGet() | public void OnGet() | ||||
| { | { | ||||
| RestoreDisplayValuesFromTempData(); | RestoreDisplayValuesFromTempData(); | ||||
| // GET 方法保留為空,主要接收方式改為 POST JSON | |||||
| NormalizeInvoiceData(); | |||||
| // 如果有 GET 參數,設置顯示資訊 | |||||
| DisplayTransDateTime = InvoiceData.TransDateTime; | |||||
| DisplayTransAmount = InvoiceData.TransAmount; | |||||
| } | } | ||||
| public async Task<IActionResult> OnGetDonateCodesAsync() | public async Task<IActionResult> OnGetDonateCodesAsync() | ||||
| @@ -266,7 +269,7 @@ public class InvoiceModel : PageModel | |||||
| if (!response.IsSuccessStatusCode) | if (!response.IsSuccessStatusCode) | ||||
| { | { | ||||
| ErrorMessage = $"提交失敗:{apiResponse?.msg ?? response.StatusCode.ToString()}"; | |||||
| ErrorMessage = $"送出失敗:{apiResponse?.msg ?? response.StatusCode.ToString()}"; | |||||
| _logger.LogWarning("{ServiceName} - {ActionName} submission failed with HTTP {StatusCode} for OrderID: {OrderID}", | _logger.LogWarning("{ServiceName} - {ActionName} submission failed with HTTP {StatusCode} for OrderID: {OrderID}", | ||||
| ServiceName, actionName, response.StatusCode, InvoiceData.OrderID); | ServiceName, actionName, response.StatusCode, InvoiceData.OrderID); | ||||
| return Page(); | return Page(); | ||||
| @@ -274,7 +277,7 @@ public class InvoiceModel : PageModel | |||||
| if (apiResponse?.msgCode == "0000") | if (apiResponse?.msgCode == "0000") | ||||
| { | { | ||||
| SuccessMessage = "發票資訊提交成功!"; | |||||
| SuccessMessage = "發票資訊送出成功!"; | |||||
| TempData[nameof(DisplayTransDateTime)] = DisplayTransDateTime; | TempData[nameof(DisplayTransDateTime)] = DisplayTransDateTime; | ||||
| TempData[nameof(DisplayTransAmount)] = DisplayTransAmount; | TempData[nameof(DisplayTransAmount)] = DisplayTransAmount; | ||||
| _logger.LogInformation("{ServiceName} - {ActionName} submitted successfully for OrderID: {OrderID}", | _logger.LogInformation("{ServiceName} - {ActionName} submitted successfully for OrderID: {OrderID}", | ||||
| @@ -283,7 +286,7 @@ public class InvoiceModel : PageModel | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| ErrorMessage = $"提交失敗:{apiResponse?.msg ?? "未知錯誤"}"; | |||||
| ErrorMessage = $"送出失敗:{apiResponse?.msg ?? "未知錯誤"}"; | |||||
| _logger.LogWarning("{ServiceName} - {ActionName} submission failed: {Message}", ServiceName, actionName, apiResponse?.msg); | _logger.LogWarning("{ServiceName} - {ActionName} submission failed: {Message}", ServiceName, actionName, apiResponse?.msg); | ||||
| } | } | ||||
| } | } | ||||
| @@ -102,6 +102,10 @@ | |||||
| <label class="form-label">購買者統編 (BuyerIdentifier)</label> | <label class="form-label">購買者統編 (BuyerIdentifier)</label> | ||||
| <input type="text" class="form-control" name="InvoiceData.BuyerIdentifier" placeholder="留空讓用戶填寫"> | <input type="text" class="form-control" name="InvoiceData.BuyerIdentifier" placeholder="留空讓用戶填寫"> | ||||
| </div> | </div> | ||||
| <div class="col-md-6"> | |||||
| <label class="form-label">捐贈碼 (LoveCode)</label> | |||||
| <input type="text" class="form-control" name="InvoiceData.LoveCode" placeholder="留空讓用戶填寫"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| <div class="d-grid gap-2"> | <div class="d-grid gap-2"> | ||||
| @@ -117,8 +121,8 @@ | |||||
| <h5>POST 測試說明</h5> | <h5>POST 測試說明</h5> | ||||
| <ul> | <ul> | ||||
| <li>所有必填欄位都會 POST 到發票頁面</li> | <li>所有必填欄位都會 POST 到發票頁面</li> | ||||
| <li>Email、手機條碼、購買者統編如果留空,將在發票頁面讓用戶填寫</li> | |||||
| <li>如果預填了這三個欄位的其中一個,用戶將直接看到該預填值</li> | |||||
| <li>Email、手機條碼、購買者統編、捐贈碼如果留空,將在發票頁面讓用戶填寫</li> | |||||
| <li>如果預填了這四個欄位的其中一個,用戶將直接看到該預填值</li> | |||||
| <li>此頁面包含有效的防偽令牌(CSRF Token)</li> | <li>此頁面包含有效的防偽令牌(CSRF Token)</li> | ||||
| </ul> | </ul> | ||||
| </div> | </div> | ||||
| @@ -174,7 +178,7 @@ | |||||
| carPlateNum: formData.get('InvoiceData.CarPlateNum')?.toString() ?? '', | carPlateNum: formData.get('InvoiceData.CarPlateNum')?.toString() ?? '', | ||||
| orderID: formData.get('InvoiceData.OrderID')?.toString() ?? '', | orderID: formData.get('InvoiceData.OrderID')?.toString() ?? '', | ||||
| buyerIdentifier: formData.get('InvoiceData.BuyerIdentifier')?.toString() ?? '', | buyerIdentifier: formData.get('InvoiceData.BuyerIdentifier')?.toString() ?? '', | ||||
| loveCode: '', | |||||
| loveCode: formData.get('InvoiceData.LoveCode')?.toString() ?? '', | |||||
| taxType: formData.get('InvoiceData.TaxType')?.toString() ?? '' | taxType: formData.get('InvoiceData.TaxType')?.toString() ?? '' | ||||
| }; | }; | ||||
| @@ -0,0 +1,16 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <!-- https://go.microsoft.com/fwlink/?LinkID=208121. --> | |||||
| <Project> | |||||
| <PropertyGroup> | |||||
| <DeleteExistingFiles>false</DeleteExistingFiles> | |||||
| <ExcludeApp_Data>false</ExcludeApp_Data> | |||||
| <LaunchSiteAfterPublish>true</LaunchSiteAfterPublish> | |||||
| <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration> | |||||
| <LastUsedPlatform>Any CPU</LastUsedPlatform> | |||||
| <PublishProvider>FileSystem</PublishProvider> | |||||
| <PublishUrl>D:\Output\Altob.NtuInvoiceGateway</PublishUrl> | |||||
| <WebPublishMethod>FileSystem</WebPublishMethod> | |||||
| <_TargetId>Folder</_TargetId> | |||||
| <EnvironmentName>Production</EnvironmentName> | |||||
| </PropertyGroup> | |||||
| </Project> | |||||
| @@ -0,0 +1,16 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <!-- https://go.microsoft.com/fwlink/?LinkID=208121. --> | |||||
| <Project> | |||||
| <PropertyGroup> | |||||
| <DeleteExistingFiles>false</DeleteExistingFiles> | |||||
| <ExcludeApp_Data>false</ExcludeApp_Data> | |||||
| <LaunchSiteAfterPublish>true</LaunchSiteAfterPublish> | |||||
| <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration> | |||||
| <LastUsedPlatform>Any CPU</LastUsedPlatform> | |||||
| <PublishProvider>FileSystem</PublishProvider> | |||||
| <PublishUrl>D:\Output\Altob.NtuInvoiceGateway</PublishUrl> | |||||
| <WebPublishMethod>FileSystem</WebPublishMethod> | |||||
| <_TargetId>Folder</_TargetId> | |||||
| <EnvironmentName>Staging</EnvironmentName> | |||||
| </PropertyGroup> | |||||
| </Project> | |||||
| @@ -73,7 +73,7 @@ | |||||
| </h3> | </h3> | ||||
| </div> | </div> | ||||
| <div class="card-body"> | <div class="card-body"> | ||||
| <h5 class="card-title text-success">表單提交方式轉頁</h5> | |||||
| <h5 class="card-title text-success">表單送出方式轉頁</h5> | |||||
| <p class="card-text">使用 HTTP POST 方法傳遞參數到發票頁面</p> | <p class="card-text">使用 HTTP POST 方法傳遞參數到發票頁面</p> | ||||
| <hr> | <hr> | ||||
| <h6 class="text-muted">特點:</h6> | <h6 class="text-muted">特點:</h6> | ||||
| @@ -124,6 +124,7 @@ | |||||
| <li>消費者信箱 (email)</li> | <li>消費者信箱 (email)</li> | ||||
| <li>手機條碼 (carrierID)</li> | <li>手機條碼 (carrierID)</li> | ||||
| <li>購買者統編 (buyerIdentifier)</li> | <li>購買者統編 (buyerIdentifier)</li> | ||||
| <li>捐贈碼 (loveCode)</li> | |||||
| </ul> | </ul> | ||||
| <div class="alert alert-warning mt-2"> | <div class="alert alert-warning mt-2"> | ||||
| <small><strong>注意:</strong>選填參數可以預填,也可以留空讓用戶在發票頁面填寫</small> | <small><strong>注意:</strong>選填參數可以預填,也可以留空讓用戶在發票頁面填寫</small> | ||||
| @@ -85,6 +85,10 @@ | |||||
| <label class="form-label">購買者統編 (buyerIdentifier)</label> | <label class="form-label">購買者統編 (buyerIdentifier)</label> | ||||
| <input type="text" class="form-control" name="buyerIdentifier" placeholder="87654321"> | <input type="text" class="form-control" name="buyerIdentifier" placeholder="87654321"> | ||||
| </div> | </div> | ||||
| <div class="col-md-6"> | |||||
| <label class="form-label">捐贈碼 (loveCode)</label> | |||||
| <input type="text" class="form-control" name="loveCode" placeholder="123456"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| <div class="d-grid gap-2"> | <div class="d-grid gap-2"> | ||||
| @@ -110,6 +114,10 @@ | |||||
| class="btn btn-outline-secondary"> | class="btn btn-outline-secondary"> | ||||
| 測試連結 3 - 預填手機條碼 | 測試連結 3 - 預填手機條碼 | ||||
| </a> | </a> | ||||
| <a href="/Invoice?identifier=12345678&transDateTime=2024-01-15%2014:30:00&transAmount=150&deviceID=DEVICE001&locationID=A&carPlateNum=ABC1234&orderID=ORDER004&taxType=1&loveCode=123456" | |||||
| class="btn btn-outline-secondary"> | |||||
| 測試連結 4 - 預填捐贈碼 | |||||
| </a> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||