Resolved my issues. After many hours I finally realised this was an error on my behalf.
The PHP ltrim function I was using to truncate the refresh_token from the initial callback response was dropping the first character off the refresh_token, in essence providing an invalid refresh_token. Not sure why it was doing this so used str_replace.and it's now working.
#Old code
$refreshToken = ltrim($refreshToken, "refresh_token:");
#New code
$refreshToken = str_replace("refresh_token:", "",$refreshToken);