candy_check 0.1.0.pre → 0.3.0

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.
Files changed (76) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +23 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +7 -8
  5. data/Guardfile +42 -0
  6. data/MIGRATION_GUIDE_0_2_0.md +141 -0
  7. data/README.md +86 -26
  8. data/Rakefile +1 -1
  9. data/candy_check.gemspec +33 -25
  10. data/lib/candy_check/app_store/receipt_collection.rb +5 -3
  11. data/lib/candy_check/app_store/subscription_verification.rb +25 -1
  12. data/lib/candy_check/app_store/verification.rb +1 -1
  13. data/lib/candy_check/app_store/verifier.rb +11 -11
  14. data/lib/candy_check/cli/app.rb +16 -33
  15. data/lib/candy_check/cli/commands/play_store.rb +12 -13
  16. data/lib/candy_check/play_store.rb +20 -10
  17. data/lib/candy_check/play_store/acknowledger.rb +19 -0
  18. data/lib/candy_check/play_store/android_publisher_service.rb +6 -0
  19. data/lib/candy_check/play_store/product_acknowledgements/acknowledgement.rb +45 -0
  20. data/lib/candy_check/play_store/product_acknowledgements/response.rb +24 -0
  21. data/lib/candy_check/play_store/product_purchases/product_purchase.rb +90 -0
  22. data/lib/candy_check/play_store/product_purchases/product_verification.rb +53 -0
  23. data/lib/candy_check/play_store/subscription_purchases/subscription_purchase.rb +154 -0
  24. data/lib/candy_check/play_store/subscription_purchases/subscription_verification.rb +55 -0
  25. data/lib/candy_check/play_store/verification_failure.rb +8 -6
  26. data/lib/candy_check/play_store/verifier.rb +24 -49
  27. data/lib/candy_check/utils/config.rb +5 -3
  28. data/lib/candy_check/version.rb +1 -1
  29. data/spec/app_store/receipt_collection_spec.rb +33 -0
  30. data/spec/app_store/subscription_verification_spec.rb +35 -2
  31. data/spec/app_store/verifier_spec.rb +24 -5
  32. data/spec/candy_check_spec.rb +2 -2
  33. data/spec/cli/commands/play_store_spec.rb +10 -43
  34. data/spec/fixtures/play_store/random_dummy_key.json +12 -0
  35. data/spec/fixtures/vcr_cassettes/play_store/product_acknowledgements/acknowledged.yml +105 -0
  36. data/spec/fixtures/vcr_cassettes/play_store/product_acknowledgements/already_acknowledged.yml +124 -0
  37. data/spec/fixtures/vcr_cassettes/play_store/product_acknowledgements/refunded.yml +122 -0
  38. data/spec/fixtures/vcr_cassettes/play_store/product_purchases/permission_denied.yml +196 -0
  39. data/spec/fixtures/vcr_cassettes/play_store/product_purchases/response_with_empty_body.yml +183 -0
  40. data/spec/fixtures/vcr_cassettes/play_store/product_purchases/valid_but_not_consumed.yml +122 -0
  41. data/spec/fixtures/vcr_cassettes/play_store/subscription_purchases/permission_denied.yml +196 -0
  42. data/spec/fixtures/vcr_cassettes/play_store/subscription_purchases/valid_but_expired.yml +127 -0
  43. data/spec/play_store/acknowledger_spec.rb +48 -0
  44. data/spec/play_store/product_acknowledgements/acknowledgement_spec.rb +54 -0
  45. data/spec/play_store/product_acknowledgements/response_spec.rb +66 -0
  46. data/spec/play_store/product_purchases/product_purchase_spec.rb +110 -0
  47. data/spec/play_store/product_purchases/product_verification_spec.rb +49 -0
  48. data/spec/play_store/subscription_purchases/subscription_purchase_spec.rb +237 -0
  49. data/spec/play_store/subscription_purchases/subscription_verification_spec.rb +65 -0
  50. data/spec/play_store/verification_failure_spec.rb +18 -18
  51. data/spec/play_store/verifier_spec.rb +32 -96
  52. data/spec/spec_helper.rb +32 -10
  53. metadata +175 -75
  54. data/lib/candy_check/play_store/client.rb +0 -126
  55. data/lib/candy_check/play_store/config.rb +0 -51
  56. data/lib/candy_check/play_store/discovery_repository.rb +0 -33
  57. data/lib/candy_check/play_store/receipt.rb +0 -81
  58. data/lib/candy_check/play_store/subscription.rb +0 -138
  59. data/lib/candy_check/play_store/subscription_verification.rb +0 -30
  60. data/lib/candy_check/play_store/verification.rb +0 -48
  61. data/spec/fixtures/api_cache.dump +0 -1
  62. data/spec/fixtures/play_store/api_cache.dump +0 -1
  63. data/spec/fixtures/play_store/auth_failure.txt +0 -18
  64. data/spec/fixtures/play_store/auth_success.txt +0 -20
  65. data/spec/fixtures/play_store/discovery.txt +0 -2841
  66. data/spec/fixtures/play_store/dummy.p12 +0 -0
  67. data/spec/fixtures/play_store/empty.txt +0 -17
  68. data/spec/fixtures/play_store/products_failure.txt +0 -29
  69. data/spec/fixtures/play_store/products_success.txt +0 -22
  70. data/spec/play_store/client_spec.rb +0 -125
  71. data/spec/play_store/config_spec.rb +0 -96
  72. data/spec/play_store/discovery_respository_spec.rb +0 -31
  73. data/spec/play_store/receipt_spec.rb +0 -88
  74. data/spec/play_store/subscription_spec.rb +0 -138
  75. data/spec/play_store/subscription_verification_spec.rb +0 -98
  76. data/spec/play_store/verification_spec.rb +0 -82
@@ -38,20 +38,53 @@ describe CandyCheck::AppStore::SubscriptionVerification do
38
38
  response = {
39
39
  'status' => 0,
40
40
  'latest_receipt_info' => [
41
- { 'item_id' => 'some_id' },
42
- { 'item_id' => 'some_other_id' }
41
+ { 'item_id' => 'some_id', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' },
42
+ { 'item_id' => 'some_other_id', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' }
43
43
  ]
44
44
  }
45
45
  with_mocked_response(response) do
46
46
  result = subject.call!
47
47
  result.must_be_instance_of CandyCheck::AppStore::ReceiptCollection
48
48
  result.receipts.must_be_instance_of Array
49
+ result.receipts.size.must_equal(2)
49
50
  last = result.receipts.last
50
51
  last.must_be_instance_of CandyCheck::AppStore::Receipt
51
52
  last.item_id.must_equal('some_other_id')
52
53
  end
53
54
  end
54
55
 
56
+ describe 'filtered product_ids' do
57
+ subject do
58
+ CandyCheck::AppStore::SubscriptionVerification.new(
59
+ endpoint,
60
+ data,
61
+ secret,
62
+ product_ids
63
+ )
64
+ end
65
+ let(:product_ids) { ['product_1'] }
66
+
67
+ it 'returns only filtered reciepts when specifc product_ids are reqested' do
68
+ response = {
69
+ 'status' => 0,
70
+ 'latest_receipt_info' => [
71
+ { 'item_id' => 'some_id', 'product_id' => 'product_1', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' },
72
+ { 'item_id' => 'some_other_id', 'product_id' => 'product_1', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' },
73
+ { 'item_id' => 'some_id', 'product_id' => 'product_2', 'purchase_date' => '2016-04-15 12:52:40 Etc/GMT' }
74
+ ]
75
+ }
76
+ with_mocked_response(response) do
77
+ result = subject.call!
78
+ result.must_be_instance_of CandyCheck::AppStore::ReceiptCollection
79
+ result.receipts.must_be_instance_of Array
80
+ result.receipts.size.must_equal(2)
81
+ last = result.receipts.last
82
+ last.must_be_instance_of CandyCheck::AppStore::Receipt
83
+ last.item_id.must_equal('some_other_id')
84
+ end
85
+ end
86
+ end
87
+
55
88
  private
56
89
 
57
90
  DummyClient = Struct.new(:response) do
@@ -89,7 +89,7 @@ describe CandyCheck::AppStore::Verifier do
89
89
  subject.verify_subscription(
90
90
  data, secret
91
91
  ).must_be_same_as receipt_collection
92
- assert_recorded([production_endpoint, data, secret])
92
+ assert_recorded([production_endpoint, data, secret, nil])
93
93
  end
94
94
  end
95
95
 
@@ -97,7 +97,7 @@ describe CandyCheck::AppStore::Verifier do
97
97
  failure = get_failure(21_000)
98
98
  with_mocked_verifier(failure) do
99
99
  subject.verify_subscription(data, secret).must_be_same_as failure
100
- assert_recorded([production_endpoint, data, secret])
100
+ assert_recorded([production_endpoint, data, secret, nil])
101
101
  end
102
102
  end
103
103
 
@@ -106,11 +106,21 @@ describe CandyCheck::AppStore::Verifier do
106
106
  with_mocked_verifier(failure, receipt) do
107
107
  subject.verify_subscription(data, secret).must_be_same_as receipt
108
108
  assert_recorded(
109
- [production_endpoint, data, secret],
110
- [sandbox_endpoint, data, secret]
109
+ [production_endpoint, data, secret, nil],
110
+ [sandbox_endpoint, data, secret, nil]
111
111
  )
112
112
  end
113
113
  end
114
+
115
+ it 'passed the product_ids' do
116
+ product_ids = ['product_1']
117
+ with_mocked_verifier(receipt_collection) do
118
+ subject.verify_subscription(
119
+ data, secret, product_ids
120
+ ).must_be_same_as receipt_collection
121
+ assert_recorded([production_endpoint, data, secret, product_ids])
122
+ end
123
+ end
114
124
  end
115
125
 
116
126
  private
@@ -134,8 +144,17 @@ describe CandyCheck::AppStore::Verifier do
134
144
  CandyCheck::AppStore::VerificationFailure.fetch(code)
135
145
  end
136
146
 
137
- DummyAppStoreVerification = Struct.new(:endpoint, :data, :secret) do
147
+ class DummyAppStoreVerification
148
+ attr_reader :endpoint, :data, :secret, :product_ids
138
149
  attr_accessor :results
150
+
151
+ def initialize(endpoint, data, secret, product_ids = nil)
152
+ @endpoint = endpoint
153
+ @data = data
154
+ @secret = secret
155
+ @product_ids = product_ids
156
+ end
157
+
139
158
  def call!
140
159
  results.shift
141
160
  end
@@ -1,9 +1,9 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe CandyCheck do
4
4
  subject { CandyCheck }
5
5
 
6
- it 'has a version' do
6
+ it "has a version" do
7
7
  subject::VERSION.wont_be_nil
8
8
  end
9
9
  end
@@ -1,51 +1,18 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe CandyCheck::CLI::Commands::PlayStore do
4
4
  include WithCommand
5
- subject { CandyCheck::CLI::Commands::PlayStore }
6
- let(:arguments) { [package, product_id, token, options] }
7
- let(:package) { 'the_package' }
8
- let(:product_id) { 'the_product' }
9
- let(:token) { 'the_token' }
10
- let(:options) do
11
- {
12
- application_name: 'YourApplication',
13
- application_version: '1.0',
14
- issuer: 'abcdefg@developer.gserviceaccount.com',
15
- key_file: 'local/google.p12',
16
- key_secret: 'notasecret'
17
- }
18
- end
5
+ subject { CandyCheck::CLI::Commands::PlayStore.new(package_name, product_id, token, "json_key_file" => json_key_file) }
6
+ let(:package_name) { "my_package_name" }
7
+ let(:product_id) { "my_product_id" }
8
+ let(:token) { "my_token" }
9
+ let(:json_key_file) { File.expand_path("../../fixtures/play_store/random_dummy_key.json", __dir__) }
19
10
 
20
- before do
21
- stub = proc do |*args|
22
- @verifier = DummyPlayStoreVerifier.new(*args)
23
- end
24
- CandyCheck::PlayStore::Verifier.stub :new, stub do
11
+ it "calls and outputs the verifier" do
12
+ VCR.use_cassette("play_store/product_purchases/valid_but_not_consumed") do
25
13
  run_command!
26
- end
27
- end
28
-
29
- it 'calls and outputs the verifier' do
30
- options.each do |k, v|
31
- @verifier.config.public_send(k).must_equal v
32
- end
33
- @verifier.arguments.must_equal [package, product_id, token]
34
- out.must_be 'Hash:', result: :stubbed
35
- end
36
-
37
- private
38
-
39
- DummyPlayStoreVerifier = Struct.new(:config) do
40
- attr_reader :arguments, :booted
41
-
42
- def boot!
43
- @booted = true
44
- end
45
-
46
- def verify(*arguments)
47
- @arguments = arguments
48
- { result: :stubbed }
14
+ assert_equal "CandyCheck::PlayStore::ProductPurchases::ProductPurchase:", out.lines.first
15
+ assert_equal CandyCheck::PlayStore::ProductPurchases::ProductPurchase, out.lines[1].class
49
16
  end
50
17
  end
51
18
  end
@@ -0,0 +1,12 @@
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "example",
4
+ "private_key_id": "123456789",
5
+ "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEoAIBAAKCAQEAvR7l72CT7UBP6P+02Iut8gKKbKyekz/pQxnckPp1VafuaIwC\nMvYfP4ffVJTcY5IhU9mISNxZf6YDQ0TuD1aOrZYG9wsIgGY0nXhOUZxe/Q5I+V7D\nOI/hSzKF7W0cNCvaJPUSo8+soCLNSQ5mjnV3sRZ6uJwGFN30i1GulqHHKkx3vGxb\niaAL9YG58dPSbPGHFTA/epqUyd1fzCuWHyL9dHW7aw4RroNyEtVdiftAQfaK20I2\nueeDfuEtCPaxQYFQqbz5kKnXQx3fwHRpC7/84xHxsrY576evGxHw4p5EJD37scNN\ncneTG3Ly79/VVSAlrSm6ltutx0+S70scCqK0ewIDAQABAoH/MjwC15LPuDVdBIbn\ngp2XlrEWE8fGV1ainzA/ZkMg55+ztBF8hAzcQAPXTqA76jbmo18k1DWzkDSIqVWl\n5m0XeQRg1T4ZBAIh97H9G7BtispAl/yT3nJZZaAF8wsIctMzHp36VYjUUbTs0nsA\nwtZw9JkEAAVxmBlc26TWuyw9uv4fYXuR+uOsWH8jTTVPvxM9FaCCdK+dOMnswm7Y\nlOAlJj5dANkB2KPwIeE461ThyMo9GHEjpsvciMhKLuBoTSucNkhdgapAmYTSI+/1\nf1cA/KEdCMs9ANr1HFujeS01+N1Xrw/yW6EazaDN1oFHCVORtlB295Eac0Wq6y/P\npf1BAoGBAPIw4HQWsolU3f4FdIvc2POAcSJDRgt++I9Qt/QXq1SJ2dGKIveFiJgo\nZjCfHQFVZ8xl64cLzQ1WagZA1JBbbk9g5RxHDxRv7q+Kn3ogugDo9GUoQvpuuAU6\nXHoR/mLinDorJUnttL3U49xTMfrrut4qkUg+daBVptPtylpio6EDAoGBAMfnYq08\nfd/cPEQ2XPeswgtzXsKNLqA6UXBM7ZauKaFLByjy8peMMF6JPOYlBKQif5k+Egmu\nWIe8oTm8Nn5Ymt32bEd+MkHUC7kFzQeiXnM3u0oKzJMXLAvjSTs296g50YM5zJTC\nl64ACQmQOLZ9tdKorl52ZcmdbBEcZ2uwRvkpAoGAKhs5SrWPgLTSi5FjO9W/mkYg\nZTaQ/PqsOC5ubO+Yh/AXgIiln6cFon6Tlax0HIE+tJibpDT3B3SYplGrIxXiTcao\nzovEIWd8deSB6Xe7HuFhbBzd2DBbqf0FiuuJ8KM5ShuqNfovzDkxDGMic198c5eu\n/oJtbNy3Tm0vGxu/GwUCgYAgmRPXShkAq0pMmUzZups+AMdAFIO47ymelXzc6HOz\ncKevPsbefabZk6mRohG6rkF+fMe2Om8HW3QzFQUR32MJtQh9NA//+hMbTd3cU9bx\nFPJ+pXostkehfKPReyoxjZQjwQYicAUKA8l1fMYyxBclTgp5Lvd0RC5+L9KRlgJM\n2QKBgGVIWRNVpGg38dDqdq/4ue1BoTFhqoMGi6WQm3xa+NH+lyJGacdUhGRz8PxN\nhVKpIj8ljg2Rq/CA9qSgL/Z9rhn8QUMWULuAroCp0S2pMBtZ2RB+Mg2FdVFR9/Ft\nfG7co6mKUGkFPtr48EMfeKY88BRsp3yGOsROGdDsCHItjOVH\n-----END RSA PRIVATE KEY-----\n",
6
+ "client_email": "info@example.com",
7
+ "client_id": "123456789",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/example.iam.gserviceaccount.com"
12
+ }
@@ -0,0 +1,105 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://www.googleapis.com/oauth2/v4/token
6
+ body:
7
+ encoding: ASCII-8BIT
8
+ string: params
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v1.0.1
12
+ Content-Type:
13
+ - application/x-www-form-urlencoded
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Content-Type:
24
+ - application/json; charset=UTF-8
25
+ Vary:
26
+ - Origin
27
+ - Referer
28
+ - X-Origin
29
+ Date:
30
+ - Mon, 22 Jun 2020 11:38:56 GMT
31
+ Server:
32
+ - scaffolding on HTTPServer2
33
+ Cache-Control:
34
+ - private
35
+ X-Xss-Protection:
36
+ - '0'
37
+ X-Frame-Options:
38
+ - SAMEORIGIN
39
+ X-Content-Type-Options:
40
+ - nosniff
41
+ Alt-Svc:
42
+ - h3-28=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443";
43
+ ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443";
44
+ ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443";
45
+ ma=2592000; v="46,43"
46
+ Transfer-Encoding:
47
+ - chunked
48
+ body:
49
+ encoding: ASCII-8BIT
50
+ string: '{"access_token":"access_token","expires_in":3599,"token_type":"Bearer"}'
51
+ recorded_at: Mon, 22 Jun 2020 11:38:56 GMT
52
+ - request:
53
+ method: post
54
+ uri: https://www.googleapis.com/androidpublisher/v3/applications/fake_package_name/purchases/products/fake_product_id/tokens/fake_token:acknowledge
55
+ body:
56
+ encoding: UTF-8
57
+ string: ''
58
+ headers:
59
+ User-Agent:
60
+ - unknown/0.0.0 google-api-ruby-client/0.34.1 Mac OS X/10.14.6 (gzip)
61
+ Accept:
62
+ - "*/*"
63
+ Accept-Encoding:
64
+ - gzip,deflate
65
+ Date:
66
+ - Mon, 22 Jun 2020 11:38:56 GMT
67
+ X-Goog-Api-Client:
68
+ - gl-ruby/2.5.1 gdcl/0.34.1
69
+ Authorization:
70
+ - Bearer some_token
71
+ Content-Type:
72
+ - application/x-www-form-urlencoded
73
+ response:
74
+ status:
75
+ code: 204
76
+ message: No Content
77
+ headers:
78
+ Content-Type:
79
+ - application/json; charset=UTF-8
80
+ Vary:
81
+ - Origin
82
+ - Referer
83
+ - X-Origin
84
+ Date:
85
+ - Mon, 22 Jun 2020 11:38:57 GMT
86
+ Server:
87
+ - ESF
88
+ Content-Length:
89
+ - '0'
90
+ X-Xss-Protection:
91
+ - '0'
92
+ X-Frame-Options:
93
+ - SAMEORIGIN
94
+ X-Content-Type-Options:
95
+ - nosniff
96
+ Alt-Svc:
97
+ - h3-28=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443";
98
+ ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443";
99
+ ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443";
100
+ ma=2592000; v="46,43"
101
+ body:
102
+ encoding: UTF-8
103
+ string: ''
104
+ recorded_at: Mon, 22 Jun 2020 11:38:57 GMT
105
+ recorded_with: VCR 6.0.0
@@ -0,0 +1,124 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://www.googleapis.com/oauth2/v4/token
6
+ body:
7
+ encoding: ASCII-8BIT
8
+ string: params
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v1.0.1
12
+ Content-Type:
13
+ - application/x-www-form-urlencoded
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Content-Type:
24
+ - application/json; charset=UTF-8
25
+ Vary:
26
+ - Origin
27
+ - Referer
28
+ - X-Origin
29
+ Date:
30
+ - Mon, 22 Jun 2020 13:11:45 GMT
31
+ Server:
32
+ - scaffolding on HTTPServer2
33
+ Cache-Control:
34
+ - private
35
+ X-Xss-Protection:
36
+ - '0'
37
+ X-Frame-Options:
38
+ - SAMEORIGIN
39
+ X-Content-Type-Options:
40
+ - nosniff
41
+ Alt-Svc:
42
+ - h3-28=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443";
43
+ ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443";
44
+ ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443";
45
+ ma=2592000; v="46,43"
46
+ Transfer-Encoding:
47
+ - chunked
48
+ body:
49
+ encoding: ASCII-8BIT
50
+ string: '{"access_token":"access_token","expires_in":3599,"token_type":"Bearer"}'
51
+ recorded_at: Mon, 22 Jun 2020 13:11:45 GMT
52
+ - request:
53
+ method: post
54
+ uri: https://www.googleapis.com/androidpublisher/v3/applications/fake_package_name/purchases/products/fake_product_id/tokens/fake_token:acknowledge
55
+ body:
56
+ encoding: UTF-8
57
+ string: ''
58
+ headers:
59
+ User-Agent:
60
+ - unknown/0.0.0 google-api-ruby-client/0.34.1 Mac OS X/10.14.6 (gzip)
61
+ Accept:
62
+ - "*/*"
63
+ Accept-Encoding:
64
+ - gzip,deflate
65
+ Date:
66
+ - Mon, 22 Jun 2020 13:11:45 GMT
67
+ X-Goog-Api-Client:
68
+ - gl-ruby/2.5.1 gdcl/0.34.1
69
+ Authorization:
70
+ - Bearer some_token
71
+ Content-Type:
72
+ - application/x-www-form-urlencoded
73
+ response:
74
+ status:
75
+ code: 400
76
+ message: Bad Request
77
+ headers:
78
+ Content-Type:
79
+ - application/json; charset=UTF-8
80
+ Vary:
81
+ - Origin
82
+ - Referer
83
+ - X-Origin
84
+ Content-Encoding:
85
+ - gzip
86
+ Date:
87
+ - Mon, 22 Jun 2020 13:11:46 GMT
88
+ Server:
89
+ - ESF
90
+ Cache-Control:
91
+ - private
92
+ X-Xss-Protection:
93
+ - '0'
94
+ X-Frame-Options:
95
+ - SAMEORIGIN
96
+ X-Content-Type-Options:
97
+ - nosniff
98
+ Alt-Svc:
99
+ - h3-28=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443";
100
+ ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443";
101
+ ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443";
102
+ ma=2592000; v="46,43"
103
+ Transfer-Encoding:
104
+ - chunked
105
+ body:
106
+ encoding: UTF-8
107
+ string: |
108
+ {
109
+ "error": {
110
+ "code": 400,
111
+ "message": "The purchase is not in a valid state to perform the desired operation.",
112
+ "errors": [
113
+ {
114
+ "message": "The purchase is not in a valid state to perform the desired operation.",
115
+ "domain": "androidpublisher",
116
+ "reason": "invalidPurchaseState",
117
+ "location": "token",
118
+ "locationType": "parameter"
119
+ }
120
+ ]
121
+ }
122
+ }
123
+ recorded_at: Mon, 22 Jun 2020 13:11:46 GMT
124
+ recorded_with: VCR 6.0.0
@@ -0,0 +1,122 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://www.googleapis.com/oauth2/v4/token
6
+ body:
7
+ encoding: ASCII-8BIT
8
+ string: params
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v1.0.1
12
+ Content-Type:
13
+ - application/x-www-form-urlencoded
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Content-Type:
24
+ - application/json; charset=UTF-8
25
+ Vary:
26
+ - Origin
27
+ - Referer
28
+ - X-Origin
29
+ Date:
30
+ - Mon, 22 Jun 2020 14:37:46 GMT
31
+ Server:
32
+ - scaffolding on HTTPServer2
33
+ Cache-Control:
34
+ - private
35
+ X-Xss-Protection:
36
+ - '0'
37
+ X-Frame-Options:
38
+ - SAMEORIGIN
39
+ X-Content-Type-Options:
40
+ - nosniff
41
+ Alt-Svc:
42
+ - h3-28=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443";
43
+ ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443";
44
+ ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443";
45
+ ma=2592000; v="46,43"
46
+ Transfer-Encoding:
47
+ - chunked
48
+ body:
49
+ encoding: ASCII-8BIT
50
+ string: '{"access_token":"access_token","expires_in":3599,"token_type":"Bearer"}'
51
+ recorded_at: Mon, 22 Jun 2020 14:37:46 GMT
52
+ - request:
53
+ method: post
54
+ uri: https://www.googleapis.com/androidpublisher/v3/applications/fake_package_name/purchases/products/fake_product_id/tokens/fake_token:acknowledge
55
+ body:
56
+ encoding: UTF-8
57
+ string: ''
58
+ headers:
59
+ User-Agent:
60
+ - unknown/0.0.0 google-api-ruby-client/0.34.1 Mac OS X/10.14.6 (gzip)
61
+ Accept:
62
+ - "*/*"
63
+ Accept-Encoding:
64
+ - gzip,deflate
65
+ Date:
66
+ - Mon, 22 Jun 2020 14:37:46 GMT
67
+ X-Goog-Api-Client:
68
+ - gl-ruby/2.5.1 gdcl/0.34.1
69
+ Authorization:
70
+ - Bearer some_token
71
+ Content-Type:
72
+ - application/x-www-form-urlencoded
73
+ response:
74
+ status:
75
+ code: 400
76
+ message: Bad Request
77
+ headers:
78
+ Content-Type:
79
+ - application/json; charset=UTF-8
80
+ Vary:
81
+ - Origin
82
+ - Referer
83
+ - X-Origin
84
+ Content-Encoding:
85
+ - gzip
86
+ Date:
87
+ - Mon, 22 Jun 2020 14:37:47 GMT
88
+ Server:
89
+ - ESF
90
+ Cache-Control:
91
+ - private
92
+ X-Xss-Protection:
93
+ - '0'
94
+ X-Frame-Options:
95
+ - SAMEORIGIN
96
+ X-Content-Type-Options:
97
+ - nosniff
98
+ Alt-Svc:
99
+ - h3-28=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443";
100
+ ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443";
101
+ ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443";
102
+ ma=2592000; v="46,43"
103
+ Transfer-Encoding:
104
+ - chunked
105
+ body:
106
+ encoding: UTF-8
107
+ string: |
108
+ {
109
+ "error": {
110
+ "code": 400,
111
+ "message": "The product purchase is not owned by the user.",
112
+ "errors": [
113
+ {
114
+ "message": "The product purchase is not owned by the user.",
115
+ "domain": "androidpublisher",
116
+ "reason": "productNotOwnedByUser"
117
+ }
118
+ ]
119
+ }
120
+ }
121
+ recorded_at: Mon, 22 Jun 2020 14:37:47 GMT
122
+ recorded_with: VCR 6.0.0