table($name, [], false); } function DQ2($sql, $value = []) { return Db::connect('mysql2')->query($sql, $value); } /** * 加密 * * @param string $string * @param string $skey */ function a_encode($string = "", $skey = '') { if (strlen($skey) === 0) { $skey = Config::get('app.ENCODE_KEY'); } $data = openssl_encrypt($string, 'AES-128-ECB', $skey, OPENSSL_RAW_DATA); $data = strtolower(bin2hex($data)); return $data; } /** * 解密 * * @param string $string * @param string $skey */ function a_decode($string = "", $skey = '') { if (strlen($skey) === 0) { $skey = Config::get('app.ENCODE_KEY'); } if (empty($string) || strlen($string) % 2 == 1) { return ''; } return openssl_decrypt(hex2bin($string), 'AES-128-ECB', $skey, OPENSSL_RAW_DATA); } /** * https get * * @param [string] $url * @return string */ function curl_get_https($url) { $curl = curl_init(); // 启动一个CURL会话 curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在 $tmpInfo = curl_exec($curl); //返回api的json对象 //关闭URL请求 curl_close($curl); return $tmpInfo; //返回json对象 } function http_post_json($url, $jsonStr, $header = []) { c_debug('http_post_json:'.$jsonStr . '----$header:' . json_encode($header)); $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt( $ch, CURLOPT_HTTPHEADER, array_merge( $header, [ 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($jsonStr), ] ) ); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return $response; } function c_post_http($url, $data) { $data = http_build_query($data); $opts = array('http' => array('method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $data)); $context = stream_context_create($opts); return file_get_contents($url, false, $context); } /** * https post * * @param [string] $url * @param [array(k=>v)] $data * @return string */ function curl_post_https($url, $data, $opt = []) { $opt = array_merge([ 'path_cert' => '', 'path_key' => '', 'header' => [] ], $opt); // Log::write(json_encode($opt) . '== curl_post_https', 'notice'); $with_ca = false; if ($opt && $opt['path_cert'] && $opt['path_key']) { $with_ca = true; } // 模拟提交数据函数 $curl = curl_init(); // 启动一个CURL会话 curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $with_ca); // 对认证证书来源的检查 if ($with_ca) { curl_setopt($curl, CURLOPT_SSLCERT, $opt['path_cert']); curl_setopt($curl, CURLOPT_SSLKEY, $opt['path_key']); } curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在 curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包 curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环 curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 curl_setopt($curl, CURLOPT_HTTPHEADER, $opt['header']); $tmpInfo = curl_exec($curl); // 执行操作 if (curl_errno($curl)) { echo 'Errno' . curl_error($curl); //捕抓异常 } curl_close($curl); // 关闭CURL会话 return $tmpInfo; // 返回数据,json格式 } function ajaxSuccessPage($data = "", $current = 1, $pageSize = 10, $total = 0, $code = 0, $only_json = false) { $json = array( "success" => true, "errorMsg" => "", "errorCode" => $code, "model" => $data, "current" => $current, "pageSize" => $pageSize, "total" => $total, ); return $only_json ? $json : json($json); } function ajaxSuccess($data = "", $code = '0', $only_json = false) { $json = array( "success" => true, "errorMsg" => "", "errorCode" => $code, "model" => $data, ); return $only_json ? $json : json($json); } function ajaxFail($errorMsg = "", $errorCode = -1, $data = null, $only_json = false) { $json = array( "success" => false, "errorMsg" => $errorMsg, "errorCode" => $errorCode, "model" => $data, ); return $only_json ? $json : json($json); } /** * 解密微信加密数据 */ function decrypt_wx_data($encrypted_data, $iv, $session_key) { if (strlen($session_key) != 24) { return -1; } if (strlen($iv) != 24) { return -2; } $aes_cipher = base64_decode($encrypted_data); $aes_key = base64_decode($session_key); $aes_iv = base64_decode($iv); $result = openssl_decrypt($aes_cipher, "AES-128-CBC", $aes_key, 1, $aes_iv); $data = json_decode($result, true); if ($data == null) { Log::write([ 'encrypted_data' => $encrypted_data, 'iv' => $iv, 'session_key' => $session_key, 'result' => $result, ], 'notice'); return -3; } return $data; } /** * 获取session_key */ function code_2_session($js_code) { $appid = Config::get('app.APPID'); $secret = Config::get('app.SECERT_KEY'); $url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . $appid . '&secret=' . $secret . '&js_code=' . $js_code . '&grant_type=authorization_code'; $result = curl_get_https($url); think\facade\Log::record($url . '--' . $result, 'notice'); $result_json = json_decode($result, true); if (array_key_exists('errcode', $result_json) && $result_json['errcode'] != 0) { think\facade\Log::record($result, 'notice'); return null; } return $result_json; } /** *随机字符串数字 * * @param integer $len */ function random_vcode($len = 6) { srand((float) microtime() * 1000000); //create a random number feed. $ychar = "0,1,2,3,4,5,6,7,8,9"; $list = explode(",", $ychar); $authnum = ''; for ($i = 0; $i < $len; $i++) { $randnum = rand(0, 9); // 10+26; $authnum .= $list[$randnum]; } return $authnum; } function rad($d) { return $d * M_PI / 180.0; } function random_password($len = 6) { srand((float) microtime() * 1000000); //create a random number feed. $ychar = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z"; $list = explode(",", $ychar); $authnum = ''; for ($i = 0; $i < $len; $i++) { $randnum = rand(0, count($list)-1); // 10+26; $authnum .= $list[$randnum]; } return $authnum; } /** * 计算两个经纬度距离 */ function c_lon_lat_distance($lon1, $lat1, $lon2, $lat2) { $radLat1 = rad($lat1); $radLat2 = rad($lat2); $a = $radLat1 - $radLat2; $b = rad($lon1) - rad($lon2); $s = 2 * asin( sqrt( pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2) ) ); return ceil($s * 6378137.0); } /** * 分隔成数组 * * @param [type] $str * @return array */ function c_dot_str_2_array($str): array { $list = []; if ($str) { $list = explode(',', $str); } return $list; } /** * 对象筛选属性 * * @param array $obj * @param array $keys * @param boolean $pass_keys 是否去掉传入的属性 */ function c_filter_property($obj, $keys, $pass_keys = false) { $re = []; if (!$pass_keys) { foreach ($keys as $k) { if (array_key_exists($k, $obj)) { $re[$k] = $obj[$k]; } } } else { // echo in_array('c',['a','b']) ? 'in--':'on=='; foreach ($obj as $k => $v) { if (!in_array($k, $keys)) { $re[$k] = $v; } } } return $re; } /** * 列表筛选属性 * * @param [type] $list * @param [type] $keys * @param boolean $pass_keys 是否去掉传入的属性 */ function c_filter_property_list($list, $keys, $pass_keys = false) { $re_list = []; foreach ($list as $one) { $re_list[] = c_filter_property($one, $keys, $pass_keys); } return $re_list; } /** * 生成订单号 * * @param [type] $order_type * @return string */ function s_order_id_render($order_type) { //1+1+2+2+2+2+2+2=14 $y = substr(date('y'), 1, 1); $pre = $y . date('mdHis'); $s_map = Cache::get(Constant::$ORDER_S_PTR); if (isset($s_map['pre']) && $s_map['pre'] == $pre) { $s_map['ptr'] += 1; } else { $s_map = ['pre' => $pre, 'ptr' => 1]; } Cache::set(Constant::$ORDER_S_PTR, $s_map); $ptr = $s_map['ptr']; $ptr = sprintf('%02d', $ptr); return $order_type . $pre . $ptr; } /** * 生成订单核销码 * * @param [type] $order_id * @return void */ function s_order_use_code($order_id) { return substr($order_id, -6); } function c_read_xml_to_map($res) { /* */ // $res = str_replace(' ', '', $res); // $res = str_replace('', '', $res); // $res = str_replace('', '', $res); // $res = str_replace("\r", "\n", $res); // $res = str_replace("\n\n", "\n", $res); // $res = trim($res); // $res = str_replace("\n", '&', $res); // $res = str_replace(']', '', $res); // $res = str_replace('', '=', $res); // $res = str_replace('=<', '', $res); // $res = trim($res, '<='); // $res = str_replace('=&', '&', $res); // $res = str_replace('<', '', $res); // /* // return_code=SUCCESS/return_code&return_msg=OK/return_msg // */ // $arr = explode('&', $res); // /* // return_code=SUCCESS/return_code // return_msg=OK/return_msg // */ // $map = []; // foreach ($arr as $one) { // $kv = explode('=', $one); // $k = $kv[0]; // $v = $kv[1]; // $v_arr = explode('/', $v); //如果有多个/ 会出问题 // $map[$k] = $v_arr[0]; // } // return $map; $res = str_replace('', '', $res); // $res = str_replace(']]>', '', $res); $ob = simplexml_load_string($res, null, LIBXML_NOCDATA); return c_safe_to_json(json_encode($ob, JSON_UNESCAPED_UNICODE)); } function s_make_wx_order($xml_str) { $res = curl_post_https('https://api.mch.weixin.qq.com/pay/unifiedorder', $xml_str); Log::write($res . '==' . $xml_str, 'notice'); return c_read_xml_to_map($res); } function s_refund_wx_order($xml_str) { $path_cert = dirname(dirname(__FILE__)) . Config::get('app.REFUND_CERT_FILE'); $path_key = dirname(dirname(__FILE__)) . Config::get('app.REFUND_KEY_FILE'); $res = curl_post_https('https://api.mch.weixin.qq.com/secapi/pay/refund', $xml_str, [ 'path_cert' => $path_cert, 'path_key' => $path_key, ]); Log::write($res . '==' . $xml_str, 'notice'); return c_read_xml_to_map($res); } function s_transfers_wx($xml_str) { $path_cert = dirname(dirname(__FILE__)) . Config::get('app.REFUND_CERT_FILE'); $path_key = dirname(dirname(__FILE__)) . Config::get('app.REFUND_KEY_FILE'); $res = curl_post_https('https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers', $xml_str, [ 'path_cert' => $path_cert, 'path_key' => $path_key, ]); Log::write($res . '==' . $xml_str, 'notice'); return c_read_xml_to_map($res); } function s_v3_api_make_token ($url, $http_method, $body) { //$url = 'https://api.mch.weixin.qq.com/v3/certificates'; // $http_method = 'GET'; $timestamp = time(); $nonce = random_vcode(32); // $body = ''; $merchant_id = Config::get('app.MCH_ID'); $serial_no = Config::get('app.CERT_SERIAL_NO'); $mch_private_key = file_get_contents(dirname(dirname(__FILE__)) . Config::get('app.REFUND_KEY_FILE')); // exit(); $url_parts = parse_url($url); $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : "")); $message = $http_method."\n". $canonical_url."\n". $timestamp."\n". $nonce."\n". $body."\n"; openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption'); $sign = base64_encode($raw_sign); $schema = 'WECHATPAY2-SHA256-RSA2048'; $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $merchant_id, $nonce, $timestamp, $serial_no, $sign); return $token; } function s_getEncrypt($str) { //$str是待加密字符串 $public_key_path = dirname(dirname(__FILE__)) . Config::get('app.REFUND_CERT_FILE'); $public_key = file_get_contents($public_key_path); $encrypted = ''; if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) { //base64编码 $sign = base64_encode($encrypted); } else { throw new Exception('encrypt failed'); } return $sign; } function s_transfers_wx2($body) { $body_str = json_encode($body); $serial_no = Config::get('app.CERT_SERIAL_NO'); $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches'; $token = s_v3_api_make_token($url,'POST', $body_str); $res = curl_post_https($url, $body_str, [ 'header' => [ 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.39 KK/0.1', 'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token, 'Accept: application/json', 'Content-Type: application/json', 'Wechatpay-Serial: '.s_getEncrypt($serial_no), 'Accept-Language: zh-CN' ] ]); Log::write($res . '== s_transfers_wx2 == ' . $body_str, 'notice'); // return c_read_xml_to_map($res); return c_safe_to_jsonx($res); } /** * js鉴权获取access_token * * @return void */ function s_gzh_get_access_token() { $access_tken = Cache::get(Constant::$GZH_ACCESS_TOKEN); if ($access_tken) { return $access_tken; } $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . Config::get('app.GZH_APP_ID') . '&secret=' . Config::get('app.GZH_SECERT_KEY'); $result = curl_get_https($url); // c_debug($result); $result_json = json_decode($result, true); if (array_key_exists('errcode', $result_json)) { Log::write($result, 'WARN'); return null; } $access_tken = $result_json['access_token']; Cache::set(Constant::$GZH_ACCESS_TOKEN, $access_tken, 7000); return $access_tken; } function s_gzh_get_jsticket() { $jsticket = Cache::get(Constant::$GZH_JS_TICKET); if ($jsticket) { return $jsticket; } Log::write('重新获取公众号ac了', 'notice'); $access_tken = s_gzh_get_access_token(); $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' . $access_tken . '&type=jsapi'; $result = curl_get_https($url); $result_json = json_decode($result, true); if (($result_json['errcode'])) { Log::write($result, 'WARN'); return null; } $jsticket = $result_json['ticket']; Cache::set(Constant::$GZH_JS_TICKET, $jsticket, 7000); return $jsticket; } /** * 用户授权获取access_token * * @param string $code * @return array(access_token,openid) */ function s_base_auth($code) { //通过code换取网页授权access_token $data_str = curl_get_https('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . Config::get('app.GZH_APP_ID') . '&secret=' . Config::get('app.GZH_SECERT_KEY') . '&code=' . $code . '&grant_type=authorization_code'); $data_obj = json_decode($data_str, true); if (empty($data_obj) || array_key_exists('errcode', $data_obj)) { Log::write($data_str . '---SNS_OAUTH2_ERR', 'ERR'); return null; } //获取成功 // {"access_token":"ACCESS_TOKEN","expires_in":7200,"refresh_token":"REFRESH_TOKEN","openid":"OPENID","scope":"SCOPE" } $db_wx_auth = D('gzh_auth'); //超找是否存在过openid $row_data = $db_wx_auth->where(array( 'openid' => $data_obj['openid'] ))->find(); $unionid = $data_obj['unionid'] ?? ''; $id = null; //如果没有存进去 if (empty($row_data)) { $data = array( 'unionid' => $unionid, 'openid' => $data_obj['openid'], 'refresh_token' => $data_obj['refresh_token'], 'create_time' => date('Y-m-d H:i:s', time()), ); $db_wx_auth->insert($data); $id = D('gzh_auth')->getLastInsID(); } //如果存在,就更新下refresh_token else { $update = [ // 'unionid' => $unionid, 'refresh_token' => $data_obj['refresh_token'], ]; if ($unionid) { $update['unionid'] = $unionid; } $db_wx_auth->where([ 'openid' => $data_obj['openid'], ])->update($update); $id = $row_data['id']; } return array( 'access_token' => $data_obj['access_token'], 'openid' => $data_obj['openid'], 'id' => $id, ); } function s_base_auth_tmp($code) { //通过code换取网页授权access_token $data_str = curl_get_https('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . Config::get('app.GZH_APP_ID') . '&secret=' . Config::get('app.GZH_SECERT_KEY') . '&code=' . $code . '&grant_type=authorization_code'); $data_obj = json_decode($data_str, true); if (empty($data_obj) || array_key_exists('errcode', $data_obj)) { Log::write($data_str . '---SNS_OAUTH2_ERR', 'ERR'); return null; } //获取成功 // {"access_token":"ACCESS_TOKEN","expires_in":7200,"refresh_token":"REFRESH_TOKEN","openid":"OPENID","scope":"SCOPE" } $db_wx_auth = D('gzh_auth_tmp'); //超找是否存在过openid $row_data = $db_wx_auth->where(array( 'openid' => $data_obj['openid'] ))->find(); $unionid = $data_obj['unionid'] ?? ''; $id = null; //如果没有存进去 if (empty($row_data)) { $data = array( 'unionid' => $unionid, 'openid' => $data_obj['openid'], 'refresh_token' => $data_obj['refresh_token'], 'create_time' => date('Y-m-d H:i:s', time()), ); $db_wx_auth->insert($data); $id = D('gzh_auth')->getLastInsID(); } //如果存在,就更新下refresh_token else { $update = [ // 'unionid' => $unionid, 'refresh_token' => $data_obj['refresh_token'], ]; if ($unionid) { $update['unionid'] = $unionid; } $db_wx_auth->where([ 'openid' => $data_obj['openid'], ])->update($update); $id = $row_data['id']; } return array( 'access_token' => $data_obj['access_token'], 'openid' => $data_obj['openid'], 'id' => $id, ); } /** * 拉取用户信息 * * @param [string] $access_tken * @return array */ function s_info_auth($code) { $base_auth_data = s_base_auth($code); //Log::write('ckaaaaaaaaaaaaaaaa1:' . microtime(),'NOTICE'); $data_str = curl_get_https('https://api.weixin.qq.com/sns/userinfo?access_token=' . $base_auth_data['access_token'] . '&openid=' . $base_auth_data['openid'] . '&lang=zh_CN'); //Log::write('ckaaaaaaaaaaaaaaaa2:' . microtime(),'NOTICE'); /** "openid":" OPENID", " nickname": NICKNAME, "sex":"1", "province":"PROVINCE" "city":"CITY", "country":"COUNTRY", "headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" */ $data_obj = json_decode($data_str, true); if (empty($data_obj) || array_key_exists('errcode', $data_obj)) { Log::write($data_str . '---SNS_OAUTH2_ERR-s_info_auth' . json_encode($base_auth_data), 'ERROR'); return null; } $db_wx_auth = D('gzh_auth'); //先找到openid $row_data = $db_wx_auth->where(array( 'openid' => $data_obj['openid'] ))->find(); if ($data_obj['headimgurl'] == null) { return null; } //组装存入的数据 $data = array( 'nickname' => base64_encode($data_obj['nickname']), //base64下昵称解决emoij表情问题 'sex' => $data_obj['sex'], 'province' => $data_obj['province'], 'city' => $data_obj['city'], 'country' => $data_obj['country'], 'headimgurl' => $data_obj['headimgurl'], 'privilege' => json_encode($data_obj['privilege']), 'unionid' => array_key_exists('unionid', $data_obj) ? $data_obj['unionid'] : null, ); $db_wx_auth->where(array( 'openid' => $data_obj['openid'], ))->save($data); return $row_data['id'] ? $row_data['id'] : null; } function c_debug($any, $tag = '', $exit = false) { Log::write($tag . '=:' . json_encode($any, JSON_UNESCAPED_UNICODE), 'notice'); if ($exit) { exit(); } } function s_send_temp_gzh_msg($tmpid, $openid, $data, $url = '') { $is_prod = false; if (env('app.envName', 'prod') == 'prod') { $is_prod = true; } if (!$is_prod) { $openid = 'oD5Hb0Tmjwsaxg5bVQEx7GoVAXwg'; } Log::write('要发公众号消息了:' . json_encode([$tmpid, $openid, $data], JSON_UNESCAPED_UNICODE), 'notice'); $gzh_ac_tk = Cache::get(Constant::$GZH_ACCESS_TOKEN); $adata = []; foreach ($data as $k => $one) { //Log::write('要发公众号消息了-221:'.json_encode($one,JSON_UNESCAPED_UNIs_base_authCODE),'notice'); $adata[$k] = [ 'value' => $one[0], // 'color'=>$one[1] ?? '#333333' ]; // Log::write('要发公众号消息了-112:'.json_encode($one,JSON_UNESCAPED_UNICODE),'notice'); } //Log::write('要发公众号消息了-2:'.json_encode($adata,JSON_UNESCAPED_UNICODE),'notice'); $qdata = [ "touser" => $openid, "template_id" => $tmpid, // "url"=>$url, // "miniprogram":{ // "appid":"xiaochengxuappid12345", // "pagepath":"index?foo=bar" // }, "data" => $adata, ]; if ($url) { $qdata['url'] = $url; } Log::write('要发公众号消息了-3:' . json_encode($qdata, JSON_UNESCAPED_UNICODE), 'notice'); $re_data = curl_post_https('https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' . $gzh_ac_tk, json_encode($qdata)); Log::write('发公众号消息返回:' . $re_data, 'notice'); /* "first": { "value":"恭喜你购买成功!", "color":"#173177" }, "keyword1":{ "value":"巧克力", "color":"#173177" }, */ } function c_array_unset_tt($arr, $key = 'goods_id') { //建立一个目标数组 $res = array(); foreach ($arr as $value) { //查看有没有重复项 if (isset($res[$value[$key]])) { unset($value[$key]); //有:销毁 } else { $res[$value[$key]] = $value; } } return $res; } function c_star_first_str($str = '') { // echo ($str) ;exit(); $str_re = str_repeat('*', mb_strlen($str) - 1); return mb_substr($str, 0, 1) . $str_re; } function c_max_len_3dot($str = '', $len = 20) { if (mb_strlen($str) <= $len) { return $str; } $str_2 = mb_substr($str, 0, $len - 3); return $str_2 . '...'; } function c_sms_fix_str($str = '') { $str = str_replace('【', '(', $str); $str = str_replace('】', ')', $str); return $str; } function c_xml_to_json($xml_str) { return json_decode(json_encode(simplexml_load_string($xml_str, 'SimpleXMLElement', LIBXML_NOCDATA)), true); } function c_formate_exception($e) { function trace_f($trace) { $xstr = ''; $i = 0; foreach ($trace as $x) { $i++; $x['file'] = $x['file'] ?? ''; $x['line'] = $x['line'] ?? ''; $x['function'] = $x['function'] ?? ''; $x['class'] = $x['class'] ?? ''; $xstr .= "[#$i] {$x['file']}:{$x['line']} {$x['function']} {$x['class']}" . PHP_EOL; } return $xstr; } return 'errror: ' . $e->getMessage() . PHP_EOL . 'file: ' . $e->getFile() . ':' . $e->getLine() . PHP_EOL . 'trace: ' . PHP_EOL . trace_f($e->getTrace()); } function c_safe_to_json($str, $catch_return = ['_' => '']) { try { $re = json_decode($str, true); } catch (Exception $e) { Log::write('转换json失败,c_safe_to_json:' . $str, 'WARN'); return $catch_return; } if (json_last_error() !== JSON_ERROR_NONE) { return $catch_return; } return $re; } function c_json_encode($data) { return json_encode($data, JSON_UNESCAPED_UNICODE); } /** * 身份证号验证 * @param $id * @return bool */ function c_is_idcard($id) { $id = strtoupper($id); $regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/"; $arr_split = array(); if (!preg_match($regx, $id)) { return FALSE; } if (15 == strlen($id)) { //检查15位 $regx = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/"; @preg_match($regx, $id, $arr_split); //检查生日日期是否正确 $dtm_birth = "19" . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4]; if (!strtotime($dtm_birth)) { return FALSE; } else { return TRUE; } } else { //检查18位 $regx = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/"; @preg_match($regx, $id, $arr_split); $dtm_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4]; if (!strtotime($dtm_birth)) { //检查生日日期是否正确 return FALSE; } else { //检验18位身份证的校验码是否正确。 //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 $arr_int = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); $arr_ch = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); $sign = 0; for ($i = 0; $i < 17; $i++) { $b = intval(substr($id . '', $i, 1)); $w = $arr_int[$i]; $sign += $b * $w; } $n = $sign % 11; $val_num = $arr_ch[$n]; if ($val_num != substr($id, 17, 1)) { return FALSE; } else { return TRUE; } } } } /** * 银行支付通用方法 */ function bank_to_pay($openid, $body, $price, $order_id, $notifyUrl) { // $appId = "8a81c1be744ea9950175dfd45869016a"; // $appKey = "4c38129bb4c64e88a5045cdf9972df1f"; $bank_appId = Config::get('app.BANK_APP_ID'); $bank_appKey = Config::get('app.BANK_APP_KEY'); $timestamp = date('YmdHis'); $nonce = md5(uniqid(microtime(true), true)); function getTimeString() { date_default_timezone_set("Asia/Shanghai"); return date("Y-m-d H:i:s", time()); //yyyy-MM-dd HH:mm:ss } function getSignHeader($appId, $appKey, $timestamp, $nonce, $body) { $b = hash("sha256", json_encode($body), false); $c = $appId . $timestamp . $nonce . $b; $e = hash_hmac('sha256', $c, $appKey, true); $f = base64_encode($e); return 'authorization: OPEN-BODY-SIG AppId="' . $appId . '",Timestamp="' . $timestamp . '",Nonce="' . $nonce . '",Signature="' . $f . '"'; } $appid = Config::get('app.APPID'); $param = [ 'mid' => Config::get('app.BANK_MID'), 'tid' => Config::get('app.BANK_TID'), 'requestTimestamp' => date("Y-m-d H:i:s", time()), 'instMid' => 'MINIDEFAULT', //业务类型 'merOrderId' => '305F' . $order_id, //账单号 'orderDesc' => $body, //账单描述 'subOpenId' => $openid, //用户openID 'totalAmount' => $price, //请求金额,整数,分为单位 'subAppId' => $appid, //小程序APPID 'tradeType' => 'MINI', 'notifyUrl' => $notifyUrl, ]; $authorization = getSignHeader($bank_appId, $bank_appKey, $timestamp, $nonce, $param); $param = json_encode($param); $url = Config::get('app.BANK_HOST') . '/v1/netpay/wx/unified-order'; Log::write($param, 'NOTICE'); $header[] = $authorization; $header[] = 'Accept:application/json'; $header[] = 'Content-Type:application/json;charset=utf-8'; $header[] = 'Content-Length:' . strlen($param); $curl = curl_init(); //初始化 curl_setopt($curl, CURLOPT_URL, $url); //设置url curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在 设为0表示不检查证书 设为1表示检查证书中是否有CN(common name)字段 设为2表示在1的基础上校验当前的域名是否与CN匹配 curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $param); curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环 curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 $reponse = curl_exec($curl); if ($reponse === false) { return ""; } $reponse = json_decode($reponse, true); if ($reponse['errCode'] != 'SUCCESS') { Log::write(json_encode($reponse), 'ERROR'); if ($reponse['errCode'] == 'DUP_ORDER') { return ['errCode' => -1, 'errMsg' => '您已经支付过了,请稍后']; } throw new ErrorException('快快快,银行支付有问题!'); } return $reponse; } /** * 银行退款通用接口 */ function bank_to_refund($order_id, $price) { // $appId = "8a81c1be744ea9950175dfd45869016a"; // $appKey = "4c38129bb4c64e88a5045cdf9972df1f"; $bank_pay_order = D('bank_pay_order')->where(['order_id' => $order_id])->find(); if (empty($bank_pay_order)) { Log::write('$bank_pay_order 不存在:' . $order_id, 'ERROR'); return ['errCode' => 'FAIL', 'reason' => 'function:bank_to_refund,info not exist']; } $bank_order_id = $bank_pay_order['bank_order_id']; $bank_info = c_safe_to_json($bank_pay_order['bank_info']); //认为不会出错 $bank_appId = $bank_info['BANK_APP_ID']; $bank_appKey = $bank_info['BANK_APP_KEY']; $timestamp = date('YmdHis'); $nonce = md5(uniqid(microtime(true), true)); function getTimeString() { date_default_timezone_set("Asia/Shanghai"); return date("Y-m-d H:i:s", time()); //yyyy-MM-dd HH:mm:ss } function getSignHeader($appId, $appKey, $timestamp, $nonce, $body) { $b = hash("sha256", json_encode($body), false); $c = $appId . $timestamp . $nonce . $b; $e = hash_hmac('sha256', $c, $appKey, true); $f = base64_encode($e); return 'authorization: OPEN-BODY-SIG AppId="' . $appId . '",Timestamp="' . $timestamp . '",Nonce="' . $nonce . '",Signature="' . $f . '"'; } $param = [ 'mid' => $bank_info['BANK_MID'], 'tid' => $bank_info['BANK_TID'], 'requestTimestamp' => date("Y-m-d H:i:s", time()), 'merOrderId' => '305F' . $order_id, //账单号 'targetOrderId' => $bank_order_id, //4200000918202101127103973012 'refundAmount' => $price, //请求金额,整数,分为单位 'refundOrderId' => '305F' . $order_id . 'D' . date("His", time()), ]; $authorization = getSignHeader($bank_appId, $bank_appKey, $timestamp, $nonce, $param); $param = json_encode($param); $url = Config::get('app.BANK_HOST') . '/v1/netpay/refund'; $header[] = $authorization; $header[] = 'Accept:application/json'; $header[] = 'Content-Type:application/json;charset=utf-8'; $header[] = 'Content-Length:' . strlen($param); $curl = curl_init(); //初始化 curl_setopt($curl, CURLOPT_URL, $url); //设置url curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在 设为0表示不检查证书 设为1表示检查证书中是否有CN(common name)字段 设为2表示在1的基础上校验当前的域名是否与CN匹配 curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $param); curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环 curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 $reponse = curl_exec($curl); if ($reponse === false) { return ""; } $reponse = json_decode($reponse, true); return $reponse; } function bank_to_query_order($order_id) { $bank_info = Config::get('app.BANK_INFO_LIST')[Config::get('app.BANK_REF_ID')]; $bank_appId = $bank_info['BANK_APP_ID']; $bank_appKey = $bank_info['BANK_APP_KEY']; $timestamp = date('YmdHis'); $nonce = md5(uniqid(microtime(true), true)); function getTimeString() { date_default_timezone_set("Asia/Shanghai"); return date("Y-m-d H:i:s", time()); //yyyy-MM-dd HH:mm:ss } function getSignHeader($appId, $appKey, $timestamp, $nonce, $body) { $b = hash("sha256", json_encode($body), false); $c = $appId . $timestamp . $nonce . $b; $e = hash_hmac('sha256', $c, $appKey, true); $f = base64_encode($e); return 'authorization: OPEN-BODY-SIG AppId="' . $appId . '",Timestamp="' . $timestamp . '",Nonce="' . $nonce . '",Signature="' . $f . '"'; } $param = [ 'mid' => $bank_info['BANK_MID'], 'tid' => $bank_info['BANK_TID'], 'requestTimestamp' => date("Y-m-d H:i:s", time()), 'merOrderId' => '305F' . $order_id, //账单号 ]; $authorization = getSignHeader($bank_appId, $bank_appKey, $timestamp, $nonce, $param); $param = json_encode($param); $url = Config::get('app.BANK_HOST') . '/v1/netpay/query'; $header[] = $authorization; $header[] = 'Accept:application/json'; $header[] = 'Content-Type:application/json;charset=utf-8'; $header[] = 'Content-Length:' . strlen($param); $curl = curl_init(); //初始化 curl_setopt($curl, CURLOPT_URL, $url); //设置url curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在 设为0表示不检查证书 设为1表示检查证书中是否有CN(common name)字段 设为2表示在1的基础上校验当前的域名是否与CN匹配 curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $param); curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环 curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 $reponse = curl_exec($curl); if ($reponse === false) { return ""; } $reponse = json_decode($reponse, true); if ($reponse['errCode'] != 'SUCCESS') { throw new ErrorException('快快快,银行支付有问题!'); } return $reponse; } function s_wx_create_mp_qrcode($scene_str = '', $scene_id = '', $action_name = '', $expire_seconds = 2592000) { $gzh_ac_tk = Cache::get(Constant::$GZH_ACCESS_TOKEN); $data = ['action_info' => ['scene' => []]]; $data['action_name'] = $action_name; if ($action_name == 'QR_LIMIT_SCENE' || $action_name == 'QR_LIMIT_STR_SCENE') { // } else { $data['expire_seconds'] = $expire_seconds; } if ($scene_str) { if (!$data['action_name']) { $data['action_name'] = 'QR_STR_SCENE'; } $data['action_info']['scene']['scene_str'] = $scene_str; } else { if ($scene_id) { if (!$data['action_name']) { $data['action_name'] = 'QR_SCENE'; } $data['action_info']['scene']['scene_id'] = $scene_id; } } // print_r(json_encode($data)); c_debug($data,'debug_xxxxxxxxxxx'); $res = http_post_json('https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token='.$gzh_ac_tk, json_encode($data)); // print_r($res); $json = c_safe_to_json($res); //{"ticket":"gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm\3sUw==","expire_seconds":60,"url":"http://weixin.qq.com/q/kZgfwMTm72WWPkovabbI"} return $json; } function s_put_queue($type, $data) {} function s_tstc_http($url, $data, $pid, $auth_key) { $data['_pid'] = $pid; ksort($data); $p_list = [$auth_key]; foreach ($data as $key => $one) { if (is_array($one)) { ksort($one); foreach ($one as $k2 => $v2) { ksort($v2); $one[$k2] = $v2; } $data[$key] = $one; } } foreach ($data as $key => $one) { $t_one = $one; if (is_array($one)) { $t_one = '['; foreach ($one as $k => $v) { $t_one .= '' . $k . '=['; $p2_list = []; foreach ($v as $k2 => $v2) { $p2_list[] = $k2 . '=' . $v2; } $t_one .= implode('&', $p2_list); $t_one .= ']'; } $t_one .= ']'; } $p_list[] = $key . '=' . $t_one; } $p_list[] = $auth_key; echo $p_str = implode('&', $p_list); // $p_str = http_build_query($data); // echo $p_str = urldecode($p_str); $data['_sig'] = md5($p_str); //echo http_build_query( $data ); $ci = curl_init(); curl_setopt_array($ci, array( CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 30, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => 'gzip', CURLOPT_SSL_VERIFYPEER => false, CURLOPT_HEADER => false, CURLINFO_HEADER_OUT => true, )); curl_setopt($ci, CURLOPT_POST, true); curl_setopt($ci, CURLOPT_POSTFIELDS, http_build_query($data)); curl_setopt($ci, CURLOPT_URL, $url); $response = curl_exec($ci); curl_close($ci); if ($response) { return c_safe_to_json($response); } Log::write('天时同城请求错误:' . json_decode($url, $data, $pid), 'ERROR'); return ['_' => '_']; } function qs_http_post($host, $port, $query, $body) { $fp = fsockopen($host, $port, $errno, $errstr, 1); if (!$fp) { return false; } $header = ''; $out = "POST ${query} HTTP/1.1\r\n"; $out .= "Host: ${host}\r\n"; $out .= "Content-Length: " . strlen($body) . "\r\n"; $out .= "Connection: close\r\n"; $out .= "\r\n"; $out .= $body; fwrite($fp, $out); $line = trim(fgets($fp)); $header .= $line; list($proto, $rcode, $result) = explode(" ", $line); $len = -1; while (($line = trim(fgets($fp))) != "") { $header .= $line; if (strstr($line, "Content-Length:")) { list($cl, $len) = explode(" ", $line); } if (strstr($line, "Connection: close")) { $close = true; } } if ($len < 0) { return false; } $body = @fread($fp, $len); if ($close) fclose($fp); return $body; } function qs_put($host, $port, $charset = 'utf-8', $name, $data) { $result = qs_http_post($host, $port, "/?charset=".$charset."&name=".$name."&opt=put", $data); if ($result == "HTTPSQS_PUT_OK") { return true; } return false; } function c_now() { return c_date(time()); } function c_date($time) { $time = $time ?: time(); return date("Y-m-d H:i:s", $time); }