kakeibo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/Gemfile +15 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +39 -0
- data/Rakefile +2 -0
- data/kakeibo.gemspec +22 -0
- data/lib/kakeibo/client/base.rb +16 -0
- data/lib/kakeibo/client/iab.rb +24 -0
- data/lib/kakeibo/client/iap.rb +49 -0
- data/lib/kakeibo/client/receipt/base.rb +0 -0
- data/lib/kakeibo/client/receipt/iab.rb +94 -0
- data/lib/kakeibo/client/receipt/iap/ios6.rb +0 -0
- data/lib/kakeibo/client/receipt/iap/ios7.rb +0 -0
- data/lib/kakeibo/client/receipt/iap.rb +85 -0
- data/lib/kakeibo/client.rb +25 -0
- data/lib/kakeibo/error.rb +12 -0
- data/lib/kakeibo.rb +56 -0
- data/spec/kakeibo/client/iab_spec.rb +44 -0
- data/spec/kakeibo/client/iap_spec.rb +32 -0
- data/spec/kakeibo/client/receipt/iab_spec.rb +78 -0
- data/spec/kakeibo/client/receipt/iap_spec.rb +57 -0
- data/spec/kakeibo/client_spec.rb +29 -0
- data/spec/kakeibo/error_spec.rb +18 -0
- data/spec/kakeibo_spec.rb +51 -0
- data/spec/samples/sample_iab_license_key +1 -0
- data/spec/samples/sample_iab_receipt +1 -0
- data/spec/samples/sample_iab_signature +1 -0
- data/spec/samples/sample_iap_receipt +1 -0
- data/spec/spec_helper.rb +18 -0
- metadata +114 -0
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
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,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
|
+
|
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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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|