Moved academic-id-consumer

parent 4c33f256
# Προγράμματα κατανάλωσης academic id API
Τα παρακάτω προγράμματα - βιβλιοθήκες καταναλώνουν το academic id API.
Μετακινήθηκε στο [https://git.minedu.gov.gr/spapad/academic-id-consumer](academic-id-consumer).
Περιέχονται δείγματα κώδικα και βιβλιοθήκες κατανάλωσης στις εξής παραλλαγές:
* [Εφαρμογή διαδικτύου αναπτυγμένη σε SLIM framework](./slim-app/)
* [Εφαρμογή διαδικτύου αναπτυγμένη σε PHP](./barebone/)
RewriteEngine On
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^queryID/(.*)$ index.php?operation=queryID&$1 [QSA,L,PT]
# RewriteRule ^(.*)$ index.php?$1 [QSA,L]
RewriteRule ^testServiceStatus/(.*)$ index.php?operation=testServiceStatus&id=$1 [L]
RewriteCond %{QUERY_STRING} ^id=(.*)$
RewriteRule ^testServiceStatus$ index.php?operation=testServiceStatus&id=%1 [L]
RewriteCond %{QUERY_STRING} ^id=(.*)$
RewriteRule ^queryIDnoCD$ index.php?operation=queryIDnoCD&identity=%1 [L]
RewriteCond %{QUERY_STRING} ^id=([^&]*)&username=([^&]*)&password=(.*)$
RewriteRule ^queryID$ index.php?operation=queryID&identity=%1&username=%2&password=%3 [L]
RewriteRule ^echo/(.*)$ index.php?operation=echo&$1 [QSA,L]
# Web Service Client σε PHP
> OBSOLETE
Υλοποιήθηκε ένας απλός web service client και σε PHP για να πραγματοποιεί τις κλήσεις στο επίσημο web service μέσω php curl.
Οι λειτουργίες του είναι:
* queryID, που επιστρέφει την απάντηση του επίσημου web service, με παραμέτρους:
* username προεραιτικό, το username για το web service
* password προεραιτικό, το password για το web service
* identity υποχρεωτικό, το academic id για έλεγχο
* queryIDis που επιστρέφει κείμενο isStudent:[true,false] όπως προκύπτει από το επίσημο web service, με παραμέτρους:
* username προεραιτικό, το username για το web service
* password προεραιτικό, το password για το web service
* identity υποχρεωτικό, το academic id για έλεγχο
* echo, που επιστρέφει το query_string, με οποιαδήποτε παράμετρο
Οι λειτουργίες δίνονται ως παράμετρος κατά την κλήση. Για παράδειγμα:
* http://local.dev/academic-id/wrapper.php?identity=123456789012 (default is queryID)
* http://local.dev/academic-id/wrapper.php?username=spapad&identity=123456789012&operation=queryIDis
* http://local.dev/academic-id/wrapper.php?operation=echo&identity=123456789012
Έγιναν αλλαγές στον κώδικα PHP για να είναι 1-1 αντίστοιχες οι λειτουργίες με την υλοποίηση σε java (http://ostmgmt.minedu.gov.gr/projects/wos2_esb/wiki/Pilot_service_Academic_ID)
Οι νέες λειτουργίες είναι:
* testServiceStatus
* queryIDnoCD
* queryID
Επίσης παράχθηκε [htaccess](.htaccess) αρχείο για να δίνονται ακριβώς ίδια endpoints.
<?php
/**
* Convinience function to send a json encoded response and exit
*
* @param $response array Array containing the response to json encode
* @param $error_code HTTP STATUS response code
*/
function error_response($response, $error_code = 200)
{
http_response_code($error_code);
header("Content-Type: application/json");
echo json_encode($response);
exit(0);
}
//
$settings_file = __DIR__ . '/settings.php';
if (is_readable($settings_file)) {
$settings = require($settings_file);
} else {
error_response(['message' => 'Error: Application Server (Internal Error, cannot read file system or missing property file)'], 500);
}
/**
* Get params.
* operation == queryID || echo
*/
$params = [
'username' => ($username = filter_input(INPUT_GET, 'username')) ? $username : $settings['username'],
'password' => ($password = filter_input(INPUT_GET, 'password')) ? $password : $settings['password'],
'identity' => ($identity = filter_input(INPUT_GET, 'identity')) ? $identity : '-1',
'operation' => (in_array($operation = filter_input(INPUT_GET, 'operation'), [
'testServiceStatus',
'queryIDnoCD', 'queryID',
'echo',
])) ? $operation : 'queryID',
'secure_endpoint_username' => isset($settings['secure_endpoint_username']) ? $settings['secure_endpoint_username'] : 'n/a',
'secure_endpoint_password' => isset($settings['secure_endpoint_password']) ? $settings['secure_endpoint_password'] : 'n/a',
];
/**
* Call remote ws
*/
function wscall($params)
{
/**
* Prep auth
*/
$pass_md5 = md5($params['password']);
$auth = "Basic " . base64_encode("{$params['username']}:{$pass_md5}");
/**
* Do the call
*/
$ch = curl_init();
$payload = json_encode(array("SubmissionCode" => $params['identity']));
curl_setopt($ch, CURLOPT_URL, "https://academicidapp.grnet.gr/admin/web/ws/users/inspectAcademicID");
// curl_setopt($ch, CURLOPT_URL, "https://academicidapp.grnet.gr/admin/web/ws/users/inspectAMKA");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: {$auth}",
'Content-Type: application/json',
'Accept: */*',
'User-Agent: AcademicIDClientTestPHP/v1.0 osteam'
]
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
if (curl_errno($ch)) {
error_response(['message' => 'Error: EDET Web Service Unreachable'], 500);
}
if (intval(($http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE)) / 100) != 2) {
http_response_code($http_code);
}
curl_close($ch);
return $result;
}
/**
* Get http request header
*/
if (!function_exists('getallheaders'))
{
function getallheaders()
{
$headers = '';
foreach ($_SERVER as $name => $value)
{
if (substr($name, 0, 5) == 'HTTP_')
{
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
}
}
return $headers;
}
}
/**
* Check the input
*
* @return true|mixed True in case of valid input, or response and exit
*/
function check_input($identity)
{
$valid = true;
if (preg_match('/^[0-9]{12}$/', $identity) !== 1) {
error_response(['message' => 'Error: Service Call Parameters Error, academic id must be 12 digit number'], 500);
}
return true;
}
/**
* Check the authentication header
*
* @return true|mixed True in case of valid auth header, or response and exit
*/
function check_authentication_header($username, $password)
{
$auth = true;
$headers = getallheaders();
if (array_key_exists('Authorization', $headers)) {
$header = $headers['Authorization'];
$auth_parts = [];
if (preg_match('/^Basic (.+)$/', $header, $auth_parts) === 1) {
if ($auth_parts[1] !== base64_encode("{$username}:{$password}")) {
error_response(['message' => 'Error: Invalid or Missing Basic Authorization Credentials'], 401);
}
} else {
error_response(['message' => 'Error: Invalid or Missing Basic Authorization Credentials'], 401);
}
} else {
error_response(['message' => 'Error: Missing Basic Authorization Header'], 401);
}
return true;
}
/**
*
*/
switch ($params['operation']) {
case 'queryID':
check_authentication_header($params['secure_endpoint_username'], $params['secure_endpoint_password']);
header("Content-Type: application/json");
$result = wscall($params);
break;
case 'queryIDnoCD':
check_authentication_header($params['secure_endpoint_username'], $params['secure_endpoint_password']);
check_input($params['identity']);
header("Content-Type: text/plain");
$result = json_decode(wscall($params), true);
$IDis = $result !== null &&
isset($result['response']) && $result['response'] == 'SUCCESS' &&
isset($result['inspectionResult']['webServiceSuccess']) &&
$result['inspectionResult']['webServiceSuccess'] == true;
$result = "isStudent:" . ($IDis ? 'true' : 'false');
break;
case 'testServiceStatus':
check_authentication_header($params['secure_endpoint_username'], $params['secure_endpoint_password']);
header("Content-Type: text/plain");
$result = "StudentID sent was:" . trim(filter_input(INPUT_GET, 'id'));
break;
case 'echo':
default:
header("Content-Type: text/plain");
unset($_GET['operation']);
$result = http_build_query($_GET);
break;
}
echo $result;
exit(0);
<?php
return [
'username' => 'username-for-endpoint',
'password' => 'password-for-endpoint',
'secure_endpoint_username' => 'username-for-this-wrapper',
'secure_endpoint_password' => 'password-for-this-wrapper',
];
# Έλεγχος δεδομένων
Είσοδος: αρχείο csv με μία στήλη με αριθμούς ΑΜΚΑ
> TODO
This diff is collapsed.
<?php
return [
'osteam_codebase' => __DIR__ . '/src',
'base_uri_student' => 'https://wso2.minedu.gov.gr/academicid',
'base_uri_query' => '',
'username' => 'username-for-endpoint',
'password' => 'password-for-endpoint',
'auth_header_student' => 'Bearer ...', // wso2 auth header
'timeout' => 1, // number of seconds between web service calls
'NO_SAFE_CURL' => true
];
<?php
namespace Gr\Gov\Minedu\Osteam\App;
use Gr\Gov\Minedu\Osteam\Slim\Client;
/**
* Description of app
*
* @author spapad
*/
class Extract
{
protected $client = null;
protected $settings = [];
public function __construct($client, $settings)
{
$this->client = $client;
$this->settings = $settings;
}
protected function generateAuth()
{
$pass_md5 = md5($this->password);
return "Basic " . base64_encode("{$this->username}:{$pass_md5}");
}
public function getAcademicID($amka, $auth_header_student)
{
if (preg_match('/^[0-9]{11}$/', $amka) !== 1) {
return 'ERROR:Service Call Parameters Error, student amka id must be 11 digit number';
}
$data = [
'fields' => 'academicID'
];
$headers = [
"Authorization: {$auth_header_student}",
'Content-Type: application/json',
'Accept: */*',
'User-Agent: osteam php command line client'
];
try {
$results = $this->client->get($this->settings['base_uri_student'] . "/{$amka}", $data, $headers);
} catch (\Exception $e) {
return "ERROR:" . $e->getMessage();
}
if ($results['success'] === false) {
return "ERROR:{$results['response']}, {$results['http_status']}";
}
// echo var_export($results, true), PHP_EOL;
return $results['response'];
}
public function getStudentInformation($academic_id, $auth_header_student)
{
if (preg_match('/^[0-9]{12}$/', $academic_id) !== 1) {
return 'ERROR:Service Call Parameters Error, student academic id must be 11 digit number';
}
$data = [
'id' => $academic_id,
'username' => $this->settings['username'],
'password' => $this->settings['password'],
'fields' => 'entryYear,studentshipType,departmentName,postGraduateProgram'
];
$headers = [
"Authorization: {$auth_header_student}",
'Content-Type: application/json',
'Accept: */*',
'User-Agent: osteam php command line client'
];
try {
$results = $this->client->get($this->settings['base_uri_query'], $data, $headers);
} catch (\Exception $e) {
return "ERROR:" . $e->getMessage();
}
if ($results['success'] === false) {
return "ERROR:{$results['response']}, {$results['http_status']}";
}
// echo var_export($results, true), PHP_EOL;
return $results['response'];
}
}
# Έλεγχος δεδομένων
Είσοδος: αρχείο csv με μία στήλη με αριθμούς ΑΜΚΑ
Έξοδος: στατιστικά στοιχεία κλήσεων στην υπηρεσία
## Endpoints
Η μέθοδος `check` του [Client](src/Client.php) καλεί την υπηρεσία που
παρέχεται μέσω WSO2, η μέθοδος `rawcheck` καλεί την πρωτογενή πηγή.
<?php
// barebone app - autoload classes from src/ dir
spl_autoload_register(function ($class_name) {
$class_name_parts = explode('\\', $class_name);
$class_filename = __DIR__ . '/src/' . end($class_name_parts) . '.php';
if (file_exists($class_filename)) {
include $class_filename;
if (class_exists($class_name)) {
return true;
}
}
return false;
});
use Gr\Gov\Minedu\Osteam\App\Client;
$settings = require(__DIR__ . '/settings.php');
/**
* --input <file> το αρχείο εισόδου
* --amka <column#> η σειρά που εμφανίζεται στο csv η στήλη με των κωδικό ΑΜΚΑ
*/
$options = getopt('', ['input:', 'amka:', 'line:', 'maxcheck:']);
$input_file = isset($options['input']) ? $options['input'] : null;
$amka_column = isset($options['amka']) ? abs(intval($options['amka'])) : 0;
$line = isset($options['line']) ? abs(intval($options['line'])) : 1;
$maxcheck = isset($options['maxcheck']) ? abs(intval($options['maxcheck'])) : null;
$have_files = false;
if ($input_file !== null) {
if (is_string($input_file)) {
$input_file = [$input_file];
}
$valid_files = array_filter($input_file, function ($v) {
return is_file($v) && is_readable($v);
});
$have_files = (count($valid_files) == 1);
}
/**
* Έλεγχος παραμέτρων
*/
if (!$have_files || $amka_column < 0 || $line < 1) {
echo "Χρήση: {$argv[0]} [--input <file>] [--amka <amka column #>]", PHP_EOL,
" input <file>: έλεγχος στοιχείων από το αρχείο <file> (ένα μόνο αρχείο)", PHP_EOL,
" amka <column #>: αριθμός στήλης που περιέχει το ΑΜΚΑ (πρώτη == 0)", PHP_EOL,
"line <start line #>: αριθμός πρώτης γραμμής με δεδομένα (πρώτη == 1)", PHP_EOL,
exit(0);
}
echo "Ζητήσατε να γίνει έλεγχος από τo αρχείo: ",
implode(', ', $valid_files), PHP_EOL,
'ένραξη στοιχείων από τη γραμμή: ', $line, PHP_EOL,
'και αριθμό στήλης ΑΜΚΑ: ', $amka_column, PHP_EOL,
'Έλεγχος ', ($maxcheck === null ? 'όλων των' : $maxcheck), ' εγγραφών', PHP_EOL;
$confirm = mb_strtoupper(readline("Να συνεχίσουμε; (y/N/ν/Ο) "));
if ($confirm !== 'Y' && $confirm !== 'Ν') {
die("Τέλος");
}
/**
*
*/
$client = new Client([
'base_uri' => $settings['base_uri'],
'username' => $settings['username'],
'password' => $settings['password']
]);
$file = $valid_files[0];
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
for ($i = 1; $i < $line; $i++) {
array_shift($lines);
echo "POP {$i} lines...", PHP_EOL;
}
$csv_data = array_map('str_getcsv', $lines);
if ($maxcheck !== null) {
array_splice($csv_data, $maxcheck);
}
// echo var_export($csv_data, true);
$get = array_walk($csv_data, function (&$v, $k) use ($client, $amka_column, $settings) {
if (!isset($v[$amka_column])) {
echo "Δεν υπάρχει στήλη με στοιχεία ΑΜΚΑ", PHP_EOL;
$v['__STATUS__'] = 'INVALID';
return;
}
$amka = $v[$amka_column];
if (preg_match('/^[0-9]{11}$/', $amka) !== 1) {
echo "Το ΑΜΚΑ {$amka} δεν είναι 11-ψήφιος αριθμός", PHP_EOL;
$v['__STATUS__'] = 'INVALID';
return;
}
echo $amka;
$response = '';
try {
$response = $client->check($amka, $settings['auth_header']);
// $response = $client->rawcheck($amka);
if ($response === false) {
$response = 'false';
}
$first = mb_substr($response, 0, 1);
switch ($first) {
case '{':
$v['__STATUS__'] = 'UNKNOWN';
break;
case 'f':
$v['__STATUS__'] = 'ERROR';
break;
case 'Π':
case 'Μ':
case 'Δ':
$v['__STATUS__'] = $first;
break;
default:
$v['__STATUS__'] = 'UNKNOWN';
break;
}
} catch (\Exception $e) {
$v['__STATUS__'] = 'ERROR';
}
echo ' ... ', $v['__STATUS__'], PHP_EOL;
if (isset($settings['timeout'])) {
sleep($settings['timeout']);
}
});
// echo var_export($csv_data, true);
echo "Results:", PHP_EOL;
$stats = [
'TOTAL' => count($csv_data),
'ERROR' => 0,
'UNKNOWN' => 0,
'Π' => 0,
'Μ' => 0,
'Δ' => 0
];
$stat = array_walk($csv_data, function ($v, $k) use (&$stats) {
$stats[$v['__STATUS__']]++;
});
foreach ($stats as $key => $val) {
echo "- {$key}: {$val}", PHP_EOL;
}
echo "% results:", PHP_EOL,
" Προπτυχιακοί: ", number_format(100 * $stats['Π'] / $stats['TOTAL'], 2), "% ({$stats['Π']})", PHP_EOL,
"Μεταπτυχιακοί: ", number_format(100 * $stats['Μ'] / $stats['TOTAL'], 2), "% ({$stats['Μ']})", PHP_EOL,
" Διδακτορικοί: ", number_format(100 * $stats['Δ'] / $stats['TOTAL'], 2), "% ({$stats['Δ']})", PHP_EOL,
" Άλλο: ", number_format(100 * ($stats['ERROR'] + $stats['UNKNOWN']) / $stats['TOTAL'], 2), "% (" . ($stats['ERROR'] + $stats['UNKNOWN']) . ")", PHP_EOL;
echo "Ολοκληρώθηκε.", PHP_EOL;
exit(0);
<?php
return [
'base_uri' => 'https://wso2.minedu.gov.gr/academicid',
'raw_check_base_uri' => '',
'username' => 'username-for-endpoint',
'password' => 'password-for-endpoint',
'auth_header' => 'Bearer ...', // wso2 auth header
'timeout' => 1, // number of seconds between web service calls
];
<?php
/*
*
*/
namespace Gr\Gov\Minedu\Osteam\App;
use Exception;
/**
* Description of Client
*
* @author spapad
*/
class Client
{
private $_debug = false;
private $_settings = [
'base_uri' => '',
'username' => '',
'password' => '',
'NO_SAFE_CURL' => true
];
public function __construct($settings = [])
{
$this->_settings = array_merge($this->_settings, $settings);
}
public function check($amka, $auth) {
$data = [
];
$headers = [
'Authorization: ' . $auth,
// 'Accept: */*',
];
$results = $this->get($this->_settings['base_uri'] . "/student/{$amka}", $data, $headers);
// echo " CHECK RESULT IS: ", var_export($results, true), PHP_EOL;
if ($results['success'] === false) {
return false;
}
return $results['response'];
}
public function rawcheck($amka) {
$pass_md5 = md5($this->_settings['password']);
$auth = "Basic " . base64_encode("{$this->_settings['username']}:{$pass_md5}");
$data = json_encode([
"AMKA" => $amka
]);
$headers = [
"Authorization: {$auth}",
'Content-Type: application/json',
'Accept: */*',
];
$results = $this->post($this->_settings['raw_check_base_uri'], $data, $headers);
echo " RAWCHECK RESULT IS: ", var_export($results, true), PHP_EOL;
if ($results['success'] === false) {
return false;
}
$parsed_result = json_decode($results['response'], true);
if ($parsed_result === false) {
return false;
}
if ($parsed_result['response'] === 'SUCCESS' && $parsed_result['errorReason'] === null) {
if (isset($parsed_result['inspectionResult'])
&& $parsed_result['inspectionResult']['webServiceSuccess'] === true
&& is_array($parsed_result['inspectionResult']['beneficiaryNames'])) {
if (count($parsed_result['inspectionResult']['beneficiaryNames']) > 0) {
if (is_array($bNames = $parsed_result['inspectionResult']['beneficiaryNames'][0]) &&
isset($bNames['beneficiaryName'])) {
return $bNames['beneficiaryName'];
}
}
}
}
return false;
}
protected function setCommonCurlOptions($ch, $uri, $headers)
{
curl_setopt($ch, CURLOPT_URL, $uri);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_USERAGENT, "OSTEAM client");
if (isset($this->_settings['NO_SAFE_CURL']) && $this->_settings['NO_SAFE_CURL'] === true) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
if ($this->_debug === true) {
curl_setopt($ch, CURLOPT_VERBOSE, true);
}
}
public function put($uri, $payload, $headers = [])
{
$ch = curl_init();
$this->setCommonCurlOptions($ch, $uri, $headers);
// curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception("Λάθος κατά την κλήση του {$uri}. Curl error: " . curl_error($ch) . " Curl info: " . var_export(curl_getinfo($ch), true));
}
if (intval(($http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE)) / 100) != 2) {
// πραγματοποιήθηκε κλήση αλλά δεν ήταν "επιτυχής"
throw new Exception("Αποτυχημένη κλήση. HTTP STATUS {$http_code}. Η απάντηση ήταν: {$result}", $http_code);
}
curl_close($ch);
return $result;
}
public function post($uri, $payload, $headers = [])
{
$ch = curl_init();
$this->setCommonCurlOptions($ch, $uri, $headers);