So it turns out that we were doing everything right, but we were having issues with strings UTF-8 characters where the string was > 30 bytes as the API was rejecting this data. After lots of testing and back-and-forth with the service provider, we eventually established that the problem was actually at their end. They were telling us that they would accept 30 UTF-8 characters, but in actual fact it was 30-bytes of UTF-8 characters. The solution was actually to use the mb_strcut()
method: http://php.net/manual/en/function.mb-strcut.php
$params->Request->Description = mb_strcut($title, 0, 30, mb_detect_encoding($title));
This will trim to 30 bytes (as a simple substr()
would) but if it trims midway through a multi-byte character it will back-track to before the current character and only return full characters at <=30-bytes.
Since we deployed this solution we've had no further issues. The reason it looked like we were sending broken information was due to the logs being output badly (facepalm)