同大陸身份證驗證一樣,該部分是按照國家增值稅發票代碼的定製規則,進行發票代碼驗證,如果需要查驗發票信息是否正確,應該通過第三方介面(大約一毛錢查驗一次),或者直接上 "國家稅務總局全國增值稅發票查驗平臺" 進行查驗。 目前能識別的增值稅發票代碼包含以下幾類: 增值稅專用發票 , 增值稅普通發票(紙質 ...
同大陸身份證驗證一樣,該部分是按照國家增值稅發票代碼的定製規則,進行發票代碼驗證,如果需要查驗發票信息是否正確,應該通過第三方介面(大約一毛錢查驗一次),或者直接上國家稅務總局全國增值稅發票查驗平臺進行查驗。
目前能識別的增值稅發票代碼包含以下幾類:增值稅專用發票,增值稅普通發票(紙質非捲票),增值稅普通發票(捲票),增值稅電子普通發票。在類庫中,增值稅代碼驗證相關的代碼均在NumberValidators.Invoices
下,其包含介面定義以及具體實現。
IVATCodeValidator
(增值稅代碼識別介面)定義如下:
/// <summary>
/// 增值稅發票代碼驗證介面
/// </summary>
public interface IVATCodeValidator <out TResult>: IValidator<TResult>
where TResult : VATCodeValidationResult, new()
{
/// <summary>
/// 用於驗證的字典數據
/// </summary>
IValidationDictionary<int, string> Dictionary { get; set; }
/// <summary>
/// 生成增值稅發票代碼
/// </summary>
/// <param name="areaNumber">行政區劃</param>
/// <param name="year">年份</param>
/// <param name="batch">批次</param>
/// <param name="kind">要生成的發票類型</param>
/// <returns></returns>
string GenerateVATCode(int areaNumber, ushort year, ushort batch, VATKind kind);
/// <summary>
/// 發票代碼驗證
/// </summary>
/// <param name="vatCode">待驗證的發票代碼</param>
/// <param name="kind">要驗證的發票類型,不指定則傳null</param>
/// <param name="minYear">允許的最小年份(註:2012年1月1日營改增開始上海試點)</param>
/// <returns></returns>
TResult Validate(string vatCode, VATKind? kind = null, ushort minYear = 2012);
}
增值稅發票代碼驗證定義了兩種驗證結果
VATCodeValidationResult
這是預設驗證結果,其定義如下:
/// <summary>
/// 增值稅發票代碼驗證結果
/// </summary>
public class VATCodeValidationResult : ValidationResult
{
/// <summary>
/// 行政區劃代碼
/// </summary>
public int AreaNumber { get; internal set; }
/// <summary>
/// 行政區功能變數名稱稱
/// </summary>
public string AreaName { get; internal set; }
/// <summary>
/// 發票類型
/// </summary>
public VATKind? Category { get; internal set; }
/// <summary>
/// 印刷年份
/// </summary>
public int Year { get; internal set; }
/// <summary>
/// 印刷批次
/// </summary>
public int Batch { get; internal set; }
/// <summary>
/// 發票聯次,僅10位長度和12位長度摺疊票發票才有
/// </summary>
public int DuplicateNumber { get; internal set; }
}
VATCode10ValidationResult
是在VATCodeValidationResult
的基礎上,額外定義了發票金額版本,其定義如下:
/// <summary>
/// 增值稅發票和普通(紙質)專有的驗證結果
/// </summary>
public class VATCode10ValidationResult : VATCodeValidationResult
{
/// <summary>
/// 發票金額版本號,僅10位長度發票才有
/// </summary>
public AmountVersion AmountVersion { get; internal set; }
}
可根據IsValid
來判斷驗證是否成功,如果驗證失敗,Errors 屬性則包含了驗證失敗的原因,具體的錯誤原因列表如下
/// <summary>
/// 發票代碼為空
/// </summary>
public const string Empty = "發票代碼為空";
/// <summary>
/// 錯誤的發票代碼
/// </summary>
public const string Error = "錯誤的發票代碼";
/// <summary>
/// 發票年份超出允許的年份範圍
/// </summary>
public const string YearOutOfRange = "發票年份超出允許的年份範圍{0} ~ {1}";
/// <summary>
/// 發票發行區域識別失敗
/// </summary>
public const string InvalidArea = "發票發行區域識別失敗";
/// <summary>
/// 無效的發票類別
/// </summary>
public const string InvalidKind = "無效的發票類別";
/// <summary>
/// 發票類別錯誤,無法生成發票代碼
/// </summary>
public const string GenerateWrongKind = "發票類別錯誤,無法生成發票代碼";
/// <summary>
/// 無效實現
/// </summary>
public const string InvalidImplement = "未能找到或無效的 {0} 位發票代碼實現";
/// <summary>
/// 長度不符
/// </summary>
public const string LengthOutOfRange = "發票代碼非 {0} 位";
因為目前類庫中已經完整收集了所有發票代碼中支持的行政區劃編號(可在航信官網上查看都有哪些區域存在稅務局),所以暫時不再需要自行傳遞Dictionary
來進行支持區域的修正。
目前IVATCodeValidator
包含VATCode10Validator
以及VATCode12Validator
兩種具體實現
VATCode10Validator
對應長度為10的發票代碼,包含增值稅專用發票、增值稅普通發票VATCode12Validator
對應長度為12的發票代碼,包含增值稅普通發票、增值稅普通發票(捲票)、增值稅電子普通發票VATCodeValidatorHelper
為靜態類,用於輔助驗證,其內部簡單的封裝了按發票代碼長度調用對應的IVATCodeValidator
實現
使用例子如下
Console.WriteLine("***增值稅發票***");
var vat10Validator = new VATCode10Validator();
var vat12Validator = new VATCode12Validator();
Console.WriteLine("隨機的增值稅發票:" + vat10Validator.GenerateRandomNumber());
Console.WriteLine("生成指定的增值稅專用發票:" + vat10Validator.GenerateVATCode(3700, 2017, 1, Invoices.VATKind.Special));
Console.WriteLine("生成指定的10位增值稅普通發票:" + vat10Validator.GenerateVATCode(1100, 2017, 2, Invoices.VATKind.Plain));
Console.WriteLine("生成指定的12位增值稅普通發票:" + vat12Validator.GenerateVATCode(1100, 2018, 6, Invoices.VATKind.Plain));
Console.WriteLine("隨機的增值稅電子/捲票/普票:" + vat12Validator.GenerateRandomNumber());
string[] vatArr = { "031001600311", "3100153130", "011001800304" };
foreach (var vat in vatArr)
{
var valid = VATCodeValidatorHelper.Validate(vat, minYear: 2012);
Console.WriteLine("{0}驗證結果:{1} 類型{2} 行政區劃名稱({3}) 驗證結果類型:{4}", vat, valid.IsValid, valid.Category, valid.AreaName, valid);
}
PS:目前1.0版本中VATCode12Validator
未支持12位的增值稅普通發票,如果需要支持,需從git上下載代碼後自行生成dll