chore: 首次簽入 Thinkyu ASP.NET 專案

- 加入 Visual Studio / ASP.NET .gitignore
- 排除建置輸出、IDE 設定、NuGet packages、大型 MSI 安裝檔
This commit is contained in:
2026-09-10 09:42:37 +08:00
commit 577060bc78
2496 changed files with 501389 additions and 0 deletions
+309
View File
@@ -0,0 +1,309 @@
using Newtonsoft.Json;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Mail;
using System.Text;
using WebLib;
namespace
{
/// <summary>
/// 三竹(MITAKE)簡訊服務提供者
/// </summary>
public class MITAKESMSProvider : BaseSMSProvider
{
private const string ApiBaseUrl = "https://message.mitake.com.tw";
/// <summary>
/// 驗證帳號密碼是否正確,回傳 token(如果驗證成功)或錯誤訊息(如果驗證失敗)
/// </summary>
/// <returns></returns>
private static bool Authenticate(out string token)
{
token = string.Empty;
var responseStr = PostJson(ApiBaseUrl + "/AuthorizationService/Token",
new MITAKEAuthRequest()
);
var responseObj = JsonConvert.DeserializeObject<MITAKEAuthResponse>(responseStr);
if (responseObj != null && !string.IsNullOrEmpty(responseObj.AccessToken))
{
token = responseObj.AccessToken;
return true;
}
return false;
}
/// <summary>
/// 發送簡訊到指定手機號碼
/// </summary>
public static bool SendMMS(MessageQueueItem message, out string failMessage)
{
failMessage = "";
try
{
InitializeSecuritySettings();
if (string.IsNullOrEmpty(message.Mobile))
{
failMessage = "手機號碼不能為空";
return false;
}
if (string.IsNullOrEmpty(message.Content))
{
failMessage = "簡訊內容不能為空";
return false;
}
if (!Authenticate(out string token))
{
failMessage = "驗證失敗,無法取得存取權杖";
return false;
}
// 組裝簡訊發送請求
var smsRequest = new MITAKESMSRequest
{
Subject = message.Subject,
Content = message.Content,
};
smsRequest.Destinations.Add(new MITAKEDestination { To = message.Mobile });
smsRequest.Attachments.Add(new MITAKEAttachment
{
AttachType = "png",
AttachName = string.Format("attach_{0}.png", message.ID),
AttachContent = message.QRCode
});
// 組裝 HTTP 標頭
var smsHeaders = new Dictionary<string, string>
{
{ "authorization", "bearer " + token },
{ "content-type", "application/json" },
{ "clientID", message.MMSAccount },
{ "actionType", "push" }
};
// 發送簡訊請求
var smsResponseStr = PostJson(ApiBaseUrl + "/msg/mms/json", smsRequest, smsHeaders, 120);
var smsResponseObj = JsonConvert.DeserializeObject<MITAKESMSResponse>(smsResponseStr);
// 檢查回應結果
if (smsResponseObj == null)
{
return false;
}
if (smsResponseObj.Messages == null || smsResponseObj.Messages.Count == 0)
{
string responsePreview = smsResponseStr.Length > 400 ? smsResponseStr.Substring(0, 400) : smsResponseStr;
failMessage = $"簡訊發送失敗,未收到有效回應:({responsePreview})";
return false;
}
var firstMessage = smsResponseObj.Messages[0];
if (firstMessage.Status != "0" && firstMessage.Status != "1" && firstMessage.Status != "2")
{
failMessage = $"簡訊發送失敗,狀態碼:{firstMessage.Status},說明:{firstMessage.StatusDesc}";
return false;
}
return true;
}
catch (Exception ex)
{
failMessage = ex.Message;
return false;
}
}
/// <summary>
/// 查詢帳號餘額
/// </summary>
//public static bool CheckBalance(out int balance, out string errorMessage)
//{
// balance = 0;
// errorMessage = "";
// try
// {
// InitializeSecuritySettings();
// // TODO: 實作三竹查詢餘額邏輯
// // GET {ApiBaseUrl}/SmQueryGet.asp
// // ?username={account}
// // &password={password}
// // &CharsetURL=UTF-8
// //
// // 回傳格式:AccountPoint=100
// throw new NotImplementedException("三竹查詢餘額尚未實作");
// }
// catch (NotImplementedException)
// {
// errorMessage = "三竹查詢餘額尚未實作";
// return false;
// }
// catch (Exception ex)
// {
// errorMessage = ex.Message;
// return false;
// }
//}
}
/// <summary>
/// 三竹簡訊授權請求
/// </summary>
public class MITAKEAuthRequest
{
[JsonProperty("clientID")]
public string ClientID { get; set; }
[JsonProperty("clientSecret")]
public string ClientSecret { get; set; }
public MITAKEAuthRequest()
{
ClientID = string.Empty;
ClientSecret = string.Empty;
using (var conn = DAC.NewConnection())
{
var dac = new DAC_MMSPlatform(conn);
MMSPlatformItem item = dac.SelectByCode(PublicVariable.CurrentMMSPlatform);
if (item != null)
{
ClientID = item.Account;
ClientSecret = item.Password;
}
}
}
}
/// <summary>
/// 三竹簡訊授權回應
/// </summary>
public class MITAKEAuthResponse
{
[JsonProperty("accessToken")]
public string AccessToken { get; set; }
[JsonProperty("expiresIn")]
public int ExpiresIn { get; set; }
[JsonProperty("tokenType")]
public string TokenType { get; set; }
}
/// <summary>
/// 三竹簡訊接收者
/// </summary>
public class MITAKEDestination
{
[JsonProperty("to")]
public string To { get; set; }
[JsonProperty("cID")]
public string CID { get; set; }
public MITAKEDestination()
{
CID = Guid.NewGuid().ToString().Replace("-", "");
}
}
/// <summary>
/// 三竹簡訊附件
/// </summary>
public class MITAKEAttachment
{
[JsonProperty("attachContent")]
public string AttachContent { get; set; }
[JsonProperty("attachType")]
public string AttachType { get; set; }
[JsonProperty("attachName")]
public string AttachName { get; set; }
}
/// <summary>
/// 三竹簡訊發送請求
/// </summary>
public class MITAKESMSRequest
{
[JsonProperty("subject")]
public string Subject { get; set; }
[JsonProperty("content")]
public string Content { get; set; }
[JsonProperty("orderTime")]
public string OrderTime { get; set; }
[JsonProperty("expireTime")]
public string ExpireTime { get; set; }
[JsonProperty("destinations")]
public List<MITAKEDestination> Destinations { get; set; }
[JsonProperty("attachments")]
public List<MITAKEAttachment> Attachments { get; set; }
public MITAKESMSRequest()
{
Subject = string.Empty;
Content = string.Empty;
OrderTime = PublicVariable.TaiwanNow.ToString("yyyyMMddHHmmss");
ExpireTime = PublicVariable.TaiwanNow.AddDays(1).ToString("yyyyMMddHHmmss");
Destinations = new List<MITAKEDestination>();
Attachments = new List<MITAKEAttachment>();
}
}
/// <summary>
/// 三竹簡訊發送回應項目
/// </summary>
public class MITAKESMSResponseItem
{
[JsonProperty("msgID")]
public string MsgID { get; set; }
[JsonProperty("cID")]
public string CID { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("statusDesc")]
public string StatusDesc { get; set; }
[JsonProperty("statusTime")]
public string StatusTime { get; set; }
[JsonProperty("point")]
public string Point { get; set; }
}
/// <summary>
/// 三竹簡訊發送回應
/// </summary>
public class MITAKESMSResponse
{
[JsonProperty("batchID")]
public string BatchID { get; set; }
[JsonProperty("messages")]
public List<MITAKESMSResponseItem> Messages { get; set; }
[JsonProperty("costPoints")]
public string CostPoints { get; set; }
}
}