2017年10月19日 星期四

C# 簡易電子發票資料Turnkey交換範例

 C# 簡易電子發票資料Turnkey交換範例

        雖然財政部所提供的Turnkey軟體中 tv-gateway-einv-1.2.11.jar( 2020/12/25 更新:Tunkey 2.0.2版位於 cht-gateway-einv-2.0.0.0.jar )已經有建立各版本的資料交換完整的物件,考慮到java在目前公司尚未有人可以協助維護,所以想了一個比較簡易型套用樣版的方式來執行為了簡單快速,省去物件的建模,一切從簡有些XSD中的選填元素沒有一定得上拋就直接省略。

2020/12/25 補充: XSD 可以透過工具轉成 XML,可google關鍵字  XSD to XML

樣版工具使用:Mustache sharp 可至NuGet下載

程式碼參考如下:

主程式:Program.cs

其中利用 XmlReader 物件載入xsd來進行驗證xml產出是否符合規範

電子發票資料交換xsd檔可在tv-gateway-einv-1.2.11.jar中找到(參考附註)


樣版檔:templateA0401.txt

A0401物件:InvoiceA0401.csInvoiceA0401ProductItem.cs

完整程式可至GitHub下載


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ENVITest
{
class InvoiceA0401
{
/// <summary>
/// 發票號碼
/// </summary>
public string InvoiceNumber;
/// <summary>
/// 發票產生日期
/// </summary>
public string InvoiceDate;
/// <summary>
/// 發票產生時間
/// </summary>
public string InvoiceTime;
/// <summary>
/// 賣方-營業人統一編號
/// </summary>
public string SellerIdentifier;
/// <summary>
/// 賣方-營業人名稱
/// </summary>
public string SellerName;
/// <summary>
/// 買方-營業人統一編號
/// </summary>
public string BuyerIdentifier;
/// <summary>
/// 買方-營業人名稱
/// </summary>
public string BuyerName;
/// <summary>
/// 發票類別 詳細定義請參考InvoiceTypeEnum 資料元規格
/// 01:三聯式
/// 02:二聯式
/// 03:二聯式收銀機
/// 04:特種稅額
/// 05:電子計算機
/// 06:三聯式收銀機
/// 07:一般稅額計算之電子發票
/// 08:特種稅額計算之電子發票
/// </summary>
///
public string InvoiceType;
/// <summary>
/// 彙開註記(選項) 彙開需要填入"*"
/// </summary>
public string GroupMark;
/// <summary>
/// 捐贈註記 詳細定義請參考DonateMarkEnum 資料元規格
/// </summary>
public string DonateMark;
/// <summary>
/// 發票金額
/// </summary>
public string SalesAmount;
/// <summary>
/// 稅 類別
/// </summary>
public string TaxType;
/// <summary>
/// 稅制
/// </summary>
public string TaxRate;
/// <summary>
/// 稅額
/// </summary>
public string TaxAmount;
/// <summary>
/// 發票含稅
/// </summary>
public string TotalAmount;
/// <summary>
/// 折讓金額
/// </summary>
public string DiscountAmount;
/// <summary>
/// 外幣原幣金額 (選項)
/// </summary>
public string OriginalCurrencyAmount;
/// <summary>
/// 匯率 (選項)
/// </summary>
public string ExchangeRate;
public List<InvoiceA0401ProductItem> ProductItems;
}
}
view raw InvoiceA0401.cs hosted with ❤ by GitHub
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ENVITest
{
class InvoiceA0401ProductItem
{
/// <summary>
/// 產品名稱
/// </summary>
public string Description;
/// <summary>
/// 數量
/// </summary>
public string Quantity;
/// <summary>
/// 單位
/// </summary>
public string Unit;
/// <summary>
/// 單價(本幣)
/// </summary>
public string UnitPrice;
/// <summary>
/// 小計金額
/// </summary>
public string Amount;
/// <summary>
/// 序號
/// </summary>
public string SequenceNumber;
}
}
using Mustache;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace ENVITest
{
class Program
{
static void Main(string[] args)
{
string templatePath = @"templateA0401.txt";
String templateA0401 = File.ReadAllText(templatePath);
HtmlFormatCompiler compiler = new HtmlFormatCompiler();
Generator generator = compiler.Compile(templateA0401);
InvoiceA0401 InvoiceA0401 = new InvoiceA0401();
InvoiceA0401.InvoiceNumber = "QE00000000";
InvoiceA0401.InvoiceDate = "20171019";
InvoiceA0401.InvoiceTime = "16:20:17";
InvoiceA0401.SellerIdentifier = "1234567890";
InvoiceA0401.SellerName = "家裡蹲";
InvoiceA0401.BuyerIdentifier = "0123456789";
InvoiceA0401.BuyerName = "廁所蹲";
InvoiceA0401.GroupMark = "*";
InvoiceA0401.DonateMark = "0";
InvoiceA0401.InvoiceType = "07";
InvoiceA0401.SalesAmount = "0";
InvoiceA0401.TaxType = "1";
InvoiceA0401.TaxRate = "0.05";
InvoiceA0401.TaxAmount = "5";
InvoiceA0401.DiscountAmount = "0";
InvoiceA0401.TotalAmount = "105";
InvoiceA0401.DiscountAmount = "0";
InvoiceA0401.ProductItems = new List<InvoiceA0401ProductItem>();
InvoiceA0401ProductItem productItem = new InvoiceA0401ProductItem();
productItem.Description = "測試品項";
productItem.Quantity = "1";
productItem.Unit = "個";
productItem.UnitPrice = "100";
productItem.Amount = "100";
productItem.SequenceNumber = "1";
InvoiceA0401.ProductItems.Add(productItem);
string resultXML = generator.Render(new
{
InvoiceA0401 = InvoiceA0401
});
//驗證產出的XML是否符合xsd的規範
XmlReaderSettings xmlReadersettings = new XmlReaderSettings();
xmlReadersettings.Schemas.Add("urn:GEINV:eInvoiceMessage:A0401:3.1",@"EInvoiceXSD/v31/A0401.xsd");
xmlReadersettings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create(new StringReader(resultXML), xmlReadersettings);
XmlDocument document = new XmlDocument();
try
{
document.Load(reader);
Console.Out.WriteLine(String.Format("XML產出完成"));
System.Diagnostics.Debug.WriteLine("XML產出完成");
System.Diagnostics.Debug.WriteLine(resultXML);
}
catch (XmlSchemaValidationException ex)
{
Console.Out.WriteLine(String.Format("<p>XML驗證錯誤: {0}</p>", ex.Message));
System.Diagnostics.Debug.WriteLine(String.Format("<p>XML驗證錯誤: {0}</p>", ex.Message));
}
}
}
}
view raw Program.cs hosted with ❤ by GitHub
<?xml version="1.0" encoding="utf-8"?>
<Invoice xsi:schemaLocation="urn:GEINV:eInvoiceMessage:A0401:3.1 A0401.xsd" xmlns="urn:GEINV:eInvoiceMessage:A0401:3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Main>
<InvoiceNumber>{{InvoiceA0401.InvoiceNumber}}</InvoiceNumber>
<InvoiceDate>{{InvoiceA0401.InvoiceDate}}</InvoiceDate>
<InvoiceTime>{{InvoiceA0401.InvoiceTime}}</InvoiceTime>
<Seller>
<Identifier>{{InvoiceA0401.SellerIdentifier}}</Identifier>
<Name>{{InvoiceA0401.SellerName}}</Name>
</Seller>
<Buyer>
<Identifier>{{InvoiceA0401.BuyerIdentifier}}</Identifier>
<Name>{{InvoiceA0401.BuyerName}}</Name>
</Buyer>
<InvoiceType>{{InvoiceA0401.InvoiceType}}</InvoiceType>
{{#if InvoiceA0401.GroupMark}}
<GroupMark>*</GroupMark>
{{/if}}
<DonateMark>{{InvoiceA0401.DonateMark}}</DonateMark>
</Main>
<Details>
{{#each InvoiceA0401.ProductItems}}
<ProductItem>
<Description>{{Description}}</Description>
<Quantity>{{Quantity}}</Quantity>
<Unit>{{Unit}}</Unit>
<UnitPrice>{{UnitPrice}}</UnitPrice>
<Amount>{{Amount}}</Amount>
<SequenceNumber>{{SequenceNumber}}</SequenceNumber>
</ProductItem>
{{/each}}
</Details>
<Amount>
<SalesAmount>{{InvoiceA0401.SalesAmount}}</SalesAmount>
<TaxType>{{InvoiceA0401.TaxType}}</TaxType>
<TaxRate>{{InvoiceA0401.TaxRate}}</TaxRate>
<TaxAmount>{{InvoiceA0401.TaxAmount}}</TaxAmount>
<TotalAmount>{{InvoiceA0401.TotalAmount}}</TotalAmount>
<DiscountAmount>{{InvoiceA0401.DiscountAmount}}</DiscountAmount>
{{#if InvoiceA0401.OriginalCurrencyAmount}}
<OriginalCurrencyAmount>{{InvoiceA0401.OriginalCurrencyAmount}}</OriginalCurrencyAmount>
{{/if}}
{{#if InvoiceA0401.ExchangeRate}}
<ExchangeRate>{{InvoiceA0401.exchangeRate}}</ExchangeRate>
{{/if}}
</Amount>
</Invoice>

附註:安裝完Turnkey程式後可在 C:\Program Files\EINVTurnkey\lib 下找到 tv-gateway-einv-1.2.11.jar ( 2020/12/25 更新:Tunkey 2.0.2版位於 cht-gateway-einv-2.0.0.0.jar )

透過解壓縮工具解開後的xsd資料夾中可發現各版本的xsd都位於此