PayPal IPN validation fails when payer name contains non-ASCII characters (windows-1252 charset)
Affected Version
UNA platform, all versions containing `modules/boonex/payment/classes/BxPaymentProviderPayPal.php` with `bx_process_pass` in the IPN validation loop (current master as of May 2026).
Bug Report
PayPal IPN validation returns `INVALID` and the transaction is rejected (error code 6: `pp_err_wrong_transaction`) whenever any IPN field contains characters that are valid in the IPN's declared charset (typically `windows-1252`) but invalid in UTF-8. This is a **data-loss bug** -- PayPal collects the payment but the buyer's order is never fulfilled.
Root Cause
In `BxPaymentProviderPayPal.php`, the `_validateCheckout()` method constructs the IPN validation request at lines 181-187:
$sRequest = 'cmd=_notify-validate';
foreach($aData as $sKey => $sValue) {
if(in_array($sKey, array('cmd', 'r')))
continue;
$sRequest .= '&' . urlencode($sKey) . '=' . urlencode(bx_process_pass($sValue));
}
The call to `bx_process_pass($sValue)` applies `htmlspecialchars($value, ENT_COMPAT, 'UTF-8', false)` via `bx_process_output()`. When the IPN data contains a byte that is valid in windows-1252 but invalid in UTF-8 (e.g. byte `0xEE` which is `è` in windows-1252), `htmlspecialchars` returns an **empty string** for the entire field value.
The validation request then sends that field as empty to PayPal. PayPal compares the validation request against what it originally sent, finds a mismatch, and returns `INVALID`.
Steps to Reproduce
- A buyer with an accented character in their name or business name (e.g. `è`, `é`, `à` encoded in windows-1252) completes a PayPal payment on a UNA site using IPN processing mode
- PayPal sends the IPN with `charset=windows-1252` and `payer_business_name` containing the non-ASCII byte
- The `_validateCheckout` loop runs `bx_process_pass` on each IPN field
- `htmlspecialchars` with UTF-8 charset destroys the field value (returns empty string)
- The validation request sent back to PayPal does not match the original IPN
- PayPal returns `INVALID`
- The transaction is rejected with error code 6 (`pp_err_wrong_transaction`)
- The buyer is charged by PayPal but never receives their purchase
Observed Example
From a live site error log (April 2026):
- Payer: France-based buyer, business name contained `î` (byte `0xEE` in windows-1252)
- Payment: Completed via PayPal IPN
- PayPal IPN charset: `windows-1252`
- Validation request sent `payer_business_name=` (empty) to PayPal
- PayPal returned `INVALID`
- Result: Payment collected by PayPal, membership never activated for buyer
Transactions with ASCII-only payer names succeed because `htmlspecialchars` passes ASCII bytes through unchanged.
Fix
In `modules/boonex/payment/classes/BxPaymentProviderPayPal.php`, line 186, change:
$sRequest .= '&' . urlencode($sKey) . '=' . urlencode(bx_process_pass($sValue));
to:
$sRequest .= '&' . urlencode($sKey) . '=' . urlencode($sValue);
Rationale: PayPal's IPN validation protocol requires the validation request to be an exact echo of the received POST data. `bx_process_pass` is an XSS/output-filtering function that transforms data in ways that break this round-trip. The IPN data should be sent back to PayPal verbatim (URL-encoded only, no content transformation).
In addition to the charset bug, `bx_process_pass` would also cause validation failures if any IPN field contained HTML-special characters (`&`, `"`, `<`, `>`) since `htmlspecialchars` converts these to HTML entities.
Impact on Existing Sites
Any UNA site using PayPal with IPN processing mode is affected. The bug only triggers when payer data contains non-ASCII characters, which means it is intermittent and difficult to diagnose -- most transactions succeed, making the failures appear random.
When this bug fires, the site operator receives payment but the buyer does not get their purchase, leading to disputes and potential chargebacks.