From 5bf94de2a65710f696d7e8d378b031da2e3bf37e Mon Sep 17 00:00:00 2001 From: Nora Trapp Date: Thu, 13 May 2021 09:32:21 -0700 Subject: [PATCH] little fixes --- .../CurrencyPickerViewController.swift | 29 ++++++++++++------- .../AppSettings/DonationViewController.swift | 4 ++- .../PaymentsSettingsViewController.swift | 4 ++- Signal/src/util/Stripe.swift | 15 ++++++++-- .../Network/API/Requests/OWSRequestFactory.h | 6 ++-- .../Network/API/Requests/OWSRequestFactory.m | 14 +++++++-- .../src/Network/API/TSNetworkManager.m | 3 +- 7 files changed, 53 insertions(+), 22 deletions(-) diff --git a/Signal/src/ViewControllers/AppSettings/CurrencyPickerViewController.swift b/Signal/src/ViewControllers/AppSettings/CurrencyPickerViewController.swift index 5e83f27a28..2706e0b52e 100644 --- a/Signal/src/ViewControllers/AppSettings/CurrencyPickerViewController.swift +++ b/Signal/src/ViewControllers/AppSettings/CurrencyPickerViewController.swift @@ -9,23 +9,26 @@ protocol CurrencyPickerDataSource { var preferredCurrencyInfos: [Currency.Info] { get } var supportedCurrencyInfos: [Currency.Info] { get } - init(updateTableContentsBlock: @escaping () -> Void) + var updateTableContents: (() -> Void)? { get set } } class CurrencyPickerViewController: OWSTableViewController2, UISearchBarDelegate { private let searchBar = OWSSearchBar() - private lazy var dataSource = DataSourceType { [weak self] in self?.updateTableContents() } + private var dataSource: DataSourceType private let completion: (Currency.Code) -> Void fileprivate var searchText: String? { searchBar.text?.ows_stripped() } - public required init(completion: @escaping (Currency.Code) -> Void) { + public required init(dataSource: DataSourceType, completion: @escaping (Currency.Code) -> Void) { + self.dataSource = dataSource self.completion = completion super.init() + self.dataSource.updateTableContents = { [weak self] in self?.updateTableContents() } + topHeader = OWSTableViewController2.buildTopHeader(forView: searchBar) } @@ -210,24 +213,28 @@ class CurrencyPickerViewController: OW } } -struct CurrencyPickerStripeDataSource: CurrencyPickerDataSource { - let currentCurrencyCode = Stripe.defaultCurrencyCode +struct StripeCurrencyPickerDataSource: CurrencyPickerDataSource { + let currentCurrencyCode: Currency.Code let preferredCurrencyInfos = Stripe.preferredCurrencyInfos let supportedCurrencyInfos = Stripe.supportedCurrencyInfos - init(updateTableContentsBlock: @escaping () -> Void) {} + var updateTableContents: (() -> Void)? + + init(currentCurrencyCode: Currency.Code = Stripe.defaultCurrencyCode) { + self.currentCurrencyCode = currentCurrencyCode + } } -class CurrencyPickerPaymentsDataSource: NSObject, CurrencyPickerDataSource { +class PaymentsCurrencyPickerDataSource: NSObject, CurrencyPickerDataSource { let currentCurrencyCode = paymentsCurrenciesSwift.currentCurrencyCode let preferredCurrencyInfos = paymentsCurrenciesSwift.preferredCurrencyInfos private(set) var supportedCurrencyInfos = paymentsCurrenciesSwift.supportedCurrencyInfosWithCurrencyConversions { - didSet { updateTableContents() } + didSet { updateTableContents?() } } - let updateTableContents: () -> Void - required init(updateTableContentsBlock: @escaping () -> Void) { - self.updateTableContents = updateTableContentsBlock + var updateTableContents: (() -> Void)? + + override init() { super.init() NotificationCenter.default.addObserver( diff --git a/Signal/src/ViewControllers/AppSettings/DonationViewController.swift b/Signal/src/ViewControllers/AppSettings/DonationViewController.swift index be5b13908a..bc60e3e443 100644 --- a/Signal/src/ViewControllers/AppSettings/DonationViewController.swift +++ b/Signal/src/ViewControllers/AppSettings/DonationViewController.swift @@ -360,7 +360,9 @@ extension DonationViewController: PKPaymentAuthorizationControllerDelegate { let picker = OWSButton { [weak self] in guard let self = self else { return } - let vc = CurrencyPickerViewController { [weak self] currencyCode in + let vc = CurrencyPickerViewController( + dataSource: StripeCurrencyPickerDataSource(currentCurrencyCode: self.currencyCode) + ) { [weak self] currencyCode in self?.currencyCode = currencyCode } self.navigationController?.pushViewController(vc, animated: true) diff --git a/Signal/src/ViewControllers/AppSettings/Payments/PaymentsSettingsViewController.swift b/Signal/src/ViewControllers/AppSettings/Payments/PaymentsSettingsViewController.swift index 3ce4532081..f8f41720fa 100644 --- a/Signal/src/ViewControllers/AppSettings/Payments/PaymentsSettingsViewController.swift +++ b/Signal/src/ViewControllers/AppSettings/Payments/PaymentsSettingsViewController.swift @@ -949,7 +949,9 @@ public class PaymentsSettingsViewController: OWSTableViewController2 { } private func didTapSetCurrencyButton() { - let view = CurrencyPickerViewController { currencyCode in + let view = CurrencyPickerViewController( + dataSource: PaymentsCurrencyPickerDataSource() + ) { currencyCode in Self.databaseStorage.write { transaction in Self.paymentsCurrencies.setCurrentCurrencyCode(currencyCode, transaction: transaction) } diff --git a/Signal/src/util/Stripe.swift b/Signal/src/util/Stripe.swift index 08df59dee4..1400081d0a 100644 --- a/Signal/src/util/Stripe.swift +++ b/Signal/src/util/Stripe.swift @@ -30,11 +30,16 @@ struct Stripe: Dependencies { } static func integralAmount(_ amount: NSDecimalNumber, in currencyCode: Currency.Code) -> UInt { + let roundedAndScaledAmount: Double if zeroDecimalCurrencyCodes.contains(currencyCode.uppercased()) { - return UInt(amount.doubleValue.rounded(.toNearestOrEven)) + roundedAndScaledAmount = amount.doubleValue.rounded(.toNearestOrEven) } else { - return UInt((amount.doubleValue * 100).rounded(.toNearestOrEven)) + roundedAndScaledAmount = (amount.doubleValue * 100).rounded(.toNearestOrEven) } + + guard roundedAndScaledAmount <= Double(UInt.max) else { return UInt.max } + guard roundedAndScaledAmount >= 0 else { return 0 } + return UInt(roundedAndScaledAmount) } } @@ -72,9 +77,12 @@ fileprivate extension Stripe { throw OWSAssertionError("Unexpected currency code") } + // The description is never translated as it's populated into an + // english only receipt by Stripe. let request = OWSRequestFactory.createPaymentIntent( withAmount: integralAmount(amount, in: currencyCode), - inCurrencyCode: currencyCode + inCurrencyCode: currencyCode, + withDescription: LocalizationNotNeeded("Thank you for your donation. Your contribution helps fuel the mission of developing open source privacy technology that protects free expression and enables secure global communication for millions around the world. Signal Technology Foundation is a tax-exempt nonprofit organization in the United States under section 501c3 of the Internal Revenue Code. Our Federal Tax ID is 82-4506840. No goods or services were provided in exchange for this donation. Please retain this receipt for your tax records.") ) return networkManager.makePromise(request: request) @@ -149,6 +157,7 @@ fileprivate extension Stripe { parameters["pk_token_payment_network"] = payment.token.paymentMethod.network.map { $0.rawValue } if payment.token.transactionIdentifier == "Simulated Identifier" { + owsAssertDebug(!FeatureFlags.isUsingProductionService, "Simulated ApplePay only works in staging") // Generate a fake transaction identifier parameters["pk_token_transaction_id"] = "ApplePayStubs~4242424242424242~0~USD~\(UUID().uuidString)" } else { diff --git a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h index fb04458de6..ca2e8fa4f9 100644 --- a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h +++ b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h @@ -197,9 +197,11 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo + (TSRequest *)pushChallengeResponseWithToken:(NSString *)challengeToken; + (TSRequest *)recaptchChallengeResponseWithToken:(NSString *)serverToken captchaToken:(NSString *)captchaToken; -#pragma mark - Stripe +#pragma mark - Donations -+ (TSRequest *)createPaymentIntentWithAmount:(NSUInteger)amount inCurrencyCode:(NSString *)currencyCode; ++ (TSRequest *)createPaymentIntentWithAmount:(NSUInteger)amount + inCurrencyCode:(NSString *)currencyCode + withDescription:(nullable NSString *)description; @end diff --git a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m index 8392e32123..2064739b58 100644 --- a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m +++ b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m @@ -878,13 +878,21 @@ NSString *const OWSRequestKey_AuthKey = @"AuthKey"; parameters:@{ @"type" : @"recaptcha", @"token" : serverToken, @"captcha" : captchaToken }]; } -#pragma mark - Stripe +#pragma mark - Donations -+ (TSRequest *)createPaymentIntentWithAmount:(NSUInteger)amount inCurrencyCode:(NSString *)currencyCode ++ (TSRequest *)createPaymentIntentWithAmount:(NSUInteger)amount + inCurrencyCode:(NSString *)currencyCode + withDescription:(nullable NSString *)description { + NSMutableDictionary *parameters = + [@{ @"currency" : currencyCode.lowercaseString, @"amount" : @(amount) } mutableCopy]; + if (description) { + parameters[@"description"] = description; + } + return [TSRequest requestWithUrl:[NSURL URLWithString:@"/v1/donation/authorize-apple-pay"] method:@"POST" - parameters:@{ @"currency" : currencyCode.lowercaseString, @"amount" : @(amount) }]; + parameters:parameters]; } @end diff --git a/SignalServiceKit/src/Network/API/TSNetworkManager.m b/SignalServiceKit/src/Network/API/TSNetworkManager.m index 72a8959cbc..2cab5146b0 100644 --- a/SignalServiceKit/src/Network/API/TSNetworkManager.m +++ b/SignalServiceKit/src/Network/API/TSNetworkManager.m @@ -449,6 +449,7 @@ dispatch_queue_t NetworkManagerQueue() NSString *_Nullable contentType = task.originalRequest.allHTTPHeaderFields[@"Content-Type"]; BOOL isJson = [contentType isEqualToString:OWSMimeTypeJson]; BOOL isProtobuf = [contentType isEqualToString:@"application/x-protobuf"]; + BOOL isFormData = [contentType isEqualToString:@"application/x-www-form-urlencoded"]; if (isJson) { NSString *jsonBody = [[NSString alloc] initWithData:task.originalRequest.HTTPBody encoding:NSUTF8StringEncoding]; @@ -457,7 +458,7 @@ dispatch_queue_t NetworkManagerQueue() OWSAssertDebug([jsonBody rangeOfString:@"'"].location == NSNotFound); [curlComponents addObject:@"--data-ascii"]; [curlComponents addObject:[NSString stringWithFormat:@"'%@'", jsonBody]]; - } else if (isProtobuf) { + } else if (isProtobuf || isFormData) { NSData *bodyData = task.originalRequest.HTTPBody; NSString *filename = [NSString stringWithFormat:@"%@.tmp", NSUUID.UUID.UUIDString];