Files
charge-pile-serve/app/controller/Bus/PlugCharge.php
MeSHard 94f7e83679 init
2025-11-10 16:12:07 +08:00

350 lines
16 KiB
PHP
Raw Permalink 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
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]);
}
}