cetustek 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -0
- data/README.md +70 -15
- data/lib/cetustek/cancel_allowance.rb +17 -39
- data/lib/cetustek/cancel_invoice.rb +20 -44
- data/lib/cetustek/create_allowance.rb +24 -61
- data/lib/cetustek/create_invoice.rb +4 -2
- data/lib/cetustek/errors.rb +24 -0
- data/lib/cetustek/models/allowance_data.rb +47 -4
- data/lib/cetustek/models/invoice_data.rb +75 -8
- data/lib/cetustek/queries.rb +64 -56
- data/lib/cetustek/query_invoice_by_order_id.rb +11 -12
- data/lib/cetustek/services/invoice_xml_builder.rb +38 -78
- data/lib/cetustek/services/response_handler.rb +9 -21
- data/lib/cetustek/soap.rb +29 -0
- data/lib/cetustek/version.rb +1 -1
- data/lib/cetustek/xml.rb +72 -0
- data/lib/cetustek.rb +3 -1
- metadata +3 -2
- data/lib/cetustek/services/invoice_service.rb +0 -28
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'savon'
|
|
4
|
+
|
|
5
|
+
module Cetustek
|
|
6
|
+
# Shared SOAP plumbing: every operation hits the same WSDL and authenticates
|
|
7
|
+
# with 網站代碼+APIPassword (source) and the 租賃者統編 (rentid).
|
|
8
|
+
module Soap
|
|
9
|
+
def soap_client
|
|
10
|
+
Savon.client(wsdl: Cetustek.config.url, open_timeout: 300, read_timeout: 300)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def source
|
|
14
|
+
Cetustek.config.site_id + Cetustek.config.password
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def rentid
|
|
18
|
+
Cetustek.config.username
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def soap_call(operation, message)
|
|
22
|
+
soap_client.call(operation, message: message.merge(source: source, rentid: rentid))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def soap_return(response, operation)
|
|
26
|
+
response.body[:"#{operation}_response"][:return]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/cetustek/version.rb
CHANGED
data/lib/cetustek/xml.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ox'
|
|
4
|
+
require 'cgi'
|
|
5
|
+
|
|
6
|
+
module Cetustek
|
|
7
|
+
# Every request document in the spec is the same shape: a UTF-8 declaration
|
|
8
|
+
# and a single <Invoice>/<Allowance> root carrying XSDVersion.
|
|
9
|
+
module Xml
|
|
10
|
+
XSD_VERSION = '2.8'
|
|
11
|
+
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
def document(root_name)
|
|
15
|
+
doc = Ox::Document.new
|
|
16
|
+
instruct = Ox::Instruct.new(:xml)
|
|
17
|
+
instruct[:version] = '1.0'
|
|
18
|
+
instruct[:encoding] = 'UTF-8'
|
|
19
|
+
doc << instruct
|
|
20
|
+
|
|
21
|
+
root = Ox::Element.new(root_name)
|
|
22
|
+
root[:XSDVersion] = XSD_VERSION
|
|
23
|
+
doc << root
|
|
24
|
+
yield root
|
|
25
|
+
|
|
26
|
+
Ox.dump(doc).force_encoding('UTF-8')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Values are HTML-escaped so that special characters (&, <, >, ", ') in any
|
|
30
|
+
# dynamic field cannot break the XML or be used for injection.
|
|
31
|
+
def tag(name, value)
|
|
32
|
+
Ox::Raw.new("<#{name}>#{CGI.escapeHTML(value.to_s)}</#{name}>")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Fields whose 備註 says "若未填,預設 X" are left out entirely when nil, so
|
|
36
|
+
# the platform applies its own default instead of parsing an empty value.
|
|
37
|
+
def append(element, name, value, skip_nil: false)
|
|
38
|
+
return if skip_nil && value.nil?
|
|
39
|
+
|
|
40
|
+
element << tag(name, value)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Shared guard every Query* class needs before it can parse a response
|
|
44
|
+
# body: nil for an empty answer or one of the documented sentinel strings
|
|
45
|
+
# (e.g. "nodata"); ResultError for a bare result code; otherwise the
|
|
46
|
+
# parsed root element, ready for parse_fields.
|
|
47
|
+
def parse_response(body, nil_values: [])
|
|
48
|
+
text = body.to_s.strip
|
|
49
|
+
return nil if text.empty? || nil_values.include?(text)
|
|
50
|
+
|
|
51
|
+
ResultCode.raise!(text, ResultCode::COMMON) unless text.start_with?('<')
|
|
52
|
+
|
|
53
|
+
root = Ox.parse(text)
|
|
54
|
+
root.is_a?(Ox::Document) ? root.root : root
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Shared response-parsing side: every Query* class turns a response
|
|
58
|
+
# element into a Hash of snake_case keys, so this lives here once instead
|
|
59
|
+
# of once per query class.
|
|
60
|
+
def parse_fields(element, fields)
|
|
61
|
+
fields.to_h { |field| [snake_case(field), text_of(element, field)] }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def text_of(element, name)
|
|
65
|
+
element&.locate(name)&.first&.text
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def snake_case(name)
|
|
69
|
+
name.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase.to_sym
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/cetustek.rb
CHANGED
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
require_relative "cetustek/version"
|
|
4
4
|
require_relative "cetustek/errors"
|
|
5
5
|
require_relative "cetustek/configuration"
|
|
6
|
+
require_relative "cetustek/xml"
|
|
7
|
+
require_relative "cetustek/soap"
|
|
6
8
|
require_relative "cetustek/models/allowance_data"
|
|
7
9
|
require_relative "cetustek/create_invoice"
|
|
8
10
|
require_relative "cetustek/cancel_invoice"
|
|
9
|
-
require_relative "cetustek/query_invoice_by_order_id"
|
|
10
11
|
require_relative "cetustek/queries"
|
|
12
|
+
require_relative "cetustek/query_invoice_by_order_id"
|
|
11
13
|
require_relative "cetustek/create_allowance"
|
|
12
14
|
require_relative "cetustek/cancel_allowance"
|
|
13
15
|
require_relative "cetustek/phone_barcode"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cetustek
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Zac
|
|
@@ -90,10 +90,11 @@ files:
|
|
|
90
90
|
- lib/cetustek/phone_barcode.rb
|
|
91
91
|
- lib/cetustek/queries.rb
|
|
92
92
|
- lib/cetustek/query_invoice_by_order_id.rb
|
|
93
|
-
- lib/cetustek/services/invoice_service.rb
|
|
94
93
|
- lib/cetustek/services/invoice_xml_builder.rb
|
|
95
94
|
- lib/cetustek/services/response_handler.rb
|
|
95
|
+
- lib/cetustek/soap.rb
|
|
96
96
|
- lib/cetustek/version.rb
|
|
97
|
+
- lib/cetustek/xml.rb
|
|
97
98
|
- sig/cetustek.rbs
|
|
98
99
|
homepage: https://github.com/7a6163/cetustek
|
|
99
100
|
licenses:
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'savon'
|
|
4
|
-
|
|
5
|
-
module Cetustek
|
|
6
|
-
module Services
|
|
7
|
-
# 2.1 CreateInvoiceV3(invoicexml, hastax, rentid, source)
|
|
8
|
-
class InvoiceService
|
|
9
|
-
def initialize(xml, hastax = 1)
|
|
10
|
-
@xml = xml
|
|
11
|
-
@hastax = hastax
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def create
|
|
15
|
-
Savon.client(
|
|
16
|
-
wsdl: Cetustek.config.url,
|
|
17
|
-
open_timeout: 300,
|
|
18
|
-
read_timeout: 300
|
|
19
|
-
).call(:create_invoice_v3, message: {
|
|
20
|
-
invoicexml: @xml,
|
|
21
|
-
source: Cetustek.config.site_id + Cetustek.config.password,
|
|
22
|
-
rentid: Cetustek.config.username,
|
|
23
|
-
hastax: @hastax
|
|
24
|
-
})
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|