cmbYouku_Api/app/service/util/CmbLifeUtils.php

253 lines
7.5 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\service\util;
use app\exception\LogicException;
use app\util\sm\cmb\Sm;
use app\util\StringUtil;
class CmbLifeUtils
{
protected static string $cmbLifeProtocolPrefix = 'cmblife://';
/**
* 生成掌上生活协议,带有签名
* @param string $funcName
* @param array $params
* @return string
* @throws LogicException
*/
public static function genProtocol(string $funcName, array $params): string
{
if (empty($funcName)) {
throw new LogicException('funcName不能为空');
}
// 处理公共参数
$cmbConfig = config('cmb');
$params['mid'] = $cmbConfig['mid'];
$params['aid'] = $cmbConfig['aid'];
$params['date'] = date('YmdHis');
$params['random'] = StringUtil::generateRandomString(32);// 随机数
$params['keyAlias'] = 'CO_PUB_KEY_SM2';
$params['cmbKeyAlias'] = 'SM2_CMBLIFE';
$signBody = self::assembleProtocol($funcName, $params, false); // 不需要urlEncode
$signKey = $cmbConfig['merchant_sm2_pri_key'];
$sign = Sm::sign($signKey, $signBody); //sm2
$params['sign'] = $sign;
return self::assembleProtocol($funcName, $params, true);
}
/***
* 拼接掌上生活协议
* @param String $funcName
* @param array $params
* @param bool $isUrlEncode
* @return string
*/
public static function assembleProtocol(string $funcName, array $params, bool $isUrlEncode)
{
$prefix = self::$cmbLifeProtocolPrefix . $funcName;
return self::getAssembleUrl($prefix, $params, $isUrlEncode);
}
/**
* 拼接签名字符串
* @param String $prefix
* @param String $queryString
* @return String
*/
public static function assembleUrl(string $prefix, string $queryString): string
{
if (empty($prefix)) {
return $queryString;
} else {
$char = strpos($prefix, '?') !== false ? '&' : '?';
return $prefix . $char . $queryString;
}
}
/**
* 拼接签名字符串
* @param string $prefix
* @param array $params
* @param bool $isUrlEncode
* @return String
*/
public static function getAssembleUrl(string $prefix, array $params, bool $isUrlEncode): string
{
return self::assembleUrl($prefix, self::mapToQueryString($params, true, $isUrlEncode));
}
/**
* 参数转为queryString
* @param array $params
* @param bool $isSort 是否排序
* @param bool $isUrlEncode 是否需要urlEncode
* @return string
*/
public static function mapToQueryString(array $params, bool $isSort, bool $isUrlEncode = true): string
{
if ($isSort) {
ksort($params);
}
$queryString = '';
foreach ($params as $key => $value) {
if (empty($value)) {
continue;
}
if ($isUrlEncode) {
$value = urlencode($value);
}
$queryString .= $key . '=' . $value . '&';
}
return trim($queryString, '&');
}
/**
* 加密
* @param string $encryptBody
* @param string $encryptKey 加密使用的key SM2公钥
* @return string
* @throws LogicException
*/
public static function encrypt(string $encryptBody, string $encryptKey)
{
if (empty($encryptBody)) {
throw new LogicException('报文不能为空');
}
if (empty($encryptKey)) {
throw new LogicException('公钥不能为空');
}
return Sm::sm4Encrypt($encryptKey, $encryptBody);
}
/**
* 解密
* @param string $encryptBody
* @param string $decryptKey 解密使用的Key SM2私钥
* @throws LogicException
*/
public static function decrypt(string $encryptBody, string $decryptKey)
{
if (empty($encryptBody)) {
throw new LogicException('报文不能为空!');
}
if (empty($decryptKey)) {
throw new LogicException('秘钥不能为空!');
}
return json_decode(Sm::sm4decrypt($decryptKey, $encryptBody), true);
}
/**
* 签名
* @param string $signBody
* @param string $signKey
* @param string $algorithmEnum
* @return string
* @throws LogicException
*/
public static function sign(string $signBody, string $signKey)
{
if (empty($signBody)) {
throw new LogicException('待签名数据不能为空!');
}
if (empty($signKey)) {
throw new LogicException('私钥不能为空');
}
return Sm::sign($signKey, $signBody);
}
/**
* 验签国密算法SM3WithSM2
* @param string $verifyBody
* @param string $sign
* @param string $verifyKey sm2公钥
* @return bool
* @throws LogicException
*/
public static function verify(string $verifyBody, string $sign, string $verifyKey)
{
if (empty($verifyBody)) {
throw new LogicException('验签数据不能为空');
}
if (empty($sign)) {
throw new LogicException("签名不能为空");
}
if (empty($verifyKey)) {
throw new LogicException("公钥不能为空");
}
return Sm::verify($verifyKey, $sign, $verifyBody);
}
/**
* 对请求签名
* @param string $funcName
* @param array $params
* @param string $signKey sm2 私钥
* @param string $signAlgorithm SM3WithSM2
* @return string
*/
public static function signForRequest(string $funcName, array $params, string $signKey, string $signAlgorithm = 'SM3WithSM2')
{
if (!empty($funcName) && !strpos($funcName, '.json')) {
$funcName = $funcName . '.json';
}
$assembleUrl = self::getAssembleUrl($funcName, $params, false);
return self::sign($assembleUrl, $signKey);
}
/**
* 对响应签名
* @param array $params
* @return string
* @throws LogicException
*/
public static function signForResponse(array $params)
{
if (empty($params)) {
throw new LogicException('参数不能为空');
}
$cmbConfig = config('cmb');
$signKey = $cmbConfig['merchant_sm2_pri_key'];
$assembleUrl = self::getAssembleUrl('', $params, false);
unset($params['sign']);
return self::sign($assembleUrl, $signKey);
}
/**
* 对响应验签
* @param array $data
* @return bool true 验签成功 false 验签失败
* @throws LogicException
*/
public static function verifyForResponse(array $data): bool
{
if (empty($data)) {
throw new LogicException('参数不能为空');
}
$cmbConfig = config('cmb');
$verifyKey = $cmbConfig['merchant_sm2_pub_key'];
$sign = $data['sign'];
unset($data['sign']);
return self::verify(self::getAssembleUrl('', $data, false), $sign, $verifyKey);
}
/**
* @param array $params
* @param string $verifyKey 验签所使用的Key为掌上生活公钥
* @return bool
* @throws LogicException
*/
public static function verifyForRequest(array $params, string $verifyKey): bool
{
if (empty($params)) {
throw new LogicException('参数不能为空');
}
$sign = $params['sign'];
unset($params['sign']);
$assembleUrl = self::getAssembleUrl('', $params, false);
return self::verify($assembleUrl, $sign, $verifyKey);
}
}