honeycrisp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 262039adf9839c205736ed3c2b0b7f07152aa2a1
4
+ data.tar.gz: 0a36b9e5a8161e54515fbe95c52562586ce12260
5
+ SHA512:
6
+ metadata.gz: c7d7f2e0f46b62f07e46b50bf3c631137e189d780cd4789192b863a1c84e01bfa821bbfd44aaff20d0fcb5a93acce851fdb52c1100a427ae61c66d98d9ce9511
7
+ data.tar.gz: 64d2f6d6cbf92341357587bed6fd3e4e6a7338bafeab97ee26b84d3762a558d8dc2deadfe4e7cb0b4bc754a467b870d2dfca261d8d9bb36e240083de30cb5821
@@ -0,0 +1,39 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /vendor/ruby
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ Gemfile.lock
32
+ .ruby-version
33
+ .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
37
+
38
+ ## OSX
39
+ .DS_Store
@@ -0,0 +1,7 @@
1
+ Version 0.0.1
2
+ -------------
3
+
4
+ Released February 17, 2015
5
+
6
+ - Initial release.
7
+ - Supports basic receipt validation.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rake', '~> 10.1'
7
+ gem 'rspec', '~> 3.0'
8
+ gem 'fakeweb', '~> 1.3'
9
+ gem 'rack', '~> 1.3'
10
+ end
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2015 Justin Rhinesmith.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,8 @@
1
+ install:
2
+ bundle exec rake install
3
+
4
+ test-install:
5
+ bundle install
6
+
7
+ test:
8
+ bundle exec rake spec
@@ -0,0 +1,69 @@
1
+ # honeycrisp
2
+
3
+ A module for validating receipts with Apple's App Store. [Click here to read the full documentation.][documentation]
4
+
5
+ ## Installation
6
+
7
+ To install using [Bundler][bundler] grab the latest stable version:
8
+
9
+ ```ruby
10
+ gem 'honeycrisp', '~> 0.0.1'
11
+ ```
12
+
13
+ To manually install `honeycrisp` via [Rubygems][rubygems] simply gem install:
14
+
15
+ ```bash
16
+ gem install honeycrisp
17
+ ```
18
+
19
+ To build and install the development branch yourself from the latest source:
20
+
21
+ ```bash
22
+ git clone git@github.com:jerhinesmith/honeycrisp.git
23
+ cd honeycrisp
24
+ make install
25
+ ```
26
+
27
+ ## Getting Started With Honeycrisp
28
+
29
+ ### Setup Work
30
+
31
+ ``` ruby
32
+ require 'rubygems' # not necessary with ruby 1.9 but included for completeness
33
+ require 'honeycrisp'
34
+
35
+ # put your own credentials here
36
+ shared_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
37
+
38
+ # set up a client to talk to the App Store
39
+ @client = Honeycrisp::Client.new shared_secret, use_sandbox: true
40
+
41
+ # alternatively, you can preconfigure the client like so
42
+ Honeycrisp.configure do |config|
43
+ config.shared_secret = shared_secret
44
+ config.use_sandbox = true
45
+ end
46
+
47
+ # and then you can create a new client without parameters
48
+ @client = Honeycrisp::Client.new
49
+ ```
50
+
51
+ ### Validate a receipt
52
+
53
+ ``` ruby
54
+ receipt = @client.validate_receipt(base64_encoded_string)
55
+ ```
56
+
57
+ ## Supported Ruby Versions
58
+
59
+ This library supports has been manually tested agains the following Ruby
60
+ implementations:
61
+
62
+ - Ruby 2.1.0
63
+
64
+ ## More Information
65
+
66
+ [bundler]: http://bundler.io
67
+ [rubygems]: http://rubygems.org
68
+ [gem]: https://rubygems.org/gems/honeycrisp
69
+ [documentation]: https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW1
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rspec/core/rake_task'
6
+ desc 'Run all specs'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task default: :spec
10
+ task test: :spec
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'honeycrisp/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'honeycrisp'
8
+ spec.version = Honeycrisp::VERSION
9
+ spec.authors = ['Justin Rhinesmith']
10
+ spec.email = ['jerhinesmith@gmail.com']
11
+ spec.summary = "A simple library for communicating with Apple's iTunes receipt validation server."
12
+ spec.description = "A simple library for communicating with Apple's iTunes receipt validation server."
13
+ spec.homepage = 'http://github.com/jerhinesmith/honeycrisp'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+ spec.required_ruby_version = '>= 1.9.3'
20
+ spec.extra_rdoc_files = ['README.md', 'LICENSE.md']
21
+ spec.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'honeycrisp', '--main', 'README.md']
22
+
23
+ spec.add_dependency 'faraday', ['>= 0.8', '< 0.10']
24
+ spec.add_dependency 'multi_json', '>= 1.3.0'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.5'
27
+ spec.extra_rdoc_files = ['README.md', 'LICENSE.md']
28
+ spec.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'honeycrisp', '--main', 'README.md']
29
+ end
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), 'honeycrisp', 'version')
2
+ require File.join(File.dirname(__FILE__), 'honeycrisp', 'configuration')
3
+ require File.join(File.dirname(__FILE__), 'honeycrisp', 'client')
4
+ require File.join(File.dirname(__FILE__), 'honeycrisp', 'receipt')
5
+ require File.join(File.dirname(__FILE__), 'honeycrisp', 'in_app_purchase')
6
+ require File.join(File.dirname(__FILE__), 'honeycrisp', 'itunes', 'error')
7
+
8
+ module Honeycrisp
9
+ extend Configuration
10
+ end
@@ -0,0 +1,56 @@
1
+ require 'faraday'
2
+ require 'logger'
3
+ require 'multi_json'
4
+
5
+ module Honeycrisp
6
+ class Client
7
+ HTTP_HEADERS = {
8
+ 'Accept' => 'application/json',
9
+ 'Content-Type' => 'application/json',
10
+ 'Accept-Charset' => 'utf-8',
11
+ 'User-Agent' => "honeycrisp/#{Honeycrisp::VERSION}" \
12
+ " (#{RUBY_ENGINE}/#{RUBY_PLATFORM}" \
13
+ " #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
14
+ }
15
+
16
+ attr_reader :shared_secret, :use_sandbox
17
+
18
+ def initialize(*args)
19
+ options = args.last.is_a?(Hash) ? args.pop : {}
20
+
21
+ @shared_secret = args[0] || Honeycrisp.shared_secret
22
+ @use_sandbox = options.fetch(:use_sandbox, Honeycrisp.use_sandbox)
23
+
24
+ raise ArgumentError, 'Shared secret is required' if @shared_secret.nil?
25
+ end
26
+
27
+ def host
28
+ use_sandbox ? 'https://sandbox.itunes.apple.com' : 'https://buy.itunes.apple.com'
29
+ end
30
+
31
+ def validate_receipt(base64_receipt)
32
+ connection.response :logger, ::Logger.new($stdout) if ENV['HONEYCRISP_DEBUG'] == 'true'
33
+
34
+ params = {
35
+ 'receipt-data' => base64_receipt,
36
+ 'password' => shared_secret
37
+ }
38
+
39
+ response = connection.post do |request|
40
+ request.url '/verifyReceipt'
41
+ request.headers.merge!(HTTP_HEADERS)
42
+ request.body = MultiJson.dump(params)
43
+ end
44
+
45
+ Honeycrisp::Receipt.new(MultiJson.load(response.body))
46
+ end
47
+
48
+ private
49
+ def connection
50
+ @connection ||= Faraday.new(url: host) do |faraday|
51
+ faraday.request :url_encoded # form-encode POST params
52
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,18 @@
1
+ module Honeycrisp
2
+ module Configuration
3
+ attr_accessor :shared_secret, :use_sandbox
4
+
5
+ def configure
6
+ yield self
7
+ end
8
+
9
+ def self.extended(base)
10
+ base.set_default_configuration
11
+ end
12
+
13
+ def set_default_configuration
14
+ self.shared_secret = ''
15
+ self.use_sandbox = true
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ module Honeycrisp
2
+ class InAppPurchase
3
+ attr_accessor :quantity, :product_id, :transaction_id, :original_transaction_id,
4
+ :purchase_date_ms, :original_purchase_date_ms, :is_trial_period
5
+
6
+ def initialize(attributes = {})
7
+ attributes.each do |k, v|
8
+ send("#{k}=", v) if respond_to?("#{k}=".to_sym)
9
+ end
10
+
11
+ # Return self
12
+ self
13
+ end
14
+
15
+ def purchase_date
16
+ Time.at(purchase_date_ms.to_i / 1000).utc
17
+ end
18
+
19
+ def original_purchase_date
20
+ Time.at(original_purchase_date_ms.to_i / 1000).utc
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ module Honeycrisp
2
+ module Itunes
3
+ CODES = {
4
+ 21000 => "The App Store could not read the JSON object you provided.",
5
+ 21002 => "The data in the receipt-data property was malformed or missing.",
6
+ 21003 => "The receipt could not be authenticated.",
7
+ 21004 => "The shared secret you provided does not match the shared secret on file for your account.",
8
+ 21005 => "The receipt server is not currently available.",
9
+ 21006 => "This receipt is valid but the subscription has expired. When this status code is returned to your server, the receipt data is also decoded and returned as part of the response.",
10
+ 21007 => "This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.",
11
+ 21008 => "This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead."
12
+ }
13
+
14
+ class Error
15
+ attr_accessor :code
16
+ attr_reader :description
17
+
18
+ def initialize(code, description = nil)
19
+ @code = code
20
+ @description = description || Honeycrisp::Itunes::CODES[code]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,70 @@
1
+ module Honeycrisp
2
+ class Receipt
3
+ # Meta fields
4
+ attr_accessor :status, :environment, :raw
5
+
6
+ # Receipt fields
7
+ attr_accessor :receipt_type, :app_item_id, :bundle_id, :application_version,
8
+ :version_external_identifier, :original_purchase_date_ms,
9
+ :original_application_version, :latest_receipt
10
+
11
+ attr_reader :in_app_purchases, :subscriptions, :errors
12
+
13
+ def initialize(receipt_hash)
14
+ # Initialize the errors array
15
+ @in_app_purchases, @subscriptions = [], []
16
+
17
+ # Set the meta-fields
18
+ self.raw = receipt_hash
19
+ self.status = receipt_hash['status'].to_i
20
+ self.environment = receipt_hash['environment']
21
+ self.latest_receipt = receipt_hash['latest_receipt']
22
+
23
+ # Set the receipt fields
24
+ receipt = receipt_hash.fetch('receipt', {})
25
+ subscriptions = receipt_hash.fetch('latest_receipt_info', [])
26
+ purchases = receipt.fetch('in_app', [])
27
+
28
+ receipt.each do |k, v|
29
+ send("#{k}=", v) if respond_to?("#{k}=".to_sym)
30
+ end
31
+
32
+ purchases.each do |purchase_hash|
33
+ @in_app_purchases << Honeycrisp::InAppPurchase.new(purchase_hash)
34
+ end
35
+
36
+ subscriptions.each do |subscription_hash|
37
+ @subscriptions << Honeycrisp::Subscription.new(subscription_hash)
38
+ end
39
+
40
+ @in_app_purchases.sort_by{ |s| s.purchase_date_ms.to_i }
41
+ @subscriptions.sort_by{ |s| s.expires_date_ms.to_i }
42
+
43
+ # Return self
44
+ self
45
+ end
46
+
47
+ def original_purchase_date
48
+ Time.at(original_purchase_date_ms.to_i / 1000).utc
49
+ end
50
+
51
+ def latest_purchase
52
+ @in_app_purchases.last
53
+ end
54
+
55
+ def latest_subscription
56
+ @subscriptions.last
57
+ end
58
+
59
+ def valid?
60
+ # Clear out any errors so we can revalidate
61
+ @errors = []
62
+
63
+ # Check the status
64
+ @errors << Honeycrisp::Itunes::Error.new(self.status) if self.status != 0
65
+
66
+ # Valid if errors array is empty
67
+ @errors.length == 0
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,13 @@
1
+ module Honeycrisp
2
+ class Subscription < InAppPurchase
3
+ attr_accessor :expires_date_ms
4
+
5
+ def expires_date
6
+ Time.at(expires_date_ms.to_i / 1000).utc
7
+ end
8
+
9
+ def expired?
10
+ Time.now.utc > expires_date
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Honeycrisp
2
+ VERSION = "0.0.1"
3
+ end
File without changes
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: honeycrisp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Justin Rhinesmith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '0.10'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.10'
33
+ - !ruby/object:Gem::Dependency
34
+ name: multi_json
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 1.3.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.3.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.5'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.5'
61
+ description: A simple library for communicating with Apple's iTunes receipt validation
62
+ server.
63
+ email:
64
+ - jerhinesmith@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files:
68
+ - README.md
69
+ - LICENSE.md
70
+ files:
71
+ - ".gitignore"
72
+ - CHANGES.md
73
+ - Gemfile
74
+ - LICENSE.md
75
+ - Makefile
76
+ - README.md
77
+ - Rakefile
78
+ - honeycrisp.gemspec
79
+ - lib/honeycrisp.rb
80
+ - lib/honeycrisp/client.rb
81
+ - lib/honeycrisp/configuration.rb
82
+ - lib/honeycrisp/in_app_purchase.rb
83
+ - lib/honeycrisp/itunes/error.rb
84
+ - lib/honeycrisp/receipt.rb
85
+ - lib/honeycrisp/subscription.rb
86
+ - lib/honeycrisp/version.rb
87
+ - spec/.gitkeep
88
+ homepage: http://github.com/jerhinesmith/honeycrisp
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options:
94
+ - "--line-numbers"
95
+ - "--inline-source"
96
+ - "--title"
97
+ - honeycrisp
98
+ - "--main"
99
+ - README.md
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 1.9.3
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 2.2.2
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: A simple library for communicating with Apple's iTunes receipt validation
118
+ server.
119
+ test_files:
120
+ - spec/.gitkeep