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
+287
View File
@@ -0,0 +1,287 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Text;
namespace
{
/// <summary>
/// EVERY8D 簡訊服務提供者
/// </summary>
public class EVERY8DSMSProvider : BaseSMSProvider
{
// EVERY8D API 相關常數
private static string BASE_URL = "https://new.e8d.tw/API21/HTTP";
private static string API_URL_SEND = string.Format("{0}/SendParam.ashx", BASE_URL);
private static string API_URL_CHECK_BALANCE = string.Format("{0}/GetCredit.ashx", BASE_URL);
/// <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 (!IsValidMobileNumber(message.Mobile))
{
failMessage = "手機號碼格式不正確";
return false;
}
var requestBody = new EVERY8DParamMMSBody
{
SB = message.Subject,
UID = message.MMSAccount,
PWD = message.MMSPassword,
ATTACHMENT = message.QRCode
};
requestBody.RecipientDataList.Add(new EVERY8DRecipient
{
Mobile = message.Mobile,
Param = message.Content,
});
string response = PostJson(API_URL_SEND, requestBody);
return ParseMMSResponse(response, out failMessage);
}
catch (Exception ex)
{
failMessage = ex.Message;
return false;
}
}
/// <summary>
/// 解析 EVERY8D API 回應
/// </summary>
private static bool ParseMMSResponse(string response, out string failMessage)
{
failMessage = "";
try
{
EVERY8DMMSResponse responseObj = JsonConvert.DeserializeObject<EVERY8DMMSResponse>(response.Trim());
if (responseObj.Result)
return true;
failMessage = GetErrorMessage(responseObj.Status);
return false;
}
catch
{
failMessage = string.Format("無法解析 API 回應:{0}", response);
return false;
}
}
/// <summary>
/// 取得錯誤訊息
/// </summary>
private static string GetErrorMessage(string status)
{
Dictionary<string, string> errorMessages = new Dictionary<string, string>
{
{ "-1", "參數錯誤,傳送失敗" },
{ "-2", "帳號或密碼錯誤,傳送失敗" },
{ "-3", "接收方屬於黑名單,傳送失敗" },
{ "-4", "預計發送時間超過24小時,傳送失敗" },
{ "-5", "內容長度超出限制,傳送失敗" },
{ "-8", "接收方手機號碼格式不符,傳送失敗" },
{ "-10", "接收方不支援MMS,傳送失敗" },
{ "-300", "帳號密碼不得為空" },
{ "101", "電信端回覆因收訊方手機關機、訊號不良、簡訊容量不足等異常原因,收訊失敗" },
{ "102", "電信端回覆因網路系統、設備出現異常,收訊失敗" },
{ "103", "電信端回覆因收訊方手機門號錯誤、空號或停用中,收訊失敗" },
{ "104", "因本手機門號為電信端之黑名單,故傳送失敗" },
{ "105", "電信端回覆經判斷因訊息內文含有敏感關鍵字進行阻擋,故傳送失敗" },
{ "106", "系統顯示經判斷因訊息內文含有敏感關鍵字進行阻擋,故傳送失敗" },
{ "301", "無額度(或額度不足)無法發送" },
{ "500", "表該門號為國際門號,請至帳號設定開啟國際簡訊發送功能" }
};
return errorMessages.ContainsKey(status) ? errorMessages[status] : string.Format("未知錯誤代碼:{0}", status);
}
/// <summary>
/// 驗證帳號額度
/// </summary>
public static bool CheckBalance(out int balance, out string errorMessage)
{
balance = 0;
errorMessage = "";
try
{
InitializeSecuritySettings();
var requestBody = new EVERY8DRequestBody();
string response = PostForm(API_URL_CHECK_BALANCE, requestBody.ToFormData());
if (decimal.TryParse(response, out decimal b))
{
balance = (int)b;
return true;
}
errorMessage = string.Format("餘額查詢失敗: {0}", response);
return false;
}
catch (Exception ex)
{
errorMessage = ex.Message;
return false;
}
}
}
/// <summary>
/// EVERY8D 簡訊接收者
/// </summary>
public class EVERY8DRecipient
{
[JsonProperty("Name")]
public string Name { get; set; }
[JsonProperty("Mobile")]
public string Mobile { get; set; }
[JsonProperty("Email")]
public string Email { get; set; }
[JsonProperty("SendTime")]
public string SendTime { get; set; }
[JsonProperty("Param")]
public string Param { get; set; }
public EVERY8DRecipient()
{
Name = string.Empty;
Mobile = string.Empty;
Email = string.Empty;
SendTime = string.Empty;
Param = string.Empty;
}
}
/// <summary>
/// EVERY8D 請求基礎類
/// </summary>
public class EVERY8DRequestBody
{
[JsonProperty("UID")]
public string UID { get; set; }
[JsonProperty("PWD")]
public string PWD { get; set; }
public EVERY8DRequestBody()
{
using (var dac = new DAC_MMSPlatform())
{
var platform = dac.SelectByCode(DAC_ProjectMMSAccount.EVERY8DPlatformCode);
if (platform != null)
{
UID = platform.Account;
PWD = platform.Password;
}
}
}
public NameValueCollection ToFormData()
{
var result = new NameValueCollection();
var properties = this.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
foreach (var property in properties)
{
var jsonPropertyAttr = property.GetCustomAttributes(typeof(JsonPropertyAttribute), false).FirstOrDefault() as JsonPropertyAttribute;
if (jsonPropertyAttr != null)
{
var value = property.GetValue(this, null);
result.Add(jsonPropertyAttr.PropertyName, value?.ToString() ?? string.Empty);
}
}
return result;
}
}
/// <summary>
/// EVERY8D MMS 請求
/// </summary>
public class EVERY8DParamMMSBody : EVERY8DRequestBody
{
[JsonProperty("SB")]
public string SB { get; set; }
[JsonProperty("ATTACHMENT")]
public string ATTACHMENT { get; set; }
[JsonProperty("TYPE")]
public string TYPE { get; set; }
[JsonProperty("RecipientDataList")]
public List<EVERY8DRecipient> RecipientDataList { get; }
public EVERY8DParamMMSBody()
{
SB = "活動通知";
ATTACHMENT = string.Empty;
TYPE = "png";
RecipientDataList = new List<EVERY8DRecipient>();
}
}
/// <summary>
/// EVERY8D MMS 回應
/// </summary>
public class EVERY8DMMSResponse
{
[JsonProperty("Result")]
public bool Result { get; set; }
[JsonProperty("Status")]
public string Status { get; set; }
[JsonProperty("Msg")]
public string Msg { get; set; }
}
/// <summary>
/// EVERY8D Credit 回應
/// </summary>
public class EVERY8DCreditResponse
{
[JsonProperty("Credit")]
public decimal Credit { get; set; }
[JsonProperty("Status")]
public string Status { get; set; }
[JsonProperty("Msg")]
public string Msg { get; set; }
}
}