liiistem-miniapp/app/common.php

1279 lines
40 KiB
PHP
Raw Normal View History

2025-09-18 10:36:08 +08:00
<?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);
}