com.drastikbydesign.stripe
com.drastikbydesign.stripe copied to clipboard
Wrong URL redirect when error + language prefix in URL
We are using the extension on a Drupal install, with language negotation by path prefix. So for example, a page in English will have a URL www.domain.org/civicrm/contribute/transact, and page in German will have a URL www.domain.org/de/civicrm/contribute/transact.
When a error occurs during the processing of a donation, the user is redirected to the URL where they came from, with a different query. The redirect URL is computed in CRM_Core_Payment_Stripe#doDirectPayment
, by giving the path and query to CRM_Utils_System::url()
. I am not sure why it is done that way rather than just appending the parameters to the entry URL, but the problem is that the url
function prepends the language prefix again, and so the user is redirected to e.g. www.domain.org/de/de/civicrm/contribute/transact.
The solutions I can see to this are:
- Don't call the
url
function, just append the parameters to the query - If above is not possible, instead of:
$parsed_url = parse_url($params['entryURL']);
do:
$entryURL = CRM_Utils_System::languageNegotiationURL($params['entryURL'], FALSE, TRUE);
$parsed_url = parse_url($entryURL);
I have tested the second solution, but I don't know enough about other CMS and their language negotiation to be sure that it works in all use cases.
@rthouvenin, you made the change here: https://github.com/drastik/com.drastikbydesign.stripe/blob/4.7-dev/CRM/Core/Payment/Stripe.php#L353:L359
changing from this:
...
else {
$qfKey = $params['qfKey'];
$parsed_url = parse_url($params['entryURL']);
$url_path = substr($parsed_url['path'], 1);
$params['stripe_error_url'] = $error_url = CRM_Utils_System::url($url_path,
$parsed_url['query'] . "&_qf_Main_display=1&qfKey={$qfKey}", FALSE, NULL, FALSE);
}
...
to this:
...
else {
$qfKey = $params['qfKey'];
$entryURL = CRM_Utils_System::languageNegotiationURL($params['entryURL'], FALSE, TRUE);
$parsed_url = parse_url($entryURL);
$url_path = substr($parsed_url['path'], 1);
$params['stripe_error_url'] = $error_url = CRM_Utils_System::url($url_path,
$parsed_url['query'] . "&_qf_Main_display=1&qfKey={$qfKey}", FALSE, NULL, FALSE);
}
...
@DaveBagler yes exactly
This issue also occurs for environments with path-element in their base-url: https://example.com/mycivicrm/
My approach was to replace:
$parsed_url = parse_url($params['entryURL']); $url_path = substr($parsed_url['path'], 1);
with
$url_path = CRM_Utils_System::currentPath();
This also works with language-switches in the url.
I would like to clarify my point:
I think the logic of DaveBaglers solution is still not consistent. parse_url($params['entryURL'])
will always give the whole path of the URL and strip only the domain. While CRM_Utils_System::url($url_path, ...);
will use CIVICRM_UF_BASEURL and add the $url_path. But CIVICRM_UF_BASEURL might already consists of a domain plus additional path-element.
In the first place parsing the entryURL we use a generic logic, while in the second place composing the error-url we use a CiviCRM-logic. It might be more stable to use CiviCRM-logic in both cases. Therefore I suggest using CRM_Utils_System::currentPath();
to get the $url_path.
@thomst, yeah I think it would be good to use CiviCRM's API, but in the meantime, @rthouvenin's solution works for my clients.