mch_id=env('WX_MCH_ID',''); $this->private_key=env('WX_PRIVATE_KEY',''); $this->appid=env('WX_APPID',''); $this->appsecret=env('WX_APPSECRET',''); $this->cert_file=env('WX_CERT_FILE',''); $this->key_file=env('WX_KEY_FILE',''); $this->appletId=env('APPLET_ID',''); $this->appletKey=env('APPLET_KEY',''); } /** * 创建对象 * @return WeixinServer */ static function creatServer() { if (empty(self::$server)) self::$server = new WeixinServer(); return self::$server; } /** * 发送模板消息 * @param $data */ function sendTemplate($data) { $access_token = $this->getAccessToken(); $url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' . $access_token; $result = $this->sendRequest($url, 'post', $data); $result = json_decode($result, true); if ($result['errcode'] == 0) { //消息发放成功 } else { //消息发放失败 ErrorRecord::create(['m_id' => 0, 'msg' => '模板消息推送失败', 'data' => json_encode($data)]); ErrorRecord::create(['m_id' => 0, 'msg' => '模板消息推送失败', 'data' => json_encode($result)]); } return $result; } /** * 根据openid获取会员信息 * @param $openid * @return false|mixed */ function getUserInfo($openid) { $access_token = $this->getAccessToken(); $url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=' . $access_token . '&openid=' . $openid . '&lang=zh_CN'; $result = $this->sendRequest($url, 'get'); $result = json_decode($result, true); if (empty($result['openid'])) { //消息发放成功 return $result; } else { //消息发放失败 ErrorRecord::create(['m_id' => 0, 'msg' => '接口获取会员用户信息失败', 'data' => $openid]); return false; } } /** * 获取会员微信细腻 * @return false|\Illuminate\Contracts\Foundation\Application|\Illuminate\Session\SessionManager|\Illuminate\Session\Store|mixed */ function getOpenId() { $openid = session('wx_openid'); if ($openid) return $openid; $code = request()->input('code', ''); if (!isset($code)) { $redirect_url = $this->getServerUrl(); $redirect_url = urlencode($redirect_url); $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appid}&redirect_uri={$redirect_url}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"; redirect($url); return false; } else { $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->appid}&secret={$this->appsecret}&code={$code}&grant_type=authorization_code"; $result = $this->sendRequest($url); $result = json_decode($result, true); if (isset($result['errcode'])) { return false; } else { $openid = $result['openid']; $url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={$this->appid}&grant_type=refresh_token&refresh_token={$result['refresh_token']} "; $result = $this->sendRequest($url); $result = json_decode($result, true); if (isset($result['access_token'])) { return $result['openid']; } session(['wx_openid' => $openid]); return $openid; } } } /** * 小程序code获取openid等信息 * @param $code * @param $invite_code * @return array|false */ function getAppletsOpenId($code){ $url = "https://api.weixin.qq.com/sns/jscode2session?appid={$this->appletId}&secret={$this->appletKey}&js_code={$code}&grant_type=authorization_code"; $result = $this->sendRequest($url); $result = json_decode($result, true); if ( !isset($result['openid'])) {//成功返回信息 return ['code'=>0,'msg'=>$result['errmsg']]; } else { return $result; } } /** * 网页授权 * @return mixed */ function authorize() { $code = request()->input('code', ''); if (empty($code)) { $redirect_url = $this->getServerUrl(); $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appid}&redirect_uri={$redirect_url}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; $this->redirect($url); return false; } else { $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->appid}&secret={$this->appsecret}&code={$code}&grant_type=authorization_code"; $result = $this->sendRequest($url); $result = json_decode($result, true); if (isset($result['errcode'])) { return false; } else { $openid = $result['openid']; $access_token = $result['access_token']; $url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={$this->appid}&grant_type=refresh_token&refresh_token={$result['refresh_token']} "; $result = $this->sendRequest($url); $result = json_decode($result, true); if (isset($result['access_token'])) { $access_token = $result['access_token']; $openid = $result['openid']; } $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}&lang=zh_CN"; $result = $this->sendRequest($url); $result = json_decode($result, true); if (isset($result['errcode'])) { return false; } return $result; } } } function redirect($uri = '', $method = 'location', $http_response_code = 302) { if (!preg_match('#^https?://#i', $uri)) { $uri = site_url($uri); } switch ($method) { case 'refresh' : header("Refresh:0;url=" . $uri); break; default : header("Location: " . $uri, TRUE, $http_response_code); break; } exit(); } /** * 获取小程序码 * @param $page //页面路径 * @param $scene //携带参数 */ function getAppletCode($page,$scene){ $access_token = $this->getAccessToken(2); $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={$access_token}"; $data['page'] = $page; $data['scene'] = $scene; $data['check_path'] = false; $data['width'] = 300; $result = $this->sendRequest($url,'post',$data); return $result; } /** * 获取 access_token * @return bool */ protected function getAccessToken($type = 1) { if($type == 1){ $key = 'vouchername'; $appId = $this->appid; $appsecret = $this->appsecret; }else{ $key = 'applet_voucher'; $appId = $this->appletId; $appsecret = $this->appletKey; } $data = RedisDataServer::creatServer()->getData($key, 'json'); if (empty($data) || $data['endtime'] < time()) { $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appsecret}"; $result = $this->sendRequest($url); $result = json_decode($result, true); // $bey = Cache::set('vouchername', array('access_token' => $result['access_token'], 'endtime' => time() + 7000), 7000); if ( isset($result['access_token'])) { RedisDataServer::creatServer()->setData($key, array('access_token' => $result['access_token'], 'endtime' => time() + 1800), 'json',1800); return $result['access_token']; } else { return false; } } else { return $data['access_token']; } } /** * 获取js授权信息 * @return mixed */ function getJsConfig($url = '') { $hash = ''; $chars = 'ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'; $max = strlen($chars) - 1; for ($i = 0; $i < 16; $i++) { $hash .= $chars[mt_rand(0, $max)]; } $data['noncestr'] = $hash; $data['jsapi_ticket'] = $this->getJsTicket(); $data['timestamp'] = time(); if (empty($url)) { $data['url'] = $this->getServerUrl(); } else { $data['url'] = $url; } ksort($data); $str = ''; foreach ($data as $key => $val) { $str .= '&'; $str .= $key . '=' . $val; } $str = mb_substr($str, 1); $data['appid'] = $this->appid; $data['signature'] = sha1($str); unset($data['jsapi_ticket']); return $data; } /** * 获取当前连接 * @return string */ function getServerUrl() { // $http_host=request()->header('host'); // $data=request()->all(); return urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); // return 'http://'.$http_host. '?' . http_build_query($data);; } /** * 获取Js调用凭证 * @return bool */ function getJsTicket() { // $data = Cache::get('js_ticket'); $data = RedisDataServer::creatServer()->getData('js_ticket', 'json'); if (empty($data) || $data['endtime'] < time()) { $access_token = $this->getAccessToken(); $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$access_token}&type=jsapi"; $result = $this->sendRequest($url); $result = json_decode($result, true); if ($result['errcode'] == 0) { //file_put_contents($this->js_ticket,serialize(array('access_token'=>$result['access_token'],'endtime'=>time()+7000))); // Cache::set('js_ticket', array('access_token' => $result['ticket'], 'endtime' => time() + 7000), 7000); RedisDataServer::creatServer()->setData('js_ticket', array('access_token' => $result['ticket'], 'endtime' => time() + 7000), 'json',7000); return $result['ticket']; } return false; } else { return $data['access_token']; } } /** * 微信签名 */ function wxSign($data, $keys) { ksort($data); $str = ''; foreach ($data as $key => $val) { if ($val) { if ($str != '') $str .= '&'; $str .= "{$key}={$val}"; } } $str .= '&key=' . $keys; $sign = strtoupper(MD5($str)); return $sign; } /** * @param $url * @param string $type 请求方式 * @param string $data 数据 数组格式 * @return mixed */ protected function sendRequest($url, $type = 'get', $data = '') { $ch = curl_init(); if ($type == 'get' && $data) { $url = $url . '?' . http_build_query($data); } curl_setopt($ch, CURLOPT_URL, $url); //设置访问路径 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //设置可以返回字符串 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $head = array('User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'); curl_setopt($ch, CURLOPT_HTTPHEADER, $head); if ($type == 'post') { curl_setopt($ch, CURLOPT_POST, TRUE);//post请求 $data = json_encode($data, JSON_UNESCAPED_UNICODE); curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置传递的参数 } $request = curl_exec($ch); curl_close($ch); return $request; } /** * JS支付签名 * @param $order_sn * @param $total_fee * @param $notify_url * @param $body * @param $wx_openid * @return bool */ public function wxJsPay($order_sn, $total_fee, $notify_url, $body, $wx_openid = '') { $is_test=env('TEST_SERVE',false); if($is_test)$total_fee = 0.01; $conf = array( 'appid' => $this->appid, 'mch_id' => $this->mch_id, 'notify_url' => $notify_url, 'openid' => $wx_openid, 'out_trade_no' => $order_sn, 'total_fee' => $total_fee * 100, 'trade_type' => 'JSAPI', 'body' => $body, ); $order = new Unifiedorder($conf); $request = $order->getOrder($this->private_key); if ($request['code'] == 1) { $datas["appId"] = $request['data']['appid']; $datas["nonceStr"] = $order->getNonceStr(); $datas["package"] = "prepay_id={$request['data']['prepay_id']}"; $datas["signType"] = 'MD5'; $datas["timeStamp"] = time(); $s = $order->wxSign($datas, $this->private_key); $datas["paySign"] = $s; return $datas; } else { return false; } } /** * JS支付签名 * @param $order_sn * @param $total_fee * @param $notify_url * @param $body * @param $wx_openid * @return bool */ public function getPayOrder($order_sn) { $is_test=env('TEST_SERVE',false); if($is_test)$total_fee = 0.01; $cert_file=base_path($this->cert_file); $key_file=base_path($this->key_file); $conf = array( 'appid' => $this->appid, 'mch_id' => $this->mch_id, 'out_trade_no' => $order_sn, ); $order = new Unifiedorder($conf, ['cert_file' => $cert_file, 'key_file' => $key_file]); $request = $order->getPayOrder($this->private_key); return $request; } /** * 微信验签 * @param $data * @return string */ function verifyCer($data) { if (isset($data['sign'])) unset($data['sign']); $conf = array( 'appid' => $this->appid, 'mch_id' => $this->mch_id, ); $order = new Unifiedorder($conf); $sign = $order->wxSign($data, $this->private_key); return $sign; } /** * 微信退款 * @param $total_fee * @param $out_trade_no * @param string $body * @param int $order_money * @return array */ function wxPayRefund($out_trade_no, $total_fee, $body = '',$order_money=0) { $is_test=env('TEST_SERVE',false); if($is_test){ $total_fee = 0.01; $order_money = 0.01; } $conf = array( 'appid' => $this->appid, 'mch_id' => $this->mch_id, 'out_trade_no' => $out_trade_no, 'out_refund_no' => 'T'.$out_trade_no.time(), 'total_fee' => $order_money * 100, 'refund_fee' => $total_fee * 100, 'refund_desc' => $body ); $order = new Unifiedorder($conf, ['cert_file' => base_path($this->cert_file), 'key_file' => base_path($this->key_file)]); $request = $order->wxPayRefund($this->private_key); ErrorRecord::create(['m_id' =>0, 'msg' => '微信退款失败', 'data' => json_encode($request)]); if ($request['code'] == 1) { return ['code' => 1, 'msg' => '退款成功', 'data' => ['ret_sn' => $request['data']['refund_id']]]; } else { return ['code' => 0, 'msg' => '微信退款失败', 'data' => ['ret_sn' => '']]; } } /** * 微信付款到零钱 * @param $order_sn * @param $total_fee * @param $openid * @param $body * @return array */ function setVerified($order_sn, $total_fee, $openid, $body) { $cert_file=base_path($this->cert_file); $key_file=base_path($this->key_file); $private_key=$this->private_key; $conf = array( 'mch_appid' => $this->appid, 'mchid' => $this->mch_id, 'openid' => $openid, 'partner_trade_no' => $order_sn, 'amount' => $total_fee * 100, 'check_name' => 'NO_CHECK', 'desc' => $body, ); $order = new Unifiedorder($conf, ['cert_file' => $cert_file, 'key_file' => $key_file]); $request = $order->setVerified($private_key); ErrorRecord::create(['m_id' =>0, 'msg' => '微信提现记录', 'data' => json_encode($request)]); return $request; } }