secret = $config['secret']; $class->appid = $config['appid']; $class->mch_id = isset($config['mch_id']) ? $config['mch_id'] : ""; $class->mch_key = isset($config['mch_key']) ? $config['mch_key'] : ""; $class->notify_url = isset($config['notify_url']) ? $config['notify_url'] : ""; $class->trade_type = isset($config['trade_type']) ? $config['trade_type'] : "JSAPI"; $class->key_pem = isset($config['key_pem']) ? $config['key_pem'] : ""; $class->cert_pem = isset($config['cert_pem']) ? $config['cert_pem'] : ""; return $class; } public function create_nonce_str($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str = ""; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } public function getParam() { return $this->orderParam; } public function orderH5Param() { return $this->orderH5Param; } public function getNotifyOrder() { $xml = file_get_contents("php://input"); return $this->xmlToArray($xml); } /** * 设置订单号 金额 描述 * @param string $rder_no 平台订单号 * @param int $money 订单金额 * @param string $title 描述 * @param string $openid 描述 * */ public function set($out_trade_no, $total_fee, $title, $openid = '') { $order['appid'] = $this->appid; $order['mch_id'] = $this->mch_id; $order['trade_type'] = $this->trade_type; $order['nonce_str'] = $this->create_nonce_str(); $order['body'] = $title; $order['out_trade_no'] = $out_trade_no; $order['total_fee'] = $total_fee; $order['notify_url'] = $this->notify_url; if ($this->trade_type == "JSAPI") { $order['openid'] = $openid; //设置用户openid } $order['spbill_create_ip'] = $_SERVER['REMOTE_ADDR']; $order['sign'] = $this->sign($order); $data = $this->arrayToXml($order); $xml_data = $this->curl_post($this->payUrl, $data); $prepay_id = $this->xmlToArray($xml_data); if ($this->trade_type == "MWEB") { $this->orderH5Param = $prepay_id; } else { $this->orderParam = array( 'appId' => $this->appid, //小程序ID 'timeStamp' => '' . time() . '', //时间戳 'nonceStr' => $this->create_nonce_str(), //随机串 'package' => 'prepay_id=' . $prepay_id['prepay_id'], //数据包 'signType' => 'MD5', //签名方式 ); $this->orderParam['paySign'] = $this->sign($this->orderParam); } return $this; } public function get_client_ip() { $cip = "unknown"; if ($_SERVER['REMOTE_ADDR']) { $cip = $_SERVER['REMOTE_ADDR']; } else if (getenv("REMOTE_ADDR")) { $cip = getenv("REMOTE_ADDR"); } return $cip; } /** * 作用:将xml转为array */ public function xmlToArray($xml) { //将XML转为array $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $array_data; } /** * @param array $map * @return string */ public function sign(array $map) { foreach ($map as $k => $v) { $Parameters[$k] = $v; } //签名步骤一:按字典序排序参数 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //签名步骤二:在string后加入KEY $String = $String . "&key=" . $this->mch_key; //签名步骤三:MD5加密 $String = md5($String); //签名步骤四:所有字符转为大写 $result_ = strtoupper($String); return $result_; } /** * 作用:格式化参数,签名过程需要使用 */ public function formatBizQueryParaMap($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if ($urlencode) { $v = urlencode($v); } //$buff .= strtolower($k) . "=" . $v . "&"; $buff .= $k . "=" . $v . "&"; } $reqPar = ''; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff) - 1); } return $reqPar; } /** * 作用:array转xml */ public function arrayToXml($arr) { $xml = ""; foreach ($arr as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . ""; } else { $xml .= "<" . $key . ">"; } } $xml .= ""; return $xml; } /** * 获取token */ public function getToken() { $url = $this->tokenUrl . $this->appid . "&secret=" . $this->secret; return json_decode($this->curl_get($url), true); } /** * 获取openid * @param string $code * @return array 成功返回数组 失败为空 */ public function getOpenid($code) { $url = $this->codedUrl . "appid=" . $this->appid . "&secret=" . $this->secret . "&js_code=" . $code . "&grant_type=authorization_code"; return json_decode($this->curl_get($url), true); } /** * 获取微信app openid * * @param [type] $code * @return void */ public function getAppOpenid($code) { $url = $this->appCodeUrl . "appid=" . $this->appid . "&secret=" . $this->secret . "&code=" . $code . "&grant_type=authorization_code"; return json_decode($this->curl_get($url), true); } /** * 发送模版消息 * * @param [type] $data * @param [type] $token * @return void */ public function sendMsg($data, $token) { return json_decode($this->curl_post($this->sendMsgUrl . $token, json_encode($data)), true); } /** * 异步回调 * @param array $order 回调数据 * @return bool true 验签通过|false 验签不通过 */ public function notifyCheck() { $order = $this->getNotifyOrder(); $uorder = $order; unset($uorder['sign']); $sign = $this->sign($uorder); //本地签名 if ($order['sign'] == $sign) { if (isset($order['return_code']) && $order['return_code'] == "SUCCESS" && $order['result_code'] && $order['result_code'] = "SUCCESS") { return true; } else { return false; } } return false; } /** * 申请退款 * @param array $order * @param string $out_trade_no 平台订单号 * @param int $total_fee 订单金额 * @param string $out_refund_no 自定义退款单号 * @parma int @refund_fee 退款金额 */ public function applyOrderRefund($order) { $order['appid'] = $this->appid; $order['mch_id'] = $this->mch_id; $order['nonce_str'] = $this->create_nonce_str(); $order['sign'] = $this->sign($order); $xml_data = $this->arrayToXml($order); $data = $this->curl_post_ssl($this->refundUrl, $xml_data); return $this->xmlToArray($data); } /** * 订单查询 * @param string $out_trade_no 订单号 * @return array 订单信息 */ public function findOrder($out_trade_no) { $order['out_trade_no'] = $out_trade_no; $order['appid'] = $this->appid; $order['mch_id'] = $this->mch_id; $order['nonce_str'] = $this->create_nonce_str(); $order['sign'] = $this->sign($order); $xml_data = $this->arrayToXml($order); $data = $this->curl_post_ssl($this->query, $xml_data); return $this->xmlToArray($data); } protected static function curl_get($url) { $headerArr = array("Content-type:application/x-www-form-urlencoded"); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArr); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); if (!$output) { throw new \Exception(curl_error($ch)); } curl_close($ch); return $output; } /** * @desc post 用于退款 */ protected static function curl_post($url, $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); if (!empty($data)) { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/xml')); $output = curl_exec($ch); if (!$output) { throw new \Exception(curl_error($ch)); } curl_close($ch); return $output; } public function curl_post_ssl($url, $vars, $second = 30, $aHeader = array()) { $ch = curl_init(); //超时时间 curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLCERT, $this->cert_pem); curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLKEY, $this->key_pem); if (count($aHeader) >= 1) { curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader); } curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $vars); $data = curl_exec($ch); if ($data) { curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); return false; } } /** * 解密手机号 * * @param string $session_key 前端传递的session_key * @param string $iv 前端传递的iv * @param string $encryptedData 前端传递的encryptedData */ public function decryptPhone($session_key, $iv, $encryptedData) { if (strlen($session_key) != 24) { return false; } $aesKey = base64_decode($session_key); if (strlen($iv) != 24) { return false; } $aesIV = base64_decode($iv); $aesCipher = base64_decode($encryptedData); $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV); $dataObj = json_decode($result); if ($dataObj == null) { return false; } if ($dataObj->watermark->appid != $this->appid) { return false; } return json_decode($result, true); } }