Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
On around line 400 of commerce_braintree.module
, in commerce_braintree_get_feedback()
function, it prepares a query string to check against a hashed value for security with Braintree. However, included in this query string is Drupal's native "q" parameter. This was causing a failure in communicating with Braintree API.
Here is the code I added to fix it. It's hack-y, but it works (and someone better than me can surely improve on it). The first 3 lines are in the original module; the next lines (beginning with the comments) are what I added.
if (isset($_SERVER['QUERY_STRING'])) {
$feedback = $_SERVER['QUERY_STRING'];
}
// Find the string length of $_GET parameter 'q' from the query string
// Then add 3 characters, for the 'q=' and the '&' character before 'http_status'
// Then remove that number of characters from the $feedback variable.
// The thing is, if we pass the whole query sring including 'q', it messes Braintree up.
$before_http_status = strlen($_GET['q']) + 3;
$feedback = substr($feedback, $before_http_status);
Great module! Seems to work so far with this fix.
Comment | File | Size | Author |
---|---|---|---|
#25 | commerce_braintree_hash_bug-1886950-25.patch | 658 bytes | rbayliss |
#22 | commerce_braintree-pantheon_fix-1886950-22.patch | 540 bytes | blazey |
#13 | hash_bug_fix-1886950-13.patch | 572 bytes | dankobiaka |
#9 | hash_bug-1886950-9.patch | 486 bytes | dankobiaka |
Comments
Comment #1
visuaLatte CreditAttribution: visuaLatte commentedFor more information, here is the query string that the module originally sent to the Braintree API:
q=checkout/34/payment/return/450i3jcn8CDjeockrLyAZLbSYHMVlUdN308whLfhqLQ&http_status=200&id=dyr5j598bcy3vkmd&kind=create_transaction
And here's the shorter version it expected (which the code above provides):
http_status=200&id=dyr5j598bcy3vkmd&kind=create_transaction
Comment #2
HazaTested with and without clean urls, with the latest version of the API.
With your code, I get a fatal error during the transaction.
Comment #3
HazaWhen you confirm the transaction, You call
Braintree_TransparentRedirect::confirm()
that use a validation function to parse the query string.The function look like (I remove some parts) (in TransparentRedirect.php) :
It first get the query without the hash, and then try to recompose the hash with the query it has and compare to the hash that is stored. Both need to be the same. This is used to avoid forged queries.
So that really look odd that you need to change the query. If the query string is altered, it should trigger an exception.
When you said "
", can you be more explicit ?
What kind of error message do you have ?
Thanks
Comment #4
visuaLatte CreditAttribution: visuaLatte commentedThe error I got was due to Drupal's 'q' parameter was being included in the full query string, which was being hashed. In comment #1, I show (from my PHP error log) what the query string being passed to the Braintree API looked like.
I think the reason for your error is because I didn't wrap my code in a conditional. Try this:
Maybe your setup and mine differed, and yours didn't include the 'q' parameter in the query string. When I left out the conditional statement, it removed 3 characters from the query string, resulting in the 'http_status' parameter being changed to 'p_status'.
Nathan
Comment #5
visuaLatte CreditAttribution: visuaLatte commentedThe error message I received was the error thrown by the code
throw new Braintree_Exception_ForgedQueryString();
.Drupal failed (took me to the error page) and in my Watchdog log, I saw that ForgedQueryString error.
Essentially, the Braintree API is looking for, and hashing, the shorter query string (beginning with 'http_status') from comment #1 above. Drupal, however, in my installation at least, was sending the full long query string, beginning with 'q'. If we check for the 'q' parameter, and, if found, strip it out, we should end up with the short query string.
When I did this, it worked.
Comment #6
HazaI also do have the q= in my query string (but not at the beginning).
On my env, it looks like that :
http_status=200&id=5mwtkkym65t8xrf4&kind=create_transaction&q=checkout/21/payment/return/Q92eohZ8u92bzv7tUKhVtgiEAYikz6qppJCtJ7n8nEI&hash=dc33763d0505be6d8b769ae536702641ff8ef617
And I did not get an exception from braintree with that.
Comment #7
visuaLatte CreditAttribution: visuaLatte commentedThat must be the difference.
Since some may have it first and some last, should we add some conditional code that makes sure the query string does not begin with 'q'?
Something like this, so it executes my code ONLY if the query string begins with 'q':
Comment #8
visuaLatte CreditAttribution: visuaLatte commentedUpdate: I updated to your latest committed version, and re-added the code from #7 above. It works for me. Let me know what works for your setup.
Comment #9
dankobiaka CreditAttribution: dankobiaka commentedI'm just using a regular expression to strip out the "q" parameter. It works.
Patch is attached.
Comment #10
HazaI still do have the same issue as before ...
Clean url disabled, using the patch from #9, on the payment step :
Braintree_Exception_ForgedQueryString: in Braintree_TransparentRedirect::parseAndValidateQueryString() (line 269 of /core/profiles/modules/contrib/commerce_braintree/braintree_php/lib/Braintree/TransparentRedirect.php).
And this is how looks my $feedback variable from commerce_braintree_get_feedback(), just before and after the preg_replace();
Comment #11
dankobiaka CreditAttribution: dankobiaka commentedCan we get this issue resolved? The before and after in #10 looks perfect to me.
Comment #12
HazaAs I said, I can't commit commit something that doesn't solve things for everyone. As said in #10, the patch from #9 leads me to a
Braintree_Exception_ForgedQueryString
Comment #13
dankobiaka CreditAttribution: dankobiaka commentedJust need to check for clean URLs before applying regular expression.
Patch attached.
I've confirmed this fix works with clean URLs enabled and disabled.
Comment #14
pcoucke CreditAttribution: pcoucke commentedThe patch from #13 fixed it for me.
Comment #14.0
pcoucke CreditAttribution: pcoucke commentedAdded sentence
Comment #15
jessepinho CreditAttribution: jessepinho commentedI would recommend stripping the 'q=' variable regardless of the clean_urls setting, since some servers (like Pantheon) still have the 'q=' part in $_SERVER['QUERY_STRING'] with clean URLs enabled.
My solution was the following:
However, Haza apparently had the q parameter in the middle of the query string, which this regex wouldn't fix. Any ideas what determines the order of the parameters in the query string?
Comment #16
Lukas von BlarerShould we get this committed? Is this issue present in 7.x-2.x as well? At least the patch still applies.
Comment #17
nyleve101 CreditAttribution: nyleve101 as a volunteer commentedIt would be great to get this committed. I had to use the patch to get it to work for 7.x-2.x.
Comment #18
HazaAs I already said, some people needs to use this patch to get the module working, while some other people gets an error if they use the patch.
At this point, we can't commit that like it is right now if it will introduce crashes for some peple.
Comment #19
Lukas von BlarerIn that case it needs work.
Comment #20
bmar777 CreditAttribution: bmar777 commentedthe patch did not work for me
here is the error log
Comment #21
JimSmith CreditAttribution: JimSmith as a volunteer and commented#13 worked for me. Thank you.
Comment #22
blazey CreditAttribution: blazey commentedHello,
Attached path solves the issue and is platform agnostic.
Comment #23
rjdjohnston CreditAttribution: rjdjohnston commented#13 worked for me. Thanks!
Comment #24
peezy CreditAttribution: peezy commented#22 works for me... thanks @blazey.
Comment #25
rbayliss CreditAttribution: rbayliss at Last Call Media commentedUnfortunately #22 requires that the q parameter is first, which might not always be the case. We can just use drupal_get_query_parameters(), which automatically strips out $_GET['q'].
Comment #26
arlingtonvoicellc CreditAttribution: arlingtonvoicellc commentedNone of the patches are working for me. I'm hitting same wall as OP. When you submit the credit card info using the drop-in UI, it immediately takes me to a page that says "Website encountered unexpected error."
Comment #27
arlingtonvoicellc CreditAttribution: arlingtonvoicellc commentedDisregard my last comment. I figured out the problem. I removed the "billing information" pane from the checkout form. Apparently you can't do that or it throws an error. Added it back and it works fine.
Comment #28
rbayliss CreditAttribution: rbayliss at Last Call Media commentedComment #29
mglaman#25 is the best approach and uses proper API methods to get query params, excluding Drupal's
q
. ReviewingComment #31
mglamanThanks, everyone.