liiistem-miniapp/app/common.php

1279 lines
No EOL
40 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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);
}