封装成了个类,参数有注解,请自行更正没有的类,没有的方法
httpRequest();方法类中有,不需要 json_encode
代码如下:
<?php
/**
* @author lianyu001 <1411479499@qq.com>
* start_time 2022-06-28
* up_time 2022-06-28
* end_time 2022-06-28
*/
if (!defined('WY_ROOT'))
exit;
require_once dirname(WY_ROOT) . '/ApiV1/function_apiv1.php';
Class baidu_applet_config {
private $appid = 'xxx'; //账号名
private $secred = 'xxx'; //账号密码
/**
* 百度小程序一键登录获取 手机号
* @param str $code 由swan.login获取的临时登录凭证,找前端要
* @param str $sign 待解密数据,encryptedData,找前端小程序要
* @param str $iv 加密向量,返回的内容中的iv字段,找前端要
* @return ary[code,msg,data] 200正常,data.mobile 其他抛出msg
*/
function get_mobile($code, $sign, $iv) {
$pub = new ALLClass();
$url = 'https://spapi.baidu.com/oauth/jscode2sessionkey';
$data = array(
"code" => $code,
"client_id" => $this->appid,
"sk" => $this->secred
);
$res = $pub->httpRequest($url, "POST", json_encode($data));
$res_arr = json_decode($res, TRUE);
if (isset($res_arr['session_key'])) {
$phone = $this->decrypt($sign, $iv, $this->appid, $res_arr['session_key']);
if (!!$phone) {
$mobile = json_decode($phone, TRUE);
return ['msg' => 'Success.', 'data' => $mobile, 'code' => 200];
} else {
return ['msg' => '解密失败,请检查参数', 'code' => 403];
}
} else {
return ['code' => 500, 'msg' => '百度小程序登录错误,请检查code是否过期'];
}
}
/**
* 数据解密:低版本使用mcrypt库(PHP < 5.3.0),高版本使用openssl库(PHP >= 5.3.0)。
* 官方提供解密方法 https://smartprogram.baidu.com/docs/develop/function/login_userdata/
* @param string $ciphertext 待解密数据,返回的内容中的data字段
* @param string $iv 加密向量,返回的内容中的iv字段
* @param string $app_key 创建小程序时生成的app_key
* @param string $session_key 登录的code换得的
* @return string | false
*/
function decrypt($ciphertext, $iv, $app_key, $session_key) {
$session_key = base64_decode($session_key);
$iv = base64_decode($iv);
$ciphertext = base64_decode($ciphertext);
$plaintext = false;
if (function_exists("openssl_decrypt")) {
$plaintext = openssl_decrypt($ciphertext, "AES-192-CBC", $session_key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
} else {
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, null, MCRYPT_MODE_CBC, null);
mcrypt_generic_init($td, $session_key, $iv);
$plaintext = mdecrypt_generic($td, $ciphertext);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}
if ($plaintext == false) {
return false;
}
// trim pkcs#7 padding
$pad = ord(substr($plaintext, -1));
$pad = ($pad < 1 || $pad > 32) ? 0 : $pad;
$plaintext = substr($plaintext, 0, strlen($plaintext) - $pad);
// trim header
$plaintext = substr($plaintext, 16);
// get content length
$unpack = unpack("Nlen/", substr($plaintext, 0, 4));
// get content
$content = substr($plaintext, 4, $unpack['len']);
// get app_key
$app_key_decode = substr($plaintext, $unpack['len'] + 4);
return $app_key == $app_key_decode ? $content : false;
}
/**
* CURL请求
* @param $url 请求url地址
* @param $method 请求方法 get post
* @param null $postfields post数据数组
* @param array $headers 请求header信息
* @param bool|false $debug 调试开启 默认false
* @return mixed
*/
function httpRequest($url, $method = "GET", $postfields = [], $headers = array(), $debug = false) {
$method = strtoupper($method);
$ci = curl_init();
/* Curl settings */
curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在发起连接前等待的时间,如果设置为0,则无限等待 */
curl_setopt($ci, CURLOPT_TIMEOUT, 7); /* 设置cURL允许执行的最长秒数 */
curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
switch ($method) {
case "POST":
curl_setopt($ci, CURLOPT_POST, true);
$tmpdatastr = is_array($postfields) ? http_build_query($postfields) : $postfields;
curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr);
break;
case "GET":
$params = "";
foreach ($postfields as $k => $v) {
$params .= $k . "=" . urlencode($v) . "&";
}
curl_setopt($ci, CURLOPT_POSTFIELDS, $params);
break;
default:
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */
break;
}
$ssl = preg_match('/^https:\/\//i', $url) ? TRUE : FALSE;
curl_setopt($ci, CURLOPT_URL, $url);
if ($ssl) {
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在
}
//curl_setopt($ci, CURLOPT_HEADER, true); /*启用时会将头文件的信息作为数据流输出*/
curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ci, CURLOPT_MAXREDIRS, 2); /* 指定最多的HTTP重定向的数量,这个选项是和CURLOPT_FOLLOWLOCATION一起使用的 */
curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ci, CURLINFO_HEADER_OUT, true);
/* curl_setopt($ci, CURLOPT_COOKIE, $Cookiestr); * *COOKIE带过去** */
$response = curl_exec($ci);
$requestinfo = curl_getinfo($ci);
$http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
if ($debug) {
echo "=====post data======\r\n";
var_dump($postfields);
echo "=====info===== \r\n";
print_r($requestinfo);
echo "=====response=====\r\n";
print_r($response);
}
curl_close($ci);
return $response;
//return array($http_code, $response,$requestinfo);
}
}
调用如下:
<?php
echo json_encode(get_baidu_mobile());
/**
* 百度一键登录解密取号
*/
function get_baidu_mobile() {
$parm = parameters_certification(['code', 'iv', 'sign']);
if (!$parm) {
return ['code' => 404, 'msg' => '参数错误.'];
}
require_once WY_ROOT . '/config/baidu_applet_config.php';//你的类文件
$cc = new baidu_applet_config();//new一个女朋友,当然也可以在类中设置静态方法 :: 直接调用就不用new了
$bb=$cc->get_mobile($parm['code'], $parm['sign'], $parm['iv']);
if($bb['code'] == 200){
$_REQUEST['mobile']=$bb['data']['mobile'];
$_REQUEST['login_type']=5;
return login('1');
}
return $bb;
}
/**
* 参数验证
* @param array $field 参数索引数组【'a','b'】
* @param array $data 需要验证数组,不传拿$_REQUEST
* @return boolean | array 不存在参数,空参数返回false,否则返回验证数组
*/
function parameters_certification($field = [], $data = []) {
if (empty($data)) {
$data = $_REQUEST;
}
if (empty($field)) {
return $data;
}
foreach ($field as $val) {
if (isset($data[$val])) {
if (is_array($data[$val])) {
if (empty($data[$val])) {
return false;
} else {
continue;
}
}
if (strlen($data[$val]) > 0) {
continue;
} else {
return false;
}
} else {
return false;
}
}
return $data;
}
?>
很简单的,偏偏找不到百度的正确方式
官方demo也给出错误的引导,这文档跳过来,跳过去,很令人懵逼,心态不好还容易暴躁。
步骤:
1.通过前端获取code、iv、sign
2.后端引入类
3.调用类中方法解密输出