Commit Graph

119 Commits

Author SHA1 Message Date
Max Radermacher
fa7f0e98fa
Clear “display badge” when your last badge expires
Also, explicitly track “old badges” vs. “new badges” when redeeming.
2023-03-23 00:32:42 -07:00
Sasha Weiss
8047472f68
Rename SubscriptionManagerProtocol 2023-03-14 17:44:38 -07:00
Harry
a146e18aaf
Set up account state and exit registration
* Go to chat list view after registration

* sync system contacts during registration

* Use explicit local credentials for storage service operations during registration

* fix tests

* Quick hack to get through double pin confirmation

* Finishing touches

* lint

* fix build

* reload phone number discoverability after storage service sync

* fix tests again

* Take chat auth on account and contact record initializers

* Change around branches for clarity in OWSUserProfile

* pr comments

* Split ChatServiceAuth into the same and AuthedAccount

* fix tests

* merge woes
2023-03-09 21:54:51 -08:00
Harry
003cc19e62
Update SignalCoreKit. Use explicit DispatchQueue instead of relying on the implicit type on promise 'on' params
* Use explicit DispatchQueue instead of relying on the implicit type on promise 'on' params

* Update SignalCoreKit
2023-02-07 16:14:39 -08:00
Pete Walters
ac919fcf43
Update Donation UI to handle inactive/failed payments
The Donations screen doesn't currently handle backend
subscription failures well. An example of this is when
the backend encounters a repeated payment processing
failure. Currently, in these situations the donation
screens will display an active donation along with the
renewal date.

To remedy this, the UI now checks that the subscription
status is 'active' before displaying any of the
active subscription UI.
2023-02-06 13:31:07 -06:00
Evan Hahn
cc92abdc90
Clean up "delete subscriber ID" request
This is similar to 227f05e932.

This change should have no user impact.

This changes the "delete subscriber ID" request in the following ways:

- Adds tests
- Converts it to Swift
- Renames `deleteSubscriptionIDRequest` to `deleteSubscriberID`
- Serializes the data inside the method, rather than requiring callers
  to do so
2023-01-27 15:11:48 -08:00
Evan Hahn
227f05e932 Clean up "set subscriber ID" request
This change should have no user impact.

This changes the "set subscriber ID" request in the following ways:

- Adds tests
- Converts it to Swift
- Renames `setSubscriptionIDRequest` to `setSubscriberID`
- Serializes the data inside the method, rather than requiring callers
  to do so

Tested this with automated tests and manually starting a subscription in
staging.
2023-01-26 13:45:25 -06:00
Evan Hahn
35c314bde5
Clean up donation configuration request
This change should have no user impact.

This changes a few things about
`OWSRequestFactory.donationConfigurationRequest()`:

- Adds tests
- Converts it to Swift
- Renames it to `donationConfiguration()`
- Makes it an unauthenticated request

I'm most concerned about that last thing, because it's a behavior
change. However, I think this is safe because:

1. I tested it in a simulator and it works

2. [Android appears to do the same thing][0]

3. A normal `curl` works just fine:

   ```
   curl --insecure 'https://chat.signal.org/v1/subscription/configuration'
   ```

[0]: 657c5d2bce/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java (L1074)
2023-01-25 13:10:22 -06:00
Evan Hahn
43cea3fa7c Remove unused parameter from subscription method
This change should have no user impact.

This argument was never used so we can remove it.

I also fixed a doc comment. It wasn't exactly wrong, but it wasn't
parsed as intended.
2023-01-21 16:13:41 -06:00
Evan Hahn
bdbb13e03f
Donations: enqueue storage syncs outside database writes
This change should have no user impact except a *very* small speedup.

Previously, we were inconsistent in this file. Now, we always call
`recordPendingLocalAccountUpdates()` outside of a write transaction.
2023-01-20 18:27:21 -08:00
Evan Hahn
ac3e0a67c1 Fix compilation errors for PayPal code
We merged 6e97ff3c8f and
bcbf52101e in rapid succession, which
caused compilation errors.

This fixes those.
2023-01-18 17:49:30 -06:00
Sasha Weiss
bcbf52101e
PayPal recurring donations
Co-Authored-By: Evan Hahn <evanhahn@signal.org>
2023-01-18 14:48:50 -08:00
Evan Hahn
6e97ff3c8f
Gifting: add PayPal support 2023-01-18 16:38:57 -06:00
Evan Hahn
aa8bb0d892
Remove unnecessary throws from Stripe method
`Stripe.confirmPaymentIntent` was marked `throws` unnecessarily. This
removes it to simplify the code slightly.
2023-01-17 13:57:32 -06:00
Sasha Weiss
818e7b5d8f
Remove SubscriptionManager.terminateTransactionIfPossible 2022-12-22 14:39:53 -08:00
Evan Hahn
8c7c35b887 Show better errors for credit/debit card failures
For example, if we get the `expired_card` error code back from Stripe,
we should show a specific error to the user.

This introduces some TODOs around error messages in a couple of spots.
We will revisit this when implementing PayPal monthly donations, as is
explained in the comments.

I tested this by using some of [Stripe's test numbers][0] (as well as
automated tests).

[0]: https://stripe.com/docs/testing#declined-payments
2022-12-13 15:45:24 -06:00
Evan Hahn
9f292a91cd Change error string for minimum donation amount
Before, the error said "Select a larger amount to donate."

Now the error says something like "The minimum amount you can donate is
$3."
2022-12-12 15:46:32 -06:00
Sasha Weiss
e8a4a7588f
Hold a reference to an in-progress ASWebAuthenticationSession 2022-12-06 16:56:24 -08:00
Sasha Weiss
7be776dd68
Use a custom scheme to complete the PayPal auth flow 2022-12-06 13:41:24 -08:00
Evan Hahn
e44da4bae9 Add "Donations" to PayPal errors and log messages
I also added a few log messages (which can replace some comments).
2022-12-02 15:50:45 -06:00
sashaweiss-signal
dc3e588f64 Users must confirm PayPal donation before donating
Co-authored-by: Evan Hahn <evanhahn@signal.org>
2022-12-02 15:27:03 -06:00
sashaweiss-signal
eea184165d Disable PayPal for iOS 13- 2022-12-02 15:01:29 -06:00
Sasha Weiss
67143d376d Add remote-config kill switch for all donation types and methods 2022-12-01 14:39:03 -08:00
Sasha Weiss
ee4799b506 One-time donations via PayPal 2022-12-01 14:39:03 -08:00
Sasha Weiss
40e765fa4f Integrate the /v1/subscription/configuration API 2022-12-01 14:39:03 -08:00
Sasha Weiss
b143e585d9 Only allow PayPal for one-time and gift donations 2022-12-01 14:39:03 -08:00
Sasha Weiss
da63036758 Move money amounts to DonationUtilities instead of Stripe 2022-12-01 14:39:03 -08:00
Sasha Weiss
3e75273150 Add a no-op PayPal donations button 2022-12-01 14:39:03 -08:00
Evan Hahn
f4e83f6bcb Enable card donations for external users
This enables credit/debit card donations for external users.

It also adds a kill switch, just in case.
2022-11-30 12:54:18 -06:00
Evan Hahn
890fa72c97
Donations: remove client-side maximum amount check
This should be enforced by the server.
2022-11-29 17:17:46 -06:00
Evan Hahn
0700f81817
Support 3D Secure for card donations
[3D Secure][0] is an additional authentication layer that some
credit/debit cards use. Typically, users open a browser and do some
authentication check before the transaction can proceed.

This adds 3DS support for credit/debit card donations.

If you want to try this yourself, I recommend using one of [Stripe's
test 3DS cards][1] in a staging build.

See also: [the equivalent commit in Signal Android][0].

[0]: https://stripe.com/docs/payments/3d-secure
[1]: https://stripe.com/docs/payments/3d-secure?platform=ios#three-ds-cards
[2]: d1df069669
2022-11-29 16:07:44 -06:00
Evan Hahn
21f2a36125
Add skeleton credit/debit card donation support
This adds very basic support for donations via credit/debit card. It's
missing important features which is why it's behind an internal-only
feature flag.

At a high level, this adds a new screen with a card form. This card data
is submitted to Stripe and then uses the same "rails" as our existing
Apple Pay donations.

This change is missing a few important features, intended to be added
soon:

- [3D Secure][3DS] support
- Validation error messages
- Input formatting (e.g., "1234" becomes "12/34")
- Gift badge support (currently only supports Apple Pay)
- Various smaller UI changes

[3DS]: https://stripe.com/docs/payments/3d-secure
2022-11-22 09:07:36 -06:00
Evan Hahn
6bf554ca17
Update subscriptions without re-prompting for Apple Pay
We shouldn't ask for Apple Pay when users update their subscriptions.
The update should just happen, unless there was previously a charge
failure.

This also fixes two other bugs:

- Some race conditions around observing subscription jobs
- One-time donations used the wrong progress spinner

This makes an upcoming change easier but is also useful on its own.
2022-11-20 08:08:15 -06:00
Evan Hahn
a207afb278 Cleanups to subscription manager methods
This change should have no user impact. It:

- Removes unnecessary `throws` annotations for methods that don't throw
- Uses `Currency.Code` instead of `String` in a few places
- Removes some comments I felt were obvious
- Changes some whitespace

I think these are useful on their own, but they'll also make an upcoming
change easier.
2022-11-16 15:50:38 -06:00
Evan Hahn
613d35f25c
Remove unused arg from "update monthly donation" method
The `priorSubscription` isn't used, so we can remove it.
2022-11-16 13:05:47 -06:00
Evan Hahn
ec78cc3a0a
Hide Apple Pay UI when the server disallows your region
_I recommend reviewing this with whitespace changes disabled._

The server's `global.donations.apayDisabledRegions` is a list of regions
(phone number prefixes) where Apple Pay is disallowed. This respects
that.
2022-11-10 16:19:47 -06:00
Sasha Weiss
242dfd2bce
Add all JobQueues to environment, via a wrapper
Currently, only some `JobQueue` types are initialized during startup
(as part of `Environment`, or `SSKEnvironment`). Initialization is
required, however, for a `JobQueue` type to restart any latent jobs.
That means that, for example, a durable `SendGiftBadge` job that failed,
and should be reattempted at a later date, will not in fact be restarted
since no `SendGiftBadgeJobQueue` will be initialized at launch.

This change adds `SSKJobQueues` and `SignalMessagingJobQueues` types,
which are intended to be singletons that hold within them a singleton
job queue for each of our `JobQueue` types. These wrappers are added to
`SSKEnvironment` and `Environment` (from SignalMessaging) respectively,
ensuring that all the `JobQueue`s they contain are initialized as part
of environment setup. The wrappers also avoid the need to add a new
property to the (already large) environment types for each new future
`JobQueue`.

This change also updates all existing call sites that accessed a
`JobQueue` from an environment object, to direct that access now through
the wrapper type.
2022-11-09 14:08:44 -06:00
Evan Hahn
513ba3863d Crash, don't throw, if donation receipt generation fails
_I recommend reviewing this with whitespace changes disabled._

We need to generate a "receipt request" before doing a donation. This is
is entirely on-device and is unlikely to fail, but it technically could.

Previously, `generateReceiptRequest` would throw if this failed. We did
a bad job handling these failures (in some cases, we just ignored the
failures completely!).

Because this represents such a catastrophic failure, we'd _like_ this to
crash the app so we can investigate it more urgently.
2022-11-09 11:49:30 -06:00
Evan Hahn
198fc1784a
Consolidate one-time & monthly donation screens
Previously, one-time donations were on one screen and monthly donations
were on another. Now, they're on a single screen with a picker.

Most of the interesting changes are in `DonateViewController`.

Other things of note:

- There are some new TODOs here for existing bugs I didn't fix. For
  example, one-time donations don't do so well if there are any problems
  at all.

- Even though we only support Apple Pay, there's code that alludes to
  additional payment methods. For example,
  `DonateChoosePaymentMethodSheet`. We'll expand on this in the future.

- Users should only be able to select currencies that the server
  supports. For example, you shouldn't be able to select EUR if the
  server doesn't support euros. This wasn't working correctly before,
  but is fixed here.

  We already fixed one part, where users could change to an unsupported
  currency (see dab02f30ae). However, if
  your _default_ currency is unsupported and you didn't change it,
  that's no good. This is unlikely for most users but could happen.

  I fixed this by changing it from (effectively)
  `Locale.current.currencyCode ?? "USD"`, which might not be supported,
  to a preference list, choosing the first one the server likes.

- I skip animations if the Reduce Motion setting is enabled.

- On the donation screen, the logic for the preview badge has changed
  slightly. If you already have a badge, we'll always use that.
2022-11-08 16:27:50 -06:00
Evan Hahn
d96d7d6160 DonationUtilities doesn't need to be an NSObject
This change should have no user impact.
2022-10-28 15:51:26 -07:00
Evan Hahn
4675434c6c Add FiatMoney type
This change should have no user impact.

We commonly pair a currency, like USD, and an amount, like 1.23. This
adds the `FiatMoney` struct. It's a simple struct with two fields.

After adding it, I tried to use it everywhere. (It's possible I missed a
spot.)

I think this is a useful change on its own, but it'll be nice for an
upcoming change, too.

See also: [Android's equivalent class][0].

[0]: cb65347bb3/core-util/src/main/java/org/signal/core/util/money/FiatMoney.java (L1)
2022-10-26 17:04:51 -05:00
Evan Hahn
e03461b176 Use "donations" in one-time/monthly donation logs
Previously, we used `[Subscriptions]` which wasn't always right. Now, we
use `[Donations]`.
2022-10-18 09:33:17 -07:00
Evan Hahn
623b1909b2
Prefer Decimal over NSDecimalNumber
This change should have no user impact.

We use `NSDecimalNumber` and `Decimal`. This tries to standardize on
`Decimal` where possible (though the former is still needed in a few
places).

Mostly a mechanical change, though a few little things changed.
2022-10-18 09:43:46 -05:00
Evan Hahn
10a78d6033
Clean up min/max checks for Stripe payments
We check whether a payment amount is too small or too large. This makes
a few changes:

- `isAmountTooLarge` was correct except for [IDR][1], which has a
  larger limit according to [Stripe's docs][0].
- Added docs for `isAmountTooSmall` and `isAmountTooLarge`.
- Updated rounding to use "normal" rounding instead of "banker's
  rounding".

[0]: https://stripe.com/docs/currencies?presentment-currency=US#minimum-and-maximum-charge-amounts
[1]: https://en.wikipedia.org/wiki/Indonesian_rupiah
2022-10-17 13:45:57 -05:00
Evan Hahn
48e87a46ce Add BYN and SLE to list of Stripe currencies
This adds [BYN][] and [SLE][] to the list of currencies, according to
Stripe's docs.

[BYN]: https://en.wikipedia.org/wiki/Belarusian_ruble
[SLE]: https://en.wikipedia.org/wiki/Sierra_Leonean_leone
2022-10-17 11:33:42 -05:00
Evan Hahn
e0ebfac315 Handle decimals in one-time and gift donations
We fetch the cost of gift badges and suggested one-time donation
amounts. For example, gift badges cost $5 and £4.

Previously, we parsed these as `UInt`s. This had two disadvantages:

1. There was no way to represent fractional amounts (like $1.23)
2. It was inconsistent with a lot of our code, which expects `Decimal`s
   or `NSDecimalNumber`s

This changes these to use `Decimal` instead.

Tested this by:

- Adding some automated tests
- Making a one-time donation (with a non-default currency)
- Sending a gift badge (with a non-default currency)
- Checking donation receipts

We also had some hard-coded presets for one-time donations, which were
unused. I removed these.
2022-10-17 09:18:05 -07:00
Evan Hahn
6ea3532540 Use set, not array, for zero-decimal currency list
We check if a currencies are in a list ([example][0]). We can speed this
up, and better clarify intent, if we use a `Set` instead of an array.

[0]: 35bc42d159/SignalMessaging/Subscriptions/DonationUtilities.swift (L72)
2022-10-14 10:08:00 -07:00
Evan Hahn
370ff654e7
Change license to AGPL
Change license to AGPL

This commit:

- Updates the `LICENSE` file

- Start every file with something like:

      // Copyright YEAR_FIRST_PUBLISHED Signal Messenger, LLC
      // SPDX-License-Identifier: AGPL-3.0-only

---

First, I removed existing license headers with this Ruby 3.1.2 script:

    require 'set'

    EXTENSIONS_TO_CHECK = Set['.h', '.hpp', '.cpp', '.m', '.mm', '.pch', '.swift']

    same = 0
    different = 0

    all_files = `git ls-files`.lines.map { |line| line.strip }
    all_files.each do |relative_path|
      if relative_path == 'Pods'
        next
      end

      unless EXTENSIONS_TO_CHECK.include? File.extname(relative_path)
        next
      end

      path = File.expand_path(relative_path)

      contents = File.read(path)
      new_contents = contents.sub(/\/\/\n\/\/  Copyright .*\n\/\/\n\n/, '')

      if contents == new_contents
        same += 1
      else
        different += 1
      end

      File.write(path, new_contents)
    end

    puts "updated #{different} file(s), left #{same} untouched"

I'm sure this script could be improved, but it worked well enough.

Then, I created `Scripts/lint/lint-license-headers` and ran it to auto-
fix a lot of files. This changed the mode of some files, but I think
that's actually desirable. For example,
`SignalServiceKit/src/Util/AppContext.m` previously had a mode of
`0755/-rwxr-xr-x`, and it's now `0644/-rw-r--r--`.

Then I fixed some stragglers and updated the precommit script.

See [a similar change in the Desktop app][0].

[0]: 8bfaf598af
2022-10-13 08:25:37 -05:00
Max Radermacher
9953f99784 Remove unused donation code 2022-10-12 11:30:39 -07:00
Max Radermacher
6f19522b55
Clarify label for recurring donations 2022-09-23 15:38:34 -07:00