jnbt / candy_check

Check and verify in-app receipts
MIT License
125 stars 71 forks source link

Receipt methods return nil #49

Closed gerard-morera closed 3 years ago

gerard-morera commented 4 years ago

I am not sure whether I am misusing the gem or there is a Bug.

From apple_store#verify I am receiving an instance of CandyCheck::AppStoreReceipt. When I try to access any of the public methods the return is nil.

The reason is that the read method does not expect the receipt to be nested:

How the receipt is:

{"receipt_type"=>"ProductionSandbox",
 "adam_id"=>0,
 "app_item_id"=>0,
 "bundle_id"=>"whatever",

 "in_app"=>
  [{"quantity"=>"1",
    "product_id"=>"some_product",
    "transaction_id"=>"10000006603456836",
    "original_transaction_id"=>"10000006603456836",
}]}

So basically to get the product_id. Instead of

 def read(field)
   attributes['product_id']
end

we would need:

def  in_app_read(field)
  attributes['in_app'].first['product_id']
end

Am I missing anything?

USAGE VERSION => 0.2.1

Thanks.

jnbt commented 4 years ago

Hi @gerard-morera,

maybe an issue could be that you're not using the deprecated transactionReceipt?

I think this gem only works this these kind of receipts.

jnbt commented 4 years ago

I just checked, and for a old-school (deprecated) receipts the AppStore API returns data like this:

{
    "receipt": {
        "original_purchase_date_pst": "2020-05-10 11:12:36 America/Los_Angeles",
        "unique_identifier": "UNIQUE_IDENTIFIER",
        "original_transaction_id": "1234567",
        "bvrs": "123456",
        "app_item_id": "1234567",
        "transaction_id": "1234567",
        "quantity": "1",
        "unique_vendor_identifier": "RANDOM-STRING",
        "product_id": "the_product_id",
        "item_id": "1234567",
        "version_external_identifier": "1234567",
        "bid": "the.bundle.id",
        "is_in_intro_offer_period": "false",
        "purchase_date_ms": "1589134356211",
        "purchase_date": "2020-05-10 18:12:36 Etc/GMT",
        "is_trial_period": "false",
        "purchase_date_pst": "2020-05-10 11:12:36 America/Los_Angeles",
        "original_purchase_date": "2020-05-10 18:12:36 Etc/GMT",
        "original_purchase_date_ms": "1589134356211"
    },
    "status": 0
}

@gerard-morera I think you're using the more modern (or let us be honest: not fully deprecated) receipt of the app, which include all In-App-Purchases at once. Apple definitely encourages to use this approach. Sadly this gem has still no support for it.

gerard-morera commented 4 years ago

Hi, @jnbt thanks for your fast answer. How can I ensure to receive the receipts on the supported format?

jnbt commented 4 years ago

@gerard-morera The way I know is the following:

  1. Implement the observer pattern for paymentQueue:updatedTransactions
  2. Invoke a In-App-Purchase
  3. The paymentQueue:updatedTransactions will be called with at least one transaction. For every transaction:
    1. Check for it's status to be SKPaymentTransactionStatePurchased
    2. You get the single transaction receipt via the transactions transactionReceipt
    3. Encode this data as base64 via base64EncodedStringWithOptions
    4. Pass this encoded value to your server / this gem