naxam / braintree-android-binding Goto Github PK
View Code? Open in Web Editor NEWXamarin Binding Library - BrainTree Android SDK
License: Other
Xamarin Binding Library - BrainTree Android SDK
License: Other
Hi, I'm trying to implement Paypal payments in Xamarin Forms, I'm following this implementation guide: http://www.xamboy.com/2020/02/28/braintree-integration-in-xamarin-forms-part-3/
I have generated the token with the briantree PHP library, when I send the token to initialize it sends me the following error:
** Com.Braintreepayments.Api.Exceptions.InvalidArgumentException: ** 'Activity is null'
public async Task InitializeAsync (string clientToken)
{
try
{
initializeTcs = new TaskCompletionSource <bool> ();
mBraintreeFragment = BraintreeFragment.NewInstance (CrossCurrentActivity.Current.Activity, clientToken);
}
catch (InvalidArgumentException e)
{
initializeTcs.TrySetException (e);
}
return await initializeTcs.Task;
}
I have been trying to get Venmo to show up with the drop-in on Android with no luck.
I noticed in the Braintree SDK docs this:
// to offer Venmo
implementation 'com.braintreepayments.api:venmo:4.+'
Is this API part of the binding?
I have the following issue in our Android implementation for Credit Card payments:
When the user selects that they don't want their card to be remembered, it still is. This happens even though we explicitly configure it to be set by the value chosen in the app.
We suspect the card is being linked to the vault during tokenization. We are going to share the relevant code with you, of both, client and server side, hoping it will be helpful.
Client Side:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Com.Braintreepayments.Api;
using Com.Braintreepayments.Api.Exceptions;
using Com.Braintreepayments.Api.Interfaces;
using Com.Braintreepayments.Api.Models;
using Plugin.CurrentActivity;
using UISend.Services;
using Xamarin.Forms;
[assembly: Dependency(typeof(UISend.Droid.Services.AndroidPayService))]
namespace UISend.Droid.Services
{
public class AndroidPayService : Java.Lang.Object, IPayService, IBraintreeResponseListener, IBraintreeErrorListener,
IPaymentMethodNonceCreatedListener, IBraintreeCancelListener, IConfigurationListener
{
TaskCompletionSource<bool> initializeTcs;
TaskCompletionSource<string> payTcs;
BraintreeFragment mBraintreeFragment;
bool isReady = false;
bool venmoReady = false;
string nonce = null;
public bool CanPay { get => isReady; }
public bool VenmoReady { get => venmoReady; }
public event EventHandler<MyEventArgs> OnTokenizationSuccessful;
public event EventHandler<string> OnTokenizationError;
public void OnCancel(int requestCode)
{
payTcs.SetCanceled();
//mBraintreeFragment.RemoveListener(this);
}
public void OnResponse(Java.Lang.Object parameter)
{
if (parameter is Java.Lang.Boolean)
{
var res = parameter.JavaCast<Java.Lang.Boolean>();
isReady = res.BooleanValue();
initializeTcs?.TrySetResult(res.BooleanValue());
//DataCollector.CollectDeviceData(mBraintreeFragment, this);
}
else if (parameter is Java.Lang.String)
{
var res = parameter.JavaCast<Java.Lang.String>();
string deviceData = res.ToString();
string nonce2 = payTcs.Task.Result;
OnTokenizationSuccessful?.Invoke(this, new MyEventArgs(nonce2, deviceData));
nonce = null;
}
}
public void OnPaymentMethodNonceCreated(PaymentMethodNonce paymentMethodNonce)
{
// Send this nonce to your server
string nonce = paymentMethodNonce.Nonce;
//mBraintreeFragment.RemoveListener(this);
payTcs?.TrySetResult(nonce);
DataCollector.CollectDeviceData(mBraintreeFragment, this);
//OnTokenizationSuccessful?.Invoke(this, nonce);
}
public void OnError(Java.Lang.Exception error)
{
if (error is ErrorWithResponse)
{
ErrorWithResponse errorWithResponse = (ErrorWithResponse)error;
BraintreeError cardErrors = errorWithResponse.ErrorFor("creditCard");
if (cardErrors != null)
{
BraintreeError expirationMonthError = cardErrors.ErrorFor("expirationMonth");
if (expirationMonthError != null)
{
OnTokenizationError?.Invoke(this, expirationMonthError.Message);
payTcs?.TrySetException(new System.Exception(expirationMonthError.Message));
}
else
{
OnTokenizationError?.Invoke(this, cardErrors.Message);
payTcs?.TrySetException(new System.Exception(cardErrors.Message));
}
}
}
//mBraintreeFragment.RemoveListener(this);
}
public async Task<string> TokenizePayPal()
{
payTcs = new TaskCompletionSource<string>();
if (isReady)
{
//mBraintreeFragment.AddListener(this);
PayPal.AuthorizeAccount(mBraintreeFragment);
}
else
{
OnTokenizationError?.Invoke(this, "Platform is not ready to accept payments");
payTcs.TrySetException(new System.Exception("Platform is not ready to accept payments"));
}
return await payTcs.Task;
}
public async Task<string> TokenizeVenmo()
{
//mBraintreeFragment.AddListener(this);
payTcs = new TaskCompletionSource<string>();
if (venmoReady)
{
Venmo.AuthorizeAccount(mBraintreeFragment, false);
}
else
{
OnTokenizationError?.Invoke(this, "Platform is not ready to accept payments");
payTcs.TrySetException(new System.Exception("Platform is not ready to accept payments"));
}
return await payTcs.Task;
}
public async Task<string> TokenizeCard(string panNumber, string expirationMonth, string expirationYear , string cvv)
{
if (isReady)
{
payTcs = new TaskCompletionSource<string>();
CardBuilder cardBuilder = new CardBuilder()
.CardNumber(panNumber).JavaCast<CardBuilder>()
.ExpirationMonth(expirationMonth).JavaCast<CardBuilder>()
.ExpirationYear(expirationYear).JavaCast<CardBuilder>()
.Cvv(cvv).JavaCast<CardBuilder>();
mBraintreeFragment.AddListener(this);
Card.Tokenize(mBraintreeFragment, cardBuilder);
}
else
{
OnTokenizationError?.Invoke(this, "Platform is not ready to accept payments");
payTcs.TrySetException(new System.Exception("Platform is not ready to accept payments"));
}
return await payTcs.Task;
}
public async Task<bool> InitializeAsync(string clientToken)
{
try
{
initializeTcs = new TaskCompletionSource<bool>();
mBraintreeFragment = BraintreeFragment.NewInstance(CrossCurrentActivity.Current.Activity, clientToken);
GooglePayment.IsReadyToPay(mBraintreeFragment, this);
mBraintreeFragment.AddListener(this);
//isReady = true;
//initializeTcs.TrySetResult(isReady);
}
catch (InvalidArgumentException e)
{
initializeTcs.TrySetException(e);
}
return await initializeTcs.Task;
}
public void OnConfigurationFetched(Configuration p0)
{
venmoReady = p0.PayWithVenmo.IsEnabled(CrossCurrentActivity.Current.Activity);
}
protected override void Dispose(bool disposing)
{
if (disposing)
mBraintreeFragment.RemoveListener(this);
base.Dispose(disposing);
}
}
}
Server side:
Result<Transaction> result = null;
try
{
Trace.WriteLine("Attempting Braintree Payment...");
var braintreePayInfo = JsonConvert.DeserializeObject<Dictionary<string, string>>(paymentInfoJson);
bool rememberPayMethod = braintreePayInfo.ContainsKey("Remember") ?
bool.Parse(braintreePayInfo["Remember"]) : false;
var gateway = new BraintreeGateway
{
Environment = Braintree.Environment.SANDBOX,
MerchantId = BraintreeConfig.MerchantId,
PublicKey = BraintreeConfig.PublicKey,
PrivateKey = BraintreeConfig.PrivateKey
};
var request = new TransactionRequest
{
Amount = decimal.Parse(braintreePayInfo["Amount"]),
Options = new TransactionOptionsRequest
{
SubmitForSettlement = true,
}
};
if(braintreePayInfo.ContainsKey("Token") && !string.IsNullOrEmpty(braintreePayInfo["Token"]))
{
// Pago con tarjeta existente
request.PaymentMethodToken = braintreePayInfo["Token"];
}
else if (braintreePayInfo.ContainsKey("Nonce") && !string.IsNullOrEmpty(braintreePayInfo["Nonce"]))
{
// Pago con cuenta paypal/venmo o nueva tarjeta
request.PaymentMethodNonce = braintreePayInfo["Nonce"];
// Guardar tarjeta en el vault?
if(order.PaymentMethod == "-BTCARD")
{
Trace.WriteLine($"Assigning value {rememberPayMethod} to StoreInVaultOnSuccess...");
request.Options.StoreInVaultOnSuccess = rememberPayMethod;
Trace.WriteLine($"Value {request.Options.StoreInVaultOnSuccess} assigned.");
}
} else
{
throw new Exception("Payment method not found");
}
if (order.PaymentMethod == "--VENMO" || order.PaymentMethod == "-BTCARD" &&
braintreePayInfo.ContainsKey("DeviceData"))
{
request.DeviceData = braintreePayInfo["DeviceData"];
}
if(rememberPayMethod)
{
string braintreeId = order.UserId.ToString().ToUpper();
try
{
Customer customer = gateway.Customer.Find(braintreeId);
Trace.WriteLine("Adding existing Customer to transaction with ID " + customer.Id + "...");
request.CustomerId = customer.Id;
}
catch
{
Trace.WriteLine("Adding new Customer to transaction with ID " + braintreeId + "...");
request.Customer = new CustomerRequest { Id = braintreeId };
}
}
result = gateway.Transaction.Sale(request);
var resultJson = JsonConvert.SerializeObject(result);
//Se le responde al user
Clients.Caller.ProcessPayment(name, orderJson, resultJson);
} catch(Exception ex)
{
var key8 = providerLocks.GetOrAdd(order.ProviderId.ToString(), new object());
lock (key8)
{
try
{
OrderHelper.RollbackOrder(order);
}
finally
{
providerLocks.TryRemove(order.ProviderId.ToString(), out _);
}
}
Trace.WriteLine("Error during Braintree Payment: " + ex.Message);
ExceptionHelper.DisplayExceptionInfo(ex);
throw ex;
}
We are using Xamarin.Forms (4.7.0.1080) version and Naxam.Braintree.Droid (2.10.0.1)
I am using the Naxam.BraintreeDropIn.Droid library in my Xamarin.Android project and Google Pay option does not show up in the pop-up. I am using a client token that refers to an account with that option enabled. I would like to know if this is the way to add Google Pay to drop in, I have followed the Braintree's documentation but I'm not sure what is wrong. Thanks in advance
Here is the code:
DropInRequest dropInRequest = new DropInRequest()
.ClientToken(clientToken);
TransactionInfo transactionInfo = TransactionInfo.NewBuilder()
.SetTotalPrice("1.00")
.SetTotalPriceStatus(WalletConstants.TotalPriceStatusFinal)
.SetCurrencyCode("USD")
.Build();
GooglePaymentRequest googlePaymentRequest = new GooglePaymentRequest().InvokeTransactionInfo(transactionInfo);
dropInRequest.InvokeGooglePaymentRequest(googlePaymentRequest);
StartActivityForResult(dropInRequest.GetIntent(this), LOAD_PAYMENT_DATA_REQUEST_CODE);
I have Xamarin.GooglePlayServices.Wallet installed(for Google Play Services-Wallet 11.4.2)
I included the wallet enabled meta-data tag in my AndroidManifest.xml
I enabled the Google Pay option in my sandbox account
Hello,
I'm trying to integrate the 3D Secure client into our Xamarin app.
However, after installing the 3D Secure nuget and trying to use the included classes, they don't seem to have the setters generated on their properties, making them unusable. See the attached screenshots below.
Would it be possible to fix this? And what about the newest version of the Braintree SDKs, is it possible to generate bindings for them?
On Debug Mode I am able to complete the payment with my token from the Server where as on release mode this is the Log :
Platform Used : Xamarin Forms -> Android
[System.out] [okhttp]:check permission begin!
[System] ClassLoader referenced unknown path: system/framework/mediatek-cta.jar
[System.out] [okhttp] e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaUtils
[System.out] [OkHttp] sendRequest>>
[System.out] [OkHttp] sendRequest<<
[com.pastryworld] type=1400 audit(0.0:604914): avc: denied { read } for name="cache" dev="dm-0" ino=17 scontext=u:r:untrusted_app:s0:c239,c256,c512,c768 tcontext=u:object_r:cache_file:s0 tclass=lnk_file permissive=0
[com.pastryworld] type=1400 audit(0.0:604916): avc: denied { read } for name="cache" dev="dm-0" ino=17 scontext=u:r:untrusted_app:s0:c239,c256,c512,c768 tcontext=u:object_r:cache_file:s0 tclass=lnk_file permissive=0
[System.out] [okhttp]:check permission begin!
[System] ClassLoader referenced unknown path: system/framework/mediatek-cta.jar
[System.out] [okhttp] e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaUtils
[System.out] [okhttp]:check permission begin!
[System] ClassLoader referenced unknown path: system/framework/mediatek-cta.jar
[System.out] [okhttp] e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaUtils
[System.out] [socket]:check permission begin!
[System] ClassLoader referenced unknown path: system/framework/mediatek-cta.jar
[System.out] [socket] e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaUtils
[System.out] [socket]:check permission begin!
[System] ClassLoader referenced unknown path: system/framework/mediatek-cta.jar
[System.out] [socket] e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaUtils
[System.out] [OkHttp] sendRequest<<
[System.out] [OkHttp] sendRequest>>
[System.out] [OkHttp] sendRequest<<
[MagnesPostRequest] MagnesPostRequest returned PayPal-Debug-Id: 28b3d69a7e0ac
[System.out] [okhttp]:check permission begin!
[System] ClassLoader referenced unknown path: system/framework/mediatek-cta.jar
[System.out] [okhttp] e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaUtils
[System.out] [socket]:check permission begin!
[System] ClassLoader referenced unknown path: system/framework/mediatek-cta.jar
[System.out] [socket] e:java.lang.ClassNotFoundException: com.mediatek.cta.CtaUtils
[Surface] Surface::disconnect(this=0x71d20db000,api=1)
[Surface] Surface::disconnect(this=0x7206c80000,api=1)
[PhoneWindow] DecorView setVisiblity: visibility = 4, Parent = android.view.ViewRootImpl@3d4f8f6, this = DecorView@91df91c[MainActivity]
[PhoneWindow] DecorView setVisiblity: visibility = 4, Parent = android.view.ViewRootImpl@5ca6631, this = DecorView@6982a4a[DropInActivity]
[Surface] Surface::disconnect(this=0x71d2276000,api=1)
[GED] ged_boost_gpu_freq, level 100, eOrigin 2, final_idx 15, oppidx_max 15, oppidx_min 0
[AndroidRuntime] Shutting down VM
[AndroidRuntime] FATAL EXCEPTION: main
[AndroidRuntime] Process: com.pastryworld, PID: 5017
[AndroidRuntime] java.lang.RuntimeException: Unable to instantiate service com.braintreepayments.api.internal.AnalyticsIntentService: java.lang.InstantiationException: java.lang.Class<com.braintreepayments.api.internal.AnalyticsIntentService> cannot be instantiated
[AndroidRuntime] at android.app.ActivityThread.handleCreateService(ActivityThread.java:3968)
[AndroidRuntime] at android.app.ActivityThread.access$1600(ActivityThread.java:226)
[AndroidRuntime] at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1900)
[AndroidRuntime] at android.os.Handler.dispatchMessage(Handler.java:107)
[AndroidRuntime] at android.os.Looper.loop(Looper.java:214)
[AndroidRuntime] at android.app.ActivityThread.main(ActivityThread.java:7386)
[AndroidRuntime] at java.lang.reflect.Method.invoke(Native Method)
[AndroidRuntime] at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
[AndroidRuntime] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
[AndroidRuntime] Caused by: java.lang.InstantiationException: java.lang.Class<com.braintreepayments.api.internal.AnalyticsIntentService> cannot be instantiated
[AndroidRuntime] at java.lang.Class.newInstance(Native Method)
[AndroidRuntime] at android.app.AppComponentFactory.instantiateService(AppComponentFactory.java:129)
[AndroidRuntime] at androidx.core.app.CoreComponentFactory.instantiateService(Unknown Source:0)
[AndroidRuntime] at android.app.ActivityThread.handleCreateService(ActivityThread.java:3963)
[AndroidRuntime] ... 8 more
[MonoDroid] UNHANDLED EXCEPTION:
[MonoDroid] Java.Lang.RuntimeException: Unable to instantiate service com.braintreepayments.api.internal.AnalyticsIntentService: java.lang.InstantiationException: java.lang.Class<com.braintreepayments.api.internal.AnalyticsIntentService> cannot be instantiated ---> Java.Lang.ReflectiveOperationException: java.lang.Class<com.braintreepayments.api.internal.AnalyticsIntentService> cannot be instantiated
[MonoDroid] --- End of inner exception stack trace ---
[MonoDroid] --- End of managed Java.Lang.RuntimeException stack trace ---
[MonoDroid] java.lang.RuntimeException: Unable to instantiate service com.braintreepayments.api.internal.AnalyticsIntentService: java.lang.InstantiationException: java.lang.Class<com.braintreepayments.api.internal.AnalyticsIntentService> cannot be instantiated
[MonoDroid] at android.app.ActivityThread.handleCreateService(ActivityThread.java:3968)
[MonoDroid] at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1900)
[MonoDroid] at android.os.Handler.dispatchMessage(Handler.java:107)
[MonoDroid] at android.os.Looper.loop(Looper.java:214)
[MonoDroid] at android.app.ActivityThread.main(ActivityThread.java:7386)
[MonoDroid] at java.lang.reflect.Method.invoke(Native Method)
[MonoDroid] at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
[MonoDroid] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
[MonoDroid] Caused by: java.lang.InstantiationException: java.lang.Class<com.braintreepayments.api.internal.AnalyticsIntentService> cannot be instantiated
[MonoDroid] at java.lang.Class.newInstance(Native Method)
[MonoDroid] at android.app.AppComponentFactory.instantiateService(AppComponentFactory.java:129)
[MonoDroid] at androidx.core.app.CoreComponentFactory.instantiateService(Unknown Source:0)
[MonoDroid] at android.app.ActivityThread.handleCreateService(ActivityThread.java:3963)
[MonoDroid] ... 8 more
[MonoDroid]
[Process] Sending signal. PID: 5017 SIG: 9
It seems there is a missing dependency in the project which means we are unable to build any project using this package with the D8 compiler.
R8 : warning : Missing class: com.kount.api.DataCollector$CompletionHandler
Tried adding this to the -nowarn list in proguard.cfg, but that didn't help.
Hello, I have integrated your binding but I get this error in Android on build:
obj\Debug\android\src\mono\com\braintreepayments\api\interfaces\TokenizationParametersListenerImplementor.java(4,8): error : error: TokenizationParametersListenerImplementor is not abstract and does not override abstract method onResult(PaymentMethodTokenizationParameters,Collection) in TokenizationParametersListener
Thanks
Thanks for all your work on this! Very much appreciated.
The only Xamarin Forms guide I can find is the Rendy article: https://www.xamboy.com/2020/01/28/braintree-integration-in-xamarin-forms-part-1/
I can get his code to build using the old Naxam packages he used. When I update these to the current equivalents (at least I think they are the equivalents) a lot seems to have changed. I tried adding the packages from the sample code in this project (also could not get those samples to build).
Error CS0117 'Card' does not contain a definition for 'Tokenize'
Error CS0117 'GooglePayment' does not contain a definition for 'IsReadyToPay'
Error CS0117 'GooglePayment' does not contain a definition for 'RequestPayment'
Error CS1061 'GooglePaymentRequest' does not contain a definition for 'InvokeTransactionInfo'
Error CS1061 'GooglePaymentRequest' does not contain a definition for 'InvokeTransactionInfo'
Error CS0117 'PayPal' does not contain a definition for 'AuthorizeAccount'
Error CS0103 The name 'BraintreeFragment' does not exist in the current context
Error CS0246 The type or namespace name 'BraintreeFragment' could not be found
Should I just use the old packages? Is there a straightforward way to understand how these packages have evolved so that maybe I could update the Rendy code?
Thanks again!
Does this support Drop in UI? if no is there any way we can achieve this easy with this package?
Thank you for this library, and any help on the above would be greatly appreciated. Thanks!
I have an Android connection VPN code. After binding, if there is no connection status event, can you bind it for me?
I cannot find InvokeTransactionInfo in the payment request. But I cannot use GooglePay because TransactionInfo is missing.
Any ideas how to set them?
I would like to change the language from english to italian
Hi! It seems Microsoft added an upper bound of Xamarin.Google.Android.Material to 1.3.0 in Xamarin.Forms 5.0.2083 (latest as of 09/08/2021).
Because of this I am unable to update the Xamarin.Forms package (and subsequently Xamarin.Essentials) to the latest releases and also use this library.
Would it be possible to re-release this package with Xamarin.Google.Android.Material >= 1.3.0 instead fo 1.3.0.1?
Hey,
Do you have any plans upgrade bindings to Braintree v3 Android sdk?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.