微信支付

支付类 原地址   https://blog.csdn.net/u010505805/article/details/76861853

 

微信支付
class Wechat{ //公众号的或者小程序支付参数 private $appId = "*************"; private $appSecret = "*************"; //商家的配置信息 private $mch_id = "*************"; private $mch_key = "*************"; //回调地址 public $notify_url = ‘‘; //退款回掉地址 public $refund_notify_url = ‘‘; private $request; private $nonce_str; public function __construct() { $this->request = Request::instance(); $this->notify_url = base_url() . ‘notice.php‘; $this->refund_notify_url = base_url() . ‘refund.php‘; $this->nonce_str = md5(date(‘YmdHis‘) . time() . rand(1000, 9999)); } //小程序登录 /** * @param $code 获取微信支付的登录code * @return mixed */ public function wxLogin($code) { $url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $this->appId . "&secret=" . $this->appSecret . "&js_code=" . $code . "&grant_type=authorization_code"; return json_decode($this->execute($url), true); } /** * @param $out_trade_no 微信支付唯一订单 * @param $openid 微信支付用户的openid * @param $price 订单支付的价格,(单位,元) * @param string $desc 订单描述 * @return array|mixed 组装支付参数 */ public function getPayParameter($out_trade_no, $openid, $price, $desc = ‘‘) { header("Content-type:text/html;charset=utf-8"); //此处进行字符集初始化, $data = array( ‘appid‘ => $this->appId, ‘body‘ => $desc, ‘mch_id‘ => $this->mch_id, ‘nonce_str‘ => $this->nonce_str, //随机字符串 ‘notify_url‘ => $this->notify_url, //异步回调地址 ‘openid‘ => $openid, //用户登录时获取的code中含有的值 ‘out_trade_no‘ => $out_trade_no, //商家订单号 ‘spbill_create_ip‘ => $this->get_real_ip(), //APP和网页支付提交用户端ip ‘total_fee‘ => $price * 100, //订单总额 //‘total_fee‘ => 1, ‘attach‘ => ‘order‘, //确定是哪个商家进行的支付 ‘trade_type‘ => ‘JSAPI‘ //交易类型 ); //将数组转化为Xml $data[‘sign‘] = $this->makeSign($data); $abc_xml = $this->arrayToXml($data); //统一下单接口prepay_id $url = ‘https://api.mch.weixin.qq.com/pay/unifiedorder‘; $xml = $this->execute($url, $abc_xml, 1); //将XMl转化为数组 $info = $this->xml2array($xml); if (!isset($info[‘prepay_id‘])) { return $info; } $params = array( ‘appId‘ => $this->appId, ‘nonceStr‘ => $data[‘nonce_str‘], ‘package‘ => ‘prepay_id=‘ . $info[‘prepay_id‘], ‘signType‘ => ‘MD5‘, ‘timeStamp‘ => ‘‘ . time(), ); $_info[‘paySign‘] = $this->makeSign($params); $_info[‘timeStamp‘] = "" . $params[‘timeStamp‘]; $_info[‘nonceStr‘] = $params[‘nonceStr‘]; $_info[‘package‘] = $params[‘package‘]; $_info[‘signType‘] = $params[‘signType‘]; $_info[‘notify_url‘] = $this->notify_url; //请求成功后进行返回数据信息 if ($info[‘return_code‘] == ‘SUCCESS‘ || $info[‘result_code‘] == ‘SUCCESS‘) { return $_info; } else { return []; } } /** * @param $openid 支付的用户的openid * @return mixed */ public function userInfo($openid) { $token = $this->getWxAccessToken(); $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" . $token . "&openid=$openid&lang=zh_CN"; return json_decode($this->execute($url), true); } //获取微信的token public function getWxAccessToken() { $key = $this->appId . ‘miniProgram_access_token‘; $accessToken = Cache::get($key); if ($accessToken) return $accessToken; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $this->appId . "&secret=" . $this->appSecret; $con = json_decode($this->execute($url)); Cache::set($key, $con->access_token, $con->expires_in); return $con->access_token; } /** * @param $url 请求url地址 * @param string $data 请求参数 * @param int $post 是否为post * @param int $cert 是否为微信的cert * @return mixed */ private function execute($url, $data = ‘‘, $post = 0, $cert = 0) { if (is_array($data)) { $data = json_encode($data); } $ch = curl_init(); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); curl_setopt($ch, CURLOPT_POST, $post); if ($post) curl_setopt($ch, CURLOPT_POSTFIELDS, $data); if ($cert) { curl_setopt($ch, CURLOPT_SSLCERT, WEB_PATH . ‘cert‘ . DS . ‘apiclient_cert.pem‘); curl_setopt($ch, CURLOPT_SSLKEY, WEB_PATH . ‘cert‘ . DS . ‘apiclient_key.pem‘); } // curl_setopt($ch, CURLOPT_HTTPHEADER, [‘Content-Type:application/json‘]); curl_setopt($ch, CURLOPT_URL, $url); $result = curl_exec($ch); curl_close($ch); return $result; } function http_post_data($url, $data_string, $header = [], $is_array = 0, $is_key_pem = false) { if (is_array($data_string)) { $data_string = json_encode($data_string); } if (!$header) { $header = [ "Content-Type: application/json; charset=utf-8", "Content-Length: " . strlen($data_string) ]; } else { $header = array_merge($header, [ "Content-Type: application/json; charset=utf-8", "Content-Length: " . strlen($data_string) ]); } $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_TIMEOUT, 3); if ($is_key_pem) { $isdir = ‘/cert/‘; 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, $isdir . ‘apiclient_cert.pem‘);//证书位置 curl_setopt($ch, CURLOPT_SSLKEYTYPE, ‘PEM‘);//CURLOPT_SSLKEY中规定的私钥的加密类型 curl_setopt($ch, CURLOPT_SSLKEY, $isdir . ‘apiclient_key.pem‘);//证书位置 // curl_setopt($ch, CURLOPT_CAINFO, ‘PEM‘); // curl_setopt($ch, CURLOPT_CAINFO, $isdir . ‘rootca.pem‘); } ob_start(); curl_exec($ch); $return_content = ob_get_contents(); ob_end_clean(); $return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($is_array) { if (!is_array($return_content)) { $return_content = json_decode($return_content, true); } } return $return_content; } // 数组转化为 xlm public function arrayToXml($data) { $data[‘sign‘] = $this->makeSign($data); ksort($data); //进行拼接数据 $abc_xml = "<xml>"; foreach ($data as $key => $val) { if (is_numeric($val)) { $abc_xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } else { $abc_xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; } } $abc_xml .= "</xml>"; return $abc_xml; } //xlm 转化为数组 public function xml2array($xml) { if (empty($xml)) { return array(); } //禁止引用外部xml实体 libxml_disable_entity_loader(true); $xmlstring = simplexml_load_string($xml, ‘SimpleXMLElement‘, LIBXML_NOCDATA); $val = json_decode(json_encode($xmlstring), true); return $val; } //微信进行拼接sign public function makeSign($params) { //签名步骤一:按字典序排序数组参数 ksort($params); $buff1 = ‘‘; foreach ($params as $k => $v) { if ($k != "sign" && $v != "" && !is_array($v)) { $buff1 .= $k . "=" . $v . "&"; } } $buff1 = trim($buff1, "&"); //签名步骤二:在string后加入KEY $string = $buff1 . "&key=" . $this->mch_key; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; } //验证图片或者视频是否涉黄 public function imgSecCheck($media_url, $media_type = 2) { $url = ‘https://api.weixin.qq.com/wxa/media_check_async?access_token=‘ . $this->getWxAccessToken(); $return = $this->execute($url, [ ‘media_url‘ => $media_url, ‘media_type‘ => $media_type, ], 1); $return = json_decode($return, true); if ($return && $return[‘errcode‘] == 0) { return true; } return false; } //验证发布内容是否违法以及敏感词汇 public function msgSecCheck($content = ‘‘) { $url = ‘https://api.weixin.qq.com/wxa/msg_sec_check?access_token=‘ . $this->getWxAccessToken(); $return = $this->execute($url, [‘content‘ => $content], 1); $return = json_decode($return, true); if ($return && $return[‘errcode‘] == 0) { return true; } return false; } /** * [sendMoney 企业付款到零钱] * @param [type] $amount [发送的金额(分)目前发送金额不能少于1元] * @param [type] $re_openid [发送人的 openid] * @param string $desc [企业付款描述信息 (必填)] * @param string $check_name [收款用户姓名 (选填)] * @return [type] [description] * https://www.cnblogs.com/echoppy/p/8603286.html */ public function sendMoney($amount, $re_openid) { $total_amount = (100) * $amount; $data = array( ‘mch_appid‘ => $this->appId,//商户账号appid ‘mchid‘ => $this->mch_id,//商户号 ‘nonce_str‘ => $this->nonce_str,//随机字符串 ‘partner_trade_no‘ => date(‘YmdHis‘) . rand(1000, 9999),//商户订单号 ‘openid‘ => $re_openid,//用户openid ‘check_name‘ => ‘NO_CHECK‘,//校验用户姓名选项, ‘amount‘ => $total_amount,//付款金额,单位为分 ‘desc‘ => ‘商户提现‘,//企业付款描述信息 ‘spbill_create_ip‘ => $this->get_real_ip(),//Ip地址 ); //生成签名算法 $secrect_key = $this->mch_key; ///这个就是个API密码。MD5 32位。 $data = array_filter($data); ksort($data); $str = ‘‘; foreach ($data as $k => $v) { $str .= $k . ‘=‘ . $v . ‘&‘; } $str .= ‘key=‘ . $secrect_key; $data[‘sign‘] = md5($str); //生成签名算法 $xml = $this->arraytoxml($data); $url = ‘https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers‘; //调用接口 //$res = $this->http_post_data($url, $xml) $res = $this->execute($url, $xml, 1, 1); $return = $this->xml2array($res); return $return; } /** * @param $amount 退款金额 * @param $re_openid 退款用户的openid * @return bool 退款成功失败 * 开发文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4 */ public function refundUserMoney($transaction_id, $total_fee, $refund_fee, $out_refund_no) { $data = array( ‘appid‘ => $this->appId,//商户账号appid ‘mch_id‘ => $this->mch_id,//商户号 ‘nonce_str‘ => $this->nonce_str,//随机字符串 ‘transaction_id‘ => $transaction_id,//微信支付商户号 ‘total_fee‘ => $total_fee * 100,//订单金额 ‘refund_fee‘ => $refund_fee * 100,//退款金额 ‘notify_url‘ => $this->refund_notify_url,//退款金额 ‘out_refund_no‘ => $out_refund_no,//退款金额 ); //生成签名算法 $secrect_key = $this->mch_key; ///这个就是个API密码。MD5 32位。 $data = array_filter($data); ksort($data); $str = ‘‘; foreach ($data as $k => $v) { $str .= $k . ‘=‘ . $v . ‘&‘; } $str .= ‘key=‘ . $secrect_key; $data[‘sign‘] = md5($str); //生成签名算法 $xml = $this->arraytoxml($data); $url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; $res = $this->execute($url, $xml, 1, 1); if (!$res) { return false; } //$res = $this->http_post_data($url, $xml); $return = $this->xml2array($res); if ($return[‘return_code‘] == ‘SUCCESS‘) { return true; } return false; } public function get_real_ip() { $ip = $_SERVER[‘REMOTE_ADDR‘]; if (isset($_SERVER[‘HTTP_X_FORWARDED_FOR‘]) && preg_match_all(‘#d{1,3}.d{1,3}.d{1,3}.d{1,3}#s‘, $_SERVER[‘HTTP_X_FORWARDED_FOR‘], $matches)) { foreach ($matches[0] AS $xip) { if (!preg_match(‘#^(10|172.16|192.168).#‘, $xip)) { $ip = $xip; break; } } } elseif (isset($_SERVER[‘HTTP_CLIENT_IP‘]) && preg_match(‘/^([0-9]{1,3}.){3}[0-9]{1,3}$/‘, $_SERVER[‘HTTP_CLIENT_IP‘])) { $ip = $_SERVER[‘HTTP_CLIENT_IP‘]; } elseif (isset($_SERVER[‘HTTP_CF_CONNECTING_IP‘]) && preg_match(‘/^([0-9]{1,3}.){3}[0-9]{1,3}$/‘, $_SERVER[‘HTTP_CF_CONNECTING_IP‘])) { $ip = $_SERVER[‘HTTP_CF_CONNECTING_IP‘]; } elseif (isset($_SERVER[‘HTTP_X_REAL_IP‘]) && preg_match(‘/^([0-9]{1,3}.){3}[0-9]{1,3}$/‘, $_SERVER[‘HTTP_X_REAL_IP‘])) { $ip = $_SERVER[‘HTTP_X_REAL_IP‘]; } return $ip ? $ip : ‘127.0.0.1‘; } }

  

相关文章