Unable to verify `$_SERVER["HTTP_HOST"]

There are several reports of this error in these forums, but none of the solutions are valid for me.

The problem: When new subscribers complete payment at PayPal they are redirected back to our site, but get this error:

ERROR: Unable to verify $_SERVER[“HTTP_HOST”].
Please contact Support for assistance.

If you are the site owner, please check the custom value in your Button Code. It MUST start with your domain name.

The subscription button code was copied from s2Member/PayPal Buttons/Resulting PayPal Code and integrated into an HTML form. The custom value mentioned in the error message is supplied:

<input type="hidden" name="custom" value="[our_site].com" />

In the gateway-core-rtn.log, incomplete information is logged with the original error. I’ve edited some info in square brackets:

LOG ENTRY: Wed Nov 14th, 2018 @ precisely 9:27 pm UTC
PHP v7.0.30 :: WordPress v4.9.8 :: s2Member v170722 :: s2Member Pro v170722
Memory 4.73 MB :: Real Memory 6.00 MB :: Peak Memory 4.85 MB :: Real Peak Memory 6.00 MB
[our_site].com/?s2member_paypal_return=1&amt=0.01&cc=USD&cm=[our_site].com&item_number=1&sig=[signature]&st=Completed&tx=[tx code]
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0
Array
(
    [transaction_subject] => [subject name]
    [payment_date] => 13:27:30 Nov 14, 2018 PST
    [txn_type] => subscr_payment
    [last_name] => [last name]
    [residence_country] => US
    [payment_gross] => 0.01
    [mc_currency] => USD
    [business] => [our PayPal email]
    [payment_type] => instant
    [protection_eligibility] => Ineligible
    [payer_status] => verified
    [payer_email] => [my email]
    [txn_id] => [17-digit ID]
    [receiver_email] => [our PayPal email]
    [first_name] => Len
    [payer_id] => [13-digit ID]
    [receiver_id] => [13-digit ID]
    [contact_phone] => [my phone]
    [payment_status] => Completed
    [payment_fee] => 0.01
    [mc_fee] => 0.01
    [mc_gross] => 0.01
    [charset] => windows-1252
    [s2member_log] => Array
        (
            [0] => Return-Data received on: Wed Nov 14, 2018 9:27:42 pm UTC
            [1] => s2Member POST vars verified through a POST back to PayPal.
            [2] => Unable to verify `$_SERVER["HTTP_HOST"]`. Please check the `custom` value in your Button Code. It MUST start with your domain name.
            [3] => Redirecting Customer to the Home Page (after displaying an error message).
        )

    [subscr_gateway] => paypal
)

However, while I am viewing the original error page I can reload the page (no changes) and the error will go away and the normal ‘Thank you! You’ve been updated to:’ page appears.

Back to the gateway-core-rtn.log after reload, it now has a complete entry:

LOG ENTRY: Thu Nov 15th, 2018 @ precisely 3:34 pm UTC
PHP v7.0.30 :: WordPress v4.9.8 :: s2Member v170722 :: s2Member Pro v170722
Memory 4.81 MB :: Real Memory 2.00 MB :: Peak Memory 4.88 MB :: Real Peak Memory 2.00 MB
[our_site].com/?s2member_paypal_return=1&amt=0.01&cc=USD&cm=[our_site].com&item_number=1&sig=[sig code]&st=Completed&tx=[tx code]
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0
Array
(
    [mc_gross] => 0.01
    [invoice] => [invoice number]~[my IP]
    [protection_eligibility] => Ineligible
    [payer_id] => [payer id]
    [payment_date] => 13:27:30 Nov 14, 2018 PST
    [payment_status] => Completed
    [charset] => windows-1252
    [first_name] => Len
    [option_selection1] => 31
    [option_selection2] => [my IP]
    [mc_fee] => 0.01
    [subscr_id] => [subscr ID]
    [custom] => [our site].com
    [payer_status] => verified
    [business] => [our PayPal email]
    [payer_email] => [my email]
    [option_name1] => Referencing Customer ID
    [option_name2] => Customer IP Address
    [contact_phone] => [my phone]
    [txn_id] => [tx ID]
    [payment_type] => instant
    [last_name] => [last name]
    [receiver_email] => [our PayPal email]
    [payment_fee] => 0.01
    [receiver_id] => [recvr ID]
    [txn_type] => subscr_payment
    [item_name] => One Pet Protected
    [mc_currency] => USD
    [item_number] => 1
    [residence_country] => US
    [transaction_subject] => [subject]
    [payment_gross] => 0.01
    [option_selection] => 31
    [option_name] => Referencing Customer ID
    [s2member_log] => Array
        (
            [0] => Return-Data received on: Thu Nov 15, 2018 3:34:28 pm UTC
            [1] => s2Member POST vars verified through a POST back to PayPal.
            [2] => s2Member originating domain ( `$_SERVER["HTTP_HOST"]` ) validated.
            [3] => s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ).
            [4] => s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ) w/ update vars.
            [5] => s2Member Level/Capabilities updated w/ advanced update routines.
            [6] => Transient Tracking Cookie set on ( `web_accept|subscr_signup|subscr_payment` ) w/ update vars.
            [7] => Redirecting Customer to the Login Page (after displaying a quick thank-you message). They need to log back in.
        )

    [subscr_gateway] => paypal
    [subscr_baid] => [subscr ID]
    [subscr_cid] => [subscr ID]
    [level] => 1
    [ccaps] => 
    [eotper] => 
    [ip] => [my IP]
)

Related notes:
– I’ve echoed the $_SERVER[‘HTTP_HOST’] value upon return to our site, it is valid (contains our domain name in the format ‘example.com’)

– All returns from PayPal fail with same error, it is not intermittent.

– Reloading the error page ALMOST always changes to success, but the error has been repeated if I try to reload too quickly after getting the original error.

– As shown by the dates in the log, I can paste the same URL that previously produced the error the next day and I get the success page on first try.

– The gateway-core-ipn.log file has this success line, even when the gateway-core-rtn.log has the ‘Unable to verify…’ error:

[2] => s2Member originating domain ($_SERVER[“HTTP_HOST”]) validated.

Any help will be appreciated.

1 Like

@Paws, have you figured out what your issue is? A site I support recently started experiencing this error after it having worked successfully for a year and a half. Since our custom value has not changed, I’m curious what may have started causing this error to occur

EDIT: also, if I copy the url in the browser, open a new tab, and paste the url of the redirect into the browser, the redirect works successfully. Why would the url not work on the first submit, but then work on the second?

Example url that was generated:
http://mysite.com/?s2member_paypal_return=1&s2member_paypal_return_tra=[secret_transaction]&amt=0.01&cc=USD&cm=mysite.com&item_number=1&sig=[secret_sig]&st=Completed&tx=[more_things]

EDIT: Another note, it does appear to be an issue with the transaction not being at a state that is ready to transfer all the info that s2 needs.

@Paul No, I have not figured out the cause, but discovered a work-around in our case. I replaced the HTML form code in my plugin with a do_shortcode() PHP call. The argument used was the shortcode generated by s2Member’s admin section with some PHP variable injections to make the shortcode correct in different situations. I cannot guarantee this is a complete solution because I haven’t finished thorough testing yet, but it does avoid the error on return from PayPal.

Maybe someone with knowledge of the inner workings of s2Member can chime in with a reason why shortcodes work consistently on first load, but submitting the info via form consistently fails on first load and succeeds on following loads, given at least a few seconds between page attempts.

Could it maybe be related to PHP version or using another chain here? Maybe an update to PHP broke some of the outdated s2member code here?

I’m using nginx with PHP 7.2 only in background via php-fpm (many many hosts nowadays use nginx). Oh and if it has something to do with pro-forms - well then good night. Best thing get rid of them anyhow. ThriveCart is now pretty much compatible with Optimizemember (an s2-member clone). Maybe someone should just write an extension for s2member to work with ThriveCart (plus extend the API so that you can extend EOT time via API to, which right now is not possible - as setting EOT via API overwrites leftover time - I do wonder if those using Gravity Forms based solutions or others are doing extensions right now - or if they simply do not allow people to extend EOT with time left).

Paws, I’m also having the same problem but don’t really understand your workaround. Any chance you could explain it a little more, or even post an example of what you did? Thanks!

For context, this is in my custom plug-in (a .php file) where the HTML form was originally used:

// construct and execute $payment_shortcode based on variables set above

$payment_shortcode = ‘[s2Member-Pro-PayPal-Form level="’.$level.’" ccaps="’.$ccaps.’" desc="’.$desc.’" ps="’.$ps.’" lc="’.$lc.’" cc="’.$cc.’" dg="’.$dg.’" ns="’.$ns.’" custom="’.$custom.’" ta="’.$ta.’" tp="’.$tp.’" tt="’.$tt.’" ra="’.$ra.’" rp="’.$rp.’" rt="’.$rt.’" rr="’.$rr.’" rrt="’.$rrt.’" rra="’.$rra.’" accept="’.$accept.’" accept_via_paypal="’.$accept_via_paypal.’" coupon="’.$coupon.’" accept_coupons="’.$accept_coupons.’" default_country_code="’.$default_country_code.’" captcha="’.$captcha.’" success="’.$success.’" /]’;

echo do_shortcode( $payment_shortcode );

Here is the init section that sets most of the variables used in the shortcode:

    // [s2Member-Pro-PayPal-Form ... /] shortcode variables
    $level = $s2member_access_level + 1;        // s2Member Access Level being purchased.
    $ccaps = "";                                // comma-delimited list of Custom Capabilities.
    $desc = "";                                 // purchase description truncated automatically to 60 characters by PayPal.
    $ps = "paypal";                             // PayPal checkout Page Style. Applies only to PayPal Express Checkout.
    $lc = "";                                   // optional 2 character Country/Locale Code (e.g., US).
    $cc = "USD";                                // 3 character Currency Code.
    $dg = "0";                                  // Digital Goods directive.
    $ns = "1";                                  // no_shipping. 0 = prompt for an address, but do not require one, 1 = do not prompt for a shipping address, 2 = prompt for an address, and require one.
    $custom="[my_site].com";               // must start with domain. Additional values can be piped in (ex: custom="[my_site].com|cv1|cv2|cv3|etc"
    $ta = "0";                                  // Trial Amount. Must be 0 when rt="L" or when rr="BN".
    $tp = "0";                                  // Trial Period. Must be 0 when rt="L" or when rr="BN".
    $tt = "D";                                  // Trial Term. D = Days, W = Weeks, M = Months, Y = Years.
    $ra = 0;                                    // Regular, Buy Now, and/or Recurring Amount. Can also be 0.00 to provide free access.
    $rp = "1";                                  // Regular Period. Must be >= 1 (ex: 1 Week, 2 Months, 1 Month, 3 Days).
    $rt = "Y";                                  // Regular Term.  = Days, W = Weeks, M = Months, Y = Years, L = Lifetime.
    $rr = "1";                                  // Recurring. 0 = non-recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; 1 = recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; BN = non-recurring "Buy Now" functionality, no Trial Period possible.
    $rrt = "";                                  // Recurring Times (i.e., a fixed number of installments). When unspecified, charges remain ongoing until cancelled, or payments fail. If set >= 1 the regular recurring charges will only continue for X billing cycles, depending on what you specify. This is only valid when rr="1" for recurring "Subscriptions".IMPORTANT NOTE: If you don't offer a trial period; i.e., the first charge occurs when a customer completes checkout, you should set this to the number of additional payments, and NOT to the total number. For instance, if I want to charge the customer a total of 3 times, and one of those charges occurs when they complete checkout, I set should this to rrt="2" for a grand total of three all together.
    $rra = "2";                                 // Reattempt billing when/if a recurring payment fails; exactly X number of times; and then automatically suspend the customer's account. By default, PayPal will retry a maximum of 2 times whenever rra="2"; after that, a Subscription would be terminated due to Max Failed Payments having been reached. The value of this attribute configures Max Failed Payments. A setting of rra="2" means that you allow a maximum of 2 failed payments. Setting rra="0" means that you allow an infinite number of failed payments.
    $accept = "paypal";                         // Accepted Billing Methods. A comma-delimited list of Billing Methods you want to accept. Due to a PayPal policy, you may NOT exclude PayPal from this list; s2Member won't let you.
    //$accept_via_paypal = "paypal,visa,mastercard,amex,discover,maestro,solo";              // Accepted Billing via PayPal. A comma-delimited list of Billing Methods you want to accept through PayPal, as opposed to processing them on-site. Due to a PayPal policy, you may NOT exclude PayPal from this list; s2Member won't let you. Tip: If you don't have a PayPal Pro account, you can set accept="paypal", or set accept_via_paypal="paypal,visa,mastercard,amex,discover,maestro,solo". With one or both of these configurations, all you need is a PayPal Standard account with Express Checkout (which is free).
    $accept_via_paypal = "paypal";              // https://www.s2member.com/forums/topic/sign-up-first-then-go-to-paypal/index.html#post-12606
    $default_country_code = "";                 // If you set this 2-character value, it will pre-configure the default Country that is selected in the drop-down menu for Checkout and Billing Update Forms. This MUST be an uppercase country code, following the ISO-3166-1 specification. If this is empty(i.e., "") s2Member will set the default country code automatically; based on currency.
    $captcha = "0";                             // When set, visitors must prove they're human by typing a captcha/security code. This service is powered by Google's reCaptcha system. 0 = do NOT require a captcha code on this Form; clean = DO require a captcha code on this Form; using the clean theme style. Possible themes: red, white, clean, and blackglass. Or, if you supplied reCaptcha v2 keys in your s2Member General Options (i.e., you are using reCaptcha v2), this must be light or dark.
    $success = "/[your-thank-you-page]/?user_full_name=%%user_full_name%%&subscr_id=%%subscr_id%%&item_name=%%item_name%%";        // Optional. Used to create a Custom Return URL on success.

You’ll need to edit some of the above variables according to the comment at the end of each line and maybe do some “if” statements to set some of these variables as your payment scheme requires, but this should get you started.

Hope this helps.

Thanks! Will try this out