Commit Graph
11 Commits
Author SHA1 Message Date
NachoSoto 2bcd0ce328 5.0.0 changes: support SK2 by default 2024-07-01 14:37:21 -05:00
NachoSoto f7e36fb993 Trusted Entitlements: add support for signing POST body (#2753)
### Changes:
- `HTTPClient` has a new `X-Post-Params-Hash` request header
- Replaced `HTTPRequest.Method.post`'s `Encodable` value with a more
specific `HTTPRequestBody` (like `HTTPResponseBody`)
- `HTTPRequestBody` allows overriding `contentForSignature` (it defaults
to `[]`) which then `Signing` uses for the hash
- Fixed `LogInOperation` not passing the `VerificationResult` to the
result `CustomerInfo`. This is captured in unit and integration tests
now.
- Add support for signing `POST` requests in `Path.logIn` and
`Path.postReceiptData`

Depends on https://github.com/RevenueCat/khepri/pull/6246
2023-07-13 07:45:16 -07:00
NachoSoto ed8d79dfdd Add Data.sha1 (#2696)
This also refactors the implementation to be able to share the same
code.

This algorithm will be used for some of the components in the new
signatures.
2023-06-23 10:45:57 -07:00
NachoSoto 1dc19f6750 Refactored Data.asString implementation (#2695) 2023-06-23 07:31:55 -07:00
NachoSoto 88a78411f6 HTTPClient: added support for sending X-Nonce (#2214)
Fixes [CSDK-631].


[CSDK-631]:
https://revenuecats.atlassian.net/browse/CSDK-631?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2023-02-08 09:05:20 -08:00
NachoSoto b87dfe5b51 Added new ReceiptParser.fetchAndParseLocalReceipt (#2204)
Fixes [CSDK-622].

### Changes:
- Extracted `FileReader` to be able to use it in `ReceiptParser`
- Extracted `MockBundle` to be able to use it in `ReceiptParser`
- Added new `public` `ReceiptParser.fetchAndParseLocalReceipt()`, **only
to `ReceiptParser`** (this is not available through `RevenueCat`).
- Added tests for the new API
- Added new API to `ReceiptParserAPITester`

Initially I thought about moving `ReceiptFetcher` to the
`Receipt|Parser` target. Unfortunately that would require moving a whole
bunch of other dependencies (`OperationDispatcher`, etc, etc).
We have no easy way to create a third "Core" framework in which to place
these common dependencies, so that wouldn't be trivial.

This solution adds a much simpler version of `ReceiptFetcher` that
simply reads from `Bundle.appStoreReceiptURL`. As it's documented there,
under normal circumstances `SKReceiptRefreshRequest` is not required, so
this implementation should work for 99% of use cases, and so this way we
avoid increasing the.codebase complexity unnecessarily.

[CSDK-622]:
https://revenuecats.atlassian.net/browse/CSDK-622?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2023-01-17 12:35:56 -08:00
NachoSoto e4bbd0528b ReceiptFetcher: refactored implementation to log error when failing to fetch receipt (#2202) 2023-01-16 07:43:34 -08:00
NachoSoto 9a289e554f PostReceiptDataOperation: replaced receipt base64 with hash for cache key (#2199)
Should fix #2198 and [SDKONCALL-200]. This is a big performance
optimization in time and memory, as we no longer need to convert the
entire receipt to `base64` and concatenate it to the string, which is
what was likely causing #2198.
This now uses `Data.hashString`, which avoids any data copies and
efficiently creates a hash with the receipt content.

Apart from the new tests for this property,
`BackendPostReceiptDataTests.testDoesntCacheForDifferentReceipts`
ensures that different receipts have different cache keys, and therefore
this new implementation still avoids collisions (other than the
extremely unlikely hash collisions).


[SDKONCALL-200]:
https://revenuecats.atlassian.net/browse/SDKONCALL-200?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2023-01-12 11:48:32 -08:00
NachoSotoandCesar de la Vega c00be57a13 ReceiptFetcher: added retry mechanism (#1945)
Fixes [CSDK-478]

~~Depends on #1941, #1942, and #1943.~~

### Example:

Log of a successful purchase after retrying 🎉 

> INFO: 💰 Purchasing Product 'com.revenuecat.monthly_4.99.1_week_intro'
DEBUG: ℹ️ Loaded receipt from url
file:///Users/nachosoto/Library/Developer/CoreSimulator/Devices/A3576DC2-355E-45BA-B32C-D2C0A3811BB4/data/Containers/Data/Application/7ACD12DA-2A12-4CF1-8A76-8295E40B64EF/StoreKit/receipt
INFO: ℹ️ Receipt parsed successfully
WARN: 🍎‼️ Local receipt is still missing purchase for
'com.revenuecat.monthly_4.99.1_week_intro':
{
  "opaque_value" : "79v2XwwAAAA=",
  "sha1_hash" : "GhOmfuioo2Z4R3zX8K60l4b0qgs=",
  "bundle_id" : "com.revenuecat.StoreKitTestApp",
  "in_app_purchases" : [
    {
      "quantity" : 1,
      "product_id" : "com.revenuecat.monthly_4.99.1_week_intro",
      "purchase_date" : "2022-09-28T01:14:24Z",
      "transaction_id" : "0",
      "is_in_intro_offer_period" : true,
      "expires_date" : "2022-09-28T01:14:34Z"
    }
  ],
  "application_version" : "1",
  "creation_date" : "2022-09-28T01:14:24Z",
  "expiration_date" : "4001-01-01T00:00:00Z"
}
DEBUG: ℹ️ Retrying Receipt fetch after  5 seconds
DEBUG: ℹ️ API request completed: POST /v1/receipts 200
DEBUG: ℹ️ PostReceiptDataOperation: Finished
DEBUG: ℹ️ Serial request done: POST receipts, 0 requests left in the
queue
DEBUG: ℹ️ Sending updated CustomerInfo to delegate.
DEBUG: ℹ️ Found 0 unsynced attributes for App User ID:
$RCAnonymousID:ec326c1613c14b489980eace90dceabb
DEBUG: ℹ️ Force refreshing the receipt to get latest transactions from
Apple.
DEBUG: ℹ️ Loaded receipt from url
file:///Users/nachosoto/Library/Developer/CoreSimulator/Devices/A3576DC2-355E-45BA-B32C-D2C0A3811BB4/data/Containers/Data/Application/7ACD12DA-2A12-4CF1-8A76-8295E40B64EF/StoreKit/receipt
DEBUG: ℹ️ PostReceiptDataOperation: Started
INFO: ℹ️ Receipt parsed successfully
DEBUG: ℹ️ PostReceiptDataOperation: Posting receipt: {
  "opaque_value" : "0nf1uwEAAAA=",
  "sha1_hash" : "lfxVVsBuSkQLtrGJseZ8zlpXc5A=",
  "bundle_id" : "com.revenuecat.StoreKitTestApp",
  "in_app_purchases" : [
    {
      "quantity" : 1,
      "product_id" : "com.revenuecat.monthly_4.99.1_week_intro",
      "purchase_date" : "2022-09-28T01:14:24Z",
      "transaction_id" : "0",
      "is_in_intro_offer_period" : true,
      "expires_date" : "2022-09-28T01:14:34Z"
    },
    {
      "product_id" : "com.revenuecat.monthly_4.99.1_week_intro",
      "quantity" : 1,
      "transaction_id" : "1",
      "is_in_intro_offer_period" : false,
      "expires_date" : "2022-09-28T01:15:04Z",
      "original_purchase_date" : "2022-09-28T01:14:24Z",
      "original_transaction_id" : "0",
      "purchase_date" : "2022-09-28T01:14:34Z"
    }
  ],
  "application_version" : "1",
  "creation_date" : "2022-09-28T01:14:35Z",
  "expiration_date" : "4001-01-01T00:00:00Z"
}
DEBUG: ℹ️ There are no requests currently running, starting request POST
receipts
DEBUG: ℹ️ API request started: POST /v1/receipts
DEBUG: ℹ️ API request completed: POST /v1/receipts 200
DEBUG: ℹ️ PostReceiptDataOperation: Finished
DEBUG: ℹ️ Serial request done: POST receipts, 0 requests left in the
queue
DEBUG: ℹ️ Sending updated CustomerInfo to delegate.
DEBUG: ℹ️ Loaded receipt from url
file:///Users/nachosoto/Library/Developer/CoreSimulator/Devices/A3576DC2-355E-45BA-B32C-D2C0A3811BB4/data/Containers/Data/Application/7ACD12DA-2A12-4CF1-8A76-8295E40B64EF/StoreKit/receipt
INFO: ℹ️ Receipt parsed successfully
DEBUG: ℹ️ Skipping products request because products were already
cached. products: ["com.revenuecat.monthly_4.99.1_week_intro"]
DEBUG: ℹ️ Skipping products request because products were already
cached. products: ["com.revenuecat.monthly_4.99.1_week_intro"]
DEBUG: ℹ️ Store products request finished
DEBUG: ℹ️ Found 0 unsynced attributes for App User ID:
$RCAnonymousID:ec326c1613c14b489980eace90dceabb
DEBUG: ℹ️ PostReceiptDataOperation: Started
INFO: ℹ️ Receipt parsed successfully
DEBUG: ℹ️ PostReceiptDataOperation: Posting receipt: {
  "opaque_value" : "tv4\/2gcAAAA=",
  "sha1_hash" : "0rh1naTc3JyfM16M\/1f6fw4ezAY=",
  "bundle_id" : "com.revenuecat.StoreKitTestApp",
  "in_app_purchases" : [
    {
      "quantity" : 1,
      "product_id" : "com.revenuecat.monthly_4.99.1_week_intro",
      "purchase_date" : "2022-09-28T01:14:24Z",
      "transaction_id" : "0",
      "is_in_intro_offer_period" : true,
      "expires_date" : "2022-09-28T01:14:34Z"
    },
    {
      "product_id" : "com.revenuecat.monthly_4.99.1_week_intro",
      "quantity" : 1,
      "transaction_id" : "1",
      "is_in_intro_offer_period" : false,
      "expires_date" : "2022-09-28T01:15:04Z",
      "original_purchase_date" : "2022-09-28T01:14:24Z",
      "original_transaction_id" : "0",
      "purchase_date" : "2022-09-28T01:14:34Z"
    }
  ],
  "application_version" : "1",
  "creation_date" : "2022-09-28T01:14:40Z",
  "expiration_date" : "4001-01-01T00:00:00Z"
}
DEBUG: ℹ️ There are no requests currently running, starting request POST
receipts
DEBUG: ℹ️ API request started: POST /v1/receipts
DEBUG: ℹ️ API request completed: POST /v1/receipts 200
DEBUG: ℹ️ PostReceiptDataOperation: Finished
DEBUG: ℹ️ Serial request done: POST receipts, 0 requests left in the
queue
INFO: 😻💰 Purchased product - 'com.revenuecat.monthly_4.99.1_week_intro'

[CSDK-478]:
https://revenuecats.atlassian.net/browse/CSDK-478?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

Co-authored-by: Cesar de la Vega <cesarvegaro@gmail.com>
2022-10-07 07:55:53 -07:00
NachoSoto c55d421fa6 NSData.asString(): optimized string creation (#1434)
I noticed that the existing implementation was creating many copies of the string as it grows, which isn't very efficient.
The new implementation allocates the required size initially and writes to the same buffer inside the loop.
2022-03-31 14:54:48 -07:00
aboedo f5697de730 renamed Purchases folder to Sources (#1416)
* renamed `Purchases` folder to `Sources`

* temporarily enabling installation test jobs

* re-disabling installation test jobs
2022-03-28 11:53:24 -03:00