Venmo
Client-Side Implementation
Set up your iOS client
Get the SDK
CocoaPods
Include Braintree/Venmo
in your Podfile:
- Ruby
# Podfile
pod 'Braintree/Venmo'
Swift Package Manager
Include the BraintreeVenmo
framework.
Carthage
Include the BraintreeCore
and BraintreeVenmo
frameworks.
Allowlist Venmo URL scheme
You must add the following to the queries schemes allowlist in your app's info.plist
:
- XML
<key>LSApplicationQueriesSchemes</key>
<array>
<string>com.venmo.touch.v2</string>
</array>
Include the app display name
You must have a display name in your app's info.plist
to help Venmo identify your application:
- XML
<key>CFBundleDisplayName</key>
<string>Your App Name</string>
Setup for app context switching
To handle workflows that involve switching to another app or SFSafariViewController
for authentication, you must register a URL type and configure your app to handle return URLs.
Register a URL type
- In Xcode, click on your project in the Project Navigator and navigate to App Target > Info > URL Types
- Click [+] to add a new URL type
- Under URL Schemes, enter your app switch return URL scheme. This scheme must start with your app's Bundle ID and be dedicated to Braintree app switch returns. For example, if the app bundle ID is
com.your-company.your-app
, then your URL scheme could becom.your-company.your-app.payments
.
Testing the URL type
You can test out your new URL scheme by opening up a URL that starts with it (e.g. com.your-company.your-app.payments://test
) in Mobile Safari on your iOS Device or Simulator.
In addition, always test your app switching on a real device.
Set your return URL
In your AppDelegate's application:didFinishLaunchingWithOptions:
implementation, use setReturnURLScheme:
with the value you set above.
For example:
- Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BTAppContextSwitcher.setReturnURLScheme("com.your-company.your-app.payments")
return true
}
Handle app context switching
Then pass the payment authorization URL to Braintree for finalization.
If you’re using SwiftUI, you must add the onOpenURL(perform:)
modifier to your ContentView
, and then call BTAppContextSwitcher
's handleOpen(url:)
method.
- Swift
.onOpenURL { url in
BTAppContextSwitcher.sharedInstance.handleOpen(url)
}
If you're using UISceneDelegate
(introduced in iOS 13), call BTAppContextSwitcher
's handleOpenURL(context:)
's method from within the scene:openURLContexts
scene delegate method.
- Swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
URLContexts.forEach { context in
if context.url.scheme?.localizedCaseInsensitiveCompare("com.your-company.your-app.payments") == .orderedSame {
BTAppContextSwitcher.sharedInstance.handleOpenURL(context: context)
}
}
}
Otherwise, if you aren't using UISceneDelegate
, call BTAppContextSwitcher
's handleOpen(_:)
's method from within the application:openURL:options
app delegate method.
- Swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if url.scheme?.localizedCaseInsensitiveCompare("com.your-company.your-app.payments") == .orderedSame {
BTAppContextSwitcher.sharedInstance.handleOpen(url)
}
return false
}
Choose an integration method
You can set up your client-side either with our Drop-in UI or with a custom integration.
Drop-in integration
Our Drop-in UI is the fastest way to set up your client-side integration.
For full details, see Drop-in Setup and Integration.
Handling the response
To handle the successful Venmo payment, cast the BTPaymentMethodNonce
to a BTVenmoAccountNonce
to access the username
property that you receive from the BTDropInResult
.
Custom integration
Alternatively, you can add Venmo to your current custom integration. Keep in mind, for compliance purposes, we require you to present the customer with an order summary before and after purchase.
The pre-purchase summary should include:
- The items ordered
- The total order price
- An indication of Venmo as the payment method
The post-purchase summary can either be shown in the UI or sent via email. It should include:
- The items purchased
- The total purchase price
- The customer's name
- The customer's Venmo username
Failing to comply with these guidelines can lead to an interruption of your Venmo service.
- Swift
class ViewController: UIViewController {
var venmoClient : BTVenmoClient?
var venmoButton : UIButton?
var apiClient : BTAPIClient!
override func viewDidLoad() {
super.viewDidLoad()
self.apiClient = BTAPIClient(authorization: "<#CLIENT_AUTHORIZATION#>")
self.venmoClient = BTVenmoClient(apiClient: self.apiClient)
// setup venmoButton ....
self.venmoButton?.isHidden = !self.venmoClient?.isVenmoAppInstalled() ?? true
}
func tappedButton() {
let request = BTVenmoRequest(paymentMethodUsage: .multiUse)
request.vault = true // Set this and use a client token with a customer ID to vault
self.venmoClient?.tokenize(request) { (venmoAccount, error) in
guard let venmoAccount = venmoAccount else {
print("Error: (error)")
return
}
// You got a Venmo nonce!
print(venmoAccount.nonce)
}
}
}
Payment method usage
You must initialize a BTVenmoRequest
with a paymentMethodUsage
:
.multiUse
: Request authorization for future payments (vaulting allowed).singleUse
: Request authorization for a one-time payment (vaulting not allowed)
If neither of these options has been specified, vaulting will be supported, but customers will see a legacy UI flow in the Venmo app. We recommend using .multiUse
or .singleUse
for the best customer experience.
The payment method usage will affect the customer flow by:
- Displaying different phrases to the customer on the transaction consent page (e.g. "Authorize
Business Name
to pay with Venmo" vs. "AuthorizeBusiness Name
to pay with Venmo for future purchases" whereBusiness Name
is the business name submitted in the Venmo application form). - Not displaying a merchant connection on the Connected Businesses page in the Venmo app when the
paymentMethodUsage
property is.singleUse
. - Allowing customers to update their funding instrument on the Connected Businesses page in the Venmo app when the
paymentMethodUsage
property is.mulitiUse
.
- Swift
let request = BTVenmoRequest(paymentMethodUsage: .multiUse)
self.venmoClient.tokenize(with: request) { (nonce, error) in
// ...
}
Universal Links
For improved security we strongly recommend merchants to use the Universal Links flow when integrating with Venmo. Customers who do not have the Venmo app installed, or if the Venmo app cannot be presented, will fallback to a web based Venmo flow. In the web based Venmo fallback customers will be presented the flow in their default browser and returned to the merchant app securely.
- Swift
let request = BTVenmoRequest(paymentMethodUsage: .multiUse) // or .singleUse
request.fallbackToWeb = true
Multiple profiles
If you have a custom integration and have onboarded multiple apps for Venmo processing with a single Braintree gateway, you'll need to pass the profile_id
to specify which Venmo profile to present during the payment flow.
You'll also need to pass the profile_id
when creating the transaction on the server side.
- Swift
let request = BTVenmoRequest(paymentMethodUsage: .multiUse)
request.profileID = "YOUR_VENMO_PROFILE_ID"
self.venmoClient.tokenize(request) { (nonce, error) in
// ...
}
Collect device data
You must collect information about the customer's device before creating each transaction.
Get the SDK
CocoaPods
Include Braintree/DataCollector
in your Podfile:
- Ruby
# Podfile
pod 'Braintree/DataCollector'
Swift Package Manager
Include the DataCollector
framework.
Carthage
Include the DataCollector
and PPRiskMagnes
frameworks.
Collect device data
- Swift
let apiClient = BTAPIClient("<TOKENIZATION_KEY_OR_CLIENT_TOKEN>")
let dataCollector = BTDataCollector(apiClient: apiClient)
dataCollector.collectDeviceData { deviceData, error in
// handle response
}
You'll need to pass this deviceData
when creating the Venmo transaction from your server.
Shipping and Billing Address collection
Starting in Braintree iOS v6.4.0, you can specify if you wish to receive a customer's Venmo shipping and billing address by setting the collectCustomerBillingAddress
and collectCustomerShippingAddress
properties on BTVenmoRequest
.
When these flags are enabled, Venmo will collect the required addresses from the consumer and send them back in the response object.
- Swift
let request = BTVenmoRequest()
request.paymentMethodUsage = .multiUse
request.collectCustomerBillingAddress = true
request.collectCustomerShippingAddress = true
self.venmoDriver?.tokenizeVenmoAccount(with: request) { (nonce, error) in
// ...
}
Once the tokenization call is successful, you will receive the shipping and billing address in the response object.
- Swift
self.venmoDriver?.tokenizeVenmoAccount(with: request) { (nonce, error) in
// Display the billing address
let billingAddress = venmoAccount.billingAddress
print(billingAddress.streetAddress)
print(billingAddress.extendedAddress)
print(billingAddress.locality)
print(billingAddress.region)
print(billingAddress.postalCode)
// Display the shipping address
let shippingAddress = venmoAccount.shippingAddress
print(shippingAddress.streetAddress)
print(shippingAddress.extendedAddress)
print(shippingAddress.locality)
print(shippingAddress.region)
print(shippingAddress.postalCode)
}
Amounts and Line Items
Starting in Braintree iOS v6.4.0, if the create call is made in the context of a purchase, you will need to pass the total amount of the transaction which will be displayed to the user on the Venmo paysheet. Additionally, you can also pass other transaction details that you would like to render to the user such as subtotal, discount, taxes, shipping amount and line items.
- Swift
let request = BTVenmoRequest(paymentMethodUsage: .multiUse)
request.profileId = "your-profile-id"
request.totalAmount = "10.00"
// Set optional amounts & line items
request.subTotalAmount = "8.00"
request.taxAmount = "1.00"
request.discountAmount = "1.00"
request.shippingAmount = "2.00"
request.lineItems = [
BTVenmoLineItem(quantity: 1, unitAmount: "4.00", name: "item-1", kind: .debit),
BTVenmoLineItem(quantity: 1, unitAmount: "4.00", name: "item-2", kind: .debit)
]
self.venmoDriver?.tokenizeVenmoAccount(with: request) { (nonce, error) in
// ...
}
Next Page: Server-side →