zuora_api_D 1.6.06

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,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0a408b85ca45825733c30c623994f5f736b7982b18258db77b723f9a53000344
4
+ data.tar.gz: 7f0f79b372f2383f8133324798b8bb442ceb6eedf36d22f64174415016fc941e
5
+ SHA512:
6
+ metadata.gz: d07bec2378404b0cf4342fb8e52c9a3b9ad0d2f141ecca6bc4eca61c6c4e36e84c61fc5d430a95c19e3a7b8cf8672ba03b5812d602dc078bba9882db07b06bac
7
+ data.tar.gz: 6676504c96ce47af6ccaafe56241aaf1e05eed62dc9ba9274acf00f615dba1c78319b764b8eb6386bd4625fde8003c4f382c7f01715033e2d2d619164380b517
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,50 @@
1
+
2
+ image: ruby:2.3.1
3
+ stages:
4
+ - setup
5
+ - test
6
+ - deploy
7
+
8
+ setup:
9
+ stage: setup
10
+ allow_failure: true
11
+ cache:
12
+ key: gems
13
+ paths:
14
+ - vendor/bundle
15
+ script:
16
+ - apt-get update -qy
17
+ - apt-get install -y nodejs
18
+ - bundle install
19
+
20
+ rubocop-testing:
21
+ stage: test
22
+ allow_failure: true
23
+ script:
24
+ - gem install rubocop
25
+ - rubocop --lint
26
+
27
+ security-testing:
28
+ stage: test
29
+ allow_failure: true
30
+ script:
31
+ - gem install brakeman
32
+ - brakeman
33
+
34
+ rspec-testing:
35
+ stage: test
36
+ script:
37
+ - bundle install
38
+ - rspec
39
+
40
+ rubygems-deploy:
41
+ stage: deploy
42
+ allow_failure: false
43
+ script:
44
+ - bundle install
45
+ - gem install rake
46
+ - version=$(rake install | grep -o 'pkg/zuora_api-.*gem')
47
+ - curl -u $USERNAME:$PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
48
+ - gem push $version
49
+ only:
50
+ - master
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.0
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in zuora.gemspec
4
+ gemspec
@@ -0,0 +1,147 @@
1
+ # Zuora Gem
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/zuora_api.svg)](https://badge.fury.io/rb/zuora_api) [![coverage report](https://gitlab.zuora.com/Connect/zuora-gem/badges/master/coverage.svg)](https://gitlab.zuora.com/Connect/zuora-gem/commits/master)
4
+
5
+ ## Installation
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'zuora_api'
10
+ ```
11
+ Then execute `bundle install` in your terminal
12
+
13
+ ## Usage
14
+
15
+ ### Zuora Login Object
16
+ In order to make API calls a Zuora Login object must be created
17
+
18
+ ```ruby
19
+ zuora_client = ZuoraAPI::Login.new(username: "username", password: "password", url: "url")
20
+ ```
21
+
22
+ | Name | Type | Description | Example |
23
+ | ------------------- | ----------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
24
+ | username | `Attribute` | Username to the Zuora environment | `zuora_client.username = "username"` |
25
+ | password | `Attribute` | password to the Zuora environment | `zuora_client.password = "Password"` |
26
+ | url | `Attribute` | Endpoint to the Zuora tenant | `zuora_client.url = "www.zuora.com"` |
27
+ | wsdl_number | `Attribute` | WSDL number of the zuora login | `wsdl = zuora_client.wsdl_number` |
28
+ | status | `Attribute` | Status of the login | `zuora_client.status` |
29
+ | current_session | `Attribute` | Current session for the login | `zuora_client.current_session` |
30
+ | environment | `Attribute` | environment of the login | `zuora_client.environment` |
31
+ | errors | `Attribute` | Any errors that the login has based on the login call | `zuora_client.errors` |
32
+ | current_error | `Attribute` | Current error from the new_session call | `zuora_client.current_error` |
33
+ | user_info | `Attribute` | Information related to the login | `zuora_client.user_info` |
34
+ | tenant_id | `Attribute` | Tenant ID the login is associated to | `zuora_client.tenant_id` |
35
+ | tenant_name | `Attribute` | Tenant Name of tenant the login is associated to | `zuora_client.tenant_name` |
36
+ | entity_id | `Attribute` | Current entity the login session is associated to | `zuora_client.entity_id` |
37
+ | rest_call | `Method` | Executes a REST call | `zuora_client.rest_call()` |
38
+ | soap_call | `Method` | Executes a SOAP call | `output_xml, input_xml = zuora_client.soap_call() do `|xml, args|` xml['ns1'].query do xml['ns1'].queryString "select id, name from account" end end` |
39
+ | query | `Method` | Executes a query call | `zuora_client.query("select id, name from account")` |
40
+ | getDataSourceExport | `Method` | Pulls a data source export with the given query and returns the file location | `zuora_client.getDataSourceExport("select id, name from account")` |
41
+ | describe_call | `Method` | Performs the describe call against the Zuora tenant for all objects or a specific object | `response = zuora_client.describe_call("Account")` |
42
+ | createJournalRun | `Method` | Creates a Journal Run | `zuora_client.createJournalRun(call)` |
43
+ | checkJRStatus | `Method` | Checks the status of a journal run | `zuora_client.checkJRStatus(journal_run_id)` |
44
+ | update_environment | `Method` | Sets the login's environment based on the url | `zuora_client.update_environment` |
45
+ | aqua_endpoint | `Method` | Returns the AQuA endpoint for the login based off the environment | `zuora_client.aqua_endpoint` |
46
+ | rest_endpoint | `Method` | Returns the REST endpoint for the login based off the environment | `zuora_client.rest_endpoint` |
47
+ | fileURL | `Method` | Returns the URL for files | `zuora_client.fileURL` |
48
+ | dateFormat | `Method` | Returns the data format syntax based on the wsdl_number | `zuora_client.dateFormat` |
49
+ | new_session | `Method` | Create a new session | `zuora_client.new_session` |
50
+ | get_session | `Method` | Returns the current session | `zuora_client.get_session`|
51
+
52
+ ## Rest Call
53
+ ```ruby
54
+ zuora_client.rest_call(method: :get, body: {}, url: zuora_client.rest_endpoint("catalog/products?pageSize=4"))
55
+ ```
56
+
57
+ ### Soap Call
58
+ Returns both output and input XML
59
+
60
+ ```ruby
61
+ zuora_client.soap_call(ns1: 'ns1', ns2: 'ns2', batch_size: nil, single_transaction: false)
62
+ ```
63
+
64
+ Example Call
65
+
66
+ ```ruby
67
+ output_xml, input_xml = zuora_client.soap_call() do |xml, args|
68
+ xml['ns1'].query do
69
+ xml['ns1'].queryString "select id, name from account"
70
+ end
71
+ end
72
+ ```
73
+ ### Query
74
+ ```ruby
75
+ zuora_client.query("select id from account")
76
+ ```
77
+ ### Data Export
78
+ Returns the file location of the data source export after downloading from Zuora
79
+
80
+ ```ruby
81
+ zuora_client.getDataSourceExport("select id from account")
82
+ ```
83
+
84
+ | Name | Description | Default | Example |
85
+ | --------- | ---------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------- |
86
+ | query | The query to execute | `N/A` | `zuora_client.getDataSourceExport("select id from account")` |
87
+ | zip | Indicates if the data source export should be a zip | `true` | `zuora_client.getDataSourceExport("select id from account", zip: false)` |
88
+ | extract | Indicates if the data source export should be extracted if it is a zip | `true` | `zuora_client.getDataSourceExport("select id from account", extract: false)` |
89
+ | encrypted | Indicates if the data source export should be encrypted | `false` | `zuora_client.getDataSourceExport("select id from account", encrypted: true)` |
90
+
91
+ ### Describe Call
92
+ This returns all available objects from the describe call as a hash. This response can be accessed by using response["Account"] to retrieve all related data about that object.
93
+
94
+ ```ruby
95
+ response = zuora_client.describe_call("Account")
96
+ ```
97
+ This returns all information and fields related to that object model as a hash.
98
+
99
+ ```ruby
100
+ response = zuora_client.describe_call()
101
+ ```
102
+
103
+ ### Journal Run
104
+ ```ruby
105
+ zuora_client.createJournalRun(call)
106
+ ```
107
+
108
+ ## Insights API
109
+
110
+ In order to make API calls a Zuora Login object must be created by running:
111
+
112
+ ```ruby
113
+ insightsapi = InsightsAPI::Login.new(api_token: "api token", url: "Nw1.api.insights.zuora.com/api/")
114
+ ```
115
+
116
+ Note that the login will default to the insights production url.
117
+
118
+ ```ruby
119
+ Date format: "YYYY-MM-DDT00:00:00Z"
120
+ ```
121
+
122
+ ### Uploading Data into Insights
123
+ ```ruby
124
+ insightsapi.upload_into_insights(dataSourceName, recordType, batchDate, filePath)
125
+ ```
126
+ dataSourceName: What system the data is coming from.
127
+ recordType: The type of records ie: "EVENTS, ATTRIBUTES, and METRICS"
128
+ batachDate: The date the data applies to.
129
+
130
+ ### Describing Insights Data
131
+ ```ruby
132
+ insightsapi.describe(type: "ACCOUNT/USER", object: "ATTRIBUTES/EVENTS/SEGMENTS/METRICS")
133
+ ```
134
+ Returns json payload describing attributes, events, metrics for each Account or User.
135
+
136
+ ### Downloading Data from Insights
137
+ ```ruby
138
+ insightsapi.data_export_insights(objecttype, segmentuuid, startDate: nil, endDate: nil, tries: 30)
139
+ ```
140
+ ```ruby
141
+ insightsapi.data_export_insights_file(objecttype, segmentuuid, startDate: nil, endDate: nil, tries: 30)
142
+ ```
143
+ Both do the same thing except one returns a url(data_export_insights) to download the file yourself and the other returns an actual Ruby temporary file(data_export_insights_file).
144
+
145
+ objectype: "ACCOUNT/USER"
146
+
147
+ segmentuuid: A single or array of string or int of a segment uuid(s) that you get from the describe call. The csv holds a column with a bool that represents if that User or Account belongs to that segment.
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "zuora"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,221 @@
1
+ require "httparty"
2
+ module InsightsAPI
3
+ class Login
4
+ attr_accessor :api_token, :url
5
+
6
+ def initialize(api_token: nil, url: nil, **keyword_args)
7
+ @api_token = api_token
8
+ @url = url
9
+ @status = "Active"
10
+ end
11
+
12
+ def insight_getstatus(uuid)
13
+ response = HTTParty.get(
14
+ "https://#{@url}/export/status/#{uuid}",
15
+ :basic_auth => { :username => @api_token })
16
+ if response.code == 200
17
+ parsed = JSON.parse(response.body)
18
+ return parsed
19
+ #error handing here
20
+ end
21
+ end
22
+
23
+ def data_export_insights_file(objecttype, segmentuuid, startDate, endDate, tries: 30)
24
+ status = data_export_insights(objecttype, segmentuuid, startDate, endDate, tries: tries)
25
+ if status['status']== "COMPLETE"
26
+ signedUrl = status['signedUrl']
27
+ return get_file(file_name: "insights-#{startDate}-#{endDate}.csv", url: signedUrl, headers: {}, count: 3, file_type: "zip")
28
+ else
29
+ return status
30
+ end
31
+ end
32
+
33
+ def data_export_insights(objecttype, segmentuuid, startDate, endDate, tries: 30)
34
+ status = insights_fetch_all(objecttype, segmentuuid, startDate, endDate)
35
+ if status['uuid'] == nil
36
+ return "Failed: #{status["response"]}"
37
+ else
38
+ fileid = status['uuid']
39
+ end
40
+ for retries in 1..tries
41
+ status = insight_getstatus(fileid)
42
+ if status['status']== "COMPLETE"
43
+ signedUrl = status['signedUrl']
44
+ return status
45
+ elsif status['status'] == "FAILED"
46
+ return status
47
+ else
48
+ sleep(60)
49
+ retries+=1
50
+ end
51
+ if retries > tries - 1
52
+ return "Timeout"
53
+ end
54
+ end
55
+ return signedUrl
56
+ end
57
+
58
+ def insights_fetch_all(objecttype, segmentuuid, startDate, endDate)
59
+ if segmentuuid.is_a? Array
60
+ segmentsForAPI = segmentuuid.join('","')
61
+ elsif segmentuuid.is_a? String
62
+ segmentsForAPI = segmentuuid
63
+ elsif segmentuuid.is_a? Integer
64
+ segmentsForAPI = segmentuuid.to_s
65
+ else
66
+ raise "Error fetching Insights data: Segmentuuid must be either an array of uuids or an single uuid in string or interger format."
67
+ end
68
+
69
+ response = HTTParty.post(
70
+ "https://#{@url}/export/type/#{objecttype}",
71
+ :basic_auth => { :username => @api_token },
72
+ :headers => {'Content-Type'=> "Application/json"},
73
+ :body =>
74
+ '
75
+ {
76
+ "endDate": "' + (dateFormat(date: endDate)).to_s + '",
77
+ "startDate":"' + (dateFormat(date: startDate)).to_s + '",
78
+ "segments": [
79
+ "'+segmentsForAPI+'"
80
+ ]
81
+ }
82
+ ')
83
+ if response.code == 200
84
+ parsed = JSON.parse(response.body)
85
+ return parsed
86
+ else
87
+ return {"uuid"=> nil, "status"=>"Error", "signedUrl"=>"signedUrl", "response" => response.body}
88
+ end
89
+ end
90
+
91
+ def dateFormat(date: nil)
92
+ date ||= DateTime.now
93
+ if date.is_a? String
94
+ if date.include? "T"
95
+ return (date.to_datetime).to_s
96
+ else
97
+ return (date.to_date).to_s + "T#{DateTime.now.to_s(:time)}:00Z"
98
+ end
99
+ elsif date.instance_of?(DateTime)
100
+ return date.to_s
101
+ elsif date.instance_of?(Date)
102
+ return (date.to_date).to_s + "T#{DateTime.now.to_s(:time)}:00Z"
103
+ else
104
+ raise "Please pass in a in format of 'YYYY-MM-DD', 'YYYY-MM-DDT00:00:00+00:00' ruby Date, or ruby DateTime"
105
+ end
106
+ end
107
+
108
+ def upload_into_insights(dataSourceName, recordType, batchDate, filePath)
109
+ begin
110
+ temp_date = dateFormat(date: batchDate)
111
+ response = HTTParty.post(
112
+ "https://#{@url}/files/upload",
113
+ :basic_auth => { :username => @api_token }, :body => {
114
+ :dataSource => dataSourceName, :recordType => recordType,
115
+ :batchDate => temp_date})
116
+ parsed = JSON.parse(response.body)
117
+ signedUrl = parsed['signedUrl']
118
+ if !File.extname(filePath) == ".gz"
119
+ zipPath = gzip_file(filePath)
120
+ else
121
+ zipPath = filePath
122
+ end
123
+
124
+ gzippedFile = File.open(zipPath)
125
+ post = HTTParty.put(signedUrl,
126
+ :body => gzippedFile.read)
127
+ if post.code == 200
128
+ return {"status"=>"COMPLETE", "signedUrl"=>"#{signedUrl}", "response" => post.code, "batchDate" => "#{temp_date}"}
129
+ else
130
+ return {"status"=>"Error", "signedUrl"=>"#{signedUrl}", "response" => post.code, "message"=> "#{post.message}", "batchDate" => "#{temp_date}"}
131
+ end
132
+ rescue Exception => e
133
+ Rails.logger.debug "[ZuoraGem]: While uploading to insights Error: #{e}"
134
+ raise e
135
+ end
136
+ end
137
+
138
+ def describe(type: "ACCOUNT", object: "attributes")
139
+ url = "https://#{@url}/export/#{object}/#{type}"
140
+ uri = URI.parse(url)
141
+ http = Net::HTTP.new(uri.host, uri.port)
142
+ http.use_ssl = true
143
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
144
+ begin
145
+ request = Net::HTTP::Get.new(uri.request_uri)
146
+ request.basic_auth(@api_token, "")
147
+ return http.request(request)
148
+ rescue Exception => e
149
+ Rails.logger.debug "[ZuoraGem]: While describing Zoura Insights objects: #{e}"
150
+ return "Failed"
151
+ end
152
+ end
153
+
154
+ def get_file(file_name: nil, url: nil, basic: {:username => nil, :password => nil}, headers: {}, count: 3, file_type: "zip")
155
+ tries ||= 2
156
+ temp_file = nil
157
+ uri = URI(url)
158
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
159
+ request = Net::HTTP::Get.new(uri)
160
+ headers.each do |k,v|
161
+ request["#{k}"] = v
162
+ end
163
+ request.basic_auth(basic[:username], basic[:password]) if (!basic[:username].blank? && !basic[:password].blank?)
164
+ http.request request do |response|
165
+ case response
166
+ when Net::HTTPNotFound
167
+ Rails.logger.fatal("[ZuoraGem]: 404 - Not Found")
168
+ raise response
169
+
170
+ when Net::HTTPUnauthorized
171
+ raise ZuoraAPI::Exceptions::ZuoraAPISessionError.new(zuora_client.current_error) if count <= 0
172
+ Rails.logger.fatal("[ZuoraGem]: Retry")
173
+ zuora_client.new_session
174
+ return get_file(:url => url, :count => count - 1, :headers => headers)
175
+
176
+ when Net::HTTPClientError
177
+ Rails.logger.debug("[ZuoraGem]: #{response}")
178
+ raise response
179
+
180
+ when Net::HTTPOK
181
+ Tempfile.open([file_name.rpartition('.').first, ".#{file_name.rpartition('.').last}"], "#{Rails.root}/tmp") do |tmp_file|
182
+ temp_file ||= tmp_file
183
+ tmp_file.binmode if (response.to_hash["content-type"].include?("application/zip") || response.to_hash["content-type"] == "application/zip")
184
+ response.read_body do |chunk|
185
+ tmp_file.write chunk.force_encoding("UTF-8")
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ rescue => ex
193
+ if !(tries -= 1).zero?
194
+ sleep 3
195
+ retry
196
+ else
197
+ raise ex
198
+ end
199
+ else
200
+ return temp_file
201
+ end
202
+
203
+ def gzip_file(filePath)
204
+ require "zip"
205
+ Zlib::GzipWriter.open(filePath + ".gz") do |gzip|
206
+ open(filePath, "rb") do |f|
207
+ f.each_chunk() {|chunk| gzip.write chunk }
208
+ end
209
+ gzip.close
210
+ end
211
+ return filePath+ ".gz"
212
+ end
213
+
214
+ end
215
+ end
216
+
217
+ class File
218
+ def each_chunk(chunk_size=2**16)
219
+ yield read(chunk_size) until eof?
220
+ end
221
+ end