前阵子接触了php对接java服务端TCP接口,这是工作一年以来第一次对接,还是php对接java。使用的是socket。
技术点概括:
代码整理:
class BlowFish
{
public $xmlObj;
public $xmlMsg;
//获取bf算法的key
public function make_openssl_blowfish_key($key)
{
if ("$key" === '')
return $key;
$len = (16 + 2) * 4;
while (strlen($key) < $len) {
$key .= $key;
}
$key = substr($key, 0, $len);
return $key;
}
//字符填充
public function padding($str)
{
$blockSize = 8;
$len = strlen($str);
$paddingLen = intval(($len + $blockSize - 1) / $blockSize) * $blockSize - $len;
$padding = str_repeat("\0", $paddingLen);
$data = $str . $padding;
return $data;
}
//16进制转byte数组
public function hex2ByteArray($hexString)
{
$string = hex2bin($hexString);
return unpack('C*', $string);
}
//字节数组转字节流
public function byteToByteStr($bytes)
{
$str = '';
foreach ($bytes as $ch) {
$str .= chr($ch);
}
return $str;
}
//字节流转16进制
public function string2Hex($string)
{
return bin2hex($string);
}
//blowfish解密算法
public function openssl_blowfish_decrypt_hex($key, $hex)
{
$key = $this->make_openssl_blowfish_key($key);
$decrypted = openssl_decrypt(hex2bin($hex), 'BF-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
return rtrim($decrypted, "\0");
}
//头部报文长度计算,经过填充才计算消息长度
public function headConvertByte($str)
{
$new = $this->padding($str);
$len = mb_strlen($new, "UTF8");
$string = "00000000" . dechex($len);
//返回最后8个字符
$lastString = substr($string, mb_strlen($string, "UTF8") - 8);
$bindata = '';
//每两位转换为16进制
for ($i = mb_strlen($lastString, "UTF8"); $i >= 2; $i -= 2) {
$bindata .= strtoupper(substr($lastString, $i - 2, 2));
}
return $bindata;
}
//bf加密,如果位数不够,则填充
public function openssl_blowfish_encrypt_hex($key, $str)
{
$data = $this->padding($str);
$key = $this->make_openssl_blowfish_key($key);
$encrypted = openssl_encrypt($data, 'BF-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
return bin2hex($encrypted);
}
//设置XML对象,参数为string
public function setXml($string, $array)
{
$this->xmlObj = new SimpleXMLElement($string);
return $this->setXmlChild($this->xmlObj, $array);
}
//设置XML消息体,传入二维数组
public function setXmlChild($xmlObj, array $array = [])
{
if (!$this->xmlObj instanceof SimpleXMLElement) {
return false;
}
return $this->addChildXml($xmlObj, $array);
}
//支持无限嵌套的xml生成
public function addChildXml($xmlObj, $array)
{
foreach ($array as $k => $value) {
if (!is_array($value)) {
$xmlObj->addchild($k, $value);
} else if (is_array($value)) {
$this->setXmlChild($xmlObj->addchild($k), $value);
}
}
return $xmlObj;
}
//截断XML表格头部,生成socket消息体
public function delXmlTableHead()
{
if ($this->xmlObj->asXml() && is_string($this->xmlObj->asXml())) {
$start = strpos($this->xmlObj->asXml(), 'message');
return $this->xmlMsg = trim('<' . substr($this->xmlObj->asXml(), $start));
}
return false;
}
//处理并解密字节流
public function convertSocketByteToPlaintext($byteString, $apiSecret)
{
$hex = $this->string2Hex($byteString);
$hexNew = substr($hex, 8);
return $this->openssl_blowfish_decrypt_hex($apiSecret, $hexNew);
}
}