Braintree now supports PayPal through their new v.zero API. This would be a great feature for the module.
I've updated the version of the Braintree PHP API in my local copy of the module and it doesn't seem to have broken anything, so that's a start. I plan on looking into it further in the coming days, but if anyone is working on this/has any ideas let me know!

| Comment | File | Size | Author |
|---|---|---|---|
| #39 | commerce_braintree-paypal_integration-2331119-39.patch | 26.62 KB | czigor |
| #34 | interdiff-29-33.txt | 4.38 KB | czigor |
| #34 | commerce_braintree-paypal_integration-2331119-33.patch | 28.7 KB | czigor |
| #15 | interdiff-2331119-14-15.txt | 20.02 KB | nikathone |
| #14 | commerce_braintree-paypal_integration-2331119-14.patch | 9.45 KB | sophie.sk |
Comments
Comment #1
nikathoneChanged version and I will be working on a patch soon.
Comment #2
rgpublicImplemented this. See https://github.com/rgpublic/commerce_braintree/tree/master
Comment #3
bojanz commented@rgpublic
Thanks! Please post a patch here.
Comment #4
user654 commented.
Comment #5
sophie.skAttached is a patch against the latest 8.x-1.x version. It's almost a direct copy of @rgpublic's work in comment #2 (with some small styling fixes etc).
Not sure if you need any tests? Doesn't look like this module has any tests at all .... :)
Comment #6
rgpublicAh, really great! I just couldnt find the time to move this forward or create an appropriate patch in recent months because I'm stuck in the midst of a bad overdue project. I already had somewhat of a bad conscience for not attending to this any sooner. Thank you so much @Sophie.SK for taking the time!! Well done! Thanks also for the styling fixes. I'm not really good at that. Shame on me :-/
I think the only thing I've added since then is in commerce_braintree.form.js in "Drupal.commerceBraintree.prototype.bootstrap" a line to remove the disabled attribute like so:
This make it possible to switch from PayPal back to credit card. Otherwise the continue button could obviously still be disabled.
Comment #7
sophie.skLet's try that again with a patch that doesn't have console logs in it 0:-)
Comment #8
sophie.skThanks for the heads up @rgpublic! I've added that line in now. Attaching an updated patch and an interdiff.
Comment #9
sophie.skWhoops. I hate JavaScript. Missed some self references... new patch and interdiff attached.
Comment #10
nikathoneTested the latest patch #9 and it's working. Is there a way to pre-fill or hide the customer profile fields when someone want to pay with paypal?
Comment #11
nikathoneAnother small patch adding a missing self reference.
Comment #12
nikathoneOops! uploaded wrong patch.
Comment #13
bojanz commentedThis will need to be reworked for #2815309: Migrate to JavaScript SDK 3.x, to use the PayPal Checkout integration option present in v3.
Planning to work on the issue in about 2 weeks, but don't let that stop you from rerolling.
Comment #14
sophie.skStarted work on a patch (attached). Mostly the JS file needed rewriting.
I've hit a wall, though. Braintree seems to think I no longer have an attached PayPal account, but I do :( Can't do any further testing but hopefully it's a good starting point for you Bojanz.
Comment #15
nikathoneHere is another patch which is working but I needed someone else to review it just to confirm that I am on the right path.
I did split the js stuff in 3 files:
js/commerce_braintree.js: main file calling HostedFields or Paypal when neededjs/hosted-fields.js: containDrupal.commerceBraintreeHostedFieldsconstructorjs/paypal.js: containDrupal.commerceBraintreePaypalconstructorAlso I did refactor the
commerce_braintree.libraries.jsto includecheckout.jsfrom https://github.com/paypal/paypal-checkout and separated paypal and braintree related js requirements into their own library. With this in place I was able to<?php $element['#attached']['library'][] = 'commerce_braintree/paypal'; ?>when building paypal form and<?php $element['#attached']['library'][] = 'commerce_braintree/hosted-fields'; ?>when building hosted fields form.Comment #16
nikathoneChange status to need review for now so that people can review.
Comment #17
nikathoneOpps dind change the status!:-)
Comment #18
sophie.skAlas, while I was able to apply the patch cleanly, it didn't work :(
When I chose "New paypal account" on checkout, the spinny Ajax loading wheel came up but then disappeared with no other changes. When I clicked on "Continue to review", I got:
Fatal error: Unsupported operand types in /var/www/html/docroot/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php on line 95No errors in console or in the log. Boo! Unfortunately I don't have the time right now to try and fix this problem.. but if it's working for you, it must be okay?! Wonder why it didn't work for me.
For the record, we apply the patch using Composer. Not sure if that makes a difference.
Comment #19
nikathone@Sophie.Sk did you link your Braintree sandbox account with your PayPal sandbox account? Since SDK v3 it is required for testing to work see https://developers.braintreepayments.com/guides/paypal/testing-go-live/p.... As for the error I really don't have any idea why it's there since I didn't experience the same problem.
Also, I am running d8.3.6, commerce latest dev as of yesterday and Commerce Braintree latest dev. Can you, please provide version a of d8 and commerce you are
running so that I can see if can reproduce the error. I will be working a little bit on this during the weekend.
Thanks
Comment #20
sophie.sk@nikathone Oh, I wonder if that's it. This is a client-created sandbox account (they don't want us using our own), so I'm not totally sure what they have and haven't set up. i'll get in touch and ask them to set that up, thanks for the pointers.
We're using 8.3.5 right now due to upgrade next week, and the stable release candidate of Commerce, so maybe a little bit behind you. I'll let you know if we have any luck with the PayPal linking.
Thanks for the speedy feedback.
Comment #21
mglamanChiming in that I ran into.
I have
Attached is why
Comment #22
mglamanThis is why. needs to be
Comment #23
nikathoneAfter the fix of "Can't switch gateways from Braintree" I was able to use some js from it to make PayPal work again. Right now I am not even sure if should keep the splitted js files approach but here is the patch attached.
Comment #24
czigor commentedThis adds only a few changes compared to #23, like a unique orderId for the sale() SDK call and some sanity checks.
Comment #25
nikathone@czigor can you please provide an interdiff. Thanks
Comment #26
mglamanWhy was it put to needs work? Especially if #24 only adds a few items to #23.
I'm attaching an interdiff for review.
Comment #27
mglamanI think I see some fixes in there. Specifically for triggering the form submit. However not fully explained.
We need to revert the changes to the `composer.json`
Trailing whitespace
Is this an issue due to sandbox and production order IDs conflicting? Maybe we should link to the documentation that explains this. Does the order ID show in the backend?
I don't think this is needed? If it wasn't successful it would have thrown an exception, correct?
Comment #28
mglamanFollow up on interdiff, again. The new patch in #24 ensures the form submit is triggered with `tokenized: true` and displays error messages.
Ensures that the submit marked as tokenized is sent.
Allows errors to render.
Comment #29
czigor commented1. Reverted the composer.json changes.
2. Fixed trailing whitespace.
3. The orderId issue appears when trying to do a paypal checkout and the payment fails for some reason. When we retry payment, paypal receives a sale() request with the same orderId and throws an exception. See https://developers.braintreepayments.com/reference/request/transaction/s... "On PayPal transactions, this field maps to the PayPal invoice number. PayPal invoice numbers must be unique in your PayPal business account." This is the case e.g. when the merchant paypal account is not configured to accept payments in a different currency and we still try to do so.
4. We definitely need a better error handling. Not all braintree error responses trigger throwing an exception.
An additional change in #24 compared to #23 was setting the paypal payment method's expiration to 0, since commerce 8.x-2.x-dev already supports non-expiring payment methods.
The "needs work" status has been set because we still need:
- Fix the "Continue to review" button on the order_information checkout page when braintree with paypal has been selected.
- Better error handling at least in createPayment() and refundPayment().
Comment #30
czigor commentedAdditionally, I'm not sure if it's ok for paypal to extend OnsitePaymentGatewayBase instead of OffsitePaymentGatewayBase.
Comment #31
czigor commentedDiscussed the onsite vs offsite issue with Bojan, came to the conclusion that this is an onsite gateway. The reason is that although we have an iframe paypal button, we play the nonce-token dance that is characteristic to onsite gateways.
Comment #32
mglamanSo the invoice number will be an order ID and a random timestamp :/? I wonder if there's a way to reconcile this. How can we reproduce this flow? Cancel payment after decline then try to use PayPal again?
Braintree has documented sandbox testing. Which areas should we add test coverage for? We have kernel tests covering some of them.
Comment #33
czigor commentedMaybe the easiest way to see that a unique orderId is required is trying to add an additional payment on the drupal Payments UI. (See screenshot, where I set the orderId in createPayment() back to $payment->getOrderId().)
Comment #34
czigor commentedTwo changes:
1. Added an if ($result->success) check after each payment gateway method to prevent creating/updating payment transactions in commerce when the remote transaction failed.
2. The "Continue to review" button is now hidden via css when the new braintree-paypal payment method is selected.
Comment #35
mglamanAll of this should be handled in
\Drupal\commerce_braintree\ErrorHelper::handleErrorsalready, which is called after a response is returned.Comment #36
czigor commentedFixed concerns in #35.
Comment #37
sophie.skThe patch is working for me now! There are a few changes from the previous SDK (can't select previously used accounts, it now asks me to login with a sandbox account), but I was able to proceed through checkout and buy the product.
A couple of UI/UX things though:
* The PayPal button should be under the address form
* The address form should have some kind of header to indicate that it is a billing address - it looks out of place right now
* There is no way of manually moving on to the next step, it's all automated redirects. I had a problem first time around where I filled in dummy info for the address, logged in with paypal, tried to change the address to something correct, but got redirected halfway through. A manual button would be good.
Attaching a screenshot to demonstrate.
Thanks for all your hard work on this :)
Comment #38
mglamanUpdated patch to address the button placement. No interdiff, added the following to
buildPayPalFormI agree. We should persist the button and force manual movement to next form. I vote we remove
commerce_braintree.paypal.form.css. We can easily trigger an event or introduce a namespaced callback to be overridden inonAuthorizeto allow auto-redirect.This is something core Drupal Commerce should probably provide whenever it's a PayPal payment method.
Putting needs work because:
Comment #39
czigor commentedRemoving auto-submission. We disable the main "Continue to review" button until the customer clicks the Paypal button and gets a nonce.
Comment #40
sophie.skI no longer get redirected automatically and I can select previously-selected PayPal accounts now. Brilliant :)
Marking as RTBC. There are still some improvements to be made in the UX but we have a lot of templating/design work to do for this client so may be able to feed back on what we've done.
Thanks for the hard work!
Comment #42
czigor commentedThanks everyone for working on this!