einvoice 0.2.8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e81da9d745a37edf6cd7d91ba444787a1ffd70fe
4
- data.tar.gz: 5d3cbbd481ff54fb6b2ac53831d33a7f102864da
3
+ metadata.gz: a5e69679681ee049f816b49bfed94ba21d79ea4f
4
+ data.tar.gz: f35afbf92608c3076ef352ac849bc36a94043620
5
5
  SHA512:
6
- metadata.gz: b65eefa4b53987624bf1e242aa8321ed0ebef2af343ebb791a26d6630b9065604c97c66016162f12f36ed216c7d43a206b30d18b304bcca717a230277aa705e8
7
- data.tar.gz: 933d45a596c8264294b582db2868d618097e62a647ab1fd0fa5c1d67078a0168844780cf70192ffef58b932f2506158f3c5bf3db1e32cb4b9a29ef9f9f3d6c3a
6
+ metadata.gz: 7f6f42e32120b6752c2431cdb5db4d2c7fe0dd6d8fdeff460d4ee9e8d84afbde1c1cee4935ccc58c20fb77a9d968073dc622abafb136d9df81885e8e7a83fc5a
7
+ data.tar.gz: b0952bfcc6df37d28a120620a1bbe11ddf400aa99b996e0f6b817ba9c789fdfdae04fb5366b82736a4b7198f2d18be81a8cac0d9a929b682a6889f3deb546abb
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
 
11
11
  .DS_Store
12
12
  spec/examples.txt
13
+ .env
data/README.md CHANGED
@@ -9,12 +9,13 @@ To support the thriving e-commerce industry and lower the business costs and bar
9
9
 
10
10
  Hence, there are several e-invoice services for B2B, B2C in Taiwan as the intermediate and value-adding platform like CHT, allPay, Neweb, ..etc. They mostly provide services like below:
11
11
 
12
- * Manage e-invoices
13
- * Issue an e-invoice
14
- * Return an e-invoice
15
- * Invalidate an e-invoice
16
- * List e-invoices
17
- * Others
12
+ * Issue an new invoice
13
+ * Issue an existed invoice
14
+ * Query issued invoices
15
+ * Cancel an issued invoice
16
+ * Allowance of an invoice
17
+ * Cancel allowance of an invoice
18
+ * Manage invoice numbers
18
19
 
19
20
  Therefore, we need a API wrapper to manage and access the APIs.
20
21
 
@@ -36,24 +37,39 @@ Or install it yourself as:
36
37
 
37
38
  ## Usage
38
39
 
39
- Assume one of your customer just make an `@order` including all transaction info for your `@product`. After created the order you're ready to issue this invoice.
40
+ ### Supported E-Invoice Providers
40
41
 
41
- ### 1. Setup initializer with credentials
42
+ * [Neweb Technologies Co., Ltd.(藍新科技)](https://github.com/abookyun/einvoice/blob/master/docs/neweb.md)
43
+
44
+ ### Setup
42
45
 
43
46
  ```ruby
44
47
  Einvoice.configure do |setup|
45
48
  setup.endpoint = ENV['EINVOICE_ENDPOINT']
49
+ setup.endpoint_url = ENV['EINVOICE_ENDPOINT_URL']
46
50
  setup.client_id = ENV['EINVOICE_CLIENT_ID']
47
51
  setup.client_secret = ENV['EINVOICE_CLIENT_SECRET']
48
52
  setup.format = "xml"
49
53
  end
50
54
  ```
51
55
 
52
- ### 2. Create method for produce payload correspond to issuing action needs
56
+ ### Initialize a client with your provider e.g. Neweb
57
+
58
+ ```ruby
59
+ client = Einvoice::Client.new(Einvoice::Neweb::Provider.new)
60
+ ```
61
+
62
+ ### Issue an invoice
63
+
64
+ Assume one of your customer just make an `order` including all transaction info for your `product`. After created the order you're ready to issue this invoice.
65
+
66
+ #### Generate invoice payload
53
67
 
54
68
  ```ruby
55
- def invoice_payload(order)
56
- {
69
+ order = Order.find(params[:id])
70
+ product = order.product
71
+
72
+ payload = {
57
73
  data_number: "#{order.data_number}",
58
74
  data_date: "#{order.created_at}",
59
75
  seller_id: "#{order.product.seller_id}",
@@ -94,30 +110,52 @@ def invoice_payload(order)
94
110
  end
95
111
  ```
96
112
 
97
- ### 3. Initialize Einvoice::Client with your provider and fire the action
113
+ #### Issue an invoice and handle results
98
114
 
99
115
  ```ruby
100
- client = Einvoice::Client.new(Einvoice::Neweb::Provider.new)
101
- client.issue(invoice_payload)
116
+ result = client.issue(payload)
117
+
118
+ if result.success?
119
+ logger.info "Issue invoice for #{order.id} is successful."
120
+ else
121
+ logger.info "Issue invoice for #{order.id} is failed with #{result.errors}."
122
+ end
102
123
  ```
103
124
 
104
- See [More Providers docs]()
125
+ See [Einvoice::Result](https://github.com/abookyun/einvoice/blob/master/lib/einvoice/result.rb)
126
+
127
+ ### Query invoices
105
128
 
106
- ### 4. Handle Einvoice::Result object
129
+ #### Generate invoice payload
107
130
 
108
131
  ```ruby
109
- result = client.issue(invoice_payload)
110
- # => Einvoice::Result
132
+ payload = {
133
+ data_number_s: "order_number1",
134
+ data_number_e: "order_number5",
135
+ invoice_date_time_s: "201512010000",
136
+ invoice_date_time_e: "201501202359",
137
+ sync_status_update: "N"
138
+ }
139
+ ```
140
+
141
+ #### Query and handle results
111
142
 
143
+ ```ruby
144
+ result = client.query(data)
112
145
  if result.success?
113
- logger.info "Issue invoice for #{order.id} is successful."
146
+ result.data["InvoiceMap"].each do |data|
147
+ order_id = data.data_number
148
+ invoice_number = data.invoice_number
149
+ invoice_date = data.invoice_date #YYYY/MM/DD
150
+ invoice_time = data.invoice_time #HH:MM:SS(24h)
151
+ end
152
+
153
+ logger.info "Query invoice for #{order.id} is successful."
114
154
  else
115
155
  logger.info "Issue invoice for #{order.id} is failed with #{result.errors}."
116
156
  end
117
157
  ```
118
158
 
119
- See [Einvoice::Result](https://github.com/abookyun/einvoice/blob/master/lib/einvoice/result.rb)
120
-
121
159
  ## Development
122
160
 
123
161
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/bin/console CHANGED
@@ -7,8 +7,5 @@ require "einvoice"
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
10
  require "pry"
14
11
  Pry.start
data/docs/neweb.md ADDED
@@ -0,0 +1,347 @@
1
+ # Neweb Technologies Co., Ltd. 藍新科技電子發票 API 說明
2
+
3
+ ## Overview
4
+
5
+ ### Request
6
+
7
+ * 由商家申請後,由藍新提供正式主機與測試主機 `hostname` & `code`。
8
+ * Request URL:"#{hostname} + #{action}"
9
+ * 傳送方式:(1) 以 Form Post 方式傳送 (2) UTF-8 編碼
10
+ * 參數:
11
+ * `storecode`:商家代碼
12
+ * `xmldata`:URLEncoded XML
13
+ * `hash`:驗證碼 = MD5(urlencoded_xmldata + `code`)
14
+ * 範例(以 [httpie](https://github.com/jkbrzt/httpie) 為例):
15
+
16
+ ```shell
17
+ http --form POST ${HOSTNAME}/IN_PreInvoiceS.action storecode=${STORECODE} hash="d537a4807813c36816517b2a32994a35" xmldata="<InvoiceRoot><Invoice><InvoiceItem><Description>item1</Description><Quantity>1</Quantity><UnitPrice>10.0</UnitPrice><Amount>10.0</Amount><SequenceNumber>1</SequenceNumber></InvoiceItem><InvoiceItem><Description>item2</Description><Quantity>1</Quantity><UnitPrice>10.0</UnitPrice><Amount>10.0</Amount><SequenceNumber>2</SequenceNumber><Unit></Unit><Remark></Remark></InvoiceItem><DataNumber>12345</DataNumber><DataDate>2016/01/20</DataDate><SellerId>12345678</SellerId><BuyerName>name</BuyerName><BuyerId>0000000000</BuyerId><CustomsClearanceMark>1</CustomsClearanceMark><InvoiceType>07</InvoiceType><DonateMark>0</DonateMark><CarrierType></CarrierType><CarrierId1></CarrierId1><CarrierId2></CarrierId2><PrintMark>N</PrintMark><NPOBAN></NPOBAN><RandomNumber>AAAA</RandomNumber><SalesAmount>19</SalesAmount><FreeTaxSalesAmount>0</FreeTaxSalesAmount><ZeroTaxSalesAmount>0</ZeroTaxSalesAmount><TaxType>1</TaxType><TaxRate>0.05</TaxRate><TaxAmount>1</TaxAmount><TotalAmount>20</TotalAmount><Contact><Name>name</Name><Address>Taipei City</Address><TEL>0212341234</TEL><Email></Email></Contact></Invoice></InvoiceRoot>"
18
+ ```
19
+
20
+ ### Response
21
+
22
+ * 回應結構(各 APIs 略有不同):
23
+ * Result
24
+ * statcode
25
+ * statdesc
26
+ * data
27
+ * 範例:
28
+
29
+ ```xml
30
+ <Result>
31
+ <statcode>0000</statcode>
32
+ <statdesc></statdesc>
33
+ </Result>
34
+ ```
35
+ * 一般性回應碼與訊息對照表:
36
+
37
+ statcode | statdesc
38
+ ---------|---------
39
+ 0000 | OK
40
+ 6001 | 某 node 值不符合長度要求
41
+ 6002 | 某 node 值不符合型別要求(只檢查數型態)
42
+ 6003 | 某 node 值為必填,卻發生空值或是 node 不存在
43
+ 7001 | Xmldata 參數為空
44
+ 7002 | Hash 參數為空
45
+ 7003 | StoreCode 參數為空
46
+ 8001 | Hash 值不符合
47
+ 9998 | xmldata 結構有誤
48
+ 9999 | 系統異常
49
+
50
+ ## Issue an new invoice
51
+
52
+ * Request:
53
+ * Action:`IN_PreInvoiceS.action`
54
+ * XmlData:
55
+
56
+ Tag | Name | Required | Type | Length | Description
57
+ :---|:-----|:--------:|:----:|:------:|:-----------
58
+ InvoiceRoot | - | Y | - | - | -
59
+ &nbsp;&nbsp;&nbsp;&nbsp;Invoice | - | Y | - | - | -
60
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataNumber | 單據號碼 | Y | 英數 | 20 | (SellerId & DataNumber) 需唯一
61
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataDate | 單據日期 | Y | 英數 | 10 | 格式:`YYYY/MM/DD`
62
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SellerId | 賣方統一編號 | Y | 英數 | 10 | -
63
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BuyerName | 買方名稱 | Y | 英數 | 60 | * B2B:買方-營業人名稱。<br/>* B2C:買方-業者通知消費者之個人識別碼資料,共 4 位 ASCII 或 2 位全型中文。
64
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BuyerId | 買方統一編號 | Y | 英數 | 10 | * B2B:買方-營業人統一編號(BAN)。<br/>* B2C:買方-填滿 10 位數 字的 "0"。
65
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CustomsClearanceMark | 通關方式註記 | N | 數 | 1 | * '1': 非經海關出口<br/>* '2': 經海關出口(若為零稅率發票,此為必填欄位)
66
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceType | 發票類別 | Y | 英數 | 2 | * '01': 三聯式<br/>* '02': 二聯式<br/>* '03': 二聯式收銀機<br/>* '04': 特種稅額<br/>* '05': 電子計算機<br/>* '06': 三聯式收銀機<br/>* '07': 一般稅額計算之電子發票<br/>* '08': 特種稅額計算之電子發票<br/>* 電子發票僅適用第 7 項及 第 8 項
67
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DonateMark | 捐贈註記 | Y | 英數 | 1 | * '0':表示「非捐贈發票」<br/>* '1':表示為「捐贈發票」<br/>* 此部分資料須由消費者決定,網購業者可於網站畫面上新增欄位,讓消費者輸入資訊,範例請參考「電子發票網頁說明資訊.doc」,倘消費者於愛心碼欄位有輸入資訊,則此欄位值帶 '1',其餘皆帶 '0'。
68
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CarrierType | 載具類別 | N | 英數 | 6 | 填入平台配發的載具類別號碼,編碼規則:AA0000,第一碼行業別(英文),第二碼載具類別(英數),後四碼載具類別(序號)若現金消費無使用載具,請免填。消費者使用手機條碼索取含買方統編發票,則不論是否已列印紙本皆為必填。手機條碼:3J0002 手機載具相關資訊請參考財政部網頁若需使用網優載具進行發票代管服務,則此欄空白,由 EIVO 系統自動帶出值
69
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CarrierId1 | 載具顯碼id | N | 英數 | 64 | 填入載具外顯碼號碼,卡片上載列之卡片號碼資訊。若紙本電子發票已列印註記為 Y,此欄位必須為空白;若此欄位非空 白,則紙本電子發票已列印註記必須為 N。消費者使用手機條碼索取含買方統編發票,則不論是否已列印紙本皆為必填。若消費者使用手機載具索取發票,則須將消費者填寫之手機載具資訊帶入此欄,範例請參考「電子發票網頁說明資訊.doc」若需使用網優載具進行發票代管服務,則此欄空白,由本系統自動帶出值
70
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CarrierId2 | 載具隱碼id | N | 英數 | 64 | 填入載具內碼號碼,營業人應載入讀取工具所讀取之原始資訊。若紙本電子發票已列印註記為 Y,此欄位必須為空白;若此欄位非空白,則紙本電子發票已列印註記必須為 N。消費者使用手機條碼索取含買方統編發票,則不論是否已列印紙本皆為必填。若消費者使用手機載具索取發票,則須將消費者填寫之手機載具資訊帶入此欄,範例請參考「電子發票網頁說明資訊.doc」若需使用網優載具進行發票代管服務,則此欄空白,由本系統自動帶出值
71
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrintMark | 紙本電子發票已列印註記 | Y | 英 | 1 | * 'Y'/'N'<br/> * PrintMark 為 Y 時載具類別號碼,載具顯碼 ID, 載具隱碼 ID 必須為空白,捐贈註記必為 N。<br/>* 消費者使用手機條碼索取含買方統編發票,則不論是否已列印紙本,其載具類別號碼、載具顯碼 ID 和載具隱碼 ID 皆為必填。
72
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NPOBAN | 發票捐贈對象統一 | N | 英數 | 10 | 受捐贈者統一編號 BAN 捐贈愛心碼請將愛心碼資料 3-7 碼「完整」填入。愛心碼申請方式請參考財政部網頁
73
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RandomNumber | 發票防偽隨機碼 | N | 英數 | 4 | 交易當下隨機產生 4 位數值,少於 4 位者踢退;若為虛擬通路,則限填 "AAAA"
74
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceItem | - | - | - | - | 可重複
75
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Description | 品名 | Y | 英數 | 256 | - | - | - |
76
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity | 數量 | Y | 數 | 17 | * 商品數量:整數 12 位,小數 4 位。<br/>* 整數部分第一位不能有零,小數為零時不顯示小數點,負號請接於整數第一位前 Ex:999999999999.9999 Ex:-2356
77
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unit | 單位 | 選 | 英數 | 6 | 可為空白,商品單位, 除鋼鐵業外, 一般空白
78
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnitPrice | 單價 | Y | 數 | 17 | 商品單價 (未稅) 原幣報價,整數 12 位,小數 4 位。整數部分第一位不能有零,小數為零時不顯示小數點,負號請接於整數第一位前 Ex:999999999999.9999 Ex:-2356
79
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Amount | 金額 | Y | 數 | 17 | * 商品單價(未稅) * 數量:整數 12 位,小數 4 位。<br/>* 整數部分第一位不能有零,小數為零時不顯示小數點,負號請接於整數第一位前 Ex:999999999999.9999 Ex:-2356
80
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SequenceNumber | 明細排列序號 | Y | 英數 | 3 | 系統使用,不重複發票明細項目之排列序號, 第一筆商品標示 '1', 其餘接續編號
81
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Remark | 單一欄位備註 | N | 英數 | 40 | 可為空白,若為健康捐請於本項填寫"健康捐"
82
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SalesAmount | 應稅銷售額合計(新台幣) | Y | 數 | 12 | 整張發票應稅品銷售額合計 (未稅) 整數(小數點以下四捨五入),請注意銷售額合計不應為負數。
83
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeTaxSalesAmount | 免稅銷售額合計(新台幣) | Y | 數 | 12 | 整張發票免稅品銷售額合計整數(小數點以下四捨五入),若無需求則填 0,請注意銷售額合計不應為負數。
84
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ZeroTaxSalesAmount | 零稅率銷售額合計(新台幣) | Y | 數 | 12 | 整張發票零稅率品項銷售額合計整數(小數點以下四捨五入),若無需求則填 0,請注意銷售額合計不應為負數。
85
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TaxType | 課稅別 | Y | 英數 | 1 | <br/>* '1':應稅<br/>* '2':零稅率<br/>* '3':免稅<br/>* '4':應稅(特種稅率)<br/>* '9':混合應稅與免稅或零稅率 (限收銀機發票無法分辨時使用)
86
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TaxRate | 稅率 | Y | 數 | 6 | 範例: 稅率為 5% 時本欄位值為 0.05
87
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TaxAmount | 營業稅額 | Y | 數 | 12 | 整數(小數點以下四捨五入),填寫方式參閱註 1,請注意此項稅額不應為負數
88
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TotalAmount | 總計 | Y | 數 | 12 | 整數 (應稅銷售額合計 + 免稅銷售額合計 + 零稅率銷售額合計 + 營業稅額 = 此總計欄位),整數部分第一位不能有零,請注意此項總額不應為負數
89
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Contact | 郵件聯絡人資訊 | - | - | - | -
90
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name | 姓名 | Y | 英數 | 64 | 郵寄信封上收件人
91
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Address | 地址 | Y | 英數 | 128 | 郵寄信封上收件人地址
92
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEL | 電話 | N | 英數 | 64 | 聯絡人電話,若啟動簡訊通知服務則為收取簡訊電話,則此欄位必填
93
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Email | email | N | 英數 | 512 | 聯絡人 Email,若啟動 Email 通知服務則此欄位必填,若須設定多筆 Email 則 以;符號間隔,例: aa@aa.net;bb@bb.net
94
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CustomerDefined | 針對有印花稅需求者 | - | - | - | -
95
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProjectNo | 專案編號 | N | 英數 | 64 | -
96
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PurchaseNo | 採購案號 | N | 英數 | 64 | -
97
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StampDutyFlag | 顯示印花稅圖章 | N | 數 | 1 | 0:不需要 1:需要
98
+
99
+ 註一、營業稅額欄位之填寫方式,應依照加值型及非加值型營業稅法第三十二條規定:「營業人依第十四條規定計算之銷項稅額,買受人為營業人者,應與銷售額於統一發票上分別載明之;買受人為非營業人者,應與銷售額合計開立統一發票。」填寫。上傳整合服務平台的發票內容應與開立內容一致。
100
+
101
+ * Response:
102
+ * 回應結構與訊息對照表:
103
+
104
+ Tag | Name | Required | Type | Length | Description
105
+ :---|:-----|:--------:|:----:|:------:|:-----------
106
+ Result | - | Y | - | - | -
107
+ &nbsp;&nbsp;&nbsp;&nbsp;statcode | 錯誤代碼 | Y | - | - | -
108
+ &nbsp;&nbsp;&nbsp;&nbsp;statdesc | 錯誤描述 | Y | - | - | -
109
+
110
+ ----
111
+
112
+ statcode | statdesc | description
113
+ :-------:|:---------|:-----------
114
+ 7001 | SellerId 不符 | StoreCode 取得商店統一編號與 <SellerId/>是否相同或該 <SellerId/> 必須存在於該商家的分支統編中
115
+ 7002 | 單據號碼重複 | 以 <SellerId/> And <DataNumber/> 為條件確認資料庫資料不可有重複。
116
+ 7003 | B2C 模式 BuyerName 不符合 | 若 <BuyerId/> 值等於 10 位的 '0',則 <BuyerName/> 必須符合共 4 位 ASCII 或 2 位全型中文。
117
+ 7004 | CustomsClearanceMark 資料不符 | <CustomsClearanceMark/>若有填寫,必須為 1 或 2
118
+ 7005 | InvoiceType 資料不符 | <InvoiceType/>值必須為「01、02、03、04、05、06」其中一個
119
+ 7006 | DonateMark 資料不符 | <DonateMark/>必須為 0 或 1
120
+ 7007 | 捐贈發票 NPOBAN 資料不可為空 | <DonateMark/> 當值等於 '1' 時,則 <NPOBAN/> 不可為空值
121
+ 7008 | PrintMark 為紙本電子發票已列印時, CarrierId1, CarrierId2, DonateMark 不符合要求 | <PrintMark/> 值=Y,則<CarrierId1/>載具顯碼 ID, <CarrierId2/> 載具隱碼 ID 必須為空白, <DonateMark/>捐贈註記必為 N
122
+ 7009 | RandomNumber 資料長度不符 | <RandomNumber/> 若非為空值時,則長度不可小於四位。
123
+ 7010 | SequenceNumber 不可重複 | <SequenceNumber/> 不可重複
124
+ 7011 | SalesAmount 為負值 | <SalesAmount/> 不可為負數
125
+ 7012 | FreeTaxSalesAmount 為負值 | <FreeTaxSalesAmount/> 不可為負數
126
+ 7013 | ZeroTaxSalesAmount 為負值 | <ZeroTaxSalesAmount/> 不可為負數
127
+ 7014 | TaxType 資料不符 | <TaxType/> 值限為「1、2、3、4、9」其中一項
128
+ 7015 | TaxAmount 為負值 | <TaxAmount/> 不可為負數
129
+ 7016 | TotalAmount 為負值 | <TotalAmount/> 不可為負數
130
+
131
+ ## Issue an existed invoice
132
+
133
+ * Request:
134
+ * Action:`IN_SellerInvoiceS.action`
135
+ * XmlData:
136
+
137
+ Tag | Description | Required | Type | Length | Detail
138
+ ----|-------------|----------|------|--------|-------
139
+ InvoiceRoot | - | Y | - | - | -
140
+ &nbsp;&nbsp;&nbsp;&nbsp;Invoice | - | Y | - | - | -
141
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceNumber | 發票號碼 | Y | 英數 | 10 | (SellerId & DataNumber) 需唯一
142
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceDate | 發票日期 | Y | 英數 | 8 | `YYYY/MM/DD` 西元年月日,平台僅接收 2006/12/06 後的所有發票
143
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceTime | 發票時間 | Y | 英數 | 8 | HH:MM:SS(24hr);[00-23]:[0 0-59]:[00-59] 範例:23:59:59
144
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SellerId | 賣方統一編號 | Y | 英數 | 10 | -
145
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BuyerName | 買方名稱 | Y | 英數 | 60 | * B2B:買方-營業人名稱。<br/>* B2C:買方-業者通知消費者之個人識別碼資料,共 4 位 ASCII 或 2 位全型中文。
146
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BuyerId | 買方統一編號 | Y | 英數 | 10 | * B2B:買方-營業人統一編號(BAN)。<br/>* B2C:買方-填滿 10 位數 字的 "0"。
147
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CustomsClearanceMark | 通關方式註記 | N | 數 | 1 | * '1': 非經海關出口<br/>* '2': 經海關出口(若為零稅率發票,此為必填欄位)
148
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceType | 發票類別 | Y | 英數 | 2 | * '01': 三聯式<br/>* '02': 二聯式<br/>* '03': 二聯式收銀機<br/>* '04': 特種稅額<br/>* '05': 電子計算機<br/>* '06': 三聯式收銀機<br/>* '07': 一般稅額計算之電子發票<br/>* '08': 特種稅額計算之電子發票<br/>* 電子發票僅適用第 7 項及 第 8 項
149
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DonateMark | 捐贈註記 | Y | 英數 | 1 | * '0':表示「非捐贈發票」<br/>* '1':表示為「捐贈發票」<br/>* 此部分資料須由消費者決定,網購業者可於網站畫面上新增欄位,讓消費者輸入資訊,範例請參考「電子發票網頁說明資訊.doc」,倘消費者於愛心碼欄位有輸入資訊,則此欄位值帶 '1',其餘皆帶 '0'。
150
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CarrierType | 載具類別 | N | 英數 | 6 | 填入平台配發的載具類別號碼,編碼規則:AA0000,第一碼行業別(英文),第二碼載具類別(英數),後四碼載具類別(序號)若現金消費無使用載具,請免填。消費者使用手機條碼索取含買方統編發票,則不論是否已列印紙本皆為必填。手機條碼:3J0002 手機載具相關資訊請參考財政部網頁若需使用網優載具進行發票代管服務,則此欄空白,由 EIVO 系統自動帶出值
151
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CarrierId1 | 載具顯碼id | N | 英數 | 64 | 填入載具外顯碼號碼,卡片上載列之卡片號碼資訊。若紙本電子發票已列印註記為 Y,此欄位必須為空白;若此欄位非空 白,則紙本電子發票已列印註記必須為 N。消費者使用手機條碼索取含買方統編發票,則不論是否已列印紙本皆為必填。若消費者使用手機載具索取發票,則須將消費者填寫之手機載具資訊帶入此欄,範例請參考「電子發票網頁說明資訊.doc」若需使用網優載具進行發票代管服務,則此欄空白,由本系統自動帶出值
152
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CarrierId2 | 載具隱碼id | N | 英數 | 64 | 填入載具內碼號碼,營業人應載入讀取工具所讀取之原始資訊。若紙本電子發票已列印註記為 Y,此欄位必須為空白;若此欄位非空白,則紙本電子發票已列印註記必須為 N。消費者使用手機條碼索取含買方統編發票,則不論是否已列印紙本皆為必填。若消費者使用手機載具索取發票,則須將消費者填寫之手機載具資訊帶入此欄,範例請參考「電子發票網頁說明資訊.doc」若需使用網優載具進行發票代管服務,則此欄空白,由本系統自動帶出值
153
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrintMark | 紙本電子發票已列印註記 | Y | 英 | 1 | * 'Y'/'N'<br/> * PrintMark 為 Y 時載具類別號碼,載具顯碼 ID, 載具隱碼 ID 必須為空白,捐贈註記必為 N。<br/>* 消費者使用手機條碼索取含買方統編發票,則不論是否已列印紙本,其載具類別號碼、載具顯碼 ID 和載具隱碼 ID 皆為必填。
154
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NPOBAN | 發票捐贈對象統一 | N | 英數 | 10 | 受捐贈者統一編號 BAN 捐贈愛心碼請將愛心碼資料 3-7 碼「完整」填入。愛心碼申請方式請參考財政部網頁
155
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RandomNumber | 發票防偽隨機碼 | N | 英數 | 4 | 交易當下隨機產生 4 位數值,少於 4 位者踢退;若為虛擬通路,則限填 "AAAA"
156
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceItem | - | - | - | - | 可重複
157
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Description | 品名 | Y | 英數 | 256 | - | - | - |
158
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity | 數量 | Y | 數 | 17 | * 商品數量:整數 12 位,小數 4 位。<br/>* 整數部分第一位不能有零,小數為零時不顯示小數點,負號請接於整數第一位前 Ex:999999999999.9999 Ex:-2356
159
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unit | 單位 | 選 | 英數 | 6 | 可為空白,商品單位, 除鋼鐵業外, 一般空白
160
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnitPrice | 單價 | Y | 數 | 17 | 商品單價 (未稅) 原幣報價,整數 12 位,小數 4 位。整數部分第一位不能有零,小數為零時不顯示小數點,負號請接於整數第一位前 Ex:999999999999.9999 Ex:-2356
161
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Amount | 金額 | Y | 數 | 17 | * 商品單價(未稅) * 數量:整數 12 位,小數 4 位。<br/>* 整數部分第一位不能有零,小數為零時不顯示小數點,負號請接於整數第一位前 Ex:999999999999.9999 Ex:-2356
162
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SequenceNumber | 明細排列序號 | Y | 英數 | 3 | 系統使用,不重複發票明細項目之排列序號, 第一筆商品標示 '1', 其餘接續編號
163
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Remark | 單一欄位備註 | N | 英數 | 40 | 可為空白,若為健康捐請於本項填寫"健康捐"
164
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SalesAmount | 應稅銷售額合計(新台幣) | Y | 數 | 12 | 整張發票應稅品銷售額合計 (未稅) 整數(小數點以下四捨五入),請注意銷售額合計不應為負數。
165
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeTaxSalesAmount | 免稅銷售額合計(新台幣) | Y | 數 | 12 | 整張發票免稅品銷售額合計整數(小數點以下四捨五入),若無需求則填 0,請注意銷售額合計不應為負數。
166
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ZeroTaxSalesAmount | 零稅率銷售額合計(新台幣) | Y | 數 | 12 | 整張發票零稅率品項銷售額合計整數(小數點以下四捨五入),若無需求則填 0,請注意銷售額合計不應為負數。
167
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TaxType | 課稅別 | Y | 英數 | 1 | <br/>* '1':應稅<br/>* '2':零稅率<br/>* '3':免稅<br/>* '4':應稅(特種稅率)<br/>* '9':混合應稅與免稅或零稅率 (限收銀機發票無法分辨時使用)
168
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TaxRate | 稅率 | Y | 數 | 6 | 範例: 稅率為 5% 時本欄位值為 0.05
169
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TaxAmount | 營業稅額 | Y | 數 | 12 | 整數(小數點以下四捨五入),填寫方式參閱註 1,請注意此項稅額不應為負數
170
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TotalAmount | 總計 | Y | 數 | 12 | 整數 (應稅銷售額合計 + 免稅銷售額合計 + 零稅率銷售額合計 + 營業稅額 = 此總計欄位),整數部分第一位不能有零,請注意此項總額不應為負數
171
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Contact | 郵件聯絡人資訊 | - | - | - | -
172
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name | 姓名 | Y | 英數 | 64 | 郵寄信封上收件人
173
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Address | 地址 | Y | 英數 | 128 | 郵寄信封上收件人地址
174
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TEL | 電話 | N | 英數 | 64 | 聯絡人電話,若啟動簡訊通知服務則為收取簡訊電話,則此欄位必填
175
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Email | email | N | 英數 | 512 | 聯絡人 Email,若啟動 Email 通知服務則此欄位必填,若須設定多筆 Email 則 以;符號間隔,例: aa@aa.net;bb@bb.net
176
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CustomerDefined | 針對有印花稅需求者 | - | - | - | -
177
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProjectNo | 專案編號 | N | 英數 | 64 | -
178
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PurchaseNo | 採購案號 | N | 英數 | 64 | -
179
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StampDutyFlag | 顯示印花稅圖章 | N | 數 | 1 | 0:不需要 1:需要
180
+
181
+ 註一、營業稅額欄位之填寫方式,應依照加值型及非加值型營業稅法第三十二條規定:「營業人依第十四條規定計算之銷項稅額,買受人為營業人者,應與銷售額於統一發票上分別載明之;買受人為非營業人者,應與銷售額合計開立統一發票。」填寫。上傳整合服務平台的發票內容應與開立內容一致。
182
+
183
+ * Response:
184
+ * 回應結構與訊息對照表:
185
+
186
+ Tag | Name | Required | Type | Length | Description
187
+ :---|:-----|:--------:|:----:|:------:|:-----------
188
+ Result | - | Y | - | - | -
189
+ &nbsp;&nbsp;&nbsp;&nbsp;statcode | 錯誤代碼 | Y | - | - | -
190
+ &nbsp;&nbsp;&nbsp;&nbsp;statdesc | 錯誤描述 | Y | - | - | -
191
+
192
+ ----
193
+
194
+ statcode | statdesc | description
195
+ :-------:|:---------|:-----------
196
+ 7001 | SellerId 不符 | StoreCode 取得商店統一編號與 <SellerId/>是否相同或該 <SellerId/> 必須存在於該商家的分支統編中
197
+ 7002 | 發票號碼重複 | 以 <InvoiceNumber/> 為條件確認資料庫資料不可有重複。
198
+ 7003 | B2C 模式 BuyerName 不符合 | 若 <BuyerId/> 值等於 10 位的 '0',則 <BuyerName/> 必須符合共 4 位 ASCII 或 2 位全型中文。
199
+ 7004 | CustomsClearanceMark 資料不符 | <CustomsClearanceMark/>若有填寫,必須為 1 或 2
200
+ 7005 | InvoiceType 資料不符 | <InvoiceType/>值必須為「01、02、03、04、05、06」其中一個
201
+ 7006 | DonateMark 資料不符 | <DonateMark/>必須為 0 或 1
202
+ 7007 | 捐贈發票 NPOBAN 資料不可為空 | <DonateMark/> 當值等於 '1' 時,則 <NPOBAN/> 不可為空值
203
+ 7008 | PrintMark 為紙本電子發票已列印時, CarrierId1, CarrierId2, DonateMark 不符合要求 | <PrintMark/> 值=Y,則<CarrierId1/>載具顯碼 ID, <CarrierId2/> 載具隱碼 ID 必須為空白, <DonateMark/>捐贈註記必為 N
204
+ 7009 | RandomNumber 資料長度不符 | <RandomNumber/> 若非為空值時,則長度不可小於四位。
205
+ 7010 | SequenceNumber 不可重複 | <SequenceNumber/> 不可重複
206
+ 7011 | SalesAmount 為負值 | <SalesAmount/> 不可為負數
207
+ 7012 | FreeTaxSalesAmount 為負值 | <FreeTaxSalesAmount/> 不可為負數
208
+ 7013 | ZeroTaxSalesAmount 為負值 | <ZeroTaxSalesAmount/> 不可為負數
209
+ 7014 | TaxType 資料不符 | <TaxType/> 值限為「1、2、3、4、9」其中一項
210
+ 7015 | TaxAmount 為負值 | <TaxAmount/> 不可為負數
211
+ 7016 | TotalAmount 為負值 | <TotalAmount/> 不可為負數
212
+
213
+ ## Query issued invoices
214
+
215
+ * Request:
216
+ * Action:`IN_InvoiceMapS.action`
217
+ * XmlData:
218
+
219
+ Tag | Name | Required | Type | Length | Description
220
+ :---|:-----|:--------:|:----:|:------:|:-----------
221
+ QryEvent | - | Y | - | - | -
222
+ &nbsp;&nbsp;&nbsp;&nbsp;InvoiceDateTimeS | 發票日期時間 (查詢開始) | N | 數 | 14 | yyyyMMddHHmmss
223
+ &nbsp;&nbsp;&nbsp;&nbsp;InvoiceDateTimdE | 發票日期時間 (結束) | N | 數 | 14 | yyyyMMddHHmmss
224
+ &nbsp;&nbsp;&nbsp;&nbsp;DataNumberS | 單據號碼 (查詢開始) | N | 英數 | 20 | -
225
+ &nbsp;&nbsp;&nbsp;&nbsp;DataNumberE | 單據號碼 (結束) | N | 英數 | 20 | -
226
+ &nbsp;&nbsp;&nbsp;&nbsp;SyncStatusUpdate | 是否更新同步狀態 | N | 英 | 1 | 'Y' or 'N'(default)
227
+
228
+ 註:若不放條件,請將 Node 的值為空,不可省略節點。
229
+
230
+ * Response:
231
+ * 回應結構與訊息對照表:
232
+
233
+ Tag | Name | Required | Type | Length | Description
234
+ :---|:-----|:--------:|:----:|:------:|:-----------
235
+ Result | - | Y | - | - | -
236
+ &nbsp;&nbsp;&nbsp;&nbsp;statcode | 錯誤代碼 | Y | - | - | -
237
+ &nbsp;&nbsp;&nbsp;&nbsp;statdesc | 錯誤描述 | Y | - | - | -
238
+ &nbsp;&nbsp;&nbsp;&nbsp;data | 資料區塊 | N | - | - | 狀態碼=0000 時,才有此 Node
239
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceMapRoot | - | Y | - | - | -
240
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceMap | 逐筆發票對應資料集合 | Y | - | - | 若有多筆發票對應資料,此 TAG 可重複
241
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataNumber | 單據號碼 | Y | 英數 | 20 | 為未配號發票檔中單據號碼
242
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceNumber | 發票號碼 | Y | 英數 | 10 | 客戶須於本系統維護發票號碼後,本系統方可配號,並回傳此一值給營業人
243
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceDate | 發票日期 | Y | 英數 | 10 | `YYYY/MM/DD` 西元年月日
244
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceTime | 發票時間 | Y | 英數 | 8 | HH:MM:SS(24hr);[00-23]:[00-59]:[0 0-59] 範例:23:59:59
245
+
246
+ ## Cancel an issued invoice
247
+
248
+ * Request:
249
+ * Action:`IN_CancelInvoiceS.action`
250
+ * XmlData:
251
+
252
+ Tag | Name | Required | Type | Length | Description
253
+ :---|:-----|:--------:|:----:|:------:|:-----------
254
+ CancelInvoiceRoot | - | Y | - | - | -
255
+ &nbsp;&nbsp;&nbsp;&nbsp;CancelInvoice | 逐筆作廢發票資料集合 | Y | - | - | -
256
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InvoiceDate | 發票日期 | Y | 英數 | 10 | `YYYY/MM/DD` 西元年月日,發票當初開立之日期
257
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SellerId | 賣方識別碼 | Y | 英數 | 10 | 賣方營業人統一編號
258
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CancelDate | 作廢日期 | Y | 英數 | 10 | `YYYY/MM/DD` 西元年月日
259
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CancelTime | 作費時間 | Y | 英數 | 8 | HH:MM:SS; (24hr);[00-23]:[00-59]:[00 -59] 範例:23:59:59
260
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CancelReason | 作費原因 | Y | 英數 | 20 | 長度至少為 1
261
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReturnTaxDocumentNumber | 專案作費核准文號 | N | 英數 | 60 | 若發票的作廢時間超過申報期間,則此欄位為必填欄位。若不填寫由上傳營業人自行負責。一般營業人二個月申報一次營業稅,則申報期為單月 15 號,超過申報期限則須與轄區國稅局申請專案核准文號方可作廢此張發票
262
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Remark | 備註 | Y | 英數 | 200 | -
263
+
264
+ * Response:
265
+ * 回應結構與訊息對照表:
266
+
267
+ Tag | Name | Required | Type | Length | Description
268
+ :---|:-----|:--------:|:----:|:------:|:-----------
269
+ Result | - | Y | - | - | -
270
+ &nbsp;&nbsp;&nbsp;&nbsp;statcode | 錯誤代碼 | Y | - | - | -
271
+ &nbsp;&nbsp;&nbsp;&nbsp;statdesc | 錯誤描述 | Y | - | - | -
272
+
273
+ ----
274
+
275
+ statcode | statdesc | description
276
+ :-------:|:---------|:-----------
277
+ 7001 | SellerId 不符 | StoreCode 取得商店統一編號與 <SellerId/> 是否相同且該 <SellerId/> 必須存在於該商家的分支統編中
278
+ 7002 | CancelReason 資料長度最少一位 | <CancelReason/> 資料長度最少一位
279
+
280
+ ## Allowance of an invoice
281
+
282
+ * Request:
283
+ * Action:`IN_AllowanceS.action`
284
+ * XmlData:
285
+
286
+ Tag | Name | Required | Type | Length | Description
287
+ :---|:-----|:--------:|:----:|:------:|:-----------
288
+
289
+ * Response:
290
+ * 回應結構與訊息對照表:
291
+
292
+ Tag | Name | Required | Type | Length | Description
293
+ :---|:-----|:--------:|:----:|:------:|:-----------
294
+ Result | - | Y | - | - | -
295
+ &nbsp;&nbsp;&nbsp;&nbsp;statcode | 錯誤代碼 | Y | - | - | -
296
+ &nbsp;&nbsp;&nbsp;&nbsp;statdesc | 錯誤描述 | Y | - | - | -
297
+
298
+ ----
299
+
300
+ statcode | statdesc | description
301
+ :-------:|:---------|:-----------
302
+
303
+ ## Cancel allowance of an invoice
304
+
305
+ * Request:
306
+ * Action:`IN_CancelAllowanceS.action`
307
+ * XmlData:
308
+
309
+ Tag | Name | Required | Type | Length | Description
310
+ :---|:-----|:--------:|:----:|:------:|:-----------
311
+
312
+ * Response:
313
+ * 回應結構與訊息對照表:
314
+
315
+ Tag | Name | Required | Type | Length | Description
316
+ :---|:-----|:--------:|:----:|:------:|:-----------
317
+ Result | - | Y | - | - | -
318
+ &nbsp;&nbsp;&nbsp;&nbsp;statcode | 錯誤代碼 | Y | - | - | -
319
+ &nbsp;&nbsp;&nbsp;&nbsp;statdesc | 錯誤描述 | Y | - | - | -
320
+
321
+ ----
322
+
323
+ statcode | statdesc | description
324
+ :-------:|:---------|:-----------
325
+
326
+ ## Assign invoice number for branches
327
+
328
+ * Request:
329
+ * Action:`IN_BranchTrackS.action`
330
+ * XmlData:
331
+
332
+ Tag | Name | Required | Type | Length | Description
333
+ :---|:-----|:--------:|:----:|:------:|:-----------
334
+
335
+ * Response:
336
+ * 回應結構與訊息對照表:
337
+
338
+ Tag | Name | Required | Type | Length | Description
339
+ :---|:-----|:--------:|:----:|:------:|:-----------
340
+ Result | - | Y | - | - | -
341
+ &nbsp;&nbsp;&nbsp;&nbsp;statcode | 錯誤代碼 | Y | - | - | -
342
+ &nbsp;&nbsp;&nbsp;&nbsp;statdesc | 錯誤描述 | Y | - | - | -
343
+
344
+ ----
345
+
346
+ statcode | statdesc | description
347
+ :-------:|:---------|:-----------
data/einvoice.gemspec CHANGED
@@ -32,4 +32,6 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency "rspec"
33
33
  spec.add_development_dependency "factory_girl"
34
34
  spec.add_development_dependency "shoulda-matchers"
35
+ spec.add_development_dependency "vcr"
36
+ spec.add_development_dependency "webmock"
35
37
  end
@@ -9,5 +9,21 @@ module Einvoice
9
9
  def issue(payload, options = {})
10
10
  provider.issue(payload, options)
11
11
  end
12
+
13
+ def query(payload, options = {})
14
+ provider.query(payload, options = {})
15
+ end
16
+
17
+ def cancel(payload, options = {})
18
+ provider.cancel(payload, options = {})
19
+ end
20
+
21
+ def allowance_for(payload, options = {})
22
+ provider.allowance_for(payload, options = {})
23
+ end
24
+
25
+ def cancel_allowance(payload, options = {})
26
+ provider.cancel_allowance(payload, options = {})
27
+ end
12
28
  end
13
29
  end
@@ -12,7 +12,7 @@ module Einvoice
12
12
  }
13
13
 
14
14
  ::Faraday::Connection.new(options) do |connection|
15
- connection.request :digest_neweb, client_secret
15
+ connection.request :digest_neweb, client_secret if self.class == Einvoice::Neweb::Provider
16
16
  connection.request :url_encoded
17
17
 
18
18
  # Parser
@@ -1,6 +1,7 @@
1
1
  require "active_model"
2
2
 
3
3
  require "einvoice/neweb/validator/invoice_validator"
4
+ require "einvoice/neweb/validator/invoice_item_validator"
4
5
 
5
6
  module Einvoice
6
7
  module Neweb
@@ -48,12 +48,22 @@ module Einvoice
48
48
  validates :tax_type, presence: true, length: { is: 1 }, inclusion: { in: %w(1 2 3 4 9) }
49
49
  validates :tax_rate, presence: true, length: { maximum: 6 }
50
50
  validates :tax_amount, presence: true, length: { maximum: 12 }, numericality: { greater_than_or_equal_to: 0 }
51
- validates :total_amount, presence: true, length: { maximum: 12 }, numericality: { greater_than_or_equal_to: 0 }
51
+ validates :total_amount, presence: true, length: { maximum: 12 }, numericality: { greater_than_or_equal_to: 0 }, total_amount: true
52
52
  validates :contact, presence: true
53
53
 
54
54
  def initialize
55
55
  raise NotImplementedError, "You should initialize with subclasses"
56
56
  end
57
+
58
+ def payload
59
+ serializable_hash(except: [:errors, :validation_context], include: [:invoice_item, :contact, :customer_defined])
60
+ end
61
+
62
+ def wrapped_payload
63
+ { invoice_root:
64
+ { invoice: payload }
65
+ }
66
+ end
57
67
  end
58
68
  end
59
69
  end
@@ -15,11 +15,11 @@ module Einvoice
15
15
  attr_accessor *VALID_OPTIONS_KEYS
16
16
 
17
17
  validates :description, presence: true, length: { maximum: 256 }
18
- validates :quantity, presence: true, length: { maximum: 17 }
18
+ validates :quantity, presence: true, length: { maximum: 17 }, quantity: true
19
19
  validates :unit, length: { maximum: 6 }
20
- validates :unit_price, presence: true, length: { maximum: 17 }
21
- validates :amount, presence: true, length: { maximum: 17 }
22
- validates :sequence_number, presence: true, length: { maximum: 3 }
20
+ validates :unit_price, presence: true, length: { maximum: 17 }, unit_price: true
21
+ validates :amount, presence: true, length: { maximum: 17 }, amount: true
22
+ validates :sequence_number, presence: true, length: { maximum: 3 }, format: { with: /\A[1-9]|[1-9][0-9]|[1-9][0-9][0-9]\Z/ }
23
23
  validates :remark, length: { maximum: 40 }
24
24
  end
25
25
  end
@@ -7,7 +7,7 @@ module Einvoice
7
7
  attr_accessor *TYPE_SPECIFIC_KEYS
8
8
 
9
9
  validates :data_number, presence: true, length: { maximum: 20 }
10
- validates :data_date, presence: true, length: { maximum: 10 }, format: { with: /\A\d{4}\/\d{2}\/\d{2}\z/ }
10
+ validates :data_date, presence: true, length: { maximum: 10 }, format: { with: /\A\d{4}\/\d{2}\/\d{2}\Z/ }
11
11
 
12
12
  def initialize
13
13
  # overwritten
@@ -0,0 +1,43 @@
1
+ module Einvoice
2
+ module Neweb
3
+ module Model
4
+ class Query < Base
5
+ VALID_OPTIONS_KEYS = [
6
+ :invoice_date_time_s,
7
+ :invoice_date_time_e,
8
+ :data_number_s,
9
+ :data_number_e,
10
+ :sync_status_update
11
+ ].freeze
12
+
13
+ attr_accessor *VALID_OPTIONS_KEYS
14
+
15
+ validates :invoice_date_time_s, presence: true, length: { maximum: 14 }, format: { with: /\A\d{4}\d{2}\d{2}\d{2}\d{2}\Z/ }
16
+ validates :invoice_date_time_e, presence: true, length: { maximum: 14 }, format: { with: /\A\d{4}\d{2}\d{2}\d{2}\d{2}\Z/ }
17
+ validates :data_number_s, presence: true, length: { maximum: 20 }
18
+ validates :data_number_e, presence: true, length: { maximum: 20 }
19
+ validates :sync_status_update, presence: true, length: { maximum: 1 }
20
+
21
+ def initialize
22
+ # overwritten
23
+ end
24
+
25
+ def attributes=(hash)
26
+ hash.each do |key, value|
27
+ send("#{key}=", value)
28
+ end
29
+ end
30
+
31
+ def payload
32
+ serializable_hash(except: [:errors, :validation_context])
33
+ end
34
+
35
+ def wrapped_payload
36
+ { invoice_map_root:
37
+ { invoice_map: payload }
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -7,7 +7,7 @@ module Einvoice
7
7
  attr_accessor *TYPE_SPECIFIC_KEYS
8
8
 
9
9
  validates :invoice_number, presence: true, length: { maximum: 20 }
10
- validates :invoice_date, presence: true, length: { maximum: 10 }, format: { with: /\A\d{4}\/\d{2}\/\d{2}\z/ }
10
+ validates :invoice_date, presence: true, length: { maximum: 10 }, format: { with: /\A\d{4}\/\d{2}\/\d{2}\Z/ }
11
11
 
12
12
  def initialize
13
13
  # overwritten
@@ -7,6 +7,7 @@ require "einvoice/neweb/model/invoice_item"
7
7
  require "einvoice/neweb/model/invoice"
8
8
  require "einvoice/neweb/model/pre_invoice"
9
9
  require "einvoice/neweb/model/seller_invoice"
10
+ require "einvoice/neweb/model/query"
10
11
 
11
12
  require "einvoice/neweb/result"
12
13
 
@@ -32,7 +33,7 @@ module Einvoice
32
33
  request.url endpoint_url || endpoint + action
33
34
  request.body = {
34
35
  storecode: client_id,
35
- xmldata: encode_xml(camelize(wrap(serialize(invoice))))
36
+ xmldata: encode_xml(camelize(invoice.wrapped_payload))
36
37
  }
37
38
  end.body
38
39
 
@@ -41,6 +42,26 @@ module Einvoice
41
42
  Einvoice::Neweb::Result.new(invoice.errors)
42
43
  end
43
44
  end
45
+
46
+ def query(payload, options)
47
+ action = "IN_InvoiceMapS.action"
48
+ query = Einvoice::Neweb::Model::Query.new
49
+ query.from_json(payload.to_json)
50
+
51
+ if query.valid?
52
+ response = connection.post do |request|
53
+ request.url endpoint_url || endpoint + action
54
+ request.body = {
55
+ storecode: client_id,
56
+ xmldata: encode_xml(camelize(query.wrapped_payload))
57
+ }
58
+ end.body
59
+
60
+ Einvoice::Neweb::Result.new(response)
61
+ else
62
+ Einvoice::Neweb::Result.new(query.errors)
63
+ end
64
+ end
44
65
  end
45
66
  end
46
67
  end
@@ -5,7 +5,7 @@ module Einvoice
5
5
  if response.is_a? ActiveModel::Errors
6
6
  response.full_messages.join('; ')
7
7
  else
8
- data = response && (response.fetch("Result").fetch("Invoice", {}) || response.fetch("Result", {}))
8
+ data = response && (response["Result"]["Invoice"] || response["Result"])
9
9
  data["statcode"] == "0000" ? nil : "#{data["statcode"]}: #{data["statdesc"]}" if data
10
10
  end
11
11
  end
@@ -14,9 +14,17 @@ module Einvoice
14
14
  if response.is_a? ActiveModel::Errors
15
15
  false
16
16
  else
17
- response && response.fetch("Result", {}) do |data|
18
- data["statcode"] == "0000" ? true : false
19
- end
17
+ data = response && (response["Result"]["Invoice"] || response["Result"])
18
+ data["statcode"] == "0000" if data
19
+ end
20
+ end
21
+
22
+ def data
23
+ if response.is_a? ActiveModel::Errors
24
+ nil
25
+ else
26
+ data = response && (response["Result"]["Invoice"] || response["Result"])
27
+ data["InvoiceMapRoot"] if data["statcode"] == "0000"
20
28
  end
21
29
  end
22
30
  end
@@ -0,0 +1,43 @@
1
+ module Einvoice
2
+ module Neweb
3
+ module Validator
4
+ class QuantityValidator < ActiveModel::EachValidator
5
+ include Einvoice::Neweb::Validator
6
+
7
+ def validate_each(record, attribute, value)
8
+ unless valid_float?(value)
9
+ record.errors.add attribute, options[:message] || :invalid
10
+ end
11
+ end
12
+ end
13
+
14
+ class UnitPriceValidator < ActiveModel::EachValidator
15
+ include Einvoice::Neweb::Validator
16
+
17
+ def validate_each(record, attribute, value)
18
+ unless valid_float?(value)
19
+ record.errors.add attribute, options[:message] || :invalid
20
+ end
21
+ end
22
+ end
23
+
24
+ class AmountValidator < ActiveModel::EachValidator
25
+ include Einvoice::Neweb::Validator
26
+
27
+ def validate_each(record, attribute, value)
28
+ unless valid_float?(value)
29
+ record.errors.add attribute, options[:message] || :invalid
30
+ end
31
+ end
32
+ end
33
+
34
+ def valid_float?(value)
35
+ integer, digit = value.to_s.split(".")[0..1]
36
+ float_value = value.to_f.to_s
37
+
38
+ return false if integer.nil? || digit.nil? || integer.delete("-").size > 12 || digit.try(:size) > 4
39
+ return false if integer != float_value.split(".")[0] || digit != float_value.split(".")[1]
40
+ end
41
+ end
42
+ end
43
+ end
@@ -41,6 +41,14 @@ module Einvoice
41
41
  end
42
42
  end
43
43
  end
44
+
45
+ class TotalAmountValidator < ActiveModel::EachValidator
46
+ def validate_each(record, attribute, value)
47
+ unless value != record.attributes.values_at("sales_amount", "free_tax_sales_amount", "zero_tax_sales_amount", "tax_amount").map(&:to_i).inject(&:+)
48
+ record.errors.add attribute, options[:message] || :invalid
49
+ end
50
+ end
51
+ end
44
52
  end
45
53
  end
46
54
  end
@@ -13,5 +13,9 @@ module Einvoice
13
13
  def success?
14
14
  raise NotImplementedError, 'You must initialize one of Einvoice::Response subclasses then use it.'
15
15
  end
16
+
17
+ def data
18
+ raise NotImplementedError, 'You must initialize one of Einvoice::Response subclasses then use it.'
19
+ end
16
20
  end
17
21
  end
@@ -2,16 +2,6 @@ require "gyoku"
2
2
 
3
3
  module Einvoice
4
4
  module Utils
5
- def serialize(object)
6
- object.serializable_hash(except: [:errors, :validation_context], include: [:invoice_item, :contact, :customer_defined])
7
- end
8
-
9
- def wrap(hash)
10
- { invoice_root:
11
- { invoice: hash }
12
- }
13
- end
14
-
15
5
  def camelize(hash)
16
6
  hash.deep_transform_keys { |k| k.to_s.camelize }
17
7
  end
@@ -1,3 +1,3 @@
1
1
  module Einvoice
2
- VERSION = "0.2.8"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: einvoice
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Yun
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-20 00:00:00.000000000 Z
11
+ date: 2016-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -178,6 +178,34 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: vcr
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: webmock
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
181
209
  description:
182
210
  email:
183
211
  - abookyun@gmail.com
@@ -194,6 +222,7 @@ files:
194
222
  - Rakefile
195
223
  - bin/console
196
224
  - bin/setup
225
+ - docs/neweb.md
197
226
  - einvoice.gemspec
198
227
  - lib/einvoice.rb
199
228
  - lib/einvoice/client.rb
@@ -205,9 +234,11 @@ files:
205
234
  - lib/einvoice/neweb/model/invoice.rb
206
235
  - lib/einvoice/neweb/model/invoice_item.rb
207
236
  - lib/einvoice/neweb/model/pre_invoice.rb
237
+ - lib/einvoice/neweb/model/query.rb
208
238
  - lib/einvoice/neweb/model/seller_invoice.rb
209
239
  - lib/einvoice/neweb/provider.rb
210
240
  - lib/einvoice/neweb/result.rb
241
+ - lib/einvoice/neweb/validator/invoice_item_validator.rb
211
242
  - lib/einvoice/neweb/validator/invoice_validator.rb
212
243
  - lib/einvoice/provider.rb
213
244
  - lib/einvoice/result.rb