Skip to content

Commit f8a5736

Browse files
committed
[Breaking] Adds async APIs to STPApplePayContext.
1 parent cd84277 commit f8a5736

File tree

9 files changed

+553
-136
lines changed

9 files changed

+553
-136
lines changed

CHANGELOG_v25_draft.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
## 25.0.0 2025-XX-YY
2+
### STPApplePayContext
3+
* [Added] Added async delegate methods.
4+
* [Changed] Replaces the `ApplePayContextDelegate.didCreatePaymentMethod` method with an async version.
5+

MIGRATING_v25_draft.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#### STPApplePayContext
2+
ApplePayContextDelegate's `applePayContext:didCreatePaymentMethod:paymentInformation:completion:` has been replaced by an async equivalent. You can use the following example to quickly migrate completion-block based code:
3+
4+
// Before:
5+
func applePayContext(
6+
_ context: STPApplePayContext,
7+
didCreatePaymentMethod paymentMethod: StripeAPI.PaymentMethod,
8+
paymentInformation: PKPayment,
9+
completion: @escaping STPIntentClientSecretCompletionBlock
10+
) {
11+
MyExampleNetworkManager.getPaymentIntent() { paymentIntentClientSecret in
12+
completion("my client secret", nil)
13+
}
14+
}
15+
16+
// After:
17+
func applePayContext(
18+
_ context: STPApplePayContext,
19+
didCreatePaymentMethod paymentMethod: StripeAPI.PaymentMethod,
20+
paymentInformation: PKPayment
21+
) async throws -> String {
22+
return try await withCheckedThrowingContinuation { continuation in
23+
MyExampleNetworkManager.getPaymentIntent() { paymentIntentClientSecret, error in
24+
if let error {
25+
continuation.resume(throwing: error)
26+
} else {
27+
continuation.resume(returning: paymentIntentClientSecret)
28+
}
29+
}
30+
}
31+
}
32+

Stripe/StripeiOSTests/STPApplePayContextFunctionalTest.swift

+125-10
Original file line numberDiff line numberDiff line change
@@ -360,17 +360,16 @@ class STPApplePayContextFunctionalTest: STPNetworkStubbingTestCase {
360360
// When the user taps 'Pay', PKPaymentAuthorizationController calls `didAuthorizePayment:completion:`
361361
// After you call its completion block, it calls `paymentAuthorizationControllerDidFinish:`
362362
let didCallAuthorizePaymentCompletion = expectation(description: "ApplePayContext called completion block of paymentAuthorizationController:didAuthorizePayment:completion:")
363-
if let authorizationController = context?.authorizationController {
364-
context?.paymentAuthorizationController(authorizationController, didAuthorizePayment: STPFixtures.simulatorApplePayPayment(), handler: { [self] result in
365-
XCTAssertEqual(expectedStatus, result.status)
366-
DispatchQueue.main.async(execute: { [self] in
367-
if let authorizationController = context?.authorizationController {
368-
context?.paymentAuthorizationControllerDidFinish(authorizationController)
369-
}
370-
didCallAuthorizePaymentCompletion.fulfill()
371-
})
363+
let authorizationController = context!.authorizationController!
364+
context?.paymentAuthorizationController(authorizationController, didAuthorizePayment: STPFixtures.simulatorApplePayPayment(), handler: { [self] result in
365+
XCTAssertEqual(expectedStatus, result.status)
366+
DispatchQueue.main.async(execute: { [self] in
367+
if let authorizationController = context?.authorizationController {
368+
context?.paymentAuthorizationControllerDidFinish(authorizationController)
369+
}
370+
didCallAuthorizePaymentCompletion.fulfill()
372371
})
373-
}
372+
})
374373
}
375374
}
376375

@@ -380,3 +379,119 @@ class STPTestPKPaymentAuthorizationController: PKPaymentAuthorizationController
380379
completion?()
381380
}
382381
}
382+
383+
// MARK: - Async delegate methods
384+
// Keeps track of which async delegate methods have been called
385+
class TestAsyncApplePayContextDelegate: NSObject, ApplePayContextDelegate {
386+
enum AsyncDelegateMethods {
387+
case didCreatePaymentMethod
388+
case didSelectShippingMethod
389+
case didSelectShippingContact
390+
case didChangeCouponCode
391+
case willCompleteWithResult
392+
case didCompleteWithStatus
393+
}
394+
395+
var delegateMethodsCalled: [AsyncDelegateMethods] = []
396+
397+
func applePayContext(
398+
_ context: StripeApplePay.STPApplePayContext,
399+
didCreatePaymentMethod paymentMethod: StripeCore.StripeAPI.PaymentMethod,
400+
paymentInformation: PKPayment
401+
) async throws -> String {
402+
delegateMethodsCalled.append(.didCreatePaymentMethod)
403+
return "pi_bad_secret_1234"
404+
}
405+
406+
func applePayContext(
407+
_ context: StripeApplePay.STPApplePayContext,
408+
didSelectShippingContact contact: PKContact
409+
) async -> PKPaymentRequestShippingContactUpdate {
410+
delegateMethodsCalled.append(.didSelectShippingContact)
411+
return .init()
412+
}
413+
414+
func applePayContext(
415+
_ context: STPApplePayContext,
416+
didSelect shippingMethod: PKShippingMethod
417+
) async -> PKPaymentRequestShippingMethodUpdate {
418+
delegateMethodsCalled.append(.didSelectShippingMethod)
419+
return .init()
420+
}
421+
422+
@available(iOS 15.0, *)
423+
func applePayContext(
424+
_ context: STPApplePayContext,
425+
didChangeCouponCode couponCode: String
426+
) async -> PKPaymentRequestCouponCodeUpdate {
427+
delegateMethodsCalled.append(.didChangeCouponCode)
428+
return .init()
429+
}
430+
431+
func applePayContext(
432+
_ context: STPApplePayContext,
433+
willCompleteWithResult authorizationResult: PKPaymentAuthorizationResult
434+
) async -> PKPaymentAuthorizationResult {
435+
delegateMethodsCalled.append(.willCompleteWithResult)
436+
return authorizationResult
437+
}
438+
439+
func applePayContext(_ context: StripeApplePay.STPApplePayContext, didCompleteWith status: StripeApplePay.STPApplePayContext.PaymentStatus, error: (any Error)?) {
440+
delegateMethodsCalled.append(.didCompleteWithStatus)
441+
}
442+
}
443+
444+
extension STPApplePayContextFunctionalTest {
445+
func testAsyncDelegateMethodsCalled() {
446+
let delegate = TestAsyncApplePayContextDelegate()
447+
let request = StripeAPI.paymentRequest(
448+
withMerchantIdentifier: "foo",
449+
country: "US",
450+
currency: "USD"
451+
)
452+
request.paymentSummaryItems = [
453+
PKPaymentSummaryItem(label: "bar", amount: NSDecimalNumber(string: "1.00")),
454+
]
455+
self.context = STPApplePayContext(paymentRequest: request, delegate: delegate)!
456+
context.apiClient = apiClient
457+
_startApplePayForContext(withExpectedStatus: .failure)
458+
waitForExpectations(timeout: 50)
459+
XCTAssertEqual(delegate.delegateMethodsCalled, [.didCreatePaymentMethod, .willCompleteWithResult])
460+
delegate.delegateMethodsCalled = []
461+
462+
// Now test that the 3 optional async methods get called:
463+
let e1 = expectation(description: "didSelectShippingMethod")
464+
XCTAssertTrue(context.responds(to: #selector((PKPaymentAuthorizationControllerDelegate.paymentAuthorizationController(_:didSelectShippingMethod:handler:)))))
465+
context.paymentAuthorizationController(
466+
context.authorizationController!,
467+
didSelectShippingMethod: .init()
468+
) { _ in
469+
e1.fulfill()
470+
}
471+
// didSelectShippingContact should be called
472+
let e2 = expectation(description: "didSelectShippingContact")
473+
XCTAssertTrue(context.responds(to: #selector(PKPaymentAuthorizationControllerDelegate.paymentAuthorizationController(_:didSelectShippingContact:handler:))))
474+
context.paymentAuthorizationController(
475+
context.authorizationController!,
476+
didSelectShippingContact: .init()
477+
) { _ in
478+
e2.fulfill()
479+
}
480+
481+
// didChangeCouponCode should be called
482+
if #available(iOS 15.0, *) {
483+
let e3 = expectation(description: "didChangeCouponCode")
484+
XCTAssertTrue(context.responds(to: #selector(PKPaymentAuthorizationControllerDelegate.paymentAuthorizationController(_:didChangeCouponCode:handler:))))
485+
context.paymentAuthorizationController(
486+
context.authorizationController!,
487+
didChangeCouponCode: .init()
488+
) { _ in
489+
e3.fulfill()
490+
}
491+
} else {
492+
// Fallback on earlier versions
493+
}
494+
waitForExpectations(timeout: 3)
495+
XCTAssertEqual(delegate.delegateMethodsCalled, [.didCompleteWithStatus, .didSelectShippingMethod, .didSelectShippingContact, .didChangeCouponCode])
496+
}
497+
}

0 commit comments

Comments
 (0)