From 5f4e567814315e794a2fdc87e0b4bf7bfa55e655 Mon Sep 17 00:00:00 2001 From: wucongxing <815046773@qq.com> Date: Wed, 19 Apr 2023 09:20:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3ca=E7=AD=BE=E7=AB=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controller/TestController.php | 563 ++++-------------------------- app/Model/UserCaCert.php | 3 +- extend/Ca/Base.php | 105 ------ extend/Ca/Ca.php | 173 ++++++--- extend/Ca/CaOffline.php | 278 +-------------- extend/Ca/CaOnline.php | 65 ++++ 6 files changed, 248 insertions(+), 939 deletions(-) delete mode 100644 extend/Ca/Base.php create mode 100644 extend/Ca/CaOnline.php diff --git a/app/Controller/TestController.php b/app/Controller/TestController.php index ab3fa22..f373a73 100644 --- a/app/Controller/TestController.php +++ b/app/Controller/TestController.php @@ -32,6 +32,8 @@ use App\Services\UserDoctorService; use App\Utils\Log; use Extend\Alibaba\Oss; use Extend\Ca\Ca; +use Extend\Ca\CaOffline; +use Extend\Ca\CaOnline; use Extend\Kuaidi100\Kuaidi; use Extend\Prescription\Prescription; use Extend\RegulatoryPlatform\regulatoryPlatform; @@ -50,29 +52,16 @@ use TCPDF; class TestController extends AbstractController { public function test(){ -// $this->test_8(); -// $this->test_3(); -// $this->test_4(); -// $this->test_6(); -// $this->test_9(); -// $this->test_10(); -// $this->test_11(); -// $this->test_5(); -// $this->test_1(); -// $this->test_11(); -// $this->test_12(); -// $this->test_13(); - $this->test_14(); } // 获取云证书-首次 public function test_1(){ - $ca = new Ca(); + $CaOffline = new CaOffline(); // // 测试医生 // $data = array(); // $data['user_id'] = "491925054435950592"; // $data['card_num'] = "410323199603261241"; -// $result = $ca->getCloudCert($data); +// $result = $CaOffline->getCloudCert($data); // // $data = array(); // $data['user_id'] = "491925054435950592"; @@ -89,7 +78,7 @@ class TestController extends AbstractController // $data = array(); // $data['user_id'] = "534534546"; // $data['card_num'] = "410323199603261240"; -// $result = $ca->getCloudCert($data); +// $result = $CaOffline->getCloudCert($data); // // $data = array(); // $data['user_id'] = "534534546"; @@ -106,7 +95,7 @@ class TestController extends AbstractController // $data = array(); // $data['user_id'] = "5345345461"; // $data['card_num'] = "91510106MABTJY4K9R"; -// $result = $ca->getCloudCert($data,"Organizational"); +// $result = $CaOffline->getCloudCert($data,"Organizational"); // // $data = array(); // $data['is_system'] = 1; @@ -120,480 +109,6 @@ class TestController extends AbstractController // } } - // 获取用户云证书数据-验证PKCS7签名 - public function test_2(){ - $ca = new Ca(); - - $params = array(); - $params['user_id'] = "491925054435950592"; - $doctor_pharmacist_cert = UserCaCert::getOne($params); - if (empty($doctor_pharmacist_cert)){ - return fail(HttpEnumCode::HTTP_ERROR,"用户数据错误"); - } - - // 获取云证书签名 - $data = array(); - $data['created_at'] = "2023-03-01 12:44:10"; - $data['department_custom_name'] = "外科"; - $data['user_name'] = "测试用户1"; - $data['sex'] = "男"; - $data['age'] = 19; - $data['allergy_history'] = "无"; - $data['icd_name'] = "感冒"; - $data['doctor_advice'] = "多吃药"; - $data['product'] = [ - [ - "product_name" => "感冒药1(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - [ - "product_name" => "感冒药2(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - [ - "product_name" => "感冒药3(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - [ - "product_name" => "感冒药4(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - [ - "product_name" => "感冒药5(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - ]; - - $result = $ca->getCertSign("491925054435950592","491925054435950592",$data); - - // 验证PKCS7签名-验证无需处理,只要不返回错误即可 - $ca->verifyPkcs7($result['signP7'],$data); - } - - // 添加签章配置(首次) - public function test_3(){ - $ca = new Ca(); - -// // 下载阿里云图片 -// $oss = new Oss(); -// -// $filename = "applet/doctor/cert/f2abdb81-fac0-4264-bc11-aa2b6cf2761c.png"; -// -// $style = "image/resize,m_lfit,w_100,h_350"; -// -// $sign_image = $oss->getCusTomObjectToRAM($filename,$style); -// $sign_image = base64_encode($sign_image); -// if (!$sign_image){ -// return fail(HttpEnumCode::SERVER_ERROR); -// } -// -// $sign_param = [ -// [ -// "llx"=> "500", // 左边底部X坐标 -// "lly"=>"3015", // 左边底部Y坐标 -// "urx"=>"850", // 右边上部x坐标 -// "ury"=>"3115", // 右边上部y坐标 -// "pageList"=>[1], -// "sealImg"=>$sign_image -// ] -// ]; -// $data = array(); -// $data['sign_param'] = json_encode($sign_param); -// $data['seal_img'] = $sign_image; -// -// $result = $ca->addUserSignConfig("491925054435950592","410323199603261241",$data); - - // 下载阿里云图片 - $oss = new Oss(); - - $filename = "applet/doctor/cert/f2abdb81-fac0-4264-bc11-aa2b6cf2761c.png"; - - $style = "image/resize,m_lfit,w_100,h_350"; - - $sign_image = $oss->getCusTomObjectToRAM($filename,$style); - $sign_image = base64_encode($sign_image); - if (!$sign_image){ - return fail(HttpEnumCode::SERVER_ERROR); - } - - $sign_param = [ - [ - "llx"=>"350", // 左边底部X坐标 - "lly"=>"190", // 左边底部Y坐标 - "urx"=>"440", // 右边上部x坐标 - "ury"=>"140", // 右边上部y坐标 - "pageList"=>[1], - "sealImg"=>$sign_image - ] - ]; - $data = array(); - $data['sign_param'] = json_encode($sign_param); - $data['seal_img'] = $sign_image; - - $result = $ca->addUserSignConfig("534534546","410323199603261240",$data); - } - - // 获取用户签章图片 - public function test_4(){ - $ca = new Ca(); - $result = $ca->getFetchUserSeal("491925054435950592"); - $data = urldecode($result[0]['sealImg']); - dump($data); - } - - // 生成处方pdf图片 - public function test_5(){ - // 下载阿里云图片 - $oss = new Oss(); - - $filename = "basic/file/prescription.jpg"; - $sign_image = $oss->getObjectToRAM($filename); - - $manager = new ImageManager(); - - $image = $manager->make($sign_image); - - $fontPath = './extend/Ca/ZiYuYongSongTi-2.ttf'; - - // 处方号 - $image->text('1234567890', 1480, 540, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - // 日期 - $image->text('2023-03-21', 354, 675, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - // 科室 - $image->text('测试科室1', 1385, 675, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - // 姓名 - $image->text('测试姓名', 354, 795, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - // 性别 - $image->text('男', 1385, 790, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - // 年龄 - $image->text('19', 354, 900, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - // 过敏史 - $image->text('对阿莫西林过敏对阿莫西林过敏', 405, 1030, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - // 初步诊断 - $image->text('对阿莫西林过敏对阿莫西林过敏', 445, 1145, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - // 医生建议 - $image->text('没有建议', 445, 1252, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(60); - $font->align('left'); - }); - - $data = array(); - $data['product'] = [ - [ - "product_name" => "感冒药1(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - [ - "product_name" => "感冒药2(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - [ - "product_name" => "感冒药3(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - [ - "product_name" => "感冒药4(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - [ - "product_name" => "感冒药5(50ml*10)", - "single_unit" => "一次一包", - "frequency_use" => "1天3次", - "single_use" => "口服", - "prescription_product_num" => "X1盒", - ], - ]; - - // 用药 - foreach ($data['product'] as $key => $item){ - if ($key <= 2){ - $x_axis = 229; - $y_axis = 1600 + $key * 350; - }else{ - $x_axis = 1240; - $y_axis = 1600 + ($key - 3) * 350; - } - - - $image->text($item['product_name'], $x_axis, $y_axis, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(50); - $font->align('left'); - }); - - $image->text("用量:" . $item['single_unit'] . " " . $item['frequency_use'], $x_axis, $y_axis+90, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(50); - $font->align('left'); - }); - - $image->text("用法:" . $item['single_use'], $x_axis, $y_axis+180, function ($font) use($fontPath) { - $font->file($fontPath); - $font->size(50); - $font->align('left'); - }); - } - - // 将处理后的图片重新保存到其他路径 -// $image->save('./runtime/2.jpg'); - - $result = (string) $image->encode('png', 75); - - // 图片生成pdf - $pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false); - - $pdf->AddPage(); - $pdf->Image('@' . $result, 10, 10, 0, 0, '', '', '', false, 300, '', false, false, 0, false, false, false); - $pdf->Output(dirname(__DIR__, 2) . "/prescription_img.pdf","F"); - } - - // pdf进行签章 - public function test_6(){ - $pdf_file = fopen("./runtime/prescription.pdf",'r'); - - $oss = new Oss(); - - $filename = "applet/doctor/cert/f2abdb81-fac0-4264-bc11-aa2b6cf2761c.png"; - - $style = "image/resize,m_lfit,w_100,h_350"; - - $sign_image = $oss->getCusTomObjectToRAM($filename,$style); - $sign_image = base64_encode($sign_image); - if (!$sign_image){ - return fail(HttpEnumCode::SERVER_ERROR); - } - - $sign_param = [ - [ // 医生端 - "llx"=>"120", // 左边底部X坐标 - "lly"=>"190", // 左边底部Y坐标 - "urx"=>"190", // 右边上部x坐标 - "ury"=>"140", // 右边上部y坐标 - "pageList"=>[1], - "sealImg"=>$sign_image - ], -// [ // 药师端 -// "llx"=>"350", // 左边底部X坐标 -// "lly"=>"190", // 左边底部Y坐标 -// "urx"=>"440", // 右边上部x坐标 -// "ury"=>"140", // 右边上部y坐标 -// "pageList"=>[1], -// "sealImg"=>$sign_image -// ] - ]; - $data = array(); - $data['sign_param'] = json_encode($sign_param); - $data['pdf_file'] = $pdf_file; - - $ca = new Ca(); - $result = $ca->addSignPdf("491925054435950592",$data); - - $file_id = $result[0]['fileId']; - - $result = $ca->getSignedFile("491925054435950592",$file_id); - if (empty($result)){ - return fail(); - } - -// $file = fopen("./runtime/test.pdf", "w") or die("Unable to open file!"); -// fwrite($file, $result); -// fclose($file); - - // 上传阿里云oss - - $oss = new Oss(); - - $filename = "applet/doctor/prescription/test.pdf"; - - $result = $oss->putObject($filename, $result); - dump($result); - } - - // 延迟队列测试 - public function test_7(){ - $out_trade_no = $this->request->input('out_trade_no'); - if ($out_trade_no == 1){ - // 增加至取消订单延迟队列 - $data = array(); - $data['order_no'] = 111; - $data['order_type'] = 1; - - $message = new CancelUnpayOrdersDelayDirectProducer($data); - $message->setDelayMs(1000 * 5 * 1); - $producer = $this->container->get(Producer::class); - $res = $producer->produce($message); - if (!$res) { - Db::rollBack(); - return fail(HttpEnumCode::SERVER_ERROR, "订单创建失败"); - } - }else{ - // 增加至取消订单延迟队列 - $data = array(); - $data['order_no'] = 2222; - $data['order_type'] = 1; - - $message = new CancelUnpayOrdersDelayDirectProducer($data); - $message->setDelayMs(1000 * 15 * 1); - $producer = $this->container->get(Producer::class); - $res = $producer->produce($message); - if (!$res) { - Db::rollBack(); - return fail(HttpEnumCode::SERVER_ERROR, "订单创建失败"); - } - } - } - - // 删除签章配置 - public function test_8(){ - $ca = new Ca(); - $result = $ca->deleteUserSignConfig("491925054435950592"); - } - - // 下载签章的pdf文件 - public function test_9(){ - $ca = new Ca(); - $result = $ca->getSignedFile("5345345461","1642769369872105473"); - if (empty($result)){ - return fail(); - } - - // 上传阿里云oss - - $oss = new Oss(); - - $filename = "applet/doctor/prescription/111.pdf"; - - $result = $oss->putObject($filename, $result); - dump($result); - } - - public function test_10(){ -// $MessagePush = new MessagePush(2,"491923510680424449","499172549291458560"); -// $result = $MessagePush->noInquiry(); - -// $MessagePush = new MessagePush(3,"491925054435950592","499176434366210048"); -// $result = $MessagePush->doctorAcceptedInquiry(); - -// $ImService = new ImService(); -// -// $params = array(); -// $params['order_inquiry_id'] = "499313028868112385"; -// $order_inquiry = OrderInquiry::getOne($params); -// if (!empty($order_inquiry)) { -// $this->order_inquiry = $order_inquiry->toArray(); -// } -// -// // 获取订单医生数据 -// $params = array(); -// $params['doctor_id'] = $order_inquiry['doctor_id']; -// $user_doctor = UserDoctor::getOne($params); -// -// // 自定义消息 -// $cloud_custom_data = array(); -// $cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; -// $cloud_custom_data['is_system'] = 1; -// $cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type']; -// $cloud_custom_data['message_rounds'] = 0; -// $cloud_custom_data['patient_family_data']['patient_name'] = $order_inquiry['patient_name']; -// $cloud_custom_data['patient_family_data']['patient_sex'] = $order_inquiry['patient_sex']; -// $cloud_custom_data['patient_family_data']['patient_age'] = $order_inquiry['patient_age']; -// -// // 消息内容 -// $message_content_data = array(); -// $message_content_data['message_type'] = 6; -// $message_content_data['title'] = "--等待医生接诊--"; -// $message_content_data['desc'] = "温馨提示:您可继续补充问诊内容,便于更快确认病情,医生均在临床一线工作,还请耐心等待,医生接诊会第一时间短信通知您。"; -// $message_content_data['data'] = [ -// "order_inquiry_id" => "499313028868112385", -// "order_prescription_id" => "498938545791315968", -// "product_name" => "测试药品", -// "pharmacist_verify_time" => date('Y-m-d H:i:s',time()), -// ]; -// $message_content = [ -// 'Data' => json_encode($message_content_data,JSON_UNESCAPED_UNICODE), -// ]; -// -// $ImService->sendMessage($user_doctor['user_id'], $order_inquiry['user_id'], $message_content, "TIMCustomElem", $cloud_custom_data); - - - -// $data = array(); -// $data['order_inquiry_id'] = "499654588596031489"; -// -// $message = new AssignDoctorProducer($data); -// $producer = ApplicationContext::getContainer()->get(Producer::class); -// $result = $producer->produce($message); - - - } // 处方上报处方平台 public function test_11(){ @@ -775,16 +290,22 @@ class TestController extends AbstractController // 获取云证书-线上 public function test_14(){ -// $ca = new Ca(); -// + $CaOnline = new CaOnline(); + // // 测试医生 // $data = array(); // $data['user_id'] = "491925054435950592"; -// $data['card_num'] = "410323199603261241"; -// $result = $ca->getCloudCert($data); +// $data['mobile'] = "13028643897"; +// $data['card_name'] = "郝明明"; +// $data['card_num'] = "130582199202032038"; +// $data['orgDept'] = "科室名称"; +// $data['org_name'] = "成都金牛欣欣相照互联网医院有限公司"; +// $data['org_number'] = "91510106MABTJY4K9R"; +// $result = $CaOnline->getCloudCert($data); // // $data = array(); // $data['user_id'] = "491925054435950592"; +// $data['type'] = 2; // $data['cert_base64'] = $result['certBase64']; // $data['cert_chain_p7'] = $result['certP7']; // $data['cert_serial_number'] = $result['certSerialnumber']; @@ -793,16 +314,50 @@ class TestController extends AbstractController // if (empty($doctor_pharmacist_cert)){ // return fail(); // } +// dump(111); - dump(111); - $data = array(); - $data['order_inquiry_id'] = "506842098249736193"; - - $message = new AssignDoctorProducer($data); - $producer = ApplicationContext::getContainer()->get(Producer::class); - $result = $producer->produce($message); - if (!$result) { - } +// // 测试药师 +// $data = array(); +// $data['user_id'] = "534534546"; +// $data['mobile'] = "18812345678"; +// $data['card_name'] = "仝成亮"; +// $data['card_num'] = "411322199212122054"; +// $data['orgDept'] = "科室名称"; +// $data['org_name'] = "成都金牛欣欣相照互联网医院有限公司"; +// $data['org_number'] = "91510106MABTJY4K9R"; +// $result = $CaOnline->getCloudCert($data); +// +// $data = array(); +// $data['user_id'] = "534534546"; +// $data['type'] = 2; +// $data['cert_base64'] = $result['certBase64']; +// $data['cert_chain_p7'] = $result['certP7']; +// $data['cert_serial_number'] = $result['certSerialnumber']; +// $data['ca_pin'] = "534534546"; +// $doctor_pharmacist_cert = UserCaCert::addDoctorPharmacistCert($data); +// if (empty($doctor_pharmacist_cert)){ +// return fail(); +// } +// // 测试医院 +// $data = array(); +// $data['user_id'] = "5345345461"; +// $data['mobile'] = "18221234167"; +// $data['org_name'] = "成都金牛欣欣相照互联网医院有限公司"; +// $data['org_number'] = "91510106MABTJY4K9R"; +// +// $result = $CaOnline->getCloudCert($data,'Organizational'); +// +// $data = array(); +// $data['is_system'] = 1; +// $data['type'] = 2; +// $data['cert_base64'] = $result['certBase64']; +// $data['cert_chain_p7'] = $result['certP7']; +// $data['cert_serial_number'] = $result['certSerialnumber']; +// $data['ca_pin'] = "5345345461"; +// $doctor_pharmacist_cert = UserCaCert::addDoctorPharmacistCert($data); +// if (empty($doctor_pharmacist_cert)){ +// return fail(); +// } } } \ No newline at end of file diff --git a/app/Model/UserCaCert.php b/app/Model/UserCaCert.php index ebf8b69..d9186db 100644 --- a/app/Model/UserCaCert.php +++ b/app/Model/UserCaCert.php @@ -13,6 +13,7 @@ use Hyperf\Snowflake\Concern\Snowflake; * @property int $cert_id 主键id * @property int $user_id 用户id(系统证书时为null) * @property int $is_system 是否系统证书(0:否 1:是) + * @property int $type 证书类型(1:线下 2:线上) * @property string $cert_base64 签名值证书 * @property string $cert_chain_p7 证书链 * @property string $cert_serial_number 证书序列号 @@ -32,7 +33,7 @@ class UserCaCert extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['cert_id', 'user_id', 'is_system', 'cert_base64', 'cert_chain_p7', 'cert_serial_number', 'ca_pin', 'created_at', 'updated_at']; + protected array $fillable = ['cert_id', 'user_id', 'is_system', 'type', 'cert_base64', 'cert_chain_p7', 'cert_serial_number', 'ca_pin', 'created_at', 'updated_at']; protected string $primaryKey = "cert_id"; diff --git a/extend/Ca/Base.php b/extend/Ca/Base.php deleted file mode 100644 index dee9ee2..0000000 --- a/extend/Ca/Base.php +++ /dev/null @@ -1,105 +0,0 @@ -container = ApplicationContext::getContainer(); - $this->client = $this->container->get(Client::class); - } - - /** - * 封装公共请求 - * @param string $path - * @param array $arg - * @return mixed - * @throws GuzzleException - */ - protected function httpRequest(string $path, array $arg = []): mixed - { - $option = [ - "headers" => [ - "app_id" => $this->app_id, - "signature" => $this->getRequestSign($arg), - ], - ]; - - $arg = array_merge($arg, $option); - - $response = $this->client->post($path, $arg); - - if ($response->getStatusCode() != '200') { - // 请求失败 - throw new BusinessException($response->getBody()->getContents()); - } - $body = json_decode($response->getBody(), true); - dump($body); - if (empty($body)) { - // 返回值为空 - throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); - } - - if ($body['result_code'] != 0) { - // 请求失败 - if (!empty($body['result_msg'])) { - throw new BusinessException($body['result_msg']); - } - throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); - } - - return $body['body']; - } - - /** - * 获取请求签名 - * @param array $data - * @return string - */ - protected function getRequestSign(array $data): string - { - $sign_data = array(); - if (isset($data['form_params'])) { - $sign_data = $data['form_params']; - } - - if (isset($data['multipart'])) { - foreach ($data['multipart'] as $item) { - // pdf进行签章时,此参数为文件流,不参与签名 - if ($item['name'] == "pdfFile") { - continue; - } - - $sign_data[$item['name']] = $item['contents']; - } - } - - if (!empty($sign_data)){ - ksort($sign_data); - $data = implode('&', $sign_data); - }else{ - $data = ""; - } - - return hash_hmac("sha1", $data, $this->secret); - } -} \ No newline at end of file diff --git a/extend/Ca/Ca.php b/extend/Ca/Ca.php index 38028aa..1121c6e 100644 --- a/extend/Ca/Ca.php +++ b/extend/Ca/Ca.php @@ -4,8 +4,6 @@ namespace Extend\Ca; use App\Constants\HttpEnumCode; use App\Exception\BusinessException; -use App\Utils\Log; -use Exception; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use Hyperf\Di\Annotation\Inject; @@ -13,39 +11,30 @@ use Hyperf\Snowflake\IdGeneratorInterface; use Hyperf\Utils\ApplicationContext; use Psr\Container\ContainerInterface; -/** - * 四川ca云证书+电子签章-线下 - */ -class Ca extends Base +abstract class Ca { + #[Inject] + protected ContainerInterface $container; + + #[Inject] + protected Client $client; + + protected string $app_id; + protected string $api_url; + protected string $secret; + + public function __construct() + { + $this->container = ApplicationContext::getContainer(); + $this->client = $this->container->get(Client::class); + } + /** - * 获取云证书 + * 申请云证书 * @param array $data * @param string $type - * @return mixed */ - public function getCloudCert(array $data,string $type = "Personal"): mixed - { - $option = [ - 'form_params' => [ - 'entityId' => $data['user_id'], // 用户唯一标识,由业务系统定义 - 'entityType' => $type,// 用户类型,可选值[Personal/Organizational] - 'pin' => $data['user_id'], // 证书PIN码 - 'cardNumber' => $data['card_num'], // 证件号码(个人身份证;企业统一社会信用代码) - ] - ]; - - try { - $response = $this->httpRequest(config("ca.api_url") . '/cloud-certificate-service' . '/api/cloudCert/open/v2/cert/offlineAuthCertEnroll', $option); - if (empty($response)) { - // 返回值为空 - throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); - } - return $response; - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } + abstract public function getCloudCert(array $data, string $type = "Personal"); /** * 获取云证书签名 @@ -59,15 +48,14 @@ class Ca extends Base $option = [ 'form_params' => [ 'entityId' => $user_id, // 用户唯一标识,由业务系统定义 - 'toSign' => hash_hmac("sha1", json_encode($data, JSON_UNESCAPED_UNICODE), config("ca.secret")), // 签名原文 + 'toSign' => hash_hmac("sha1", json_encode($data, JSON_UNESCAPED_UNICODE), $this->secret), // 签名原文 'pin' => $pin, // 证书PIN码 ] ]; - dump($option); try { $response = $this->httpRequest( - config("ca.api_url") . '/cloud-certificate-service' . '/api/cloudCert/open/cert/sign', + $this->api_url . '/cloud-certificate-service' . '/api/cloudCert/open/cert/sign', $option ); if (empty($response)) { @@ -80,8 +68,10 @@ class Ca extends Base } } - // PKCS7签名验证接口 - // 对客户端签名信息进行验证,返回证书信息,同时可以配置回调服务,在验证成功后回调业务系统 + /** + * PKCS7签名验证接口 + * 对客户端签名信息进行验证,返回证书信息,同时可以配置回调服务,在验证成功后回调业务系统 + */ public function verifyPkcs7(string $sign_p7, array $data) { $generator = $this->container->get(IdGeneratorInterface::class); @@ -91,7 +81,7 @@ class Ca extends Base 'opType' => "签名验证", 'requestId' => $generator->generate(),// 业务流水号,唯一 'signedData' => $sign_p7, // 签名值:签名接口返回的signP7 - 'toSign' => hash_hmac("sha1", json_encode($data, JSON_UNESCAPED_UNICODE), config("ca.secret")), // 签名原文 + 'toSign' => hash_hmac("sha1", json_encode($data, JSON_UNESCAPED_UNICODE), $this->secret), // 签名原文 ] ]; @@ -99,7 +89,7 @@ class Ca extends Base try { $response = $this->httpRequest( - config("ca.api_url") . '/signgw-service/api/signature/verifyPkcs7', + $this->api_url . '/signgw-service/api/signature/verifyPkcs7', $option ); if (empty($response)) { @@ -114,12 +104,12 @@ class Ca extends Base /** * 添加签章配置 - * @param string $user_id 用户id - * @param string $card_num 身份证号 + * @param string $user_id + * @param string $card_num * @param array $data - * @return mixed + * @return bool */ - public function addUserSignConfig(string $user_id, string $card_num, array $data): mixed + public function addUserSignConfig(string $user_id, string $card_num, array $data): bool { $option = [ 'form_params' => [ @@ -137,7 +127,7 @@ class Ca extends Base try { $response = $this->httpRequest( - config("ca.api_url") . '/signature-server/api/open/signature/userSignConfig', + $this->api_url . '/signature-server/api/open/signature/userSignConfig', $option ); @@ -150,9 +140,9 @@ class Ca extends Base /** * 删除签章配置 * @param string $user_id - * @return mixed + * @return bool */ - public function deleteUserSignConfig(string $user_id): mixed + public function deleteUserSignConfig(string $user_id): bool { $option = [ 'form_params' => [ @@ -163,7 +153,7 @@ class Ca extends Base try { $this->httpRequest( - config("ca.api_url") . '/signature-server/api/open/signature/delSignConfig', + $this->api_url . '/signature-server/api/open/signature/delSignConfig', $option ); return true; @@ -187,7 +177,7 @@ class Ca extends Base try { $response = $this->httpRequest( - config("ca.api_url") . '/signature-server/api/open/signature/fetchUserSeal', + $this->api_url . '/signature-server/api/open/signature/fetchUserSeal', $option ); if (empty($response)) { @@ -206,7 +196,7 @@ class Ca extends Base * @param array $data * @return mixed */ - public function addSignPdf(string $user_id, array $data) + public function addSignPdf(string $user_id, array $data): mixed { $option = [ 'multipart' => [ @@ -235,7 +225,7 @@ class Ca extends Base try { $response = $this->httpRequest( - config("ca.api_url") . '/signature-server/api/open/signature/signPdf', + $this->api_url . '/signature-server/api/open/signature/signPdf', $option ); @@ -251,11 +241,11 @@ class Ca extends Base /** * 下载签章的pdf文件 - * @param string $user_id + * @param string $entity_id * @param string $file_id - * @return mixed + * @return string */ - public function getSignedFile(string $entity_id, string $file_id): mixed + public function getSignedFile(string $entity_id, string $file_id): string { $arg = [ 'form_params' => [ @@ -267,14 +257,14 @@ class Ca extends Base try { $option = [ "headers" => [ - "app_id" => config("ca.app_id"), + "app_id" => $this->app_id, "signature" => $this->getRequestSign($arg), ], ]; $option = array_merge($arg, $option); - $response = $this->client->post(config("ca.api_url") . '/signature-server/api/open/signature/fetchSignedFile', $option); + $response = $this->client->post($this->api_url . '/signature-server/api/open/signature/fetchSignedFile', $option); if ($response->getStatusCode() != '200') { // 请求失败 @@ -306,7 +296,7 @@ class Ca extends Base try { $response = $this->httpRequest( - config("ca.api_url") . '/signature-server/api/open/signature/verifyPdf', + $this->api_url . '/signature-server/api/open/signature/verifyPdf', $option ); @@ -319,4 +309,79 @@ class Ca extends Base throw new BusinessException($e->getMessage()); } } + + /** + * 封装公共请求 + * @param string $path + * @param array $arg + * @return mixed + * @throws GuzzleException + */ + public function httpRequest(string $path, array $arg = []): mixed + { + $option = [ + "headers" => [ + "app_id" => $this->app_id, + "signature" => $this->getRequestSign($arg), + ], + ]; + + $arg = array_merge($arg, $option); + + $response = $this->client->post($path, $arg); + + if ($response->getStatusCode() != '200') { + // 请求失败 + throw new BusinessException($response->getBody()->getContents()); + } + $body = json_decode($response->getBody(), true); + dump($body); + if (empty($body)) { + // 返回值为空 + throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); + } + + if ($body['result_code'] != 0) { + // 请求失败 + if (!empty($body['result_msg'])) { + throw new BusinessException($body['result_msg']); + } + throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); + } + + return $body['body']; + } + + /** + * 获取请求签名 + * @param array $data + * @return string + */ + public function getRequestSign(array $data): string + { + $sign_data = array(); + if (isset($data['form_params'])) { + $sign_data = $data['form_params']; + } + + if (isset($data['multipart'])) { + foreach ($data['multipart'] as $item) { + // pdf进行签章时,此参数为文件流,不参与签名 + if ($item['name'] == "pdfFile") { + continue; + } + + $sign_data[$item['name']] = $item['contents']; + } + } + + if (!empty($sign_data)) { + ksort($sign_data); + $data = implode('&', $sign_data); + } else { + $data = ""; + } + + return hash_hmac("sha1", $data, $this->secret); + } } \ No newline at end of file diff --git a/extend/Ca/CaOffline.php b/extend/Ca/CaOffline.php index 7003da6..05d46ab 100644 --- a/extend/Ca/CaOffline.php +++ b/extend/Ca/CaOffline.php @@ -10,7 +10,7 @@ use Hyperf\Snowflake\IdGeneratorInterface; /** * 四川ca云证书+电子签章-线下 */ -class CaOffline extends Base +class CaOffline extends Ca { public function __construct() { @@ -25,12 +25,12 @@ class CaOffline extends Base } /** - * 获取云证书 + * 申请云证书 * @param array $data * @param string $type * @return mixed */ - public function getCloudCert(array $data,string $type = "Personal"): mixed + protected function getCloudCert(array $data,string $type = "Personal"): mixed { $option = [ 'form_params' => [ @@ -52,276 +52,4 @@ class CaOffline extends Base throw new BusinessException($e->getMessage()); } } - - /** - * 获取云证书签名 - * @param string $user_id - * @param string $pin - * @param array $data - * @return mixed - */ - public function getCertSign(string $user_id, string $pin, array $data): mixed - { - $option = [ - 'form_params' => [ - 'entityId' => $user_id, // 用户唯一标识,由业务系统定义 - 'toSign' => hash_hmac("sha1", json_encode($data, JSON_UNESCAPED_UNICODE), $this->secret), // 签名原文 - 'pin' => $pin, // 证书PIN码 - ] - ]; - - try { - $response = $this->httpRequest( - $this->api_url . '/cloud-certificate-service' . '/api/cloudCert/open/cert/sign', - $option - ); - if (empty($response)) { - // 返回值为空 - throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); - } - return $response; - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } - - // PKCS7签名验证接口 - // 对客户端签名信息进行验证,返回证书信息,同时可以配置回调服务,在验证成功后回调业务系统 - public function verifyPkcs7(string $sign_p7, array $data) - { - $generator = $this->container->get(IdGeneratorInterface::class); - - $option = [ - 'form_params' => [ - 'opType' => "签名验证", - 'requestId' => $generator->generate(),// 业务流水号,唯一 - 'signedData' => $sign_p7, // 签名值:签名接口返回的signP7 - 'toSign' => hash_hmac("sha1", json_encode($data, JSON_UNESCAPED_UNICODE), $this->secret), // 签名原文 - ] - ]; - - dump($option); - - try { - $response = $this->httpRequest( - $this->api_url . '/signgw-service/api/signature/verifyPkcs7', - $option - ); - if (empty($response)) { - // 返回值为空 - throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); - } - return $response; - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } - - /** - * 添加签章配置 - * @param string $user_id 用户id - * @param string $card_num 身份证号 - * @param array $data - * @return bool - */ - public function addUserSignConfig(string $user_id, string $card_num, array $data): bool - { - $option = [ - 'form_params' => [ - 'userId' => $user_id,//用户标识信息(为云证书entityId) - 'configKey' => $user_id, // 签章配置唯一标识,一张云证书配置一个 - 'keypairType' => "3", // 秘钥类型(3云证书) - 'certSn' => $card_num, // 证书序列号,使用医生身份证号即可 - 'signType' => "4", // 签章方式(签章类型; 4客户端坐标签章;5客户端关键字签章;) - 'signParam' => $data['sign_param'], // 签章配置,JSON - 'sealImg' => $data['seal_img'], // 签章图片,base64格式 - 'sealType' => "4", - 'signTemplate' => "0", - ] - ]; - - try { - $response = $this->httpRequest( - $this->api_url . '/signature-server/api/open/signature/userSignConfig', - $option - ); - - return true; - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } - - /** - * 删除签章配置 - * @param string $user_id - * @return bool - */ - public function deleteUserSignConfig(string $user_id): bool - { - $option = [ - 'form_params' => [ - 'userId' => $user_id,//用户标识信息(为云证书entityId) - 'configKey' => $user_id, // 签章配置唯一标识,一张云证书配置一个 - ] - ]; - - try { - $this->httpRequest( - $this->api_url . '/signature-server/api/open/signature/delSignConfig', - $option - ); - return true; - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } - - /** - * 获取用户签章图片 - * @param string $user_id - * @return mixed - */ - public function getFetchUserSeal(string $user_id): mixed - { - $option = [ - 'form_params' => [ - 'userId' => $user_id,//用户标识信息(为云证书entityId) - ] - ]; - - try { - $response = $this->httpRequest( - $this->api_url . '/signature-server/api/open/signature/fetchUserSeal', - $option - ); - if (empty($response)) { - // 返回值为空 - throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); - } - return $response; - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } - - /** - * PDF添加电子签章 - * @param string $user_id - * @param array $data - * @return mixed - */ - public function addSignPdf(string $user_id, array $data): mixed - { - $option = [ - 'multipart' => [ - [ - 'name' => 'pdfFile', - 'contents' => $data['pdf_file'],// 待签章PDF文件(字节流) - ], - [ - 'name' => 'userId', - 'contents' => $user_id, // 用户标识信息 - ], - [ - 'name' => 'configKey', - 'contents' => $user_id, // 签章配置唯一标识 - ], - [ - 'name' => 'signParams', - 'contents' => $data['sign_param'],// 签章参数,JSON格式数据,如果不指定,那么以签章配置接口配置为准 - ], - [ - 'name' => 'cloudCertPass', - 'contents' => $user_id,// 云证书PIN码,云证书签章时使用 - ], - ] - ]; - - try { - $response = $this->httpRequest( - $this->api_url . '/signature-server/api/open/signature/signPdf', - $option - ); - - if (empty($response)) { - // 返回值为空 - throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); - } - return $response; - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } - - /** - * 下载签章的pdf文件 - * @param string $user_id - * @param string $file_id - * @return mixed - */ - public function getSignedFile(string $entity_id, string $file_id): mixed - { - $arg = [ - 'form_params' => [ - 'userId' => $entity_id,// 用户标识信息(为云证书entityId) - 'fileId' => $file_id,// 签章接口返回的文件标识 - ] - ]; - - try { - $option = [ - "headers" => [ - "app_id" => $this->app_id, - "signature" => $this->getRequestSign($arg), - ], - ]; - - $option = array_merge($arg, $option); - - $response = $this->client->post($this->api_url . '/signature-server/api/open/signature/fetchSignedFile', $option); - - if ($response->getStatusCode() != '200') { - // 请求失败 - throw new BusinessException($response->getBody()->getContents()); - } - - // 将 Stream 对象转换为字符串 - return (string)$response->getBody()->getContents(); - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } - - /** - * PDF签章文件验证 - * @param array $data - * @return mixed - */ - public function verifyPdf(array $data): mixed - { - $option = [ - 'multipart' => [ - [ - 'name' => 'pdfFile', - 'contents' => $data['pdf_file'],// 待签章PDF文件(字节流) - ], - ] - ]; - - try { - $response = $this->httpRequest( - $this->api_url . '/signature-server/api/open/signature/verifyPdf', - $option - ); - - if (empty($response)) { - // 返回值为空 - throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); - } - return $response; - } catch (GuzzleException $e) { - throw new BusinessException($e->getMessage()); - } - } } \ No newline at end of file diff --git a/extend/Ca/CaOnline.php b/extend/Ca/CaOnline.php new file mode 100644 index 0000000..6691da7 --- /dev/null +++ b/extend/Ca/CaOnline.php @@ -0,0 +1,65 @@ +app_id = $offline['app_id']; + $this->api_url = $offline['api_url']; + $this->secret = $offline['secret']; + } + + /** + * 申请云证书 + * @param array $data + * @param string $type + * @return mixed + */ + protected function getCloudCert(array $data, string $type = "Personal"): mixed + { + $option = [ + 'form_params' => [ + 'entityId' => $data['user_id'], // 用户唯一标识,由业务系统定义 + 'entityType' => $type,// 用户类型,可选值[Personal/Organizational] + 'personalPhone' => (string)$data['mobile'], // 联系人电话 + 'personalName' => $data['card_name'] ?? "", // 个人姓名,类型为Personal时必填 + 'personalIdNumber' => $data['card_num'] ?? "", // 个人证件号,类型为Personal时必填 + 'orgName' => $data['org_name'] ?? "", // 组织机构名称,信用代码类型为Organizational时必填 + 'orgNumber' => $data['org_number'] ?? "", // 组织机构代码,信用代码类型为Organizational时必填 + 'pin' => $data['user_id'], // 证书PIN码 + 'province' => "四川省", // 卫生证书:省、州 + 'locality' => "成都市", // 卫生证书:城市 + 'authType' => "实人认证", // 委托鉴证方式[实人认证、线下认证、其它方式认证] + 'authTime' => time(), // 委托鉴证时间(鉴证完成的时间戳)单位:秒 + 'authResult' => "认证通过", // 委托鉴证结果[认证通过] + 'authNoticeType' => "数字证书申请告知", // 委托鉴证告知类型[数字证书申请告知] + ] + ]; + + try { + $response = $this->httpRequest($this->api_url . '/cloud-certificate-service' . '/api/cloudCert/open/v2/cert/certEnroll', $option); + if (empty($response)) { + // 返回值为空 + throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); + } + return $response; + } catch (GuzzleException $e) { + throw new BusinessException($e->getMessage()); + } + } +} \ No newline at end of file