* @date: 2019/3/15 */ namespace payment\wechat; class BaseWechat { const API_URL_PREFIX = 'https://api.mch.weixin.qq.com'; //接口API URL前缀 protected $signType = 'MD5'; //签名方式 protected $appId; //公众账号ID protected $mchId; //商户号 protected $key; //支付密钥 protected $sslcertPath; //证书路径 protected $sslkeyPath; //证书路径 protected $notifyUrl; //支付结果回调通知地址 protected function __construct($config) { isset($config['appid']) || json_error('缺少参数:appid'); isset($config['mch_id']) || json_error('缺少参数:mch_id'); isset($config['key']) || json_error('缺少参数:key'); $this->appId = $config['appid']; //支付、退款、企业付款使用 $this->mchId = $config['mch_id']; $this->key = $config['key']; } //生成签名 protected function makeSign($param) { //签名步骤一:按字典序排序数组参数 ksort($param); $param = array_filter($param); $string = $this->toUrlParams($param); //签名步骤二:在string后加入KEY $string = $string . "&key=" . $this->key; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; } //参数拼接 url: key=value&key=value protected function toUrlParams($param) { $string = ''; if ($param) { $array = []; foreach ($param as $key => $val) { $array[] = $key . '=' . $val; } $string = implode("&", $array); } return $string; } //输出xml字符 protected function dataToXml($param) { if (!is_array($param) || count($param) <= 0) return false; $xml = ""; foreach ($param as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . ""; } else { $xml .= "<" . $key . ">"; } } $xml .= ""; return $xml; } //将xml转为array protected function xmlToArray($xml) { if (!$xml) return false; //禁止引用外部xml实体 libxml_disable_entity_loader(true); $xmlString = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); $array = json_decode(json_encode($xmlString), true); return $array; } //产生一个指定长度的随机字符串 不长于32位 protected function getRandomString($length = 32) { $str = ''; $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; for ($i = 0; $i < $length; $i++) { $str .= $strPol[mt_rand(0, strlen($strPol) - 1)]; } return $str; } //post方式提交xml到对应的接口url protected function postXmlCurl($xml, $url, $useCert = false, $second = 30) { $ch = curl_init(); curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch, CURLOPT_URL, self::API_URL_PREFIX . $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); //生产环境设置为2 curl_setopt($ch, CURLOPT_HEADER, false); //设置header curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //要求结果为字符串且输出到屏幕上 if ($useCert) { //使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLCERT, $this->sslcertPath); curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLKEY, $this->sslkeyPath); } //post提交方式 curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); if (!($data = curl_exec($ch))) $data = ['errno' => curl_errno($ch), 'error' => curl_error($ch)] + curl_getinfo($ch); curl_close($ch); return $data; } //get方式提交 protected function getCurl($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 60); //设置cURL允许执行的最长秒数 curl_setopt($ch, CURLOPT_HEADER, false); //是否抓取头文件的信息,默认值为false,表示不显示响应头 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); if (!($data = curl_exec($ch))) $data = ['errno' => curl_errno($ch), 'error' => curl_error($ch)] + curl_getinfo($ch); //转码 $fromEncoding = 'auto'; //未知原编码,通过auto自动检测后,转换编码为utf-8 if (is_array($data)) { $data = json_decode(mb_convert_encoding(json_encode($data), 'UTF-8', $fromEncoding), true); } else { $data = json_decode(mb_convert_encoding($data, 'UTF-8', $fromEncoding), true); } curl_close($ch); return $data; } }