游戏中需要对接银联渠道
对方需求是需要使用非对称加密算法
签名机制:
对于报文的签名处理机制如下:首先,对报文中出现签名域(sign)之外的所有数据元采用key=value的形式按照名称排序,然后以&作为连接符拼接成待签名串。其次,对待签名串使用SHA-1算法做摘要,再使用接入方的签名私钥证书中的私钥对摘要做签名操作(签名时算法选择SHA-1)。最后,对签名做Base64编码,将编码后的签名串放在签名(sign)表单域里和其他表单域一起通过HTTPPost的方式传输给佰付美服务端
代码如下:
第一步:得到验签签名
$signStr = $this->makeSig($orderReq,$onlineConfig['private_key']);
第二步:生成验签的方法
public function makeSig($params, $prikey)
{
$mk = self::makeSource($params);
DI()->logger->info("makeSig参数数组sha1结果为:" .__CLASS__ , $mk );
$my_sign = $this->sign($mk,$prikey);
DI()->logger->info("makeSig生成的签名为:" . __CLASS__, $my_sign);
return $my_sign;
}
第三步:将参数数组按键升序,然后按键值&key=value形式拼接
public function makeSource($params)
{
DI()->logger->info("makeSource参数数组为:" . __CLASS__, json_encode($params));
ksort($params);
$query_string = array();
foreach ($params as $key => $val )
{
array_push($query_string, $key . '=' . $val);
}
$query_string = join('&', $query_string);
DI()->logger->info("排序数组拼接字符串为:" . __CLASS__, $query_string);
return $query_string;
}
第四步:将算法签名做sha1信息摘要,然后做base64_encode加密。返回调用处。
/**RSA签名
* $data待签名数据
* $priKey商户私钥
* 签名用商户私钥
* 使用MD5摘要算法
* 最后的签名,需要用base64编码
* return Sign签名
*/
public function sign($data, $priKey) {
//$priKey = file_get_contents(__DIR__ . "/CHL20103/private_key.pem");
//转换为openssl密钥
$res = openssl_get_privatekey($priKey);
//调用openssl内置签名方法,生成签名$sign
openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA1);
//释放资源
openssl_free_key($res);
//base64编码
$sign = base64_encode($sign);
return $sign;
}
验签:收到渠道回调的时候需要验证对方的签名。
第一步:将对方的签名参数和生成签名的参数规则一样,转化成key=value形式
$mk = $this->makeSource($notifyData);
$bool = $this->verify($mk,$sign,$pubKey);
第二步:将mk,sign,公钥值传递给验签方法,获得验签后的bool值。
/**RSA验签
* $data待签名数据
* $sign需要验签的签名
* $pubKey银联公钥
* 验签用银联公钥,摘要算法为MD5
* return 验签是否通过 bool值
*/
function verify($data, $sign,$pubKey) {
//$pubKey = file_get_contents(__DIR__."\CHL20103\public_key.pem");
//转换为openssl格式密钥
$res = openssl_get_publickey($pubKey);
//调用openssl内置方法验签,返回bool值
$result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA1);
//释放资源
openssl_free_key($res);
//返回资源是否成功
return $result;
}