/ fail

We tried AMIMOTO. You won‘t believe what happened next

UPDATE: The server we had with AMIMOTO was bespoke to this client, and the issue that caused the failure is not present on the standard installs as far as we were advised over email a few hours ago, about 8 hours after having written this.

Okay, clickbaity headline, but my God, this was something else.

I’m on site at a client currently. The task is to speed up the site as it’s getting sluggish. One of the approaches is to choose a better host as the current one rescinded the caching because cache-grind was too intensive.

So we’d trial a few different hosts to see whose solution is the best to work with. AMIMOTO was in the list as they seem to host some pretty big stuff over in Japan, AND they have EU servers (London and Frankfurt).

This morning one of the customer service people raised an alarm that people are being double charged, which is, for very obvious reasons, not ideal.

First question: where do the charges come from?

Cross referencing some of the triplicate charges (yup, TRIPLE charged), it turns out that the order numbers don’t match up with what’s in Stripe and what’s on the site. So that means that whatever is charging, isn’t the live site.

Stripe has additional metadata attached to the charges coming from WooCommerce, because the Stripe extension is awesome, so that was the first place to look. All said the URL of the live site, which didn’t make sense.

While I was logging into the different hosting environments where there were dev / test sites (including local), the keys were rotated to stop additional charges from happening.

That stopped the problem from getting worse. By that time we’ve ruled out everything, except AMIMOTO, where we had trouble logging in as their instructions were rather cryptic.

Ok, but why was this happening?

What was still a mystery is why the meta had the live site’s url in it. That meta depends on the result of a call to get_site_url(), which should have been AMIMOTO’s version of the site, which, by the way, was definitely not the live site’s URL.

To connect to the database to find the orders that were incorrectly created on the dev site, I had to look into the various config files to get the access details.

While doing that, I also discovered this wonderful little snippet:

$schema = isset($_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO']) ? $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] : 'https';
$server_name = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '<livesite URL>';
define('WP_SITEURL', "{$schema}://{$server_name}");
define('WP_HOME',    "{$schema}://{$server_name}");

Excuse my all caps, but

WHY ARE YOU FALLING BACK ON THE LIVE SITE’S URL!??!?!!?

We now also had the "why"

The "why"

  1. when you migrate a site, you obviously don’t want to charge customers on THAT server too, because that’s dumb
  2. the Subscriptions plugin is rather clever, as it saves an option derived from the site’s URL, which hosts do not change when migrating sites. Both the home and siteurl options are fair game though as they are needed to point at the actual URL so you can stay on the site
  3. if Subscriptions’s saved derived option AND the actual site URL do not match, Subscriptions will NOT charge orders because see #1
  4. Subscriptions’s comparison depends on the get_site_url function
  5. get_site_url will return whatever is saved in the options table under option name siteurl UNLESS there’s a PHP constant by the name of WP_SITEURL. In which case it’ll return that
  6. the code snippet above defines that constant based on the value of the $_SERVER superglobal’s value at the HTTP_HOST key, OR the default if that doesn’t exist
  7. PHP’s documentation says this about that option:

    ’HTTP_HOST’
    Contents of the Host: header from the current request, if there is one.

  8. note the "if there is one" part right there
  9. because Subscriptions’s scheduling works by kicking off WP’s own cron, there will not be any HTTP_HOST headers
  10. consequently when Subscrpitions checks whether it’s on the live site or a duplicate, get_site_url() will return the live site’s url, because wp-config.php declared it so in the absense of the alternative
  11. and therefore charges the customers
  12. and also saves the live site’s URL in the charge meta

For additional lulz

On the site that I could reach I only found 39 orders that shouldn’t have been charged. There were more. What probably happened is that AMIMOTO set up another site, which didn’t get set up properly, or some other reason we weren’t given access to. Thank god for rotating keys.

Sendgrid’s keys also had to be rotated for the same reason.

On top of everything, no one got back to me on their intercom chat service FOR 24 HOURS! I understand that they’re in Japan, and as such 8 hours ahead of me, but if there’s a pending message from 16 hours ago, AND one right now, I better damn get a response to at least one of them.

But no...

Conclusion

No other host I had any experience with has ever failed this spectacularly.

Photo by Kev Seto on Unsplash

Gabor Javorszky

I'm a freelance WordPress / WooCommerce developer focusing on Subscriptions and advanced functionality. Get in touch: @javorszky / gabor (at) javorszky (dot) co (dot) uk. Read more on the About page.

Read More