Commit Graph
10 Commits
Author SHA1 Message Date
Mark Villacampa 6f8e53ac40 Fix Xcode 16 warnings (#4334)
When compiling with Xcode 16, we started throwing a bunch of new warnings. Here's a list and explanation of each:

- The most common one was needing to explicitly restate the @unchecked Sendable conformance from a parent class.
- There were a couple switches where a new entry was added in tvOS but only for iOS 18, and needed to add it to make it exhaustive.
- There we a couple of places where we were adding a protocol conformance to a class from a different module e.g. extension DispatchTimeInterval: Comparable. This is considered unsafe now because the owners of the module could add the conformance later. Solved by removing the conformance which wasn't being used widely in the codebase, only in tests.
- Finally there was a class where we were capturing SKRequest and SKProductsRequest instances in a sendable block, but only to either log something, or use them as dictionary key, so I just made the classes Sendable (with the new @retroactice attribute because they belong to a different module)
2024-10-02 11:53:45 +02:00
NachoSoto 789a0e5e4d PurchasedProductsFetcher: cache current entitlements (#2507)
To optimize potentially computing offline `CustomerInfo`, this caches
what's likely the most expensive part.
2023-05-19 18:08:03 -07:00
NachoSoto 22f85b3d74 DispatchTimeInterval: fixed Xcode 14.3 compilation (#2397) 2023-04-11 01:22:22 -07:00
NachoSoto b495540308 Offline Entitlements: store ProductEntitlementMapping in cache (#2355)
## Changes:
- `DeviceCache` support for caching `ProductsEntitlementsResponse` as
well as "last updated" date
- Added `JSONEncoder.encode` helper matching `JSONDecoder.decode`
version, with an optional `logErrors` parameter
- `OfferingsManager. updateProductsEntitlementsCacheIfStale`
- `Purchases.updateAllCaches` also updates this new cache
- Added `OfferingsManager` / `DeviceCache` / `Purchases` tests
- Integration test for fetching mapping
2023-03-23 13:30:19 -07:00
NachoSoto d4ecc7b298 DispatchTimeInterval & Date: avoid 32-bit overflows, fix watchOS crashes (#2342)
Fixes #2338, [SDKONCALL-237], [SDK-2974].

`Int` is actually 32 bits in 32-bit platforms, like `watchOS` still is
(sort of).
This fixes 2 potential `Int` overflows: `Date.millisecondsSince1970` and
`DispatchTimeInterval` arithmetic using `nanoseconds`.

See also #2340.

[SDKONCALL-237]:
https://revenuecats.atlassian.net/browse/SDKONCALL-237?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2023-03-16 13:24:16 -07:00
NachoSoto a157adfdee EntitlementInfo: add a grace period limit to outdated entitlements (#2288)
This prevents users from keeping an outdated active entitlement forever.
One could start a free trial then block all further requests from the
backend in order to keep that active.

When this check fails, a new warning log is generated:
> WARN: ⚠️ Entitlement is no longer active (expired 2023-02-12 18:15:11
+0000) and it's outside grace period window (last updated 2023-02-12
18:13:31 +0000)
2023-03-01 09:45:29 -08:00
NachoSoto 50f906e0ae ReceiptFetcher: throttle receipt refreshing to avoid StoreKit throttle errors (#2146)
Fixes #2116.

Depends on #2134, #2144, #2145.

We've known that, especially for sandbox accounts with lots of
purchases, the SDK can get flooded with a lot of transactions to process
at once.
I've been making some improvements for this (like #2115).

Another consequence of this behavior, is that we can end up failing due
to `StoreKit` throttling us (see #2116):

> 2022-12-03 12:31:58.670892+0100 app[673:61074]
<SKReceiptRefreshRequest: 0x283edc860>: Finished refreshing receipt with
error: Error Domain=ASDErrorDomain Code=603 "Request throttled"
UserInfo={NSLocalizedFailureReason=Unified receipt is valid and current,
NSLocalizedDescription=Request throttled, AMSServerErrorCode=0}

This change avoids that by skipping the refresh if less than 2 seconds
have elapsed. I chose 2 to make this a low-ish risk change, with a huge
benefit for multiple semi-concurrent requests coming from a big
transaction queue.
2022-12-15 09:14:01 -08:00
NachoSoto c8ed10d9a0 Extracted asyncWait to poll async conditions in tests (#2134)
This is necessary because we can't use `Quick` v6.x yet.

Abstracting this out to use it in #2069.
2022-12-15 08:51:15 -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
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