roku-iap 0.0.1

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
+ SHA1:
3
+ metadata.gz: af19132440286500b4ed9bbc5f98c6475ce3b953
4
+ data.tar.gz: a3c99d3a416ad14e80d03dec3e8c36a481ce56d2
5
+ SHA512:
6
+ metadata.gz: 0683090cedde7c59f81c28157163467888d511e59f09dc42934ac9aed0bbeda9e7ae862335256b54c9f0cc9a3beb93e8669bc858895a56a30326444aa241f945
7
+ data.tar.gz: c21dc2ecc31d8585052bd8dea00fbe6a48f9b397ede3d90b727f1e69e613e6f98a293c3cd38b7ab0896f560933cb424dfb8a2e5d4515c89405f051336494e1b1
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 DailyBurn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,65 @@
1
+ A simple Ruby client for the [Roku Web Service Api](http://sdkdocs.roku.com/display/sdkdoc/Web+Service+API).
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ gem 'roku-iap'
8
+
9
+ And then execute:
10
+
11
+ $ bundle
12
+
13
+ Or install it yourself as:
14
+
15
+ $ gem install roku-iap
16
+
17
+ ##Usage
18
+
19
+ Initialize a client with your Roku API key:
20
+
21
+ ```ruby
22
+ client = Roku::Iap::Client.new 'roku_api_key'
23
+ ```
24
+
25
+ Call any of the following methods (outlined in the Roku sdk docs):
26
+
27
+ ```ruby
28
+ result = client.validate_transaction 'some-transaction-id'
29
+ result = client.validate_refund 'some-refund-id'
30
+ result = client.cancel_subscription 'some-tranasaction-id', 'cancellation_date', 'partner_ref_id'
31
+ result = client.refund_subscription 'some-transaction-id', 'amount', 'partner_ref_id', 'comments'
32
+ ```
33
+
34
+ ## Response
35
+
36
+ The returned Roku::Iap::Response object has underscored attributes correlating to the xml returned by the Roku API. ```successful?``` can be called on the result to confirm that the response contains no errors.
37
+
38
+ ```ruby
39
+ result = client.validate_transaction 'some-transaction-id'
40
+
41
+ if result.successful?
42
+ puts result.amount #"9.99"
43
+ puts result.purchase_date #"2014-11-03T00:07:23"
44
+ else
45
+ puts result.error_message #"Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)."
46
+ end
47
+ ```
48
+
49
+ Non-200 status code responses will raise a Roku::Iap::Exceptions::General, and are distinct from errors returned by the Roku API (which you may call ```result.error_message``` to elaborate upon)
50
+
51
+ ```ruby
52
+ begin
53
+ result = client.validate_transaction 'some-transaction-id'
54
+ rescue Roku::Iap::Exceptions::General => e
55
+ # enqueue to try again later
56
+ end
57
+ ```
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b some-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin some-new-feature`)
65
+ 5. Create new Pull Request
@@ -0,0 +1,4 @@
1
+ require 'roku/iap/version'
2
+ require 'roku/iap/client'
3
+ require 'roku/iap/response'
4
+ require 'roku/iap/exceptions'
@@ -0,0 +1,65 @@
1
+ class Roku::Iap::Client
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'json'
5
+
6
+ PRODUCTION_HOST = "https://apipub.roku.com"
7
+
8
+ def initialize(dev_token)
9
+ @dev_token = dev_token
10
+ @host = PRODUCTION_HOST
11
+ end
12
+
13
+ def validate_transaction(transaction_id)
14
+ path = "/listen/transaction-service.svc/validate-transaction/#{@dev_token}/#{transaction_id}"
15
+ get_data(path)
16
+ end
17
+
18
+ def validate_refund(refund_id)
19
+ path = "/listen/transaction-service.svc/validate-refund/#{@dev_token}/#{refund_id}"
20
+ get_data(path)
21
+ end
22
+
23
+ def cancel_subscription(transaction_id, cancellation_date, partner_ref_id="")
24
+ path = "/listen/transaction-service.svc/cancel-subscription"
25
+ request_body_json = {
26
+ :partnerApiKey => @dev_token,
27
+ :transactionId => transaction_id,
28
+ :cancellationDate => cancellation_date,
29
+ :partnerReferenceId => partner_ref_id
30
+ }.to_json
31
+ post_data(path, request_body_json)
32
+ end
33
+
34
+ def refund_subscription(transaction_id, amount, partner_ref_id="", comments="")
35
+ path = "/listen/transaction-service.svc/refund-subscription"
36
+ request_body_json = {
37
+ :partnerApiKey => @dev_token,
38
+ :transactionId => transaction_id,
39
+ :amount => amount,
40
+ :partnerReferenceId => partner_ref_id,
41
+ :comments => comments
42
+ }.to_json
43
+ post_data(path, request_body_json.to_s)
44
+ end
45
+
46
+ protected
47
+
48
+ def get_data(path)
49
+ uri = URI.parse "#{@host}#{path}"
50
+ req = Net::HTTP::Get.new uri.request_uri
51
+ res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') { |http| http.request req }
52
+ Roku::Iap::Response.new res
53
+ end
54
+
55
+ def post_data(path, request_body_json)
56
+ uri = URI.parse "#{@host}#{path}"
57
+ req = Net::HTTP::Post.new uri.request_uri
58
+ res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
59
+ req.content_type = "application/json"
60
+ req.body = request_body_json
61
+ http.request req
62
+ end
63
+ Roku::Iap::Response.new res
64
+ end
65
+ end
@@ -0,0 +1,7 @@
1
+ module Roku
2
+ module Iap
3
+ module Exceptions
4
+ class General < Exception; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ class Roku::Iap::Response
2
+
3
+ require 'rexml/document'
4
+
5
+ attr_accessor :raw_response #, :error_code, :error_details, :error_message, :status, :amount, :cancelled, :channel_id, :channel_name, :coupon_code, :currency, :expiration_date, :original_purchase_date, :partner_reference_id, :product_id, :product_name, :purchase_date, :quantity, :roku_customer_id, :tax, :total, :transaction_id
6
+
7
+ def initialize(response)
8
+ if response.code.to_i == 200
9
+ self.raw_response = REXML::Document.new(response.body)
10
+ self.raw_response.root.each do |e|
11
+ underscore = e.name.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
12
+ self.class.class_eval("attr_accessor :#{underscore}")
13
+ send "#{underscore}=", e.text.nil? ? "" : e.text
14
+ end
15
+ else
16
+ puts response.body
17
+ raise Roku::Iap::Exceptions::General, response.code.to_i
18
+ end
19
+ end
20
+
21
+ def successful?
22
+ self.try(:status) == "Success"
23
+ end
24
+
25
+ def unauthorized?
26
+ self.try(:error_message) == "UNAUTHORIZED"
27
+ end
28
+
29
+ protected
30
+
31
+ def try(att)
32
+ begin send "#{att}"; rescue NoMethodError ; end
33
+ end
34
+
35
+ end
@@ -0,0 +1,5 @@
1
+ module Roku
2
+ module Iap
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'roku/iap/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'roku-iap'
7
+ spec.version = Roku::Iap::VERSION
8
+ spec.authors = ['DailyBurn']
9
+ spec.email = ['dev@dailyburn.com']
10
+ spec.description = %q{Verify and manage Roku in app purchases}
11
+ spec.summary = %q{Verify and manage Roku in app purchases}
12
+ spec.homepage = 'https://github.com/DailyBurn/roku-iap'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.require_paths = ['lib']
17
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roku-iap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - DailyBurn
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-04 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Verify and manage Roku in app purchases
14
+ email:
15
+ - dev@dailyburn.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - LICENSE
21
+ - README.md
22
+ - lib/roku/iap.rb
23
+ - lib/roku/iap/client.rb
24
+ - lib/roku/iap/exceptions.rb
25
+ - lib/roku/iap/response.rb
26
+ - lib/roku/iap/version.rb
27
+ - roku-iap.gemspec
28
+ homepage: https://github.com/DailyBurn/roku-iap
29
+ licenses:
30
+ - MIT
31
+ metadata: {}
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 2.2.1
49
+ signing_key:
50
+ specification_version: 4
51
+ summary: Verify and manage Roku in app purchases
52
+ test_files: []