php7.x下 微信官方SDK无法使用 mcrypt_module_open()的解决方法,亲测有效

  • 时间:
  • 浏览:2918
  • 来源:吧啦熊

出现此问题的原因是php7以后弃用了mcrypt扩展

解决方案:

1.安装php mcrypt 扩展 (不推荐)

由于mcrypt扩展在php7.2 弃用,所以需要继续使用这个扩展的话需要自行编译mcrypt扩展,安装代码根据服务器环境自行百度。

2.修改sdk pkcs7Encoder.php 文件,修改代码如下

<?php

include_once "errorCode.php";

/**
 * PKCS7Encoder class
 *
 * 提供基于PKCS7算法的加解密接口.
 */
class PKCS7Encoder
{
	public static $block_size = 32;

	/**
	 * 对需要加密的明文进行填充补位
	 * @param $text 需要进行填充补位操作的明文
	 * @return 补齐明文字符串
	 */
	function encode($text)
	{
		$block_size = PKCS7Encoder::$block_size;
		$text_length = strlen($text);
		//计算需要填充的位数
		$amount_to_pad = PKCS7Encoder::$block_size - ($text_length % PKCS7Encoder::$block_size);
		if ($amount_to_pad == 0) {
			$amount_to_pad = PKCS7Encoder::block_size;
		}
		//获得补位所用的字符
		$pad_chr = chr($amount_to_pad);
		$tmp = "";
		for ($index = 0; $index < $amount_to_pad; $index++) {
			$tmp .= $pad_chr;
		}
		return $text . $tmp;
	}

	/**
	 * 对解密后的明文进行补位删除
	 * @param decrypted 解密后的明文
	 * @return 删除填充补位后的明文
	 */
	function decode($text)
	{

		$pad = ord(substr($text, -1));
		if ($pad < 1 || $pad > 32) {
			$pad = 0;
		}
		return substr($text, 0, (strlen($text) - $pad));
	}

}

/**
 * Prpcrypt class
 *
 * 提供接收和推送给公众平台消息的加解密接口.
 */
class Prpcrypt
{
	public $key;

	function Prpcrypt($k)
	{
		$this->key = base64_decode($k . "=");
	}

	/**
	 * 对明文进行加密
	 * @param string $text 需要加密的明文
	 * @return string 加密后的密文
	 */
	public function encrypt($text, $appid)
	{
		 try {
        //获得16位随机字符串,填充到明文之前
				$random = $this->getRandomStr();//"aaaabbbbccccdddd";
				$text = $random . pack("N", strlen($text)) . $text . $appid;
				$iv = substr($this->key, 0, 16);
				$pkc_encoder = new PKCS7Encoder;
				$text = $pkc_encoder->encode($text);
				$encrypted = openssl_encrypt($text,'AES-256-CBC',substr($this->key, 0, 32),OPENSSL_ZERO_PADDING,$iv);
				return array(ErrorCode::$OK, $encrypted);
			} catch (Exception $e) {
				//print $e;
				return array(ErrorCode::$EncryptAESError, null);
			}
 
		/*
		try {
			//获得16位随机字符串,填充到明文之前
			$random = $this->getRandomStr();
			$text = $random . pack("N", strlen($text)) . $text . $appid;
			// 网络字节序
			$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
			$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
			$iv = substr($this->key, 0, 16);
			//使用自定义的填充方式对明文进行补位填充
			$pkc_encoder = new PKCS7Encoder;
			$text = $pkc_encoder->encode($text);
			mcrypt_generic_init($module, $this->key, $iv);
			//加密
			$encrypted = mcrypt_generic($module, $text);
			mcrypt_generic_deinit($module);
			mcrypt_module_close($module);

			//print(base64_encode($encrypted));
			//使用BASE64对加密后的字符串进行编码
			return array(ErrorCode::$OK, base64_encode($encrypted));
		} catch (Exception $e) {
			//print $e;
			return array(ErrorCode::$EncryptAESError, null);
		}
		*/
	}

	/**
	 * 对密文进行解密
	 * @param string $encrypted 需要解密的密文
	 * @return string 解密得到的明文
	 */
	public function decrypt($encrypted, $appid)
	{
/*
		try {
			//使用BASE64对需要解密的字符串进行解码
			$ciphertext_dec = base64_decode($encrypted);
			$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
			$iv = substr($this->key, 0, 16);
			mcrypt_generic_init($module, $this->key, $iv);

			//解密
			$decrypted = mdecrypt_generic($module, $ciphertext_dec);
			mcrypt_generic_deinit($module);
			mcrypt_module_close($module);
		} catch (Exception $e) {
			return array(ErrorCode::$DecryptAESError, null);
		}


		try {
			//去除补位字符
			$pkc_encoder = new PKCS7Encoder;
			$result = $pkc_encoder->decode($decrypted);
			//去除16位随机字符串,网络字节序和AppId
			if (strlen($result) < 16)
				return "";
			$content = substr($result, 16, strlen($result));
			$len_list = unpack("N", substr($content, 0, 4));
			$xml_len = $len_list[1];
			$xml_content = substr($content, 4, $xml_len);
			$from_appid = substr($content, $xml_len + 4);
		} catch (Exception $e) {
			//print $e;
			return array(ErrorCode::$IllegalBuffer, null);
		}
		if ($from_appid != $appid)
			return array(ErrorCode::$ValidateAppidError, null);
		return array(0, $xml_content);
		
		*/
		
		 try {
        $iv = substr($this->key, 0, 16);          
        $decrypted = openssl_decrypt($encrypted,'AES-256-CBC',substr($this->key, 0, 32),OPENSSL_ZERO_PADDING,$iv);
			} catch (Exception $e) {
				return array(ErrorCode::$DecryptAESError, null);
			}
			try {
				//去除补位字符
				$pkc_encoder = new PKCS7Encoder;
				$result = $pkc_encoder->decode($decrypted);
				//去除16位随机字符串,网络字节序和AppId
				if (strlen($result) < 16)
					return "";
				$content = substr($result, 16, strlen($result));
				$len_list = unpack("N", substr($content, 0, 4));
				$xml_len = $len_list[1];
				$xml_content = substr($content, 4, $xml_len);
				$from_appid = substr($content, $xml_len + 4);
				if (!$appid)
					$appid = $from_appid;
				 
			} catch (Exception $e) {
				//print $e;
				return array(ErrorCode::$IllegalBuffer, null);
			}
			if ($from_appid != $appid)
				return array(ErrorCode::$ValidateAppidError, null);
		 
			return array(0, $xml_content, $from_appid); 
			 
 
	}


	/**
	 * 随机生成16位字符串
	 * @return string 生成的字符串
	 */
	function getRandomStr()
	{

		$str = "";
		$str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
		$max = strlen($str_pol) - 1;
		for ($i = 0; $i < 16; $i++) {
			$str .= $str_pol[mt_rand(0, $max)];
		}
		return $str;
	}

}

?>

猜你喜欢

【技术】state-machine状态机设计模式在项目中的应用

状态机的定义状态机是一种用来进行对象建模的工具,它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前”节点的转移函数

2020-05-21

CentOS 7.x下使用yum安装MySQL5.6

CentOS 7.x下使用yum安装MySQL5.6

2020-04-16

不破不立,继续前行

2019,不破不立,继续前行。

2018-12-24

【大结局】人不彪悍枉少年:青春略有遗憾才更值得回味

网剧《人不彪悍枉少年》迎来了大结局。和小编预想的不同,无论是杨夕、花彪还是黄澄澄和李渔,没有一对最终在一起。花彪因奶奶患上老年痴呆,选择在奶奶彻底记忆不清前带奶奶环游世界。杨夕

2018-12-21

清华学霸情侣马艺妮和宋思睿,被爆学术造假,死缠烂打约3p

清华大学的特将候选人,还参加过最强大脑的清华校花马艺妮和男友宋思睿,两人死缠烂打约北京大学妹子3p被曝光。马艺妮曾在《最强大脑》节目中,说自己遇到了现实版的“肖奈”。不久前,北

2018-12-05