import { VenmoReturnUrlCodeBlock } from '~/components/CodeBlockInstances/Venmo/VenmoReturnUrl.tsx' import { InstallationUrlCodeBlock } from '~/components/CodeBlockInstances/Venmo/InstallationUrl.tsx' import { HandleOpenUrlContextCodeBlock } from '~/components/CodeBlockInstances/Shared/HandleOpenUrlContext.tsx' import { HandleOpenUrlCodeBlock } from '~/components/CodeBlockInstances/Shared/HandleOpenUrl.tsx'
Client-Side Implementation
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
Custom integration
- 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.
build.gradle
:
- Kotlin
- Groovy
dependencies {
implementation("com.braintreepayments.api:venmo:5.2.0")
}
Invoking the Venmo flow
Create an instance of VenmoClient
and VenmoLauncher
. When ready to launch
the Venmo flow, make a call to venmoClient.createPaymentAuthRequest()
- see
startVenmoFlow()
for an example in the code sample below. Store the
VenmoPendingRequest
obtained from a call to venmoLauncher.launch()
to use
later. In your onResume()
method, call venmoLauncher.handleReturnToApp()
.
Once you have a successful result, complete the Venmo flow by calling
venmoClient.tokenize()
. See individual methods for detailed docs.
- Kotlin
class VenmoActivity : AppCompatActivity() {
private lateinit var venmoClient: VenmoClient
private lateinit var venmoLauncher: VenmoLauncher
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// must be initialized on onCreate()
venmoLauncher = VenmoLauncher()
// can be initialized outside onCreate() if desired
venmoClient = VenmoClient(
context = requireContext(),
authorization = "TOKENIZATION_KEY or CLIENT_TOKEN",
appLinkReturnUrl = Uri.parse("https://merchant-app.com") // Merchant App Link
)
}
// ONLY REQUIRED IF YOUR ACTIVITY LAUNCH MODE IS SINGLE_TOP
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleReturnToApp(intent)
}
// ALL OTHER ACTIVITY LAUNCH MODES
override fun onResume() {
super.onResume()
handleReturnToApp(intent)
}
private fun handleReturnToApp(intent: Intent) {
super.onResume()
val pendingRequest: VenmoPendingRequest.Started = pendingRequest
pendingRequest?.let {
val paymentAuthResult: VenmoPaymentAuthResult = venmoLauncher.handleReturnToApp(
pendingRequest = it,
intent = intent
)
if (paymentAuthResult is VenmoPaymentAuthResult.Success) {
// complete the venmo flow with the successful paymentAuthResult
completeVenmoFlow(paymentAuthResult)
} else {
// handle error - user did not complete Venmo flow
}
// clear pendingRequest
}
}
private fun startVenmoFlow(venmoRequest: VenmoRequest) {
venmoClient.createPaymentAuthRequest(
context = requireActivity(),
request = venmoRequest
) { paymentAuthRequest ->
if (paymentAuthRequest is VenmoPaymentAuthRequest.Failure) {
// handle paymentAuthRequest.error
} else if (paymentAuthRequest is VenmoPaymentAuthRequest.ReadyToLaunch) {
val pendingRequest: VenmoPendingRequest = venmoLauncher.launch(
activity = requireActivity(),
paymentAuthRequest = paymentAuthRequest
)
if (pendingRequest is VenmoPendingRequest.Started) {
// store pendingRequest for future use
} else if (pendingRequest is VenmoPendingRequest.Failure) {
// handle pendingRequest.error
}
}
}
}
private fun completeVenmoFlow(paymentAuthResult: VenmoPaymentAuthResult.Success) {
venmoClient.tokenize(paymentAuthResult) { result: VenmoResult ->
this.handleVenmoResult(result)
}
}
private fun handleVenmoResult(result: VenmoResult) {
when (result) {
is VenmoResult.Success -> {
/* handle result.nonce */
}
is VenmoResult.Failure -> {
/* handle result.error */
}
is VenmoResult.Cancel -> {
/* handle user canceled */
}
}
}
private fun storePendingRequest(request: VenmoPendingRequest.Started) {
// store pending request
}
private val pendingRequest: VenmoPendingRequest.Started
get() = {
/* fetch stored pending request */
}
private fun clearPendingRequest() {
// clear/reset pending request
}
}
Get the SDK
Add the following in your app-level build.gradle
:
- Kotlin
- Groovy
dependencies {
implementation("com.braintreepayments.api:venmo:4.49.1")
}
Invoking the Venmo flow
Create a BraintreeClient
with a
ClientTokenProvider
or Tokenization Key. Construct a VenmoClient
, add a VenmoListener
, and
call tokenizeVenmoAccount
to get a nonce that can be sent to your server:
- Java
- Kotlin
public class MyActivity extends AppCompatActivity implements VenmoListener {
private BraintreeClient braintreeClient;
private VenmoClient venmoClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
braintreeClient = new BraintreeClient(this, new ExampleClientTokenProvider());
venmoClient = new VenmoClient(this, braintreeClient);
dataCollector = new DataCollector(braintreeClient);
venmoClient.setListener(this);
}
private void tokenizeVenmoAccount() {
VenmoRequest request = new VenmoRequest(VenmoPaymentMethodUsage.MULTI_USE);
request.setProfileId("your-profile-id");
request.setShouldVault(false);
venmoClient.tokenizeVenmoAccount(this, request);
}
@Override
public void onVenmoSuccess(@NonNull VenmoAccountNonce venmoAccountNonce) {
dataCollector.collectDeviceData(MyActivity.this, (deviceData, dataCollectorError) -> {
// send venmoAccountNonce.getString() and deviceData to server
});
}
@Override
public void onVenmoFailure(@NonNull Exception error) {
if (error instanceof UserCanceledException) {
// user canceled
} else {
// handle error
}
}
}
Payment method usage
You must specify how you will use the customer's Venmo account by passing the `VenmoPaymentMethodUsage` into your `VenmoRequest`:
MULTI_USE
: Request authorization for future payments (vaulting allowed)SINGLE_USE
: Request authorization for a one-time payment (vaulting not allowed)
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 isSINGLE_USE
. -
Allowing customers to update their funding instrument on the Connected Businesses page in the
Venmo app when the
paymentMethodUsage
property isMULTI_USE
.
- A validation error will be returned if attempting to vault via PaymentMethod.create or Customer.create.
-
The transaction will be processed normally but the nonce will
not be vaulted if
store-in-vault
orstore-in-vault-on-success
is passed during transaction.sale.
- Kotlin
- Java
val request = VenmoRequest(VenmoPaymentMethodUsage.MULTI_USE)
venmoClient.tokenizeVenmoAccount(this, request)
App Links
For improved security we strongly recommend merchants to use the App 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.
- Kotlin
- Java
val request = VenmoRequest(VenmoPaymentMethodUsage.MULTI_USE) // or VenmoPaymentMethodUsage.SINGLE_USE
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.
profile_id
for each profile can be found
by logging into the Control Panel, clicking
the gear icon in the top right corner, selecting Processing from the drop-down
menu, scrolling to Venmo, and clicking the Options link.
Collect device data
You must collect information about the customer's device before creating each transaction.
- Kotlin
- Java
dataCollector.collectDeviceData(this@MyActivity) { deviceData, dataCollectorError ->
// send venmoAccountNonce.string and deviceData to server
}
deviceData
when creating the Venmo transaction from your
server.
Shipping and Billing Address collection
You can specify if you wish to receive a customer's Venmo shipping and billing address by passing the `collectCustomerBillingAddress` and `collectCustomerShippingAddress` flags into your `VenmoRequest`. When these flags are enabled, Venmo will collect the required addresses from the consumer and send them back in the reponse object.
- Java
- Kotlin
VenmoRequest request = new VenmoRequest(VenmoPaymentMethodUsage.MULTI_USE);
request.setProfileId("your-profile-id");
request.setCollectCustomerBillingAddress(true);
request.setCollectCustomerShippingAddress(true);
venmoClient.tokenizeVenmoAccount(this, request);
- Java
- Kotlin
@Override
public void onVenmoSuccess(@NonNull VenmoAccountNonce venmoAccountNonce) {
PostalAddress billingAddress = venmoAccountNonce.getBillingAddress();
String streetAddress = billingAddress.getStreetAddress();
String extendedAddress = billingAddress.getExtendedAddress();
String locality = billingAddress.getLocality();
String region = billingAddress.getRegion();
String postalCode = billingAddress.getPostalCode();
PostalAddress shippingAddress = venmoAccountNonce.getShippingAddress();
// ...
}
Amounts and Line Items
If you are making the tokenization call 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.
- Java
- Kotlin
VenmoRequest request = new VenmoRequest(VenmoPaymentMethodUsage.MULTI_USE);
request.setProfileId("your-profile-id");
request.setTotalAmount('10.00'); // Set optional amounts & line items
request.setSubTotalAmount('8.00');
request.setTaxAmount('1.00');
request.setDiscountAmount('1.00');
request.setShippingAmount('2.00');
ArrayList<venmolineitem> lineItems = new ArrayList<>();
lineItems.add(new VenmoLineItem(VenmoLineItem.KIND_DEBIT, "item-name", 2, "5.00"));
lineItems.add(new VenmoLineItem(VenmoLineItem.KIND_CREDIT, "credited-item-name", 1, "2.00"));
request.setLineItems(lineItems);
venmoClient.tokenizeVenmoAccount(this, request);
totalAmount
, which is required in the context of purchase. If the tokenize call is
for vaulting only, totalAmount
can be omitted.
- All amounts are expected to be in USD
- All amounts must be non-negative
- All amounts must be of string type and must contain either a whole number or a number with two decimal places
- Line-item should have four properties: item name, quantity, unit amount and type
-
Line-item
type
must be eitherCREDIT
orDEBIT
- The amounts for all individual line items present must add up to the total amount, or sub-total when present
- All individual amounts (discount, shipping, tax, sub-total) must add up to the total amount
VenmoLineItem
constructor takes in paramters in a specific order: type, name,
quantity, unitAmount