1279 lines
No EOL
40 KiB
PHP
1279 lines
No EOL
40 KiB
PHP
<?php
|
||
|
||
use think\facade\Config;
|
||
use think\facade\Db;
|
||
use think\facade\Log;
|
||
use think\facade\Cache;
|
||
use app\Constant;
|
||
// 应用公共文件
|
||
/**
|
||
* m_开头的是 业务通用方法
|
||
* c 开头是基础方法
|
||
* 有些不是m和c开头的.是基础方法,
|
||
*/
|
||
|
||
/**
|
||
* 快捷方法
|
||
*
|
||
* @param [type] $name
|
||
*/
|
||
function D($name) {
|
||
return Db::table($name, [], false);
|
||
}
|
||
function DQ($sql, $value = []) {
|
||
return Db::query($sql, $value);
|
||
}
|
||
function D2($name) {
|
||
return Db::connect('mysql2')->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) {
|
||
/*<xml>
|
||
<return_code><![CDATA[SUCCESS]]></return_code>
|
||
<return_msg><![CDATA[OK]]></return_msg>
|
||
<appid><![CDATA[wx3c5f8f6a8ff6954b]]></appid>
|
||
<mch_id><![CDATA[1579360191]]></mch_id>
|
||
<nonce_str><![CDATA[cp6wwNef4GOeHyk2]]></nonce_str>
|
||
<sign><![CDATA[91F7CC6640922C8ABA5960778ADE30B1]]></sign>
|
||
<result_code><![CDATA[SUCCESS]]></result_code>
|
||
<prepay_id><![CDATA[wx2401465457053258a360ba621918835100]]></prepay_id>
|
||
<trade_type><![CDATA[JSAPI]]></trade_type>
|
||
</xml>
|
||
*/
|
||
// $res = str_replace(' ', '', $res);
|
||
// $res = str_replace('<xml>', '', $res);
|
||
// $res = str_replace('</xml>', '', $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('<![CDATA[', '', $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('<![CDATA[]]>', '<![CDATA[-]]>', $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);
|
||
} |