Skip to content

Commit

Permalink
Enable bank payments in native Link
Browse files Browse the repository at this point in the history
  • Loading branch information
tillh-stripe committed Feb 7, 2025
1 parent bf78561 commit 6fadddf
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol {
}

func listPaymentDetails(
elementsSession: STPElementsSession,
completion: @escaping (Result<[ConsumerPaymentDetails], Error>) -> Void
) {
retryingOnAuthError(completion: completion) { completionRetryingOnAuthErrors in
Expand All @@ -306,9 +307,12 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol {
completion(.failure(PaymentSheetError.unknown(debugDescription: "Paying with Link without valid session")))
return
}

let supportedPaymentMethodTypes = self.supportedPaymentDetailsTypes(for: elementsSession)

session.listPaymentDetails(
with: self.apiClient,
supportedPaymentMethodTypes: supportedPaymentMethodTypes,
consumerAccountPublishableKey: self.publishableKey,
completion: completionRetryingOnAuthErrors
)
Expand Down Expand Up @@ -364,7 +368,13 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol {
}
}

func sharePaymentDetails(id: String, cvc: String?, allowRedisplay: STPPaymentMethodAllowRedisplay?, completion: @escaping (Result<PaymentDetailsShareResponse, Error>) -> Void) {
func sharePaymentDetails(
id: String,
cvc: String?,
allowRedisplay: STPPaymentMethodAllowRedisplay?,
expectedPaymentMethodType: String?,
completion: @escaping (Result<PaymentDetailsShareResponse, Error>
) -> Void) {
retryingOnAuthError(completion: completion) { [apiClient, publishableKey] completionRetryingOnAuthErrors in
guard let session = self.currentSession else {
stpAssertionFailure()
Expand All @@ -380,6 +390,7 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol {
id: id,
cvc: cvc,
allowRedisplay: allowRedisplay,
expectedPaymentMethodType: expectedPaymentMethodType,
consumerAccountPublishableKey: publishableKey,
completion: completionRetryingOnAuthErrors
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,13 @@ extension ConsumerSession {

func listPaymentDetails(
with apiClient: STPAPIClient = STPAPIClient.shared,
supportedPaymentMethodTypes: Set<ConsumerPaymentDetails.DetailsType>,
consumerAccountPublishableKey: String?,
completion: @escaping (Result<[ConsumerPaymentDetails], Error>) -> Void
) {
apiClient.listPaymentDetails(
for: clientSecret,
supportedPaymentMethodTypes: supportedPaymentMethodTypes,
consumerAccountPublishableKey: consumerAccountPublishableKey,
completion: completion)
}
Expand Down Expand Up @@ -239,6 +241,7 @@ extension ConsumerSession {
id: String,
cvc: String?,
allowRedisplay: STPPaymentMethodAllowRedisplay?,
expectedPaymentMethodType: String?,
consumerAccountPublishableKey: String?,
completion: @escaping (Result<PaymentDetailsShareResponse, Error>) -> Void
) {
Expand All @@ -248,6 +251,7 @@ extension ConsumerSession {
consumerAccountPublishableKey: consumerAccountPublishableKey,
allowRedisplay: allowRedisplay,
cvc: cvc,
expectedPaymentMethodType: expectedPaymentMethodType,
completion: completion)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ extension STPAPIClient {
consumerAccountPublishableKey: String?,
allowRedisplay: STPPaymentMethodAllowRedisplay?,
cvc: String?,
expectedPaymentMethodType: String?,
completion: @escaping (Result<PaymentDetailsShareResponse, Error>) -> Void
) {
let endpoint: String = "consumers/payment_details/share"
Expand All @@ -305,6 +306,9 @@ extension STPAPIClient {
if let allowRedisplay {
parameters["allow_redisplay"] = allowRedisplay.stringValue
}
if let expectedPaymentMethodType {
parameters["expected_payment_method_type"] = expectedPaymentMethodType
}

APIRequest<PaymentDetailsShareResponse>.post(
with: self,
Expand All @@ -322,6 +326,7 @@ extension STPAPIClient {

func listPaymentDetails(
for consumerSessionClientSecret: String,
supportedPaymentMethodTypes: Set<ConsumerPaymentDetails.DetailsType>,
consumerAccountPublishableKey: String?,
completion: @escaping (Result<[ConsumerPaymentDetails], Error>) -> Void
) {
Expand All @@ -330,7 +335,7 @@ extension STPAPIClient {
let parameters: [String: Any] = [
"credentials": ["consumer_session_client_secret": consumerSessionClientSecret],
"request_surface": "ios_payment_element",
"types": ["card"],
"types": supportedPaymentMethodTypes.map(\.rawValue),
]

post(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,10 @@ private extension PayWithLinkViewController {
stpAssertionFailure(LinkAccountError.noLinkAccount.localizedDescription)
return
}

linkAccount.listPaymentDetails { result in

linkAccount.listPaymentDetails(
elementsSession: context.elementsSession
) { result in
switch result {
case .success(let paymentDetails):
if paymentDetails.isEmpty {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,12 @@ extension PaymentSheet {
case .success(let paymentDetails):
if elementsSession.linkPassthroughModeEnabled {
// If passthrough mode, share payment details
linkAccount.sharePaymentDetails(id: paymentDetails.stripeID, cvc: paymentMethodParams.card?.cvc, allowRedisplay: paymentMethodParams.allowRedisplay) { result in
linkAccount.sharePaymentDetails(
id: paymentDetails.stripeID,
cvc: paymentMethodParams.card?.cvc,
allowRedisplay: paymentMethodParams.allowRedisplay,
expectedPaymentMethodType: paymentDetails.expectedPaymentMethodTypeForPassthroughMode
) { result in
switch result {
case .success(let paymentDetailsShareResponse):
confirmWithPaymentMethod(paymentDetailsShareResponse.paymentMethod, linkAccount, shouldSave)
Expand Down Expand Up @@ -514,7 +519,12 @@ extension PaymentSheet {

if elementsSession.linkPassthroughModeEnabled {
// allowRedisplay is nil since we are not saving a payment method.
linkAccount.sharePaymentDetails(id: paymentDetails.stripeID, cvc: paymentDetails.cvc, allowRedisplay: nil) { result in
linkAccount.sharePaymentDetails(
id: paymentDetails.stripeID,
cvc: paymentDetails.cvc,
allowRedisplay: nil,
expectedPaymentMethodType: paymentDetails.expectedPaymentMethodTypeForPassthroughMode
) { result in
switch result {
case .success(let paymentDetailsShareResponse):
confirmWithPaymentMethod(paymentDetailsShareResponse.paymentMethod, linkAccount, shouldSave)
Expand Down Expand Up @@ -733,3 +743,15 @@ private func isEqual(_ lhs: STPPaymentIntentShippingDetails?, _ rhs: STPPaymentI

return rhs == lhsConverted
}

private extension ConsumerPaymentDetails {

var expectedPaymentMethodTypeForPassthroughMode: String? {
switch type {
case .card, .unparsable:
return nil
case .bankAccount:
return "card"
}
}
}

0 comments on commit 6fadddf

Please sign in to comment.