350 lines
16 KiB
PHP
350 lines
16 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
namespace app\controller\Bus;
|
|||
|
|
|
|||
|
|
use app\controller\Aes;
|
|||
|
|
use app\controller\HardMessage;
|
|||
|
|
use app\controller\HMACMD5;
|
|||
|
|
use app\model\ChargeOrder as ChargeOrderModel;
|
|||
|
|
use app\model\Vinlicense;
|
|||
|
|
use app\Request;
|
|||
|
|
use DateInterval;
|
|||
|
|
use DateTime;
|
|||
|
|
use Firebase\JWT\JWT;
|
|||
|
|
use Firebase\JWT\Key;
|
|||
|
|
use Overtrue\Pinyin\Pinyin;
|
|||
|
|
use think\facade\Db;
|
|||
|
|
use think\facade\Log;
|
|||
|
|
|
|||
|
|
|
|||
|
|
class PlugCharge
|
|||
|
|
{
|
|||
|
|
public function insert_start_charge(Request $request)
|
|||
|
|
{
|
|||
|
|
$params = file_get_contents('php://input');
|
|||
|
|
$params = json_decode($params, true);
|
|||
|
|
$OperatorID = empty($params['OperatorID']) ? '' : $params['OperatorID'];
|
|||
|
|
$authorization = $request->header()['authorization'];//传递过来的token
|
|||
|
|
$auths = explode(' ', trim($authorization));
|
|||
|
|
$auth = $auths[count($auths) - 1];
|
|||
|
|
$checkParams = $this->checkParams($params);
|
|||
|
|
if ($checkParams != 2)
|
|||
|
|
return json(['Msg' => $checkParams . '为空', 'Ret' => 4003, 'Data' => ['Status' => 1]]);
|
|||
|
|
if ($auth) {
|
|||
|
|
if ($this->checkToken_assess($auth) == 1) {
|
|||
|
|
$data = json_encode(['Status' => 1]);
|
|||
|
|
$data = $this->Encrypt($data);
|
|||
|
|
$seq = empty($Seq) ? '0001' : $params['Seq'];
|
|||
|
|
$datetime = empty($TimeStamp) ? date('YmdHis') : $params['TimeStamp'];
|
|||
|
|
$sig = $OperatorID . $data . $datetime . $seq;
|
|||
|
|
$s = $this->HmacMD5($sig);
|
|||
|
|
return json(['Msg' => 'Token过期或者无效', 'Ret' => 4002, 'Data' => $data, 'Sig' => $s]);
|
|||
|
|
}
|
|||
|
|
$checkSig = $this->checkSig($params['OperatorID'], $params);
|
|||
|
|
if ($checkSig == 1) {
|
|||
|
|
$data = json_encode(['Status' => 1]);
|
|||
|
|
$data = $this->Encrypt($data);
|
|||
|
|
$seq = empty($Seq) ? '0001' : $params['Seq'];
|
|||
|
|
$datetime = empty($TimeStamp) ? date('YmdHis') : $params['TimeStamp'];
|
|||
|
|
$sig = $OperatorID . $data . $datetime . $seq;
|
|||
|
|
$s = $this->HmacMD5($sig);
|
|||
|
|
return json(['Msg' => '签名错误', 'Ret' => 4001, 'Data' => $data, 'Sig' => $s]);
|
|||
|
|
}
|
|||
|
|
$data = $this->Decrypt($params['Data']);
|
|||
|
|
$data = json_decode($data, true);
|
|||
|
|
if (isset($data['vin']) && isset($data['connectorID'])) {
|
|||
|
|
Log::write("The Plug Message come on :" . $data['vin'] . $data['connectorID']);
|
|||
|
|
$CheckVinIsExist = Db::table('vinlicense')->where('EvcInfoNo', $data['vin'])->find();
|
|||
|
|
if (!empty($CheckVinIsExist)) {
|
|||
|
|
$AppointmentTime = Db::table('appointment_time')->where('id', 1)->value('AppointmentTime');
|
|||
|
|
$currentDate = new DateTime();
|
|||
|
|
$combinedDateTime = new DateTime($currentDate->format('Y-m-d') . ' ' . $AppointmentTime);
|
|||
|
|
$AppointmentTime = $combinedDateTime->format('Y-m-d H:i:s');
|
|||
|
|
$nowTime = $currentDate->format('Y-m-d H:i:s');
|
|||
|
|
$nowDay = $currentDate->format('Y-m-d');
|
|||
|
|
$check = Db::table('appointment')->whereDay('action_time', $nowDay)->where('Vin', $data['vin'])->where('ConnectorID', $data['connectorID'])->find();
|
|||
|
|
if (empty($check)) {
|
|||
|
|
Db::table('appointment')->save(['action_time' => $nowTime, 'ConnectorID' => $data['connectorID'], 'Vin' => $data['vin'], 'plug_time' => $AppointmentTime]);
|
|||
|
|
}
|
|||
|
|
// $check = Db::table('appointment')->whereDay('action_time', $nowDay)->where('Vin', $data['vin'])->find();
|
|||
|
|
// if (empty($check)) {
|
|||
|
|
// Db::table('appointment')->save(['action_time' => $nowTime, 'ConnectorID' => $data['connectorID'], 'Vin' => $data['vin'], 'plug_time' => $AppointmentTime]);
|
|||
|
|
// } else {
|
|||
|
|
// $checkVin = Db::table('appointment')->whereDay('action_time', $nowDay)->where('Vin', $data['vin'])->value('ConnectorID');
|
|||
|
|
// if ($checkVin != $data['connectorID']) {
|
|||
|
|
// Db::table('appointment')->whereDay('action_time', $nowDay)->where('Vin', $data['vin'])->save(['action_time' => $nowTime, 'ConnectorID' => $data['connectorID']]);
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
}
|
|||
|
|
$kk['SuccStat'] = 0;
|
|||
|
|
$kk['FailReason'] = 0;
|
|||
|
|
return $this->encodeData($kk, $params, 0);
|
|||
|
|
} else {
|
|||
|
|
$kk['SuccStat'] = 1;
|
|||
|
|
$kk['FailReason'] = 1;
|
|||
|
|
return $this->encodeData($kk, $params, 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return $this->encodeData(['Status' => 1], $params, 4002, 'Bearer 未添加');
|
|||
|
|
// $OperatorID = Config::get('hard.OperatorID');
|
|||
|
|
// $OperatorSecret = Config::get('hard.OperatorSecret');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public function PlugGennerateOrder($ConnectorID, $vin): array
|
|||
|
|
{
|
|||
|
|
$station_id = Db::table('charge_pile')->where('ConnectorID', $ConnectorID)->value('charge_station_id');
|
|||
|
|
$EquipAuthSeq = Db::table('charge_pile')->where('ConnectorID', $ConnectorID)->value('EquipAuthSeq');
|
|||
|
|
$no = Db::table('charge_pile')->where('ConnectorID', $ConnectorID)->value('no');
|
|||
|
|
if (empty($EquipAuthSeq)) {
|
|||
|
|
$EquipAuthSeq = $this->generate_EquipmentAuth(7);
|
|||
|
|
Db::table('charge_pile')->where('ConnectorID', $ConnectorID)->update(['EquipAuthSeq' => $EquipAuthSeq]);
|
|||
|
|
}
|
|||
|
|
$Hard = new HardMessage();
|
|||
|
|
$openid = 'o-wLg5DGWU_rYwfmp1-1Wck1lKGw';
|
|||
|
|
$area = Db::table('user')->where('openid', $openid)->value('area');
|
|||
|
|
$pinyin = new Pinyin();
|
|||
|
|
$s = $pinyin->sentence($area);
|
|||
|
|
$s = strtr($s, array(' ' => ''));
|
|||
|
|
$table = 'charge_order_' . $s;
|
|||
|
|
$table_user = 'user_' . $s;
|
|||
|
|
$AuthMessage = $Hard->Get_query_equip_auth($EquipAuthSeq, $ConnectorID);
|
|||
|
|
if (isset($AuthMessage['FailReason']) && isset($AuthMessage['SuccStat'])) {//认证成功 请求启动充电
|
|||
|
|
if ($AuthMessage['FailReason'] == 0 && $AuthMessage['SuccStat'] == 0) {
|
|||
|
|
$StartChargeSeq = $this->generate_StartChargeSeq(7);
|
|||
|
|
ChargeOrderModel::insert(['openid' => $openid, 'area' => $area, 'StartChargeSeq' => $StartChargeSeq]);
|
|||
|
|
$ChargeModel = 1;
|
|||
|
|
$StartCharge = $Hard->Get_query_start_charge_test($StartChargeSeq, $ConnectorID, 'QRCode', $ChargeModel, $vin); //ChargeModel vin
|
|||
|
|
if ($StartCharge['StartChargeSeqStat'] == 1 && $StartCharge['SuccStat'] == 0 && $StartCharge['FailReason'] == 0) {
|
|||
|
|
$order_number = $this->generate_order(6);
|
|||
|
|
$charge_date = date('Y-m-d', time());
|
|||
|
|
$account = 200;
|
|||
|
|
$Equipment_number = Db::table('charge_pile')->where('ConnectorID', $ConnectorID)->value('charge_pile_number');
|
|||
|
|
$mess = [
|
|||
|
|
'order_number' => $order_number,
|
|||
|
|
'charge_station_id' => $station_id,
|
|||
|
|
'openid' => $openid,
|
|||
|
|
'charge_date' => $charge_date,
|
|||
|
|
'Equipment_number' => $Equipment_number,
|
|||
|
|
'StartChargeSeq' => $StartChargeSeq,
|
|||
|
|
'status' => $StartCharge['StartChargeSeqStat'],
|
|||
|
|
'StartChargeSeqStat' => $StartCharge['StartChargeSeqStat'],
|
|||
|
|
'ConnectorID' => $ConnectorID,
|
|||
|
|
'WithholdingMoney' => $account,
|
|||
|
|
'EvcInfoNo' => $vin
|
|||
|
|
];
|
|||
|
|
Db::table($table_user)->where('openid', $openid)->update(['account' => Db::raw('account-' . $account)]);
|
|||
|
|
Db::table($table)->save($mess);
|
|||
|
|
$time = date('Y-m-d H:i:s');
|
|||
|
|
Log::write('Reservation order has been generated. The Message is ' . $time . json($mess)->getContent());
|
|||
|
|
return ['code' => 200, 'message' => '订单创建成功', 'order_number' => $order_number];
|
|||
|
|
} elseif ($StartCharge['SuccStat'] == 1) {
|
|||
|
|
if ($StartCharge['FailReason'] == 0) {
|
|||
|
|
return ['code' => 1, 'message' => '设备认证操作结果失败'];
|
|||
|
|
} elseif ($StartCharge['FailReason'] == 1) {
|
|||
|
|
return ['code' => 1, 'message' => '设备认证操作结果失败 此设备不存在'];
|
|||
|
|
} elseif ($StartCharge['FailReason'] == 2) {
|
|||
|
|
return ['code' => 1, 'message' => '设备认证操作结果失败 此设备离线'];
|
|||
|
|
} elseif ($StartCharge['FailReason'] == 90) {
|
|||
|
|
return ['code' => 1, 'message' => '设备认证操作结果失败 车辆未备案'];
|
|||
|
|
} elseif ($StartCharge['FailReason'] == 91) {
|
|||
|
|
return ['code' => 2, 'message' => '设备认证操作结果失败 该车辆充电中'];
|
|||
|
|
} else {
|
|||
|
|
return ['code' => 1, 'message' => '未知错误 设备认证成功 请求充电失败'];
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return ['code' => 1, 'message' => '未知错误 设备认证成功 请求充电失败'];
|
|||
|
|
}
|
|||
|
|
} elseif ($AuthMessage['SuccStat'] == 1) {
|
|||
|
|
if ($AuthMessage['FailReason'] == 0) {
|
|||
|
|
return ['code' => 1, 'message' => '设备认证操作结果失败'];
|
|||
|
|
} elseif ($AuthMessage['FailReason'] == 1) {
|
|||
|
|
return ['code' => 1, 'message' => '设备认证操作结果失败 此设备尚未插枪'];
|
|||
|
|
} elseif ($AuthMessage['FailReason'] == 2) {
|
|||
|
|
return ['code' => 1, 'message' => '设备认证操作结果失败 设备检测失败'];
|
|||
|
|
} else {
|
|||
|
|
return ['code' => 1, 'message' => '未知错误 设备认证失败'];
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return ['code' => 1, ' message' => '未知错误 设备认证失败'];
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
return ['code' => 1, 'message' => '未知错误 设备认证失败'];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public function ModifyAppointmentTime($time): \think\response\Json
|
|||
|
|
{
|
|||
|
|
$dateTime = new DateTime($time);
|
|||
|
|
$formattedTime = $dateTime->format('H:i:s');
|
|||
|
|
$modify = Db::table('appointment_time')->where('id', 1)->save(['AppointmentTime' => $formattedTime]);
|
|||
|
|
if ((int)$modify == 1) {
|
|||
|
|
return json(['code' => 200, 'msg' => '修改成功']);
|
|||
|
|
} else {
|
|||
|
|
return json(['code' => 1, 'msg' => '修改失败']);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public function ShowAppointmentTime(): \think\response\Json
|
|||
|
|
{
|
|||
|
|
$AppointmentTime = Db::table('appointment_time')->where('id', 1)->value('AppointmentTime');
|
|||
|
|
return json(['code' => 200, 'msg' => '显示成功', 'data' => $AppointmentTime]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function generate_StartChargeSeq($length): string
|
|||
|
|
{
|
|||
|
|
$chars = '0123456789';
|
|||
|
|
$time = time();
|
|||
|
|
$password = config('hard.OperatorID') . $time . '2';//2代表是生成的充电订单号
|
|||
|
|
for ($i = 0; $i < $length; $i++) {
|
|||
|
|
$password .= $chars[mt_rand(0, strlen($chars) - 1)];
|
|||
|
|
}
|
|||
|
|
return $password;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function generate_order($length): string
|
|||
|
|
{
|
|||
|
|
$chars = '0123456789';
|
|||
|
|
$time = time();
|
|||
|
|
$password = 'DZZS' . $time;
|
|||
|
|
for ($i = 0; $i < $length; $i++) {
|
|||
|
|
$password .= $chars[mt_rand(0, strlen($chars) - 1)];
|
|||
|
|
}
|
|||
|
|
return $password;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function generate_EquipmentAuth($length): string
|
|||
|
|
{
|
|||
|
|
$chars = '0123456789';
|
|||
|
|
$time = time();
|
|||
|
|
$password = config('hard.OperatorID') . $time . '1';//1代表是生成的设备认证流水号
|
|||
|
|
for ($i = 0; $i < $length; $i++) {
|
|||
|
|
$password .= $chars[mt_rand(0, strlen($chars) - 1)];
|
|||
|
|
}
|
|||
|
|
return $password;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public function Encrypt($data): string
|
|||
|
|
{
|
|||
|
|
$aes = new Aes();
|
|||
|
|
return $aes->encrypt($data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function Decrypt($data)
|
|||
|
|
{
|
|||
|
|
$aes = new Aes();
|
|||
|
|
return $aes->decrypt($data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function HmacMD5($data): string
|
|||
|
|
{
|
|||
|
|
$md5 = new HMACMD5();
|
|||
|
|
return $md5->HMAC($data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function CurlSend($url, $data = '', $token = '')
|
|||
|
|
{
|
|||
|
|
$data = json_encode($data);
|
|||
|
|
// echo $data;
|
|||
|
|
$ch = curl_init();
|
|||
|
|
$headers = array();
|
|||
|
|
if ($token) {
|
|||
|
|
$headers[] = 'Authorization: Bearer ' . $token;
|
|||
|
|
}
|
|||
|
|
$headers[] = 'Content-Type: application/json;charset=utf-8';
|
|||
|
|
$headers[] = 'Content-Length: ' . strlen($data);
|
|||
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|||
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
|
|||
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
|
|||
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|||
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|||
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
|||
|
|
curl_setopt($ch, CURLOPT_POST, 1);
|
|||
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
|||
|
|
$curl_return = curl_exec($ch);
|
|||
|
|
curl_close($ch);
|
|||
|
|
return json_decode(trim($curl_return), true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function checkParams($params)
|
|||
|
|
{
|
|||
|
|
$arr = ['OperatorID', 'Data', 'TimeStamp', 'Seq', 'Sig'];
|
|||
|
|
// 参数检查
|
|||
|
|
foreach ($arr as $v) {
|
|||
|
|
if (empty($params[$v])) {
|
|||
|
|
return $v;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function checkSig($OperatorID, $params): int
|
|||
|
|
{
|
|||
|
|
$sig = $OperatorID . $params['Data'] . $params['TimeStamp'] . $params['Seq'];
|
|||
|
|
$ecry_sig = $this->HmacMD5($sig);
|
|||
|
|
if ($params['Sig'] != $ecry_sig) {
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
return 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
public function signToken(): string
|
|||
|
|
{
|
|||
|
|
$key = config('hard.DataSecretIV'); //这里是自定义的一个随机字串,应该写在config文件中的,解密时也会用,相当 于加密中常用的 盐 salt
|
|||
|
|
$token = array(
|
|||
|
|
"iss" => $key, //签发者 可以为空
|
|||
|
|
"aud" => '', //面象的用户,可以为空
|
|||
|
|
"iat" => time(), //签发时间
|
|||
|
|
"nbf" => time() + 1, //在什么时候jwt开始生效 (这里表示生成100秒后才生效)
|
|||
|
|
"exp" => time() + 7200, //token 过期时间
|
|||
|
|
"data" => [ //记录的userid的信息,这里是自已添加上去的,如果有其它信息,可以再添加数组的键值对
|
|||
|
|
'name' => 'zuxing'
|
|||
|
|
]
|
|||
|
|
);
|
|||
|
|
// print_r($token);
|
|||
|
|
$jwt = JWT::encode($token, $key, "HS256"); //根据参数生成了 token
|
|||
|
|
return $jwt;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//验证token
|
|||
|
|
private function checkToken_assess($token): int
|
|||
|
|
{
|
|||
|
|
$key = config('hard.DataSecretIV');
|
|||
|
|
$key = new Key($key, 'HS256');
|
|||
|
|
$status = array("code" => 2);
|
|||
|
|
try {
|
|||
|
|
JWT::$leeway = 60;//当前时间减去60,把时间留点余地
|
|||
|
|
$decoded = JWT::decode($token, $key, array('HS256')); //HS256方式,这里要和签发的时候对应
|
|||
|
|
$arr = (array)$decoded;
|
|||
|
|
$res['code'] = 1;
|
|||
|
|
$res['data'] = $arr['data'];
|
|||
|
|
return 2;
|
|||
|
|
|
|||
|
|
} catch (\Firebase\JWT\SignatureInvalidException $e) { //签名不正确
|
|||
|
|
$status['msg'] = "签名不正确";
|
|||
|
|
return 1;
|
|||
|
|
} catch (\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
|
|||
|
|
$status['msg'] = "token失效";
|
|||
|
|
return 1;
|
|||
|
|
} catch (\Firebase\JWT\ExpiredException $e) { // token过期
|
|||
|
|
$status['msg'] = "token失效";
|
|||
|
|
return 1;
|
|||
|
|
} catch (\Exception $e) { //其他错误
|
|||
|
|
$status['msg'] = "未知错误";
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private function encodeData($data, $params, $ret, $msg = ''): \think\response\Json
|
|||
|
|
{
|
|||
|
|
$data = json_encode($data);
|
|||
|
|
$data = $this->Encrypt($data);
|
|||
|
|
$seq = empty($Seq) ? '0001' : $params['Seq'];
|
|||
|
|
$datetime = empty($TimeStamp) ? date('YmdHis') : $params['TimeStamp'];
|
|||
|
|
$sig = $params['OperatorID'] . $data . $datetime . $seq;
|
|||
|
|
$s = $this->HmacMD5($sig);
|
|||
|
|
return json(['Msg' => $msg, 'Ret' => $ret, 'Data' => $data, 'Sig' => $s]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|