pikaju / flutter-braintree

Flutter plugin that wraps the native Braintree SDKs. Enables payments with credit cards, PayPal, Google Pay and more.
https://pub.dev/packages/flutter_braintree
MIT License
64 stars 115 forks source link

Please Add billingAddress Feature in tokenizeCreditCard #138

Closed BunnyBuddy closed 11 months ago

BunnyBuddy commented 11 months ago

Previously, we managed this functionality through the backend. However, this approach posed challenges in saving user information. Now, with the utilization of hoisted fields on our website, we've achieved a solution. However, the same hoisted fields feature isn't available in our mobile app due to the limitation of the JavaScript SDK. Interestingly, I've noticed a similar method in the native Android and iOS SDKs of Braintree. To address this issue, we need to implement a comparable mechanism in our mobile app. Currently, the package we're using doesn't offer a straightforward way to include billingAddress during tokenization.

I kindly request your assistance in adding this particular feature to the package. Your support in this matter would be greatly appreciated.

BunnyBuddy commented 11 months ago

Okay, I got a little in it and figured this out. If someone needs this, then you gotta do it manually. First of all make a copy of this package if you're using the package manually in your code.

/// FOR ANDROID

  1. Go to the file here (flutter-braintree/android/src/main/java/com/example/flutter_braintree/FlutterBraintreeCustom.java)
  2. Where you see,
    if (type.equals("tokenizeCreditCard")) {
                tokenizeCreditCard();
            } else if (type.equals("requestPaypalNonce")) {
                payPalClient = new PayPalClient(this, braintreeClient);
                payPalClient.setListener(this);
                requestPaypalNonce();
            } else {
                throw new Exception("Invalid request type: " + type);
            }

    just add another else if as,

else if (type.equals("tokenizeCreditCardWithBillingAddress")) {
                tokenizeCreditCardWithBillingAddress();
            }
  1. in the same file you'll find the method tokenizeCreditCard, add another method just like it, underneath or above however you like,
protected void tokenizeCreditCardWithBillingAddress() {
        Intent intent = getIntent();
        Card card = new Card();
        card.setExpirationMonth(intent.getStringExtra("expirationMonth"));
        card.setExpirationYear(intent.getStringExtra("expirationYear"));
        card.setCvv(intent.getStringExtra("cvv"));
        card.setCardholderName(intent.getStringExtra("cardholderName"));
        card.setNumber(intent.getStringExtra("cardNumber"));
        card.setPostalCode(intent.getStringExtra("postalCode"));
        card.setStreetAddress(intent.getStringExtra("streetAddress"));

        CardClient cardClient = new CardClient(braintreeClient);
        CardTokenizeCallback callback = (cardNonce, error) -> {
            if(cardNonce != null){
                onPaymentMethodNonceCreated(cardNonce);
            }
            if(error != null){
                onError(error);
            }
        };
        cardClient.tokenize(card, callback);
    }
  1. Now go back a directory and in this file (flutter-braintree/android/src/main/java/com/example/flutter_braintree/FlutterBraintreePlugin.java) find the if else in the onMethodCall and add the following else if,

    if (call.method.equals("tokenizeCreditCardWithBillingAddress")) {
      Intent intent = new Intent(activity, FlutterBraintreeCustom.class);
      intent.putExtra("type", "tokenizeCreditCard");
      intent.putExtra("authorization", (String) call.argument("authorization"));
      assert(call.argument("request") instanceof Map);
      Map request = (Map) call.argument("request");
      intent.putExtra("cardNumber", (String) request.get("cardNumber"));
      intent.putExtra("expirationMonth", (String) request.get("expirationMonth"));
      intent.putExtra("expirationYear", (String) request.get("expirationYear"));
      intent.putExtra("cvv", (String) request.get("cvv"));
      intent.putExtra("cardholderName", (String) request.get("cardholderName"));
      intent.putExtra("postalCode", (String) request.get("postalCode"));
      intent.putExtra("streetAddress", (String) request.get("streetAddress"));
    
      activity.startActivityForResult(intent, CUSTOM_ACTIVITY_REQUEST_CODE);
    }
  2. Its done for Android (just use Braintree.tokenizeCreditCardWithBillingAddress(...))

/// FOR IOS

  1. With IOS its easy, just add an else if in the file (flutter-braintree/ios/Classes/FlutterBraintreeCustomPlugin.swift).
  2. Find the condition where it says "else if call.method == "tokenizeCreditCard" {",

right where this condition ends, add another else if,

else if call.method == "tokenizeCreditCardWithBillingAddress" {
            let cardClient = BTCardClient(apiClient: client!)

            guard let cardRequestInfo = dict(for: "request", in: call) else {return}

            let card = BTCard()
            card.number = cardRequestInfo["cardNumber"] as? String
            card.expirationMonth = cardRequestInfo["expirationMonth"] as? String
            card.expirationYear = cardRequestInfo["expirationYear"] as? String
            card.cvv = cardRequestInfo["cvv"] as? String
            card.postalCode = cardRequestInfo["postalCode"] as? String
            card.streetAddress = cardRequestInfo["streetAddress"] as? String

            cardClient.tokenizeCard(card) { (nonce, error) in
                self.handleResult(nonce: nonce, error: error, flutterResult: result)
                self.isHandlingResult = false
            }
        }
  1. And its done

P.S. I don't know if this was the right way to do it or not but I just did what worked for me and it may or may not work for you.