candy_check 0.1.0.pre → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 45e40e19795d3d805ea61453fe6bea1d5e94ec3a
4
- data.tar.gz: 9ba798923e9c36b324aa93c860f6ea75687e56bc
2
+ SHA256:
3
+ metadata.gz: 417a8850353b9726251dcae68864b46f77d30de0e73db9488c68c52282a90e70
4
+ data.tar.gz: 5dbcba7f14f6c81d73a0baa7554c01f0e53cb7167e0ff22029a6ddd8deac6b23
5
5
  SHA512:
6
- metadata.gz: f6e4a4bd35ab65c5ad309052f8b27408b3bd570701a39674f9b6120900242ebe2199bf5814788a8fa9572774a8686cc3b57908eeda35223a5c7786b4e921181e
7
- data.tar.gz: 8f3e4cd0adff6af8067667294fb439e05a840e69c9b24d73c0af0a607d348d4a8ffcbe3392e469fd2fab36e26155241739936ae91a8c1509f32595f7a1bf299d
6
+ metadata.gz: 6777436feed72baacb24e07634fa921f9723c37f207f8c9ab373aa68b007f326236877ecff04a32001ee046c0c5200d033218939e59b5af429e2b65d3e15504c
7
+ data.tar.gz: bc28443c9277dbad870f04fcc85a4c92705c7ce72d4a88b9a4ab9c882a5e90e7281a3ef13a77e1f12866e0c77b3896d8ea6be542184041a16d3eb15d16758917
@@ -5,3 +5,26 @@ AllCops:
5
5
  - 'vendor/**/*'
6
6
  Style/Documentation:
7
7
  Enabled: false
8
+ Style/FrozenStringLiteralComment:
9
+ Enabled: false
10
+ Style/NumericPredicate:
11
+ Enabled: false
12
+ Lint/UnifiedInteger:
13
+ Enabled: false
14
+ Style/PercentLiteralDelimiters:
15
+ PreferredDelimiters:
16
+ default: ()
17
+ "%i": ()
18
+ "%w": ()
19
+ Metrics/BlockLength:
20
+ Exclude:
21
+ - 'spec/**/*'
22
+ Security/MarshalLoad:
23
+ Exclude:
24
+ - 'lib/candy_check/play_store/discovery_repository.rb'
25
+ Style/DateTime:
26
+ Enabled: false
27
+ Style/Encoding:
28
+ Enabled: false
29
+ Style/ExpandPathArguments:
30
+ Enabled: false
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.7.1
@@ -2,18 +2,17 @@ language: ruby
2
2
  sudo: false
3
3
  cache: bundler
4
4
  rvm:
5
- - '2.3.1'
6
- - '2.3.0'
7
- - '2.2'
8
- - '2.1'
9
- - '2.0'
5
+ - 2.6.5
6
+ - 2.5.7
7
+ - 2.4.9
8
+ - jruby-9.2.9.0
10
9
  - ruby-head
11
- - rbx-2
12
- - jruby-20mode
13
- - jruby-21mode
14
10
  - jruby-head
15
11
  matrix:
16
12
  allow_failures:
17
13
  - rvm: ruby-head
18
14
  - rvm: jruby-head
19
15
  fast_finish: true
16
+ before_install:
17
+ - gem update --system
18
+ - gem install bundler -v 2.0.2
@@ -0,0 +1,42 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ directories %w(lib spec) \
6
+ .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ guard :minitest do
19
+ # with Minitest::Unit
20
+ # watch(%r{^test/(.*)\/?test_(.*)\.rb$})
21
+ # watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
22
+ # watch(%r{^test/test_helper\.rb$}) { 'test' }
23
+
24
+ # with Minitest::Spec
25
+ watch(%r{^spec/(.*)_spec\.rb$})
26
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
27
+ watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
28
+
29
+ # Rails 4
30
+ # watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
31
+ # watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' }
32
+ # watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" }
33
+ # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
34
+ # watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" }
35
+ # watch(%r{^test/.+_test\.rb$})
36
+ # watch(%r{^test/test_helper\.rb$}) { 'test' }
37
+
38
+ # Rails < 4
39
+ # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
40
+ # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" }
41
+ # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
42
+ end
@@ -0,0 +1,141 @@
1
+ # Migration Guide from v0.1.x to v0.2.0
2
+
3
+ Due to changes in the PlayStore API, Candy Check needed to introduce some breaking changes in version `0.2.0`.
4
+
5
+ To adapt your old implementation to these changes, follow the steps below:
6
+
7
+ ## Authorization
8
+
9
+ First we have to change, how our verifier authenticates against the Google API.
10
+
11
+ Change code like this
12
+
13
+ ```ruby
14
+ # < v0.2.0
15
+ config = CandyCheck::PlayStore::Config.new(
16
+ application_name: 'YourApplication',
17
+ application_version: '1.0',
18
+ issuer: 'abcdefg@developer.gserviceaccount.com',
19
+ key_file: 'local/google.p12',
20
+ key_secret: 'notasecret',
21
+ cache_file: 'tmp/candy_check_play_store_cache'
22
+ )
23
+ verifier = CandyCheck::PlayStore::Verifier.new(config)
24
+ verifier.boot!
25
+ ```
26
+
27
+ to
28
+
29
+ ```ruby
30
+ # v0.2.0
31
+ authorization = CandyCheck::PlayStore.authorization("/path/to/key.json")
32
+ verifier = CandyCheck::PlayStore::Verifier.new(authorization: authorization)
33
+ ```
34
+
35
+ If you're not sure how to get a `.json` key file, follow this part of the [`README`](/README.md#getting-the-json-key-file).
36
+
37
+ If you need other means of authentication follow this part of the [`README`](/README.md#building-an-authorization-object).
38
+
39
+ ## Verifying Purchases
40
+
41
+ To be more descriptive and consistent with the PlayStore API, the verifier got a new signature and return values have been adapted accordingly.
42
+
43
+ ### Verifying Product Purchases
44
+
45
+ Change all occurences of
46
+
47
+ ```ruby
48
+ # < v0.2.0
49
+ verifier.verify("my-package-name", "my product id", "my token")
50
+ # => Receipt or VerificationFailure
51
+ ```
52
+
53
+ to
54
+
55
+ ```ruby
56
+ # v0.2.0
57
+ verifier.verify_product_purchase(
58
+ package_name: "my-package-name",
59
+ product_id: "my product id",
60
+ token: "my token"
61
+ )
62
+ # => ProductPurchase or VerificationFailure
63
+ ```
64
+
65
+ *NOTE:* Take a closer look at the possible return values: `CandyCheck::PlayStore::Receipt` was moved to `CandyCheck::PlayStore::ProductPurchases::ProductPurchase`. In case you're matching at the class name of the result, please adapt your code accordingly.
66
+
67
+ #### Accessing Raw ProductPurchase Attributes
68
+
69
+ CandyCheck `< 0.2.0` provided the raw `ProductPurchase` attributes given by the PlayStore API like this:
70
+
71
+ ```ruby
72
+ # < v0.2.0
73
+ result = verifier.verify("my-package-name", "my product id", "my token")
74
+ result.attributes
75
+ # => Hash
76
+ ```
77
+
78
+ To get the same behaviour in CandyCheck `0.2.0`, change the code above to:
79
+
80
+ ```ruby
81
+ # v0.2.0
82
+ result = verifier.verify_product_purchase(
83
+ package_name: "my-package-name",
84
+ product_id: "my product id",
85
+ token: "my token"
86
+ )
87
+ result.product_purchase.to_h
88
+ # => Hash
89
+ ```
90
+
91
+ The hash key access must be changed from strings in `camelCase` to symbols in `snake_case`:
92
+
93
+ ```ruby
94
+ # < 0.2.0
95
+ result.attributes["purchaseState"]
96
+
97
+ # 0.2.0
98
+ result.product_purchase.to_h[:purchase_state]
99
+ ```
100
+
101
+ ## Verifying Subscription Purchases
102
+
103
+ Change all occurences of
104
+
105
+ ```ruby
106
+ # < v0.2.0
107
+ verifier.verify_subscription("my-package-name", "my-subscription-id", "my-token")
108
+ # => Subscription or VerificationFailure
109
+ ```
110
+
111
+ to
112
+
113
+ ```ruby
114
+ # v0.2.0
115
+ verifier.verify_subscription_purchase(
116
+ package_name: "my-package-name",
117
+ subscription_id: "my-subscription-id",
118
+ token: "my-token"
119
+ )
120
+ # => SubscriptionPurchase or VerificationFailure
121
+ ```
122
+
123
+ *NOTE:* Again take a closer look at the possible return values: `CandyCheck::PlayStore::Subscription` was moved to `CandyCheck::PlayStore::SubscriptionPurchases::SubscriptionPurchase`. In case you're matching at the class name of the result, please adapt your code accordingly.
124
+
125
+ ## Using the CLI
126
+
127
+ The way the CandyCheck CLI gets used, needed to be changed too.
128
+
129
+ The old PlayStore command:
130
+
131
+ ```bash
132
+ # < v0.2.0
133
+ $ candy_check play_store PACKAGE PRODUCT_ID TOKEN --issuer=ISSUER --key-file=KEY_FILE
134
+ ```
135
+
136
+ was changed to
137
+
138
+ ```bash
139
+ # v0.2.0
140
+ $ candy_check play_store PACKAGE PRODUCT_ID TOKEN --json-key-file=/path/to/key.json
141
+ ```
data/README.md CHANGED
@@ -4,7 +4,6 @@
4
4
  [![Build Status](https://travis-ci.org/jnbt/candy_check.svg?branch=master)](https://travis-ci.org/jnbt/candy_check)
5
5
  [![Coverage Status](https://coveralls.io/repos/jnbt/candy_check/badge.svg?branch=master)](https://coveralls.io/r/jnbt/candy_check?branch=master)
6
6
  [![Code Climate](https://codeclimate.com/github/jnbt/candy_check/badges/gpa.svg)](https://codeclimate.com/github/jnbt/candy_check)
7
- [![Gemnasium](https://img.shields.io/gemnasium/jnbt/candy_check.svg?style=flat)](https://gemnasium.com/jnbt/candy_check)
8
7
  [![Inline docs](http://inch-ci.org/github/jnbt/candy_check.svg?branch=master)](http://inch-ci.org/github/jnbt/candy_check)
9
8
  [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg?style=flat)](http://www.rubydoc.info/github/jnbt/candy_check/master)
10
9
 
@@ -43,12 +42,7 @@ called "[service account](https://developers.google.com/accounts/docs/OAuth2Serv
43
42
  new account by yourself, export the generated certificate file and grant the correct permissions to the account for
44
43
  your app using the [Google Developer Console](https://console.developers.google.com).
45
44
 
46
- Further more this gem uses the [official Ruby SDK](https://github.com/google/google-api-ruby-client) for the API interactions
47
- which suggest to use a locally cached service discovery. If you don't omit the `cache_file` configuration this is done
48
- automatically.
49
-
50
- If you have set up the Android app correctly you should get a [`purchaseToken`](http://developer.android.com/google/play/billing/billing_reference.html#getBuyIntent) per purchased item. You should use this string in combination with `packageName` and `productId`
51
- to verify the purchase.
45
+ If you have set up the Android app correctly you should get a [`purchaseToken`](http://developer.android.com/google/play/billing/billing_reference.html#getBuyIntent) per purchased item. You should use this string in combination with `packageName` and `productId` to verify the purchase.
52
46
 
53
47
  ## Usage
54
48
 
@@ -81,42 +75,108 @@ For **subscription verification**, Apple also returns a list of the user's purch
81
75
  verifier.verify_subscription(your_receipt_data, your_secret) # => ReceiptCollection or VerificationFailure
82
76
  ```
83
77
 
78
+ If you want to restrict the subscription verification to some specific products, pass their ids as an array:
79
+
80
+ ```ruby
81
+ # ... create your verifier as above
82
+ product_ids = ['sk_product_id_1', 'sk_product_id_2'...]
83
+ verifier.verify_subscription(your_receipt_data, your_secret, product_ids) # => ReceiptCollection or VerificationFailure
84
+ ```
85
+
84
86
  Please see the class documentation for [`CandyCheck::AppStore::ReceiptCollection`](http://www.rubydoc.info/github/jnbt/candy_check/master/CandyCheck/AppStore/ReceiptCollection) for further details.
85
87
 
86
88
  ### PlayStore
87
89
 
88
- First initialize and **boot** a verifier instance for your application. This loads the API discovery and
89
- fetches the needed OAuth access token. When configuring a `cache_file` the discovery is loaded (or dumped) to
90
- this file:
90
+ > :warning: Version `0.2.0` of `CandyCheck` introduced some breaking changes to the PlayStore functionality to adapt to changes in the Google API. If you're upgrading from a `CandyCheck` version `< 0.2.0` see the [migration guide](/MIGRATION_GUIDE_0_2_0.md) for more.
91
+
92
+ #### Authorization
93
+
94
+ ##### Getting the JSON Key File
95
+
96
+ First we have to get a `.json` key file, that gives access to the Google API.
97
+
98
+ This `.json` key file can be generated under the following URL (make sure to adapt the `project=my-project-name` parameter accordingly):
99
+
100
+ [https://console.developers.google.com/apis/credentials/serviceaccountkey?project=my-project-name](https://console.developers.google.com/apis/credentials/serviceaccountkey?project=my-project-name)
101
+
102
+ ##### Building an Authorization Object
103
+
104
+ With the `.json` key file downloaded, we can build an authorization object:
91
105
 
92
106
  ```ruby
93
- config = CandyCheck::PlayStore::Config.new(
94
- application_name: 'YourApplication',
95
- application_version: '1.0',
96
- issuer: 'abcdefg@developer.gserviceaccount.com',
97
- key_file: 'local/google.p12',
98
- key_secret: 'notasecret',
99
- cache_file: 'tmp/candy_check_play_store_cache'
100
- )
101
- verifier = CandyCheck::PlayStore::Verifier.new(config)
102
- verifier.boot!
107
+ authorization = CandyCheck::PlayStore.authorization("/path/to/key.json")
103
108
  ```
104
109
 
105
- For the PlayStore your client should deliver the purchases token, package name and product id:
110
+ > **Note:** `CandyCheck` provides the `CandyCheck::PlayStore.authorization` method as convenience to build an authorization object. In case you need more control over your authorization object, refer to the [`google-auth-library-ruby`](https://github.com/googleapis/google-auth-library-ruby) docs, which describes building authorization objects in detail.
111
+
112
+ ##### Building a verifier
113
+
114
+ With the `authorization` object in place, we can build a verifier:
106
115
 
107
116
  ```ruby
108
- verifier.verify(package, product_id, token) # => Receipt or VerificationFailure
117
+ verifier = CandyCheck::PlayStore::Verifier.new(authorization: authorization)
109
118
  ```
110
119
 
111
- Please see the class documenations [`CandyCheck::PlayStore::Receipt`](http://www.rubydoc.info/github/jnbt/candy_check/master/CandyCheck/PlayStore/Receipt) and [`CandyCheck::PlayStore::VerificationFailure`](http://www.rubydoc.info/github/jnbt/candy_check/master/CandyCheck/PlayStore/VerificationFailure) for further details about the responses.
120
+ > **Note:** If you need to verify against multiple Google Service Accounts, just instantiate a new verifier with another authorization object that got build with a different `.json` key file.
121
+
122
+ #### Verifying product purchases
123
+
124
+ This `verifier` can be used to verify product purchases in the PlayStore, all you need to do is to pass the `package_name`, `product_id` and `token` of the product purchase you want to verify:
125
+
126
+ ```ruby
127
+ result = verifier.verify_product_purchase(
128
+ package_name: "my-package-name",
129
+ product_id: "my product id",
130
+ token: "my token"
131
+ )
132
+ # => ProductPurchase or VerificationFailure
133
+ ```
134
+
135
+ On success this will return an instance of `CandyCheck::Playstore::ProductPurchases::ProductPurchase`, which is a wrapper for the raw [google-api-ruby-client](https://github.com/googleapis/google-api-ruby-client) data, but additionally provides some handy convenience methods.
136
+ Please see the class documentations [`CandyCheck::PlayStore::ProductPurchases::ProductPurchase`](http://www.rubydoc.info/github/jnbt/candy_check/master/CandyCheck/PlayStore/ProductPurchases/ProductPurchase) and [`CandyCheck::PlayStore::VerificationFailure`](http://www.rubydoc.info/github/jnbt/candy_check/master/CandyCheck/PlayStore/VerificationFailure) for further details about the responses.
137
+
138
+ #### Verifying subscriptions
112
139
 
113
140
  In order to **verify a subscription** from the Play Store, do the following:
114
141
 
115
142
  ```ruby
116
- verifier.verify_subscription(package, subscription_id, token) # => Subscription or VerificationFailure
143
+ result = verifier.verify_subscription_purchase(
144
+ package_name: "my-package-name",
145
+ subscription_id: "my-subscription-id",
146
+ token: "my-token"
147
+ )
148
+ # => SubscriptionPurchase or VerificationFailure
117
149
  ```
118
150
 
119
- Please see documenation for [`CandyCheck::PlayStore::Subscription`](http://www.rubydoc.info/github/jnbt/candy_check/master/CandyCheck/PlayStore/Subscription) for further details.
151
+ Please see documenation for [`CandyCheck::PlayStore::SubscriptionPurchases::SubscriptionPurchase`](http://www.rubydoc.info/github/jnbt/candy_check/master/CandyCheck/PlayStore/SubscriptionPurchases/SubscriptionPurchase) for further details.
152
+
153
+
154
+ ##### Building an acknowledger
155
+
156
+ With the `authorization` object in place, we can build an acknowledger:
157
+
158
+ ```ruby
159
+ acknowledger = CandyCheck::PlayStore::Acknowledger.new(authorization: authorization)
160
+ ```
161
+
162
+ > **Note:** If you need to acknowledge against multiple Google Service Accounts, just instantiate a new acknowledger with another authorization object that got build with a different `.json` key file.
163
+
164
+ #### Acknowledging the purchase
165
+ Google Play purchases if not acknowledged are automatically refunded. The acknowledgement can be done client-side or server-side. If server-side validation is being used we recommend to proceed with the acknowledgement afterwards, since it is the only save way to ensure the users received what they have paid for.
166
+
167
+ ```ruby
168
+ result = acknowledger.acknowledge_product_purchase(
169
+ package_name: "my-package-name",
170
+ product_id: "my-subscription-id",
171
+ token: "my-token"
172
+ )
173
+ # => ProductAcknowledgements::Response
174
+ ```
175
+
176
+ The acknowledger response has 2 methods:
177
+
178
+ - `#acknowledged?` returns a boolean. It returns true only if it has been acknowledged at this moment (that's Google Play behaviour).
179
+ - `#error` returns a hash with `status_code` and `body` keys.
120
180
 
121
181
  ## CLI
122
182
 
@@ -142,7 +202,7 @@ For the PlayStore you need to specify at least the issuer, the key file, your pa
142
202
  purchase token:
143
203
 
144
204
  ```bash
145
- $ candy_check play_store PACKAGE PRODUCT_ID TOKEN --issuer=ISSUER --key-file=KEY_FILE
205
+ $ candy_check play_store PACKAGE_NAME PRODUCT_ID TOKEN --json-key-file=/path/to/key.json
146
206
  ```
147
207
 
148
208
  See all options:
data/Rakefile CHANGED
@@ -12,4 +12,4 @@ end
12
12
 
13
13
  RuboCop::RakeTask.new
14
14
 
15
- task default: [:spec, :rubocop]
15
+ task default: %i(spec)
@@ -1,34 +1,42 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'candy_check/version'
5
+ require "candy_check/version"
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = 'candy_check'
8
- spec.version = CandyCheck::VERSION
9
- spec.authors = ['Jonas Thiel']
10
- spec.email = ['jonas@thiel.io']
11
- spec.summary = 'Check and verify in-app receipts'
12
- spec.homepage = 'https://github.com/jnbt/candy_check'
13
- spec.license = 'MIT'
8
+ spec.name = "candy_check"
9
+ spec.version = CandyCheck::VERSION
10
+ spec.authors = ["Jonas Thiel", "Christoph Weegen"]
11
+ spec.email = ["jonas@thiel.io"]
12
+ spec.summary = "Check and verify in-app receipts"
13
+ spec.homepage = "https://github.com/jnbt/candy_check"
14
+ spec.license = "MIT"
14
15
 
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']
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
19
20
 
20
- spec.required_ruby_version = Gem::Requirement.new('>= 2.0')
21
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4")
21
22
 
22
- spec.add_dependency 'multi_json', '~> 1.10'
23
- spec.add_dependency 'google-api-client', '~> 0.8.6'
24
- spec.add_dependency 'thor', '~> 0.19'
23
+ spec.add_dependency "google-api-client", "~> 0.43.0"
24
+ spec.add_dependency "multi_json", "~> 1.10"
25
+ spec.add_dependency "thor", "~> 0.19"
25
26
 
26
- spec.add_development_dependency 'rubocop', '~> 0.39'
27
- spec.add_development_dependency 'inch', '~> 0.5'
28
- spec.add_development_dependency 'bundler', '~> 1.7'
29
- spec.add_development_dependency 'rake', '~> 11.1'
30
- spec.add_development_dependency 'coveralls', '~> 0.8'
31
- spec.add_development_dependency 'minitest', '~> 5.9'
32
- spec.add_development_dependency 'minitest-around', '~> 0.3'
33
- spec.add_development_dependency 'webmock', '~> 2.1'
27
+ spec.add_development_dependency "bundler", "~> 2.0"
28
+ spec.add_development_dependency "coveralls", "~> 0.8"
29
+ spec.add_development_dependency "inch", "~> 0.7"
30
+ spec.add_development_dependency "minitest", "~> 5.10"
31
+ spec.add_development_dependency "minitest-around", "~> 0.4"
32
+ spec.add_development_dependency "minitest-focus"
33
+ spec.add_development_dependency "rake", "~> 12.0"
34
+ spec.add_development_dependency "rubocop", "~> 0.48"
35
+ spec.add_development_dependency "timecop", "~> 0.8"
36
+ spec.add_development_dependency "webmock", "~> 3.0"
37
+ spec.add_development_dependency "vcr"
38
+ spec.add_development_dependency "pry"
39
+ spec.add_development_dependency "awesome_print"
40
+ spec.add_development_dependency "guard"
41
+ spec.add_development_dependency "guard-minitest"
34
42
  end