-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[AppStore, Subscription] Add verification returning both receipt and receipt collection #15
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
|
||
language: ruby | ||
sudo: false | ||
cache: bundler | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
#!/usr/bin/env rake | ||
# frozen_string_literal: true | ||
|
||
require 'bundler/gem_tasks' | ||
require 'rake/testtask' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module AppStore | ||
# Configure the verifier | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module AppStore | ||
# Verifies a receipt and latest_receipt_info block | ||
# The call return either a {SubscriptionReceipt} or a {VerificationFailure} | ||
class FullSubscriptionVerification < CandyCheck::AppStore::Verification | ||
# Performs the verification against the remote server | ||
# @return [SubscriptionReceipt] if successful | ||
# @return [VerificationFailure] otherwise | ||
def call! | ||
verify! | ||
return VerificationFailure.fetch(@response['status']) unless valid? | ||
subscription_receipt | ||
end | ||
|
||
private | ||
|
||
def subscription_receipt | ||
receipt = Receipt.new(@response['receipt']) | ||
receipt_collection = ReceiptCollection.new( | ||
@response['latest_receipt_info'] | ||
) | ||
|
||
SubscriptionReceipt.new(receipt, receipt_collection) | ||
end | ||
|
||
def valid? | ||
super && @response['latest_receipt_info'] | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module AppStore | ||
# Describes a successful response from the AppStore verification server | ||
class SubscriptionReceipt | ||
attr_reader :receipt, :receipt_collection | ||
|
||
# Initializes a new instance | ||
def initialize(receipt, receipt_collection) | ||
@receipt = receipt | ||
@receipt_collection = receipt_collection | ||
end | ||
|
||
def transactions | ||
@receipt_collection.receipts | ||
end | ||
|
||
def valid? | ||
@receipt.is_a?(CandyCheck::AppStore::Receipt) && | ||
@receipt_collection.is_a?(CandyCheck::AppStore::ReceiptCollection) | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module AppStore | ||
# Verifies receipts against the verification servers. | ||
# The call return either an {Receipt} or a {VerificationFailure} | ||
class Verifier | ||
# HTTPS endpoint for production receipts | ||
PRODUCTION_ENDPOINT = 'https://buy.itunes.apple.com/verifyReceipt'.freeze | ||
PRODUCTION_ENDPOINT = 'https://buy.itunes.apple.com/verifyReceipt' | ||
# HTTPS endpoint for sandbox receipts | ||
SANDBOX_ENDPOINT = 'https://sandbox.itunes.apple.com/verifyReceipt'.freeze | ||
SANDBOX_ENDPOINT = 'https://sandbox.itunes.apple.com/verifyReceipt' | ||
# Status code from production endpoint when receiving a sandbox | ||
# receipt which occurs during the app's review process | ||
REDIRECT_TO_SANDBOX_CODE = 21_007 | ||
|
@@ -44,6 +46,16 @@ def verify_subscription(receipt_data, secret = nil) | |
fetch_receipt_information(receipt_data, secret) | ||
end | ||
|
||
# Calls a subscription verification for the given input | ||
# @param receipt_data [String] the raw data to be verified | ||
# @param secret [string] the optional shared secret | ||
# @return [SubscriptionReceipt] if successful | ||
# @return [VerificationFailure] otherwise | ||
def verify_subscription_with_full_response(receipt_data, secret = nil) | ||
@verifier = FullSubscriptionVerification | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's weird to have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. However I would like to keep it consistent with the rest of the code. |
||
fetch_receipt_information(receipt_data, secret) | ||
end | ||
|
||
private | ||
|
||
def fetch_receipt_information(receipt_data, secret = nil) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'thor' | ||
|
||
module CandyCheck | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module CLI | ||
module Commands | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module CLI | ||
module Commands | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module CLI | ||
module Commands | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module CLI | ||
module Commands | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'pp' | ||
|
||
module CandyCheck | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'google/api_client' | ||
|
||
require 'candy_check/play_store/discovery_repository' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
module PlayStore | ||
# Describes a successfully validated subscription | ||
|
@@ -25,17 +27,18 @@ def initialize(attributes) | |
|
||
# Check if the expiration date is passed | ||
# @return [bool] | ||
# rubocop:disable Style/NumericPredicate | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not supported in older versions. |
||
def expired? | ||
overdue_days > 0 | ||
end | ||
# rubocop:enable Style/NumericPredicate | ||
|
||
# Check if in trial. This is actually not given by Google, but we assume | ||
# that it is a trial going on if the paid amount is 0 and | ||
# renewal is activated. | ||
# @return [bool] | ||
def trial? | ||
price_is_zero = price_amount_micros == 0 | ||
price_is_zero && payment_received? | ||
price_amount_micros.zero? && payment_received? | ||
end | ||
|
||
# see if payment is ok | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'candy_check/utils/attribute_reader' | ||
require 'candy_check/utils/config' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'date' | ||
|
||
module CandyCheck | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
# frozen_string_literal: true | ||
|
||
module CandyCheck | ||
# The current gem's version | ||
VERSION = '0.1.1'.freeze | ||
VERSION = '0.1.2' | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels a bit like
response_status_ok?
is not self-contained if you have to check@response
before you use it. Maybe it would be nicer with two black boxes:response_status_ok?
andresponse_has_receipt?
which both take care of validating all that they need. This would mean duplicating the@response
check, but I think that's acceptable, or if the response is only set once, then you could even cache/memoize this in ahas_response?
methodThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it 👍