braintree / braintree_php

Braintree PHP library
https://developer.paypal.com/braintree/docs/start/overview
MIT License
547 stars 224 forks source link

Insufficient info in Authorization errors #308

Closed Synchro closed 1 year ago

Synchro commented 2 years ago

General information

Issue description

I have an integration issue, but I could not track down the cause because the SDK omits critical information.

Sample code:

$gateway = new Braintree\Gateway(
      [
          'environment' => config('payments.braintree.env'),
          'merchantId'  => config('payments.braintree.merchant_id'),
          'publicKey'   => config('payments.braintree.public_key'),
          'privateKey'  => config('payments.braintree.private_key'),
      ]
);
$customer = $gateway->customer()->find('<valid customer ID>');
// dump($customer);
$params = [
    "amount" => "8.4",
    "customerId" => "<valid customer ID>",
    "merchantAccountId" => "<account ID>",
    "options" => ["submitForSettlement" => true]
  ];

try{
    $result = $gateway->transaction()->sale($params);
} catch (Exception $e) {
    dump($e);
}

I was certain that that the credentials were correct because the call to customer->find() worked, but this code throws an Authorization exception, which is exceedingly unhelpful:

Braintree\Exception\Authorization {#2363
  #message: ""
  #code: 0
  #file: "vendor/braintree/braintree_php/lib/Braintree/Util.php"
  #line: 63

Note that it contains no contextual information at all. So I spent a long time trying to figure out what was wrong, mainly (since this was Authorization, after all) looking at roles and permissions. Eventually it occurred to me that I should check all my inputs, so I called:

$merchantAccount = $gateway->merchantAccount()->find('<account ID>');

Which gave me the enormously helpful:

Braintree/Exception/NotFound with message 'merchant account with id not found'

So my request here is to have that exception thrown (or at least some contextual info to hint at the cause) in the exception thrown from sale. I'd say the right way to do this is to throw the existing Braintree\Exception\Authorization exception, but include the previous Braintree\Exception\NotFound exception inside it so you don't break BC, but can get at the extra info by calling getPrevious() on the outer exception – which is not currently being used.

TiaNex-Com commented 1 year ago

yes, after i deleted the default api keys in my sandbox account, i always got the "Braintree\Exception\Authentication" 401 error.

hollabaq86 commented 1 year ago

👋 @synchro, thanks for reaching out. I'm going to forward this feedback to the engineering team that determines authorization for review. This definitely presents a scenario where the SDK is surfacing an Authorization error but the underlying issue (merchant account) isn't getting surfaced in the error response for the SDK to surface.

Since the underlying root of the issue is on the API response and not the SDK itself, I'm going to go ahead and close this.