Skip to content

Commit 2698c53

Browse files
Add Crypto to PaymentSheet (#4480)
## Summary Add Crypto to PaymentSheet ## Motivation Add Crypto to PaymentSheet ## Testing Added tests + tested with Basic Non-Card Payment Examples project ## Changelog See diff --------- Co-authored-by: David Estes <[email protected]>
1 parent 657f9d4 commit 2698c53

20 files changed

+942
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## X.Y.Z 2025-XX-YY
22
### PaymentSheet
33
* [Fixed] Fixed an issue in Embedded Payment Element (private beta) where the row could be selected even though there's no valid payment option.
4+
* [Added] Support for Crypto in PaymentSheet
45

56
## 24.6.0 2025-02-18
67
* [Fixed] The SDK and example apps now compile in Xcode 16.2

Example/PaymentSheet Example/PaymentSheetUITest/EmbeddedUITest.swift

+4
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,10 @@ class EmbeddedUITests: PaymentSheetUITestCase {
667667
app.buttons["Present embedded payment element"].waitForExistenceAndTap()
668668

669669
app.buttons["Apple Pay"].waitForExistenceAndTap()
670+
app.swipeUp() // scroll to see the checkout button
671+
XCTAssertTrue(app.buttons["Checkout"].waitForExistence(timeout: 10))
670672
app.buttons["Checkout"].waitForExistenceAndTap()
673+
XCTAssertTrue(app.buttons["Checkout"].isEnabled)
671674
payWithApplePay()
672675
XCTAssertTrue(app.staticTexts["Success!"].waitForExistence(timeout: 10))
673676

@@ -1018,6 +1021,7 @@ class EmbeddedUITests: PaymentSheetUITestCase {
10181021
XCTAssertTrue(app.staticTexts["Add card"].waitForExistence(timeout: 10))
10191022
continueButton.tap()
10201023

1024+
app.swipeUp() // scroll to see the confirm button
10211025
let confirmButton = app.buttons["Confirm Payment"]
10221026
XCTAssertTrue(confirmButton.waitForExistenceAndTap())
10231027

Example/PaymentSheet Example/PaymentSheetUITest/PaymentSheetLPMUITest.swift

+19
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,25 @@ class PaymentSheetStandardLPMUIOneTests: PaymentSheetStandardLPMUICase {
207207
XCTAssertTrue(app.staticTexts["Success!"].waitForExistence(timeout: 15.0))
208208
}
209209

210+
func testCryptoPaymentMethod() throws {
211+
var settings = PaymentSheetTestPlaygroundSettings.defaultValues()
212+
settings.layout = .horizontal
213+
settings.currency = .usd
214+
settings.merchantCountryCode = .US
215+
loadPlayground(app, settings)
216+
app.buttons["Present PaymentSheet"].tap()
217+
218+
// Select Crypto
219+
tapPaymentMethod("Crypto")
220+
221+
// Pay
222+
app.buttons["Pay $50.99"].waitForExistenceAndTap()
223+
webviewAuthorizePaymentButton.waitForExistenceAndTap(timeout: 10)
224+
225+
// Close the webview, Crypto's test playground is out of scope
226+
app.otherElements["TopBrowserBar"].buttons["Close"].waitForExistenceAndTap(timeout: 10)
227+
}
228+
210229
func testZipPaymentMethod() throws {
211230
var settings = PaymentSheetTestPlaygroundSettings.defaultValues()
212231
settings.layout = .horizontal

StripePaymentSheet/StripePaymentSheet/Resources/JSON/form_specs.json

+28-1
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,34 @@
877877
}
878878
}
879879
}
880-
},
880+
},
881+
{
882+
"type": "crypto",
883+
"async": false,
884+
"selector_icon": {
885+
"light_theme_png": "https://js.stripe.com/v3/fingerprinted/img/payment-methods/[email protected]",
886+
"light_theme_svg": "https://js.stripe.com/v3/fingerprinted/img/payment-methods/icon-pm-crypto-15fd4ffeafd1b13e40688c8a06d79ba4.svg",
887+
"dark_theme_png": "https://js.stripe.com/v3/fingerprinted/img/payment-methods/[email protected]",
888+
"dark_theme_svg": "https://js.stripe.com/v3/fingerprinted/img/payment-methods/icon-pm-crypto_dark-f19bb5c5400c6cde94dd53b7f1ce7217.svg"
889+
},
890+
"fields": [
891+
],
892+
"next_action_spec": {
893+
"confirm_response_status_specs": {
894+
"requires_action": {
895+
"type": "redirect_to_url"
896+
}
897+
},
898+
"post_confirm_handling_pi_status_specs": {
899+
"succeeded": {
900+
"type": "finished"
901+
},
902+
"requires_action": {
903+
"type": "canceled"
904+
}
905+
}
906+
}
907+
},
881908
{
882909
"type": "mobilepay",
883910
"async": false,

StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ extension PaymentSheet {
317317
return []
318318
case .alipay, .EPS, .FPX, .giropay, .grabPay, .netBanking, .payPal, .przelewy24, .klarna,
319319
.bancontact, .iDEAL, .cashApp, .affirm, .zip, .revolutPay, .amazonPay, .alma,
320-
.mobilePay, .swish, .twint, .sunbit, .billie, .satispay:
320+
.mobilePay, .swish, .twint, .sunbit, .billie, .satispay, .crypto:
321321
return [.returnURL]
322322
case .USBankAccount:
323323
return [
@@ -330,7 +330,7 @@ extension PaymentSheet {
330330
return [.returnURL, .userSupportsDelayedPaymentMethods]
331331
case .afterpayClearpay:
332332
return [.returnURL, .shippingAddress]
333-
case .link, .unknown, .crypto:
333+
case .link, .unknown:
334334
return [.unsupported]
335335
@unknown default:
336336
return [.unsupported]

StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extension PaymentSheet {
3535
.sunbit,
3636
.billie,
3737
.satispay,
38+
.crypto,
3839
.boleto,
3940
.swish,
4041
.twint,
@@ -59,17 +60,17 @@ extension PaymentSheet {
5960
guard elementsSession.supportsLink else {
6061
return false
6162
}
62-
63+
6364
// Disable Link if the merchant is using card brand filtering
6465
guard configuration.cardBrandAcceptance == .all else {
6566
return false
6667
}
67-
68+
6869
// Disable Link if the merchant is using billing address collection API
6970
guard !configuration.requiresBillingDetailCollection() else {
7071
return false
7172
}
72-
73+
7374
return true
7475
}
7576

StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLPMConfirmFlowTests.swift

+10
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,16 @@ final class PaymentSheet_LPM_ConfirmFlowTests: STPNetworkStubbingTestCase {
227227
}
228228
}
229229

230+
func testCryptoConfirmFlows() async throws {
231+
try await _testConfirm(intentKinds: [.paymentIntent],
232+
currency: "USD",
233+
paymentMethodType: .crypto,
234+
merchantCountry: .US) { form in
235+
// Crypto has no input fields
236+
XCTAssertEqual(form.getAllUnwrappedSubElements().count, 1)
237+
}
238+
}
239+
230240
func testAlipayConfirmFlows() async throws {
231241
try await _testConfirm(intentKinds: [.paymentIntent],
232242
currency: "USD",

StripePayments/StripePaymentsTestUtils/Resources/recorded_network_traffic/PaymentSheetLPMConfirmFlowTests/testCryptoConfirmFlows/0000_post_create_payment_intent.tail

+18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

StripePayments/StripePaymentsTestUtils/Resources/recorded_network_traffic/PaymentSheetLPMConfirmFlowTests/testCryptoConfirmFlows/0001_get_v1_payment_intents_pi_3QNinPFY0qyl6XeW1C6tfI7s.tail

+65
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

StripePayments/StripePaymentsTestUtils/Resources/recorded_network_traffic/PaymentSheetLPMConfirmFlowTests/testCryptoConfirmFlows/0002_post_v1_payment_intents_pi_3QNinPFY0qyl6XeW1C6tfI7s_confirm.tail

+99
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)