zuora_api_D 1.6.06

Sign up to get free protection for your applications and to get access to all the features.
@@ -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