kakeibo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4a5e283691ed79f090e5e549b7f9611d6a00b9ca
4
+ data.tar.gz: e3425ee404da395fea670c351aa4e443eb3cef64
5
+ SHA512:
6
+ metadata.gz: 65199f7c22547873e2ffce9aa1f58bf767ada37eb1ecce871274956a4ed2d04c53b008e1bcdd65bfa286317f0c6a3aaf1f5f9806690048b5a4aa87b8749ae38a
7
+ data.tar.gz: edc580d5a152670c00565fe62d22b950ce9f96866a2bb70dcb3e2e8ceb5df8e9855f1438271ad406d104db2a2e05b162b122b641742d59bf24390caaa975c6f2
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+
24
+ examples
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kakeibo.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rspec'
8
+ gem 'webmock', require: false
9
+ gem 'vcr'
10
+ gem 'guard'
11
+ gem 'guard-rspec', require: false
12
+ gem 'simplecov', require: false
13
+ gem 'simplecov-rcov', require: false
14
+ gem 'awesome_print'
15
+ end
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec, cmd: 'bundle exec rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 haruyama-makoto
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Kakeibo
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'kakeibo'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install kakeibo
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Refernces
24
+
25
+ ### iOS
26
+
27
+ ### Android
28
+
29
+ * [Google Play In-app Billing](http://developer.android.com/google/play/billing/index.html)
30
+ * [Purchasing In-app Billing Products](http://developer.android.com/training/in-app-billing/purchase-iab-products.html)
31
+ * [Security Best Practices](http://developer.android.com/google/play/billing/billing_best_practices.html)
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( https://github.com/[my-github-username]/kakeibo/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/kakeibo.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "kakeibo"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Spring_MT"]
9
+ spec.email = ["today.is.sky.blue.sky@gmail.com"]
10
+ spec.summary = %q{IAP and IAB receipt validation module.}
11
+ spec.description = %q{IAP and IAB receipt validation module.}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.6"
21
+ spec.add_development_dependency "rake"
22
+ end
@@ -0,0 +1,16 @@
1
+ class Kakeibo
2
+ class Client
3
+ class Base
4
+
5
+ def initialize
6
+ end
7
+
8
+ def fetch
9
+ raise "Please define fetchmethod"
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+
16
+
@@ -0,0 +1,24 @@
1
+ require 'kakeibo/client/base'
2
+ require 'kakeibo/client/receipt/iab'
3
+
4
+ class Kakeibo
5
+ class Client
6
+ class Iab < Base
7
+ def initialize(environment: :production)
8
+ @raw_data = nil
9
+ @option = nil
10
+ end
11
+
12
+ def fetch(raw_data, option={})
13
+ @raw_data = raw_data
14
+ @option = option
15
+ true
16
+ end
17
+
18
+ def get_receipt
19
+ Kakeibo::Client::Receipt::Iab.new(@raw_data, @option)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,49 @@
1
+ require 'uri'
2
+ require 'net/https'
3
+ require 'json'
4
+
5
+ require 'kakeibo/client/base'
6
+ require 'kakeibo/client/receipt/iap'
7
+
8
+ class Kakeibo
9
+ class Client
10
+ class Iap < Base
11
+ PRODUCTION_ENDPOINT = "https://buy.itunes.apple.com/verifyReceipt"
12
+ SANDBOX_ENDPOINT = "https://sandbox.itunes.apple.com/verifyReceipt"
13
+ attr_reader :response
14
+
15
+ def initialize
16
+ @response = nil
17
+ end
18
+
19
+ def fetch(base64_encoded_data, option={})
20
+ endpoint = PRODUCTION_ENDPOINT
21
+ if option[:environment] == :sandbox
22
+ endpoint = SANDBOX_ENDPOINT
23
+ end
24
+
25
+ parameters = {
26
+ 'receipt-data' => base64_encoded_data
27
+ }
28
+ parameters['password'] = option[:shared_secret] unless option[:shared_secret].nil?
29
+
30
+ uri = URI(endpoint)
31
+ http = Net::HTTP.new(uri.host, uri.port)
32
+ http.use_ssl = true
33
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
34
+
35
+ request = Net::HTTP::Post.new(uri.request_uri)
36
+ request['Accept'] = 'application/json'
37
+ request['Content-Type'] = 'application/json'
38
+ request.body = parameters.to_json
39
+ @response = http.request(request)
40
+ @response.value
41
+ @response
42
+ end
43
+
44
+ def get_receipt
45
+ Kakeibo::Client::Receipt::Iap.new(response.body)
46
+ end
47
+ end
48
+ end
49
+ end
File without changes
@@ -0,0 +1,94 @@
1
+ require 'json'
2
+ require 'kakeibo/error'
3
+
4
+ class Kakeibo
5
+ class Client
6
+ class Receipt
7
+ class Iab
8
+ VALID_RECEIPT = 0
9
+ INVALID_JSON = 1
10
+ SIGNATURE_IS_NIL = 2
11
+ BASE64_ENCODED_PUBILC_KEY_IS_NIL = 3
12
+ INVALID_SIGNATURE = 4
13
+ INVALID_DEVELOPER_PAYLOAD = 5
14
+
15
+ attr_reader :status
16
+ attr_reader :order_id
17
+ attr_reader :receipt_data
18
+
19
+ def initialize(raw_receipt_data, option={})
20
+ @raw_receipt_data = raw_receipt_data
21
+ @receipt_data = nil
22
+ @signature = option[:signature]
23
+ @base64_encoded_public_key = option[:base64_encoded_public_key]
24
+ @developer_payload = option[:developer_payload]
25
+
26
+ @order_id = nil
27
+ @status = nil
28
+ valid?
29
+ end
30
+
31
+ def valid?
32
+ begin
33
+ @receipt_data ||= JSON.parse(@raw_receipt_data, symbolize_names: true)
34
+ rescue JSON::ParserError => e
35
+ @status = INVALID_JSON
36
+ return false
37
+ end
38
+
39
+ @order_id = @receipt_data[:orderId]
40
+
41
+ if @signature.nil?
42
+ @status = SIGNATURE_IS_NIL
43
+ return false
44
+ end
45
+ if @base64_encoded_public_key.nil?
46
+ @status = BASE64_ENCODED_PUBILC_KEY_IS_NIL
47
+ return false
48
+ end
49
+
50
+ public_key = OpenSSL::PKey::RSA.new(Base64.decode64(@base64_encoded_public_key))
51
+ unless public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(@signature), @raw_receipt_data)
52
+ @status = INVALID_SIGNATURE
53
+ return false
54
+ end
55
+
56
+ if !@receipt_data[:developerPayload].nil? && (@receipt_data[:developerPayload] != @developer_payload)
57
+ @status = INVALID_DEVELOPER_PAYLOAD
58
+ return false
59
+ end
60
+
61
+ @status = VALID_RECEIPT
62
+ return true
63
+ end
64
+
65
+ def error
66
+ return nil if valid?
67
+ Kakeibo::Error.new(@status, message)
68
+ end
69
+
70
+ private
71
+
72
+ def message
73
+ case @status
74
+ when INVALID_JSON
75
+ "Receipt data is invalid json. #{@raw_receipt_data}"
76
+ when SIGNATURE_IS_NIL
77
+ "Option :signature is required at fetch."
78
+ when BASE64_ENCODED_PUBILC_KEY_IS_NIL
79
+ "Option :base64_encoded_public_key is required at fetch. Base64_encoded_public_key is license keys on a per-app. Please see youe Google Play account"
80
+ when INVALID_SIGNATURE
81
+ "Signature is invalid."
82
+ when INVALID_DEVELOPER_PAYLOAD
83
+ "Developer payload is invalid."
84
+ else
85
+ "Unknown Error: #{@status}"
86
+ end
87
+ end
88
+
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+
File without changes
File without changes
@@ -0,0 +1,85 @@
1
+ require 'json'
2
+ require 'kakeibo/error'
3
+
4
+ class Kakeibo
5
+ class Client
6
+ class Receipt
7
+ class Iap
8
+ VALID_RECEIPT = 0
9
+ INVALID_JSON = 1
10
+ IS_SANDBOX_STATUS = 21007
11
+
12
+ attr_reader :status
13
+ attr_reader :receipt_data
14
+
15
+ def initialize(raw_receipt_data, option={})
16
+ @raw_receipt_data = raw_receipt_data
17
+ @receipt_data = nil
18
+ @transaction_id = option[:transaction_id]
19
+ @status = nil
20
+ valid?
21
+ end
22
+
23
+ def valid?
24
+ begin
25
+ @receipt_data ||= JSON.parse(@raw_receipt_data, symbolize_names: true)
26
+ rescue JSON::ParserError => e
27
+ @status = INVALID_JSON
28
+ return false
29
+ end
30
+
31
+ @status = @receipt_data[:status]
32
+ return false if @status != VALID_RECEIPT
33
+ return true if @transaction_id.nil?
34
+ if ios7?(@receipt_data)
35
+ @receipt_data[:receipt][:in_app].one? { |r| r[:transaction_id] == @transaction_id }
36
+ else
37
+ @receipt_data[:receipt][:transaction_id] == @transaction_id
38
+ end
39
+ end
40
+
41
+ def error
42
+ return nil if valid?
43
+ Kakeibo::Error.new(@status, message)
44
+ end
45
+
46
+ private
47
+
48
+ def ios7?(receipt_data)
49
+ return false if receipt_data["receipt"].nil?
50
+ receipt = receipt_data["receipt"]
51
+ return false if receipt_data["in_app"].nil?
52
+ true
53
+ end
54
+
55
+ def message
56
+ case @status
57
+ when INVALID_JSON
58
+ "Receipt data is invalid json. #{@raw_receipt_data}"
59
+ when 21000
60
+ "The App Store could not read the JSON object you provided."
61
+ when 21002
62
+ "The data in the receipt-data property was malformed."
63
+ when 21003
64
+ "The receipt could not be authenticated."
65
+ when 21004
66
+ "The shared secret you provided does not match the shared secret on file for your account."
67
+ when 21005
68
+ "The receipt server is not currently available."
69
+ when 21006
70
+ "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."
71
+ when 21007
72
+ "This receipt is a sandbox receipt, but it was sent to the production service for verification."
73
+ when 21008
74
+ "This receipt is a production receipt, but it was sent to the sandbox service for verification."
75
+ else
76
+ "Unknown Error: #{@status}"
77
+ end
78
+ end
79
+
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+
@@ -0,0 +1,25 @@
1
+ require 'forwardable'
2
+
3
+ require 'kakeibo/client/iab'
4
+ require 'kakeibo/client/iap'
5
+
6
+ class Kakeibo
7
+ # 各platformへの問い合わせを担う
8
+ class Client
9
+ extend Forwardable
10
+
11
+ def initialize(platform)
12
+ # iap iabのそれぞれのclientのインスタンスを返す
13
+ constant = Object
14
+ constant = constant.const_get 'Kakeibo'
15
+ constant = constant.const_get 'Client'
16
+ @client = constant.const_get(platform, false).new
17
+ end
18
+
19
+ def_delegator :@client, :fetch, :fetch
20
+ def_delegator :@client, :get_receipt, :get_receipt
21
+
22
+ end
23
+ end
24
+
25
+
@@ -0,0 +1,12 @@
1
+ class Kakeibo
2
+ class Error
3
+ attr_reader :status
4
+ attr_reader :message
5
+
6
+ def initialize(status, message)
7
+ @status = status
8
+ @message = message
9
+ end
10
+
11
+ end
12
+ end
data/lib/kakeibo.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'kakeibo/error'
2
+ require 'kakeibo/client'
3
+
4
+ class Kakeibo
5
+ attr_reader :receipt
6
+
7
+ def initialize(platform, retry_count: 1, logger: nil)
8
+ @platform = platform # :Iap or :Iab
9
+ @retry_count = retry_count
10
+ @logger = logger || Logger.new(STDOUT)
11
+ @receipt = nil
12
+ end
13
+
14
+ # option
15
+ # For IAP
16
+ # :transaction_id -> SKPaymentTransaction#transactionIdentifier OPTIONAL
17
+ # For IAB
18
+ # :signature => included IAB response REQUIRED
19
+ # :base64_encoded_public_key => license key REQUIRED
20
+ # :developer_payload => developer payload OPTIONAL
21
+ def fetch(data, option={})
22
+ client = ::Kakeibo::Client.new @platform
23
+ count = 0
24
+ response = nil
25
+ begin
26
+ count += 1
27
+ response = client.fetch(data, option)
28
+ rescue => e
29
+ @logger.error("ERROR #{e} #{e.message}")
30
+ if count < @retry_count
31
+ retry
32
+ else
33
+ raise e
34
+ end
35
+ end
36
+ @receipt = client.get_receipt
37
+
38
+ # IAP sandboxの場合の処理
39
+ if @receipt.instance_of?(Kakeibo::Client::Receipt::Iap) && @receipt.status == Kakeibo::Client::Receipt::Iap::IS_SANDBOX_STATUS
40
+ response = client.fetch(data, option.merge({environment: :sandbox}))
41
+ @receipt = client.get_receipt
42
+ end
43
+ @receipt
44
+ end
45
+
46
+ def valid?
47
+ return false if @receipt.nil?
48
+ @receipt.valid?
49
+ end
50
+
51
+ def error
52
+ return nil if @receipt.nil?
53
+ @receipt.error
54
+ end
55
+
56
+ end
@@ -0,0 +1,44 @@
1
+ require File.join(__dir__, '../..' ,'spec_helper')
2
+ describe Kakeibo::Client::Iab do
3
+
4
+ describe '#initialize' do
5
+ context 'sandbox' do
6
+ subject { Kakeibo::Client::Iab.new }
7
+ it do
8
+ expect(subject.instance_variable_get(:@raw_data)).to be_nil
9
+ expect(subject.instance_variable_get(:@option)).to be_nil
10
+ end
11
+ end
12
+ context 'production' do
13
+ subject { Kakeibo::Client::Iab.new(environment: :production) }
14
+ it do
15
+ expect(subject.instance_variable_get(:@raw_data)).to be_nil
16
+ expect(subject.instance_variable_get(:@option)).to be_nil
17
+ end
18
+ end
19
+ end
20
+
21
+ describe '#fetch' do
22
+ context 'valid' do
23
+ subject { Kakeibo::Client::Iab.new }
24
+ it do
25
+ subject.fetch('test')
26
+ expect(subject.instance_variable_get(:@raw_data)).to eq('test')
27
+ expect(subject.instance_variable_get(:@option)).to eq({})
28
+ end
29
+ end
30
+ end
31
+
32
+ describe '#get_receipt' do
33
+ context 'valid' do
34
+ before do
35
+ end
36
+ subject { Kakeibo::Client::Iab.new }
37
+ it do
38
+ subject.fetch('{"orderId":"1"}')
39
+ expect(subject.get_receipt).to be_a(Kakeibo::Client::Receipt::Iab)
40
+ end
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,32 @@
1
+ require File.join(__dir__, '../..' ,'spec_helper')
2
+ require 'webmock/rspec'
3
+ require 'json'
4
+
5
+ describe Kakeibo::Client::Iap do
6
+
7
+ describe '#fetch' do
8
+ context 'valid' do
9
+ before do
10
+ stub_request(:post, Kakeibo::Client::Iap::PRODUCTION_ENDPOINT).to_return({body: "{\"status\":0}", status: 200})
11
+ end
12
+ subject { Kakeibo::Client::Iap.new.fetch('test') }
13
+ it do
14
+ expect(JSON.parse(subject.body, symbolize_names: true)).to eq({status: 0})
15
+ end
16
+ end
17
+ end
18
+
19
+ describe '#get_receipt' do
20
+ context 'valid' do
21
+ before do
22
+ stub_request(:post, Kakeibo::Client::Iap::PRODUCTION_ENDPOINT).to_return({body: "{\"status\":0}", status: 200})
23
+ end
24
+ subject { Kakeibo::Client::Iap.new }
25
+ it do
26
+ subject.fetch('test')
27
+ expect(subject.get_receipt).to be_a(Kakeibo::Client::Receipt::Iap)
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,78 @@
1
+ require File.join(__dir__, '../../..' ,'spec_helper')
2
+
3
+ describe Kakeibo::Client::Receipt::Iap do
4
+ let(:valid_json) { IO.read(File.join(__dir__, '../../..', '/samples/sample_iab_receipt')).chomp! }
5
+ let(:valid_signature) { IO.read(File.join(__dir__, '../../..', '/samples/sample_iab_signature')).chomp! }
6
+ let(:license_key) { IO.read(File.join(__dir__, '../../..', '/samples/sample_iab_license_key')).chomp! }
7
+
8
+ describe '#initialize' do
9
+ context 'valid' do
10
+ subject { Kakeibo::Client::Receipt::Iab.new('{"orderId":"1"}') }
11
+ it { expect(subject.status).to eq Kakeibo::Client::Receipt::Iab::SIGNATURE_IS_NIL }
12
+ end
13
+ end
14
+
15
+ describe '#valid?' do
16
+ context 'valid' do
17
+ subject { Kakeibo::Client::Receipt::Iab.new(valid_json, {signature: valid_signature, base64_encoded_public_key: license_key}) }
18
+ it { expect(subject.valid?).to be_truthy }
19
+ end
20
+ context 'valid with payload' do
21
+ pending 'Prepareing payload response.....'
22
+ end
23
+
24
+ context 'invalid' do
25
+ subject { Kakeibo::Client::Receipt::Iab.new('{"orderId":"1"}', {signature: valid_signature, base64_encoded_public_key: license_key}) }
26
+ it { expect(subject.valid?).to be_falsey }
27
+ end
28
+ end
29
+
30
+ describe '#error' do
31
+ context 'valid' do
32
+ subject { Kakeibo::Client::Receipt::Iab.new(valid_json, {signature: valid_signature, base64_encoded_public_key: license_key}) }
33
+ it { expect(subject.error).to be_nil }
34
+ end
35
+
36
+ context 'invalid with invaid json' do
37
+ subject { Kakeibo::Client::Receipt::Iab.new('test') }
38
+ it do
39
+ expect(subject.error).to be_a(Kakeibo::Error)
40
+ expect(subject.error.status).to eq(Kakeibo::Client::Receipt::Iab::INVALID_JSON)
41
+ expect(subject.error.message).to eq("Receipt data is invalid json. test")
42
+ end
43
+ end
44
+
45
+ context 'invalid with nil signature' do
46
+ subject { Kakeibo::Client::Receipt::Iab.new(valid_json, {base64_encoded_public_key: license_key}) }
47
+ it do
48
+ expect(subject.error).to be_a(Kakeibo::Error)
49
+ expect(subject.error.status).to eq(Kakeibo::Client::Receipt::Iab::SIGNATURE_IS_NIL)
50
+ end
51
+ end
52
+ context 'invalid with nil base64_encoded_public_key' do
53
+ subject { Kakeibo::Client::Receipt::Iab.new(valid_json, {signature: valid_signature}) }
54
+ it do
55
+ expect(subject.error).to be_a(Kakeibo::Error)
56
+ expect(subject.error.status).to eq(Kakeibo::Client::Receipt::Iab::BASE64_ENCODED_PUBILC_KEY_IS_NIL)
57
+ end
58
+ end
59
+ context 'invalid with invalid signature' do
60
+ subject { Kakeibo::Client::Receipt::Iab.new(valid_json, {signature: 'test', base64_encoded_public_key: license_key}) }
61
+ it do
62
+ expect(subject.error).to be_a(Kakeibo::Error)
63
+ expect(subject.error.status).to eq(Kakeibo::Client::Receipt::Iab::INVALID_SIGNATURE)
64
+ end
65
+ end
66
+ context 'invalid with invalid developer payload' do
67
+ subject { Kakeibo::Client::Receipt::Iab.new(valid_json, {signature: valid_signature, base64_encoded_public_key: license_key}) }
68
+ it do
69
+ pending 'Prepareing payload response.....'
70
+ expect(subject.error).to be_a(Kakeibo::Error)
71
+ expect(subject.error.status).to eq(Kakeibo::Client::Receipt::Iab::INVALID_DEVELOPER_PAYLOAD)
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+
@@ -0,0 +1,57 @@
1
+ require File.join(__dir__, '../../..' ,'spec_helper')
2
+
3
+ describe Kakeibo::Client::Receipt::Iap do
4
+ let(:valid_json) { "{\"status\":0}" }
5
+ let(:not_authenticated_json) { "{\"status\":21003}" }
6
+
7
+ describe '#initialize' do
8
+ context 'valid' do
9
+ subject { Kakeibo::Client::Receipt::Iap.new(valid_json) }
10
+ it { expect(subject.status).to eq 0 }
11
+ end
12
+ end
13
+
14
+ describe '#valid?' do
15
+ context 'valid' do
16
+ subject { Kakeibo::Client::Receipt::Iap.new(valid_json) }
17
+ it { expect(subject.valid?).to be_truthy }
18
+ end
19
+
20
+ context 'invalid with invaid json' do
21
+ subject { Kakeibo::Client::Receipt::Iap.new('test') }
22
+ it { expect(subject.valid?).to be_falsey }
23
+ end
24
+
25
+ context 'invalid with notauthenticated' do
26
+ subject { Kakeibo::Client::Receipt::Iap.new(not_authenticated_json) }
27
+ it { expect(subject.valid?).to be_falsey }
28
+ end
29
+ end
30
+
31
+ describe '#error' do
32
+ context 'valid' do
33
+ subject { Kakeibo::Client::Receipt::Iap.new(valid_json) }
34
+ it { expect(subject.error).to be_nil }
35
+ end
36
+
37
+ context 'invalid with invaid json' do
38
+ subject { Kakeibo::Client::Receipt::Iap.new('test') }
39
+ it do
40
+ expect(subject.error).to be_a(Kakeibo::Error)
41
+ expect(subject.error.status).to eq(Kakeibo::Client::Receipt::Iap::INVALID_JSON)
42
+ expect(subject.error.message).to eq("Receipt data is invalid json. test")
43
+ end
44
+ end
45
+
46
+ context 'invalid not authenticated' do
47
+ subject { Kakeibo::Client::Receipt::Iap.new(not_authenticated_json) }
48
+ it do
49
+ expect(subject.error).to be_a(Kakeibo::Error)
50
+ expect(subject.error.status).to eq(21003)
51
+ expect(subject.error.message).to eq("The receipt could not be authenticated.")
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+
@@ -0,0 +1,29 @@
1
+ require File.join(__dir__, '..' ,'spec_helper')
2
+
3
+ describe Kakeibo::Client do
4
+
5
+ describe '#initialize' do
6
+
7
+ context 'iap client' do
8
+ subject { Kakeibo::Client.new(:Iap) }
9
+ it do
10
+ expect(subject.instance_variable_get(:@client)).to be_a(Kakeibo::Client::Iap)
11
+ end
12
+ end
13
+
14
+ context 'iab client' do
15
+ subject { Kakeibo::Client.new(:Iab) }
16
+ it do
17
+ expect(subject.instance_variable_get(:@client)).to be_a(Kakeibo::Client::Iab)
18
+ end
19
+ end
20
+
21
+ context 'not exeists client' do
22
+ it do
23
+ expect{ Kakeibo::Client.new(:test) }.to raise_error(NameError)
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(__dir__, '..' ,'spec_helper')
2
+
3
+ describe Kakeibo::Error do
4
+
5
+ describe '#initialize' do
6
+
7
+ context 'Error' do
8
+ subject { Kakeibo::Error.new(1, 'test') }
9
+ it do
10
+ expect(subject.status).to eq 1
11
+ expect(subject.message).to eq 'test'
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
@@ -0,0 +1,51 @@
1
+ require __dir__ + '/spec_helper'
2
+
3
+ describe Kakeibo do
4
+ let(:iab_valid_receipt_json) { IO.read(__dir__ + '/samples/sample_iab_receipt').chomp! }
5
+ let(:iab_valid_signature) { IO.read(__dir__ + '/samples/sample_iab_signature').chomp! }
6
+ let(:iab_license_key) { IO.read(__dir__ + '/samples/sample_iab_license_key').chomp! }
7
+ let(:iap_valid_receipt_json) { IO.read(__dir__ + '/samples/sample_iap_receipt').chomp! }
8
+
9
+ describe 'integration test' do
10
+ context 'iap' do
11
+ context 'valid' do
12
+ subject { Kakeibo.new(:Iap) }
13
+ it do
14
+ subject.fetch(iap_valid_receipt_json)
15
+ expect(subject.valid?).to be_truthy
16
+ expect(subject.error).to be_nil
17
+ end
18
+ end
19
+ context 'invalid with invalid receipt' do
20
+ subject { Kakeibo.new(:Iap, retry_count: 2).fetch('test') }
21
+ it do
22
+ expect(subject.error).to be_a(Kakeibo::Error)
23
+ expect(subject.error.status).to eq(21002)
24
+ expect(subject.error.message).to eq("The data in the receipt-data property was malformed.")
25
+ end
26
+ end
27
+ end
28
+
29
+ context 'iab' do
30
+ context 'valid' do
31
+ subject { Kakeibo.new(:Iab) }
32
+ it do
33
+ subject.fetch(iab_valid_receipt_json, {signature: iab_valid_signature, base64_encoded_public_key: iab_license_key})
34
+ expect(subject.valid?).to be_truthy
35
+ expect(subject.error).to be_nil
36
+ expect(subject.receipt.order_id,).to eq "12999763169054705758.1352167300083930"
37
+ end
38
+ end
39
+ context 'invalid with invalid signature' do
40
+ subject { Kakeibo.new(:Iab) }
41
+ it do
42
+ subject.fetch(iab_valid_receipt_json, {signature: 'test', base64_encoded_public_key: iab_license_key})
43
+ expect(subject.valid?).to be_falsey
44
+ expect(subject.error.status).to eq(Kakeibo::Client::Receipt::Iab::INVALID_SIGNATURE)
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1 @@
1
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjZfUt8uwnoq6mtaEGWkwX66/4Wd0SCfl73fED0lYySp7K4dJgrOK+JbTMgKc96LxQ4biEplYD8rObXrjzsrJ5/sgjLizLbJLjAcZgiweIlcD/LJz/hq5fQDISwLRXUfoBxU0n3hxTqlaFbnoWvyh9bEJ9g9nr96AZ1JbLu1cBFDegS8tAPFRcfkcM2uxU3RzQQ5I3oFOxxnwSLHG+CWGjPUSuwv7pS2ILKKGqaXOYkaqTESDqiPUL84NQ5WgNUg2v55xRn/vREtHMMj028cdml2og+wWI/p8hJgxlsdORTG+JMtPixNDaKcbxvE16XuNytE96IFiYTAqfKQiyWok/wIDAQAB
@@ -0,0 +1 @@
1
+ {"orderId":"12999763169054705758.1352167300083930","packageName":"com.SpringMT.haruyamamakoto.testmoney","productId":"001","purchaseTime":1405675241311,"purchaseState":0,"purchaseToken":"fialngokjphgdodbakfbeihn.AO-J1OxXTH5bWyOOEeSorA8vXGpKBxEfY0uo7mS2qcB7jSKWnJk2tIjMxFeK-ThbVDEQU1YWQrosbWYqffNeam3DWiiLAIbvR7TYtY3_-dPbyxt5-7qLqryrK5m1VP493CBCVxMPnDiv"}
@@ -0,0 +1 @@
1
+ Lp2Oxctml9TGj2/QcwwDTN1V7GEcawOeBcS8Da2cdxf7GjLt29SWwqNDFJfMKR20V8VqP0TaBQ0JQS8YcR7HqcY8iUeZklojJiYqbjGZVoUp8Bsd3VdF0vo47HWAeBzVifC43psHRR1JVCnznI12xIfE89pr/MpYIVlxVF5gNJGcTt+bA0qwgzA0TJ1RhoMJVzv2fzgP34wzw8611x1EBtJ0xqEJOcT8NDm82w1YqGlNFgPltCIe3tKb7ZFS5w3+bu3ZnJx4MJvCh9/sNioXwwcrtAFbSPIARZpRzIxyGbe9soDYz0SOC9ujnr1a9XdB60thODZV+YjOg7/72P6VDw==
@@ -0,0 +1 @@
1
+ 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
@@ -0,0 +1,18 @@
1
+ require 'bundler'
2
+ Bundler.setup(:default, :test)
3
+ Bundler.require(:default, :test)
4
+
5
+ require 'simplecov'
6
+ require 'simplecov-rcov'
7
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
8
+ SimpleCov.start
9
+
10
+ $TESTING=true
11
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
12
+
13
+ VCR.configure do |c|
14
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
15
+ c.hook_into :webmock
16
+ c.allow_http_connections_when_no_cassette = true
17
+ end
18
+
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kakeibo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Spring_MT
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: IAP and IAB receipt validation module.
42
+ email:
43
+ - today.is.sky.blue.sky@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - Guardfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - kakeibo.gemspec
55
+ - lib/kakeibo.rb
56
+ - lib/kakeibo/client.rb
57
+ - lib/kakeibo/client/base.rb
58
+ - lib/kakeibo/client/iab.rb
59
+ - lib/kakeibo/client/iap.rb
60
+ - lib/kakeibo/client/receipt/base.rb
61
+ - lib/kakeibo/client/receipt/iab.rb
62
+ - lib/kakeibo/client/receipt/iap.rb
63
+ - lib/kakeibo/client/receipt/iap/ios6.rb
64
+ - lib/kakeibo/client/receipt/iap/ios7.rb
65
+ - lib/kakeibo/error.rb
66
+ - spec/kakeibo/client/iab_spec.rb
67
+ - spec/kakeibo/client/iap_spec.rb
68
+ - spec/kakeibo/client/receipt/iab_spec.rb
69
+ - spec/kakeibo/client/receipt/iap_spec.rb
70
+ - spec/kakeibo/client_spec.rb
71
+ - spec/kakeibo/error_spec.rb
72
+ - spec/kakeibo_spec.rb
73
+ - spec/samples/sample_iab_license_key
74
+ - spec/samples/sample_iab_receipt
75
+ - spec/samples/sample_iab_signature
76
+ - spec/samples/sample_iap_receipt
77
+ - spec/spec_helper.rb
78
+ homepage: ''
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.2.2
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: IAP and IAB receipt validation module.
102
+ test_files:
103
+ - spec/kakeibo/client/iab_spec.rb
104
+ - spec/kakeibo/client/iap_spec.rb
105
+ - spec/kakeibo/client/receipt/iab_spec.rb
106
+ - spec/kakeibo/client/receipt/iap_spec.rb
107
+ - spec/kakeibo/client_spec.rb
108
+ - spec/kakeibo/error_spec.rb
109
+ - spec/kakeibo_spec.rb
110
+ - spec/samples/sample_iab_license_key
111
+ - spec/samples/sample_iab_receipt
112
+ - spec/samples/sample_iab_signature
113
+ - spec/samples/sample_iap_receipt
114
+ - spec/spec_helper.rb