| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- <?php
- /**
- * Created by PhpStorm.
- * User: dingran
- * Date: 2020/3/2
- * Time: 下午2:19
- */
- namespace app\common\services;
- class ApiSign
- {
- /** 请求网关 */
- private $gateway = '';
- /** 密钥 */
- private $key;
- /** 平台标识码 */
- private $unique_code;
- /** 请求的参数 */
- private $parameters;
- private $sign_type = 'MD5';
- public function __construct()
- {
- }
- public function setGateWay($gateWay)
- {
- $this->gateway = $gateWay;
- return $this;
- }
- public function setKey($key)
- {
- $this->key = $key;
- return $this;
- }
- public function setUniqueCode($code)
- {
- $this->unique_code = $code;
- return $this;
- }
- public function setSignType($signType)
- {
- $this->sign_type = $signType;
- return $this;
- }
- /**
- *获取参数值
- */
- function getParameter($parameter) {
- return isset($this->parameters[$parameter]) ? $this->parameters[$parameter] : '';
- }
- /**
- *设置参数值
- */
- function setParameter($parameter, $parameterValue) {
- $this->parameters[$parameter] = $parameterValue;
- }
- /**
- * 一次性设置参数
- */
- function setReqParams($post, $filterField = null){
- if($filterField !== null){
- forEach($filterField as $k=>$v){
- unset($post[$v]);
- }
- }
- //判断是否存在空值,空值不提交
- forEach($post as $k=>$v){
- if(empty($v)){
- unset($post[$k]);
- }
- }
- $this->parameters = $post;
- }
- /**
- *获取所有请求的参数
- *@return array
- */
- function getAllParameters() {
- return $this->parameters;
- }
- /**
- * 取得链接
- */
- public function getLink()
- {
- $para = $this->buildRequestPara();
- return $this->gateway . '?' . $this->createLinkstringUrlencode($para);
- }
- /**
- * 验证消息是否是合法消息
- */
- public function verify()
- {
- // 判断请求是否为空
- if (empty($_POST) && empty($_GET)) {
- return false;
- }
- $data = $_POST ?: $_GET;
- $this->setReqParams($data);
- // 生成签名结果
- $is_sign = $this->getSignVeryfy($data['sign']);
- if ($is_sign) {
- return true;
- } else {
- return false;
- }
- }
- /**
- * 生成要请求的参数数组
- * @param $para_temp 请求前的参数数组
- * @return 要请求的参数数组
- */
- private function buildRequestPara()
- {
- //除去待签名参数数组中的空值和签名参数
- $para_filter = $this->paraFilter();
- //对待签名参数数组排序
- $para_sort = $this->argSort($para_filter);
- //生成签名结果
- $mysign = $this->buildRequestMysign($para_sort);
- //签名结果与签名方式加入请求提交参数组中
- $para_sort['sign'] = $mysign;
- return $para_sort;
- }
- /**
- * 生成签名
- * @param $para_temp 请求前的参数数组
- * @return 签名
- */
- public function generateSign()
- {
- //除去待签名参数数组中的空值和签名参数
- $para_filter = $this->paraFilter();
- //对待签名参数数组排序
- $para_sort = $this->argSort($para_filter);
- //生成签名结果
- $mysign = $this->buildRequestMysign($para_sort);
- return $mysign;
- }
- /**
- * 除去数组中的空值和签名参数
- * @param $para 签名参数组
- * return 去掉空值与签名参数后的新签名参数组
- */
- private function paraFilter()
- {
- $para_filter = array();
- foreach($this->parameters as $k => $v) {
- if("" != $v && "sign" != $k) {
- $para_filter[$k] = $v;
- }
- }
- return $para_filter;
- }
- /**
- * 对数组排序
- * @param $para 排序前的数组
- * return 排序后的数组
- */
- private function argSort($para)
- {
- ksort($para);
- reset($para);
- return $para;
- }
- /**
- * 生成签名结果
- * @param $para_sort 已排序要签名的数组
- * return 签名结果字符串
- */
- private function buildRequestMysign($para_sort)
- {
- //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
- $prestr = $this->createLinkstring($para_sort);
- $mysign = '';
- switch (strtoupper(trim($this->sign_type))) {
- case 'MD5':
- $mysign = $this->md5Sign($prestr, $this->key);
- break;
- default:
- $mysign = '';
- }
- return $mysign;
- }
- /**
- * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
- * @param $para 需要拼接的数组
- * return 拼接完成以后的字符串
- */
- private function createLinkstring($para)
- {
- $arg = '';
- foreach ($para as $key => $val) {
- $arg .= $key . '=' . urlencode($val) . '&';
- }
- //去掉最后一个&字符
- $arg = substr($arg, 0, count($arg) - 2);
- //如果存在转义字符,那么去掉转义
- if (get_magic_quotes_gpc()) {
- $arg = stripslashes($arg);
- }
- return $arg;
- }
- /**
- * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码
- * @param $para 需要拼接的数组
- * return 拼接完成以后的字符串
- */
- private function createLinkstringUrlencode($para)
- {
- $arg = '';
- foreach ($para as $key => $val) {
- $arg .= $key . '=' . urlencode($val) . '&';
- }
- //去掉最后一个&字符
- $arg = substr($arg, 0, count($arg) - 2);
- //如果存在转义字符,那么去掉转义
- if (get_magic_quotes_gpc()) {
- $arg = stripslashes($arg);
- }
- return $arg;
- }
- /**
- * 签名字符串
- * @param $prestr 需要签名的字符串
- * @param $key 私钥
- * return 签名结果
- */
- private function md5Sign($prestr, $key)
- {
- $prestr = $prestr . $key;
- return md5($prestr);
- }
- /**
- * 验证签名
- * @param $prestr 需要签名的字符串
- * @param $sign 签名结果
- * @param $key 私钥
- * return 签名结果
- */
- private function md5Verify($prestr, $sign, $key)
- {
- $prestr = $prestr . $key;
- $mysgin = md5($prestr);
- if ($mysgin == $sign) {
- return true;
- } else {
- return false;
- }
- }
- /**
- * 获取返回时的签名验证结果
- * @param $para_temp 通知返回来的参数数组
- * @param $sign 返回的签名结果
- * @return bool 签名验证结果
- */
- public function getSignVeryfy($sign)
- {
- //除去待签名参数数组中的空值和签名参数
- $para_filter = $this->paraFilter();
- //对待签名参数数组排序
- $para_sort = $this->argSort($para_filter);
- //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
- $prestr = $this->createLinkstring($para_sort);
- $is_sgin = false;
- $key = $this->unique_code ? $this->key.$this->unique_code : $this->key;
- switch (strtoupper(trim($this->sign_type))) {
- case 'MD5':
- $is_sgin = $this->md5Verify($prestr, $sign, $key);
- break;
- default:
- $is_sgin = false;
- }
- return $is_sgin;
- }
- }
|