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.
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cetustek
4
- VERSION = "0.8.0"
4
+ VERSION = "0.10.0"
5
5
  end
@@ -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.8.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