Commit Graph
65 Commits
Author SHA1 Message Date
Antonio Pallares f120cb26cc Preferred locale override (#5288)
* Add new public APIs to RevenueCatUI to set the preferred local for the UI components

* fix compliation of RevenueCatUI with new APIs

* add API tests

* implement preferred locale in paywalls

* complete implementation

* adapt unit tests

* adapt paywalls tester

* Add new tests to check preferred locale override

* fix lint

* discard all changes in RevenueCatUI (for separate PR)

* remove trailing comma

* fix tests

* Fix tests

* fix paywalls tester compilation

* remove spoiler from future PR

* Refactor `PreferredLocalesProvider` (#5299)

* refactor: reduce `PreferredLocalesProviderType` into `PreferredLocalesProvider` class

* make `preferredLocaleOverride` private in `PreferredLocalesProvider`

* make `SystemInfo`'s `preferredLocalesProvider` private

* rename `PreferredLocalesProvider`'s mock init parameters

* fix compilation issue
2025-06-30 16:28:32 +02:00
Antonio Pallares e0c94708be [Diagnostics] add host parameter to http_request_performed event (#4982)
* feat: implement fallback host in all URL requests

* cleanup fallback host API implementation

* Adapt existing tests to changes in `HTTPRequestPath`

* fix implementation

* add unit tests for fallback API host

* add extra unit test

* fix tests

* fix lint

* implement new `host` parameter in `http_request_performed` diagnostics event

* add unit tests for new `host` diagnostics parameter

* change the logic from fallback hosts to fallback paths

* fix test

* fix fallback endpoint for get product entitlement mapping

* fix backend integration tests not building after changes

* rewrite fallback host functionality knowing that only some specific requests support a fallback host

For those requests that support a fallback host, the path, headers and response structure remain the same

* fix text name

* fix unit test

* remove extra comma

* fix unit test
2025-04-25 17:05:33 +00:00
Antonio Pallares e991e0708a Use fallback API hosts when receiving server down response (#4970)
* feat: implement fallback host in all URL requests

* cleanup fallback host API implementation

* Adapt existing tests to changes in `HTTPRequestPath`

* fix implementation

* add unit tests for fallback API host

* add extra unit test

* fix tests

* fix lint

* change the logic from fallback hosts to fallback paths

* fix test

* fix fallback endpoint for get product entitlement mapping

* fix backend integration tests not building after changes

* rewrite fallback host functionality knowing that only some specific requests support a fallback host

For those requests that support a fallback host, the path, headers and response structure remain the same

* fix text name
2025-04-25 12:00:13 +00:00
Toni RicoandRevenueCat Git Bot 868f848bae Add X-Is-Backgrounded header (#4938)
* Add X-Is-Backgrounded header

* Add unit test for presence of new header

* [skip ci] Generating new test snapshots (#4939)

* [skip ci] Generating new test snapshots (#4940)

* [skip ci] Generating new test snapshots (#4941)

* [skip ci] Generating new test snapshots (#4942)

* [skip ci] Generating new test snapshots (#4943)

* [skip ci] Generating new test snapshots (#4944)

* [skip ci] Generating new test snapshots (#4945)

* Lock isAppBackgrounded state to false during tests

* one more update

* Revert "Lock isAppBackgrounded state to false during tests"

This reverts commit 6a915a756a.

* Lock isAppBackgrounded state to false during tests

* Update tests

* Fix iOS 15 snapshot tests

* Remove unused isApplicationBackgrounded async method

---------

Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
2025-04-03 10:37:02 +02:00
Antonio Pallares b0292f2ee7 [Diagnostics] add missing parameter to http_request_performed event (#4857)
* refactor: create `DiagnosticsEvent.Properties` struct with all possible fields in a diagnostics event

* chore: remove unnecessary `CodingKeys` and values as `JSONEncoder.KeyEncodingStrategy.convertToSnakeCase` is used in the diagnostics requests

* tests: WIP: adapt unit tests to new `DiagnosticsEvent.Properties`

* fix: have values in Diagnostics events be snake case

* tests: adapt unit tests to Diagnostics events changes

* fix: `name` parameter in DiagnosticsEvent

* tests: fix snapshot testing of JSON to use `.iso8601` date format

* tests: have `JSONEncoder` of snapshot tests be a copy of the encoder user in the SDK

* tests: update the dates in the `CustomerInfo` snapshots for decoding tests to have ISO 8601 format

* fix: remove duplicated import

* refactor: centralize some info transformations in `DiagnosticsEvent.Properties`' init

* tests: add snapshot tests for `DiagnosticsEvents` object

* feat: add `is_retry` parameter to Diagnostics `http_request_performed` event

* tests: consider new `isRetry` parameter in existing `DiagnosticsEvent` tests

* fix: make sure that the `http_request_performed` event is always called

The previous implementation would skip sending the event in the case of getting a `networkError`
2025-03-07 11:26:32 +01:00
Antonio Pallares 25d1507411 UI Preview Mode: add extra header to network requests (#4752)
* feat: add new header to network requests when in UI preview mode

* test: add unit tests for header in network requests when in UI Preview mode
2025-01-31 12:33:19 +01:00
JayShortway 57766ce7a2 Adds X-Is-Debug-Build header (#4364) 2024-10-10 17:00:03 +02:00
Toni Rico 4503a837e6 [Diagnostics] Refactor diagnostics track methods to handle background work automatically (#4270)
* Refactor diagnostics track methods to handle background work automaticaly

* fix swiftlint
2024-09-26 16:33:28 +02:00
Toni RicoandRevenueCat Git Bot fe181bd5e9 Add kochava integration (#4274)
* Reapply "Add `$kochavaDeviceId` attribution convenience method (#4238)" (#4265)

This reverts commit f2ce4416da.

* Add userAgent tracking for attribution networks

* Fix tests

* Add X-Platform-Device header

* Rename user agent to device version

* Use correct attribution method

* [skip ci] Generating new test snapshots (#4278)

* [skip ci] Generating new test snapshots (#4279)

* [skip ci] Generating new test snapshots (#4280)

* [skip ci] Generating new test snapshots (#4281)

* [skip ci] Generating new test snapshots (#4282)

* [skip ci] Generating new test snapshots (#4283)

* Generating new test snapshots (#4284)

* Fix ttests

---------

Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
2024-09-25 19:59:36 +02:00
Toni Rico 597af5f215 [Diagnostics] Add backend_error_code property (#4236)
<!-- Thank you for contributing to Purchases! Before pressing the
"Create Pull Request" button, please provide the following: -->

### Checklist
- [ ] If applicable, unit tests
- [ ] If applicable, create follow-up issues for `purchases-android` and
hybrids

### Motivation
<!-- Why is this change required? What problem does it solve? -->
<!-- Please link to issues following this format: Resolves #999999 -->

### Description
This adds the `backend_error_code` property to diagnostics
`http_request_performed` events.
2024-09-04 09:03:34 +02:00
Will Taylor 348258a41f only retry post receipt for 429 status codes 2024-07-25 16:46:31 -05:00
Will Taylor a4055375f6 retry requests with HTTP status 429 2024-07-23 12:41:16 -05:00
Cesar de la Vega 29250a4f11 Add X-Preferred-Locales header (#4008)
Added a new `X-Supported-Locales` header to be used in the new customer
center feature
2024-07-02 17:32:50 +02:00
NachoSoto 2bcd0ce328 5.0.0 changes: support SK2 by default 2024-07-01 14:37:21 -05:00
Josh Holtz c6e185ff07 Only install swiftlint on Xcode 15 jobs (#3913)
### Motivation

Better implementation of
https://github.com/RevenueCat/purchases-ios/pull/3909 and what was just
commited to `5.0-dev`

### Description

- Only install `swiftlint` on Xcode 15.3 jobs
- Also moved Ruby 3.2.2 install into `install-bundle-dependencies` which
was also done in `5.0-dev`
2024-05-18 08:21:02 -05:00
Toni Rico bb8066d9b3 Add http_request_performed diagnostics event (#3897)
### Description
This adds a new diagnostics event `http_request_performed` with some
useful information we would like to track about the http requests
performed to our servers.
2024-05-16 15:13:40 +02:00
NachoSoto 1cea9978aa Trusted Entitlements: tests for signature verification without header hash (#3505)
Follow up to #3424. This adds coverage to ensure that the backend
continues to sign correctly for old SDK versions that don't support
this.
2023-12-21 12:47:34 -08:00
NachoSoto fb76e662e8 Trusted Entitlements: add support for signing request headers (#3424)
This adds support for including arbitrary headers in the signature
verification, therefore preventing tampering of them.
2023-12-21 11:53:10 -08:00
NachoSoto e31a531ca1 HTTPClient: test all request headers (#3425)
This allows us to verify exactly what headers are included in all
requests.

It also simplifies the implementation for #3424.
2023-11-17 12:19:49 -08:00
Josh HoltzandNachoSoto 7d78633fd8 Adds X-Storefront request header for App Store Storefront (#3405)
### Motivation

Allow backend to determine Storefront of customer

### Description

- Adds `X-Storefront` as a default header
- Uses `StoreKit 1` implementation since its not `async`
- `StoreKit 2` implementation is `async` and would require a some
restructuring that we don't need right now

---------

Co-authored-by: NachoSoto <ignaciosoto90@gmail.com>
2023-11-14 14:04:07 -08:00
NachoSoto ea952f0108 ErrorUtils.purchasesError(withSKError:): handle URLErrors (#3346)
Fixes #3343.

`SKPaymentTransaction.error` docs say:
> The error property is undefined except when `transactionState` is set
to `SKPaymentTransactionState.failed`. Your application can read the
error property to determine why the transaction failed. For a list of
error constants, see `SKErrorDomain` in StoreKit Constants.

Which is why [`PurchasesOrchestrator` only considered that
domain](https://github.com/RevenueCat/purchases-ios/blob/4.28.1/Sources/Purchasing/Purchases/PurchasesOrchestrator.swift#L792).

This expands this handling to consider any other network error,
therefore providing more precise errors.

Since offline connection error detection was only in `HTTPClient`, I
also moved that out and removed `NetworkError.offlineConnection`, so
that we detect this when converting `NetworkError.networkError` instead.
2023-10-25 20:25:09 -07:00
NachoSoto ed80980d08 HTTPClient: verbose logs for request IDs (#3320)
See https://github.com/RevenueCat/khepri/pull/6798.
This can help debug issues as it helps us cross-reference requests on
our end.

### Changes:
- Logging `X-Request-ID` and `X-Amzn-Trace-ID` headers if present (only
in verbose mode)
- Logging these even for failed requests
- Also logging `request_handled_by_load_shedder` for failed requests
- To accomplish that. `HTTPURLResponse` now conforms to our
`HTTPResponseType`, this allows us to extract headers in an uniform way

### Example:
```
[network] DEBUG: ℹ️ API request completed: GET '/v1/subscribers/$RCAnonymousID%3Ad9dc4f3b33054cf28c0f2ec9da0f48d5' (304)
Request-ID: 'be534c50-5231-403b-be2f-7c077861751d'; Amzn-Trace-ID: 'Root=1-6532c6ca-7ef80f961ec9c4145484df13'
```
2023-10-25 20:24:23 -07:00
NachoSoto 341f0d340c Integration Tests: improve flaky tests (#3163)
We get a lot of flaky failures on `OfflineStoreKitIntegrationTests`
(example:
https://app.circleci.com/pipelines/github/RevenueCat/purchases-ios/14843/workflows/a3cffa7c-da25-4811-931d-fc241befee0f/jobs/118214/tests).
I managed to reproduce locally running some of these 100+ times on a
loop until they failed.

I traced the issue to this sequence:
- SK2 purchase
- `StoreKit.Transaction.unfinished` is empty

This is likely due to a race condition. In practice, when computing
offline `CustomerInfo`, we never check it right away, since we need to
wait for the server to return a 500.

I filed a Radar for this: `FB13133387`.

To make tests more realistic, I introduced a delay in `HTTPClient`
returning fake 5xx errors. I haven't been able to reproduce this issue
again, so this should make `OfflineStoreKitIntegrationTests` more
reliable.

I've also added a new debug log that could help debug similar issues,
because `Strings.offline.computed_offline_customer_info` was not very
complete.
2023-09-07 12:25:19 -07:00
NachoSoto 75c0d03ce6 HTTPClient: also parse errors with application/json;charset=utf8 (#3041)
See #2529.
2023-08-17 09:45:22 -07:00
NachoSoto 833524314d HTTPClient: extracted HTTPRequestPath protocol (#2986)
This paves the way to add a second set of paths with a separate server
URL to be able to shed requests to offerings and product entitlement
mapping to a separate server.

### Changes:
- New `HTTPRequestPath` with the same properties as `HTTPRequest.Path` +
a new `serverHostURL`
- Moved proxy logic from `SystemInfo`/`HTTPClient` to `HTTPRequestPath`
- Simplified `HTTPRequest` implementation
2023-08-10 15:23:13 -07: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 48e9560c09 Trusted Entitlements: log signature errors on requests with .informational mode (#2751)
Example (the first `warn` log is `debug` and when running RC tests
only):
```
[signing] WARN: ⚠️ INVALID SIGNATURE DETECTED:
Request: GET /v1/subscribers/identify
Response: 200
Headers: ["X-Signature: signature", "X-RevenueCat-Request-Time: 1658749988564", "Content-Length: 0", "X-RevenueCat-ETag: etag"]
Body (length: 0): e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
[signing] ERROR: 😿‼️ Request to subscribers/identify failed verification. This is likely due to a malicious user intercepting and modifying requests.
```
2023-07-07 14:05:55 -07:00
NachoSoto bd3ac5faf6 Trusted Entitlements: produce verification failures for static endpoints with no signature (#2752)
Equivalent to https://github.com/RevenueCat/purchases-android/pull/1119
2023-07-06 10:08:45 -07:00
NachoSoto 95a5a97c1c Trusted Entitlements: add API key and HTTPRequest.Path to signature (#2746)
Depends on #2747.

### Changes:
- Changed `Signing` to a `final class`, so it can be instantiated with
the api key.
-  Updated all `SigningTests` to include the correct signatures
2023-07-05 16:39:04 -07:00
NachoSoto 3f538fc6f9 Trusted Entitlements: update handling of 304 responses (#2698)
### Changes:
- `ETagManager` no longer stores the verification mode
- Created new `VerifiedHTTPResponse`, which has the
`VerificationResult`, extracted from `HTTPResponse`
- Removed `VerificationResult.from(cache:response:)`
- Changed `SignatureVerificationHTTPClientTests` to test using the real
`ETagManager`, so they become more "end to end" unit tests. A lot of
them were relying on implementation details of the mock instead of the
real `ETagManager`.
- Removed several `HTTPClient` tests that were checking a behavior that
was impossible (for example, no verification result despite it being
enabled), or that checked behavior based on the cached
`VerificationResult`
2023-06-30 12:24:53 -07:00
NachoSoto 7298dfa69f ETagManager: refactored e-tag creation and tests (#2671)
We had lots of different parts of the code doing
`request.url?.absoluteString` and also using different values for
e-tags.
This refactor combines all that to use a single `eTag(for:)` method.

I did this as part of #2665, which is getting closed, but it will still
be useful if we ever decide to change the content of e-tags.
2023-06-21 11:02:45 -07:00
NachoSoto f9660fbd1f LoadShedderIntegrationTests: verify requests are actually handled by load shedder (#2663) 2023-06-19 08:16:57 -07:00
NachoSoto ed35ab2da9 HTTPClient: disable URLSession cache (#2668)
Turns out this was breaking an HTTP 304 integration test in #2659. I'm
very confused why we hadn't seen it before.

Possibly it didn't matter for normal requests, but it was breaking
signature verification because the `nonce` was different on the new
request, and therefore it wouldn't match the cached signature.
2023-06-16 10:26:39 -07:00
NachoSoto 6d1cf97a41 ErrorResponse: drastically improved error messages, no more "unknown error"s (#2660)
## Description:

We've gotten several reports with error messages that aren't very
helpful, like #2390.

Turns out that whenever the API returned a non-successful response but
without an error code, we always produced _"unknown error"_.
This improves the behavior to default to showing the status code. One
example that was very obvious is setting up the SDK with an invalid API
key.

## Examples:

### `OfferingsManager.Error`:

- Before:
```
[Purchases] - ERROR: 🍎‼️ Error fetching offerings - The operation couldn’t be completed. (RevenueCat.OfferingsManager.Error error 0.)
Underlying error: The operation couldn’t be completed. (RevenueCat.NetworkError error 6.)
```

- After:
```
[Purchases] - ERROR: 🍎‼️ Error fetching offerings - The operation couldn’t be completed. (RevenueCat.OfferingsManager.Error error 0.)
Underlying error: Unknown error. API request failed with status code 401
```

### `BackendError`:
- Before:
```
[Purchases] - ERROR: 😿‼️ Unknown error.
```

- After:
```
[Purchases] - ERROR: 😿‼️ Unknown error. API request failed with status code 401
```

### Request debug logs:
- Before:
```
[Purchases] - DEBUG: ℹ️ API request failed: GET /v1/subscribers/$RCAnonymousID:988f9b85609b4a57af255750bec1fbb2/offerings: Unknown error.
```
- After:
```
[Purchases] - DEBUG: ℹ️ API request failed: GET /v1/subscribers/$RCAnonymousID:988f9b85609b4a57af255750bec1fbb2/offerings: Unknown error. API request failed with status code 401
```

### `CustomerInfoManager`:
- Before:
```
[Purchases] - WARN: ⚠️ Attempt to update CustomerInfo from network failed.
The operation couldn’t be completed. (RevenueCat.BackendError error 0.)
Underlying error: Unknown error
```

- After:
```
[Purchases] - WARN: ⚠️ Attempt to update CustomerInfo from network failed.
The operation couldn’t be completed. (RevenueCat.BackendError error 0.)
Underlying error: Unknown error. API request failed with status code 401
```
2023-06-16 09:19:16 -07:00
NachoSoto 208bf53386 HTTPClient: improved log for failed requests (#2669) 2023-06-16 07:49:52 -07:00
NachoSoto 06b0f3d723 Add InternalDangerousSettings.forceSignatureFailures (#2635)
Similar to #2486. This will be used for SDK-3181.

```
- WARN: ⚠️ Returning fake signature verification failure for 'GET /v1/subscribers/$RCAnonymousID:fc0508bea4a74a41bfc9a69db30d925f'
- ERROR: 😿‼️ Request failed signature verification. Request to /v1/subscribers/$RCAnonymousID%3Afc0508bea4a74a41bfc9a69db30d925f failed verification
```
2023-06-13 13:43:16 -07:00
NachoSoto 2276d5c2ce AppleReceipt.debugDescription: don't pretty-print JSON (#2564) 2023-05-31 07:11:23 -07:00
NachoSoto 94537a39af HTTPClient: don't assume error responses are JSON (#2529)
When receiving 500 responses, `HTTPClient` was always calling
`ErrorResponse.from(_ data: Data)`, which tried to decode the content as
if it was JSON.
However, if the response had something completely different, it would
fail to decode.

This wasn't really a bug because `HTTPClient` was still forwarding the
right result, but now it will do so without even trying to parse it.
2023-05-24 09:51:50 -07:00
NachoSoto 50ffbfb3e9 Performance: new check to ensure serialization / deserialization is done from background thread (#2496) 2023-05-19 11:58:12 -07:00
NachoSoto e9e6d887c2 Offline Entitlements: integration tests (#2501)
## Example tests:
```swift
func testOfferingsAreCachedInMemory() async throws {
    let onlineOfferings = try await Purchases.shared.offerings()
    expect(onlineOfferings.all).toNot(beEmpty())

    self.serverDown()

    let offlineOfferings = try await Purchases.shared.offerings()
    expect(offlineOfferings) === onlineOfferings
}

func testOfferingsAreCachedOnDisk() async throws {
    let onlineOfferings = try await Purchases.shared.offerings()
    expect(onlineOfferings.all).toNot(beEmpty())

    self.serverDown()
    await self.resetPurchases()

    let offlineOfferings = try await Purchases.shared.offerings()
    expect(offlineOfferings.response) == onlineOfferings.response

    let offering = try XCTUnwrap(offlineOfferings.current)
    expect(offering.availablePackages.count) == onlineOfferings.current?.availablePackages.count
    expect(offering.monthly?.storeProduct.productIdentifier) == "com.revenuecat.monthly_4.99.1_week_intro"
}
```
2023-05-19 10:54:42 -07:00
NachoSoto b04d894ccb DangerousSettings: debug-only forceServerErrors (#2486) 2023-05-16 09:59:51 -04:00
NachoSoto d68ca889e9 HTTPClient: log actual response status code (#2487)
We were currently logging the status code retrieved from `ETagManager`,
which made it seem like etags weren't working.

Example:
> API request completed: GET /v1/subscribers/identify (200)

With this change, we now log the actual response status code so we can
verify the server is returning the correct status code:
> API request completed: GET /v1/subscribers/identify (304)
2023-05-15 19:28:25 -04:00
Andy BoedoandNachoSoto 618ff121d2 Custom Entitlements Computation mode (#2439)
### Changes:

- Added `Purchases.configureInCustomEntitlementsComputationMode`
- Added `Purchases.switchUser(to:)`
- Disabled parts of the SDK in this new mode
- New example app for testing `customEntitlementsComputation` mode

---------

Co-authored-by: NachoSoto <ignaciosoto90@gmail.com>
2023-04-25 13:21:46 -07:00
NachoSotoandAndy Boedo 8b4c2eb706 ETagManager/HTTPClient: sending new X-RC-Last-Refresh-Time header (#2373)
Fixes SDK-3024 and SDK-3026.

---------

Co-authored-by: Andy Boedo <andresboedo@gmail.com>
2023-04-14 14:32:24 -07:00
NachoSoto 06f80c30a1 HTTPClient: debug log when performing redirects (#2371)
This will be used to detect the load balancer redirecting to the load
shedder. See also #2362.
2023-03-23 14:34:14 -07:00
NachoSoto 47465b01f8 HTTPClient: new flag to force server errors (#2370)
This will help testing offline entitlements.
Note that this is only available as an `internal` API, and only on
`debug` builds.
2023-03-23 14:21:47 -07:00
NachoSoto 0475dac6a9 ETagManager: don't ignore failed etags with Signing.VerificationMode.informational (#2331)
Essentially we don't want to modify any behavior on `.informational`
mode. Everything will continue behaving normally, and simply report
verification failures.
2023-03-13 12:24:02 -07:00
NachoSoto 4341745d10 IdentityManager: clear ETagManager and DeviceCache if verification is enabled but cached CustomerInfo is not (#2330)
Android counterpart:
https://github.com/RevenueCat/purchases-android/pull/844
2023-03-13 11:57:18 -07:00
NachoSoto da9ba397a3 Update CustomerInfo.requestDate from 304 responses (#2310)
### Purpose:

This is a prerequisite for #2288. The new grace period means that if we
didn't update the date from the cached responses, entitlements would
become stale and expired after 3 days.

### Changes:
- Added `HTTPResponseBody.copy(with newRequestDate:)` to be able to
modify responses from the header request date
- `CustomerInfo` implements this method to modify its request date
- Added `HTTPResponse.requestDate` to be able to keep track of the
request date from the server
- Added `VerificationResult.from(cache:response:)` to determine the most
restrictive verification result based on what's cached or checked from a
response
- Added `HTTPResponse.copy(with:)` to modify the verification result of
a response using the previous method
- `HTTPClient` now uses the most restrictive verification result
- `HTTPClient` updates request date from server responses or cached
responses (unless verification failed). This was the missing piece for
#2288.

### Tests:
- Verify that `ETagManager` does not use an ETag if verification was
previously not enabled
- Verify that `ETagManager` returns the request date from the server
when returning a cached response
- Verify that `HTTPClient` updates the request date from the server or
from a cached response
- Verify that `HTTPClient` does not update request date if verification
failed
- Tests for `HTTPResponse` request date parsing
- Test for `CustomerInfoResponseHandler` updating request date
- Tests for `CustomerInfo.copy(with newRequestDate:)`


### Other smaller changes:
- Moved `CustomerInfo.asData()` into `Encodable.asJSONEncodedData()`
- Renamed `requestTime` to `requestDate` everywhere for consistency
2023-03-01 09:24:32 -08:00
NachoSoto b707f8abc8 Signing: added request time & eTag to signature verification (#2309)
See https://github.com/RevenueCat/khepri/pull/5300
2023-02-27 09:07:23 -08:00