<?php
// Turn off all error reporting
error_reporting(0);
/*************************************************************
* Global Variables *
*************************************************************/
$urlBase = 'XXXXXXXXXXXXXXXXXXXXXXX/phcws/';
$usernameLogin = 'XXXXXX';
$passwordLogin = 'XXXXXX';
$appTypeLogin = 'XXXXXXXXXXXXXXXXXXXXXXXXX';
$companyLogin = '';
// After click "Login in PHC GO" button
if (!empty($_POST['makeLogin'])){
echo "<h3>You are logged in PHC GO</h3><h2>Generate Customer, Product and signed Invoice</h2>";
/*************************************************************
* Called webservice to login into PHC GO *
*************************************************************/
$url = $urlBase."REST/UserLoginWS/userLoginCompany";
$params = array(
'userCode' => $usernameLogin,
'password' => $passwordLogin,
'applicationType' => $appTypeLogin,
'company' => $companyLogin
);
$query = http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (X11; Linux x86_64)');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '');
curl_setopt($ch, CURLOPT_COOKIEFILE, '');
$response = curl_exec($ch);
$response = json_decode($response, true);
$tokenHeader = array(
'Authorization' => 'Engine-Auth:'.$response['result'][0]['token'],
'Content-Type' => 'application/json'
);
/*************************************************************
* Called webservice to query invoice documents (FT, FS, FR) *
*************************************************************/
$url = $urlBase."REST/SearchWS/QueryAsEntities";
$params = array('itemQuery' => '{"groupByItems":[],"lazyLoaded":false,"joinEntities":[],"orderByItems":[],"SelectItems":[],"entityName":"Td","filterItems":[{"comparison":0,"filterItem":"inactivo","valueItem":"0","groupItem":1,"checkNull":false,"skipCheckType":false,"type":"Number"}]}');
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response['result'])) {
$_SESSION['typeOfInvoice'] = '';
foreach ($response['result'] as $value) {
if ($value['tiposaft'] == 'FT' || $value['tiposaft'] == 'FS' || $value['tiposaft'] == 'FR') {
$_SESSION['typeOfInvoice'] .= "<option value=" . $value['ndoc'] . ">" . $value['nmdoc'] ."</option><br>";
}
}
}
// Button for choosing the invoice type from PHC GO
echo "<form method='post' action=''>";
echo "Choose type of invoice document:<br><br><select id='typeOfInvoices' name='typeOfInvoices'>";
echo "<option value='0'>Select one...</option>";
echo $_SESSION['typeOfInvoice'];
echo "</select>";
echo "<br><br><br><input type='submit' name='generate_ft' value='Generate'>";
echo "</form>";
/*************************************************************
* Called webservice to logout from PHC GO *
*************************************************************/
$url = $urlBase."REST/UserLoginWS/userLogout";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, false);
$response = curl_exec($ch);
// After click "Generate" button
} else if (!empty($_POST['generate_ft'])){
/*************************************************************
* Called webservice to login into PHC GO *
*************************************************************/
$url = $urlBase."REST/UserLoginWS/userLoginCompany";
$params = array(
'userCode' => $usernameLogin,
'password' => $passwordLogin,
'applicationType' => $appTypeLogin,
'company' => $companyLogin
);
$query = http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (X11; Linux x86_64)');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '');
curl_setopt($ch, CURLOPT_COOKIEFILE, '');
$response = curl_exec($ch);
$response = json_decode($response, true);
$tokenHeader = array(
'Authorization' => 'Engine-Auth:'.$response['result'][0]['token'],
'Content-Type' => 'application/json'
);
/*************************************************************
* Called webservice to check if the client exists *
*************************************************************/
$url = $urlBase."REST/SearchWS/QueryAsEntities";
$params = array('itemQuery' => '{"groupByItems":[],"lazyLoaded":false,"joinEntities":[],"orderByItems":[],"SelectItems":[],"entityName":"Cl","filterItems":[{"comparison":0,"filterItem":"ncont","valueItem":"235047660","groupItem":1,"checkNull":false,"skipCheckType":false,"type":"Number"}]}');
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (is_array($response['result']) && !empty($response['result'][0])) {
$_SESSION['number_client'] = $response['result'][0]['no'];
echo "<h3>Client nº" . $response['result'][0]['no'] . " already exists in PHC GO</h3>";
} else {
/*************************************************************
* Called webservice to get a new instance of the client *
*************************************************************/
$url = $urlBase."REST/ClWS/getNewInstance";
$params = array('ndos' => 0);
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response['result'])) {
/*************************************************************
* Data for creating a new customer *
*************************************************************/
$response['result'][0]['nome'] = 'Customer Test wxy';
$response['result'][0]['morada'] = 'Lagoas Park';
$response['result'][0]['local'] = 'Lisboa';
$response['result'][0]['codpost']= '1234-123';
$response['result'][0]['email'] = 'customer3@phc.pt';
$response['result'][0]['ncont'] = '212187449';
/*************************************************************
* Called webservice to save the client *
*************************************************************/
$url = $urlBase."REST/ClWS/Save";
$params = array(
'itemVO' => json_encode($response['result'][0]),
'runWarningRules' => 'false'
);
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response['result'])) {
echo "<h3>Client nº" . $response['result'][0]['no'] . " is inserted in PHC GO</h3>";
$_SESSION['number_client'] = $response['result'][0]['no'];
}
}
}
/*************************************************************
* Called webservice to check if the product exists *
*************************************************************/
$url = $urlBase."REST/SearchWS/QueryAsEntities";
$params = array('itemQuery' => '{"groupByItems":[],"lazyLoaded":false,"joinEntities":[],"orderByItems":[],"SelectItems":[],"entityName":"St","filterItems":[{"comparison":0,"filterItem":"ref","valueItem":"REF_1","groupItem":1,"checkNull":false,"skipCheckType":false,"type":"Number"}]}');
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (is_array($response['result']) && !empty($response['result'][0])) {
$_SESSION['ref_product'] = $response['result'][0]['ref'];
echo "<h3>Ref: " . $response['result'][0]['ref'] . " already exists in PHC GO</h3>";
} else {
/*************************************************************
* Called webservice to get a new instance of the product *
*************************************************************/
$url = $urlBase."REST/StWS/getNewInstance";
$params = array('ndos' => 0);
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response['result'])) {
/*************************************************************
* Add new product details *
*************************************************************/
$response['result'][0]['ref'] = 'REF_1';
$response['result'][0]['design'] = 'Test Product W';
$response['result'][0]['epv1'] = '9.99';
$response['result'][0]['iva1incl'] = true;
$response['result'][0]['inactivo'] = false;
/*************************************************************
* Called webservice to save the product *
*************************************************************/
$url = $urlBase."REST/StWS/Save";
$params = array(
'itemVO' => json_encode($response['result'][0]),
'runWarningRules' => 'false'
);
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response['result'])) {
echo "<h3>Ref: " . $response['result'][0]['ref'] . " is inserted in PHC GO</h3>";
$_SESSION['ref_product'] = $response['result'][0]['ref'];
}
}
}
// Save option chosen in select box for invoice type
$_SESSION['typeOfInvoices'] = $_POST['typeOfInvoices'];
/*************************************************************
* Called webservice to get a new instance of FT (Invoice) *
*************************************************************/
$url = $urlBase."REST/FtWS/getNewInstance";
$params = array('ndos' => $_SESSION['typeOfInvoices']);
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response['result'])) {
/*************************************************************
* Add new line to the invoice document *
*************************************************************/
$newLine = '{ "actqtt2": false,
"amostra": false,
"armazem": 0,
"articleAutoCreationCode": 0,
"avencano": 0,
"avencastamp": "",
"bistamp": "",
"ccstamp": "",
"cliref": "",
"codigo": "",
"codmotiseimp": "",
"componente": false,
"compound": false,
"cpoc": 0,
"davencaft": "1900-01-01 00:00:00Z",
"desc2": 0,
"desc3": 0,
"desc4": 0,
"desc5": 0,
"desc6": 0,
"desconto": 0,
"design": "Caixa e tamboril",
"ecusto": 0,
"elucro": 0,
"emargem": 0,
"epv": 14.99,
"etiliquido": 14.99,
"ettiva": 0,
"evalcomissao": 0,
"facturaFt": false,
"familia": "",
"fechabo": false,
"firefs": [],
"fistamp": "",
"ftstamp": "d08-4a6a-a07f-b6eed883678",
"iva": 23,
"ivadata": "1900-01-01 00:00:00Z",
"ivaincl": true,
"ivarec": 0,
"litem": "",
"litem2": "",
"lordem": 0,
"lrecno": "",
"maxQttRefund": 0,
"miseimpstamp": "",
"motiseimp": "",
"nvol": 0,
"ofistamp": "",
"ofnstamp": "",
"oftstamp": "",
"oref": "",
"originalMaxQttRefund": 0,
"pbuni": 0,
"pluni": 0,
"pvmoeda": 0,
"qtt": 1,
"rdata": "1900-01-01 00:00:00Z",
"rdstamp": "",
"ref": "C001",
"stns": false,
"sujirs": false,
"tabiva": 0,
"tmoeda": 0,
"tnvol": 0,
"tpbrut": 0,
"tpliq": 0,
"treestamp": "",
"tvol": 0,
"unidade": "",
"usr1": "",
"usr2": "",
"vuni": 0 }';
// Add the new line to the invoice (FT) data
$response['result'][0]['fis'][0] = json_decode($newLine);
// Update the invoice using actEntity
$urlFt = $urlBase."REST/FtWS/actEntity";
$paramsFt = array(
'entity' => json_encode($response['result'][0]),
'code' => 0,
'newValue' => json_encode([])
);
$queryFt = http_build_query($paramsFt);
curl_setopt($ch, CURLOPT_URL, $urlFt);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $queryFt);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response)) {
// Associate the client with the invoice
$response['result'][0]['no'] = $_SESSION['number_client'];
// Eliminate financial discount of client
$response['result'][0]['efinv'] = 0;
$response['result'][0]['fin'] = 0;
/*************************************************************
* Update invoice again using actEntity (if needed) *
*************************************************************/
$urlFt = $urlBase."REST/FtWS/actEntity";
$paramsFt = array(
'entity' => json_encode($response['result'][0]),
'code' => 0,
'newValue' => json_encode([])
);
$queryFt = http_build_query($paramsFt);
curl_setopt($ch, CURLOPT_URL, $urlFt);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $queryFt);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response)) {
/*************************************************************
* Called webservice to save the invoice (FT) *
*************************************************************/
$url = $urlBase."REST/FtWS/Save";
$params = array(
'itemVO' => json_encode($response['result'][0]),
'runWarningRules' => 'false'
);
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response['result'])) {
// If the invoice is still a draft, sign the document
if ($response['result'][0]['draftRecord'] == 1) {
$_SESSION['ftstamp'] = $response['result'][0]['ftstamp'];
/*************************************************************
* Called webservice to sign the invoice document *
*************************************************************/
$url = $urlBase."REST/FtWS/signDocument";
$params = array('ftstamp' => $response['result'][0]['ftstamp']);
$query = http_build_query($params);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $tokenHeader);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
$response = json_decode($response, true);
if (!empty($response['result'])) {
echo "<h3>" . $response['result'][0]['nmdoc'] . " nº <u>" . $response['result'][0]['fno'] . "</u> is signed and inserted in PHC GO</h3>";
}
}
}
}
}
}
/*************************************************************
* Called webservice to logout from PHC GO *
*************************************************************/
$url = $urlBase."REST/UserLoginWS/userLogout";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, false);
$response = curl_exec($ch);
} else {
echo "<h1>Conect to PHC GO</h1>";
echo "<form method='post' action=''>";
echo "<input type='submit' name='makeLogin' value='Login in PHC GO'>";
echo "</form>";
}
?>
Module ModuleExample
' The Main entry point – choose between login branch and invoice generation branch.
Async Function Main() As Task
' Create an HttpClient with a cookie container.
Dim cookieContainer As New CookieContainer()
Dim handler As New HttpClientHandler() With {
.CookieContainer = cookieContainer,
.UseCookies = True
}
Using client As New HttpClient(handler)
Dim urlBase As String = "XXXXXXXXXXXXXXXXXXXXXXX/phcws/"
Dim username As String = "XXXXXX"
Dim password As String = "XXXXXX"
Dim appType As String = "XXXXXXXXXXXXXXXXXXXXXXXXX"
Dim company As String = ""
Console.WriteLine("Enter 1 for login and invoice query, 2 for generating invoice:")
Dim choice = Console.ReadLine()
If choice = "1" Then
' --- LOGIN BRANCH ---
' Call login endpoint to obtain the token.
Dim token = Await Login(client, urlBase, username, password, appType, company)
If token IsNot Nothing Then
' Query available invoice documents (FT, FS, FR) so that the partner can choose the type.
Dim invoiceOptions = Await QueryInvoiceDocuments(client, urlBase, token)
Console.WriteLine("Available invoice document types:")
Console.WriteLine(invoiceOptions)
' Logout after the query.
Await Logout(client, urlBase, token)
End If
ElseIf choice = "2" Then
' --- GENERATE INVOICE BRANCH ---
' Re-login to obtain the token.
Dim token = Await Login(client, urlBase, username, password, appType, company)
If token IsNot Nothing Then
' 1. Check if the client exists (using NIF) and create a new client if necessary.
Dim clientNumber = Await CheckOrCreateClient(client, urlBase, token)
' 2. Check if the product exists (using reference) and create a new product if needed.
Dim productRef = Await CheckOrCreateProduct(client, urlBase, token)
' 3. Get a new invoice instance (FT) using the selected invoice type.
Dim invoiceType As String = "YOUR_SELECTED_INVOICE_TYPE" ' Replace with the selected value.
Dim invoiceData = Await GetNewInvoiceInstance(client, urlBase, token, invoiceType)
' 4. Add a new invoice line (e.g. product, quantity, price) to the invoice data.
invoiceData = AddInvoiceLine(invoiceData)
' 5. Associate the client to the invoice and clear any discount values.
invoiceData = UpdateInvoiceWithClient(invoiceData, clientNumber)
' 6. Update the invoice using actEntity.
invoiceData = Await ActEntity(client, urlBase, token, invoiceData)
' 7. Save the invoice.
Dim savedInvoice = Await SaveInvoice(client, urlBase, token, invoiceData)
' 8. If the invoice is still a draft, sign it.
If IsDraft(savedInvoice) Then
Await SignInvoice(client, urlBase, token, savedInvoice)
End If
' 9. Logout after all operations.
Await Logout(client, urlBase, token)
End If
End If
Console.WriteLine("Process complete. Press any key to exit...")
Console.ReadKey()
End Using
End Function
' Called webservice to login into PHC GO
Async Function Login(client As HttpClient, urlBase As String, username As String, password As String, appType As String, company As String) As Task(Of String)
Dim url = urlBase & "REST/UserLoginWS/userLoginCompany"
Dim parameters = New Dictionary(Of String, String) From {
{"userCode", username},
{"password", password},
{"applicationType", appType},
{"company", company}
}
Dim content As New FormUrlEncodedContent(parameters)
Dim response = Await client.PostAsync(url, content)
Dim jsonString = Await response.Content.ReadAsStringAsync()
Dim json = JObject.Parse(jsonString)
If json("messages") IsNot Nothing Then
Console.WriteLine("Error in login. Please verify your credentials.")
Return Nothing
End If
Dim token = json("result")(0)("token").ToString()
Return token
End Function
' Called webservice to query invoice documents (FT, FS, FR)
Async Function QueryInvoiceDocuments(client As HttpClient, urlBase As String, token As String) As Task(Of String)
Dim url = urlBase & "REST/SearchWS/QueryAsEntities"
Dim queryJson As String = "{""groupByItems"":[],""lazyLoaded"":false,""joinEntities"":[],""orderByItems"":[],""SelectItems"":[],""entityName"":""Td"",""filterItems"":[{""comparison"":0,""filterItem"":""inactivo"",""valueItem"":""0"",""groupItem"":1,""checkNull"":false,""skipCheckType"":false,""type"":""Number""}]}"
Dim parameters = New Dictionary(Of String, String) From {
{"itemQuery", queryJson}
}
Dim content As New FormUrlEncodedContent(parameters)
client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Engine-Auth", token)
Dim response = Await client.PostAsync(url, content)
Dim jsonString = Await response.Content.ReadAsStringAsync()
Dim json = JObject.Parse(jsonString)
Dim options As New StringBuilder()
For Each item In json("result")
Dim type = item("tiposaft").ToString()
If type = "FT" OrElse type = "FS" OrElse type = "FR" Then
options.AppendLine(item("ndoc").ToString() & " - " & item("nmdoc").ToString())
End If
Next
Return options.ToString()
End Function
' Called webservice to logout from PHC GO
Async Function Logout(client As HttpClient, urlBase As String, token As String) As Task
Dim url = urlBase & "REST/UserLoginWS/userLogout"
' Assuming logout is a GET request
Await client.GetAsync(url)
End Function
' Called webservice to check if the client exists using query (filter by NIF) and create one if not.
Async Function CheckOrCreateClient(client As HttpClient, urlBase As String, token As String) As Task(Of String)
Dim url = urlBase & "REST/SearchWS/QueryAsEntities"
Dim queryJson As String = "{""groupByItems"":[],""lazyLoaded"":false,""joinEntities"":[],""orderByItems"":[],""SelectItems"":[],""entityName"":""Cl"",""filterItems"":[{""comparison"":0,""filterItem"":""ncont"",""valueItem"":""235047660"",""groupItem"":1,""checkNull"":false,""skipCheckType"":false,""type"":""Number""}]}"
Dim parameters = New Dictionary(Of String, String) From {
{"itemQuery", queryJson}
}
Dim content As New FormUrlEncodedContent(parameters)
client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Engine-Auth", token)
Dim response = Await client.PostAsync(url, content)
Dim jsonString = Await response.Content.ReadAsStringAsync()
Dim json = JObject.Parse(jsonString)
If json("result") IsNot Nothing AndAlso json("result").HasValues Then
Dim clientNo = json("result")(0)("no").ToString()
Console.WriteLine("Client #" & clientNo & " already exists in PHC GO")
Return clientNo
Else
' Get new instance of client.
url = urlBase & "REST/ClWS/getNewInstance"
parameters = New Dictionary(Of String, String) From {
{"ndos", "0"}
}
content = New FormUrlEncodedContent(parameters)
Dim responseNew = Await client.PostAsync(url, content)
jsonString = Await responseNew.Content.ReadAsStringAsync()
json = JObject.Parse(jsonString)
' Fill client data.
json("result")(0)("nome") = "Customer Test wxy"
json("result")(0)("morada") = "Lagoas Park"
json("result")(0)("local") = "Lisboa"
json("result")(0)("codpost") = "1234-123"
json("result")(0)("email") = "customer3@phc.pt"
json("result")(0)("ncont") = "212187449"
' Save client.
url = urlBase & "REST/ClWS/Save"
Dim clientData = json("result")(0).ToString()
parameters = New Dictionary(Of String, String) From {
{"itemVO", clientData},
{"runWarningRules", "false"}
}
content = New FormUrlEncodedContent(parameters)
Dim responseSave = Await client.PostAsync(url, content)
jsonString = Await responseSave.Content.ReadAsStringAsync()
json = JObject.Parse(jsonString)
Dim newClientNo = json("result")(0)("no").ToString()
Console.WriteLine("Client #" & newClientNo & " is inserted in PHC GO")
Return newClientNo
End If
End Function
' Called webservice to check if the product exists using query (filter by reference) and create one if not.
Async Function CheckOrCreateProduct(client As HttpClient, urlBase As String, token As String) As Task(Of String)
Dim url = urlBase & "REST/SearchWS/QueryAsEntities"
Dim queryJson As String = "{""groupByItems"":[],""lazyLoaded"":false,""joinEntities"":[],""orderByItems"":[],""SelectItems"":[],""entityName"":""St"",""filterItems"":[{""comparison"":0,""filterItem"":""ref"",""valueItem"":""REF_1"",""groupItem"":1,""checkNull"":false,""skipCheckType"":false,""type"":""Number""}]}"
Dim parameters = New Dictionary(Of String, String) From {
{"itemQuery", queryJson}
}
Dim content As New FormUrlEncodedContent(parameters)
client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Engine-Auth", token)
Dim response = Await client.PostAsync(url, content)
Dim jsonString = Await response.Content.ReadAsStringAsync()
Dim json = JObject.Parse(jsonString)
If json("result") IsNot Nothing AndAlso json("result").HasValues Then
Dim productRef = json("result")(0)("ref").ToString()
Console.WriteLine("Product ref " & productRef & " already exists in PHC GO")
Return productRef
Else
' Get new instance of product.
url = urlBase & "REST/StWS/getNewInstance"
parameters = New Dictionary(Of String, String) From {
{"ndos", "0"}
}
content = New FormUrlEncodedContent(parameters)
Dim responseNew = Await client.PostAsync(url, content)
jsonString = Await responseNew.Content.ReadAsStringAsync()
json = JObject.Parse(jsonString)
' Set product details.
json("result")(0)("ref") = "REF_1"
json("result")(0)("design") = "Test Product W"
json("result")(0)("epv1") = "9.99"
json("result")(0)("iva1incl") = True
json("result")(0)("inactivo") = False
' Save product.
url = urlBase & "REST/StWS/Save"
Dim productData = json("result")(0).ToString()
parameters = New Dictionary(Of String, String) From {
{"itemVO", productData},
{"runWarningRules", "false"}
}
content = New FormUrlEncodedContent(parameters)
Dim responseSave = Await client.PostAsync(url, content)
jsonString = Await responseSave.Content.ReadAsStringAsync()
json = JObject.Parse(jsonString)
Dim newProductRef = json("result")(0)("ref").ToString()
Console.WriteLine("Product ref " & newProductRef & " is inserted in PHC GO")
Return newProductRef
End If
End Function
' Called webservice to get a new instance of an invoice (FT)
Async Function GetNewInvoiceInstance(client As HttpClient, urlBase As String, token As String, invoiceType As String) As Task(Of JObject)
Dim url = urlBase & "REST/FtWS/getNewInstance"
Dim parameters = New Dictionary(Of String, String) From {
{"ndos", invoiceType}
}
Dim content As New FormUrlEncodedContent(parameters)
client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Engine-Auth", token)
Dim response = Await client.PostAsync(url, content)
Dim jsonString = Await response.Content.ReadAsStringAsync()
Dim json = JObject.Parse(jsonString)
Return CType(json("result")(0), JObject)
End Function
' Adds a new line to the invoice document.
Function AddInvoiceLine(invoiceData As JObject) As JObject
Dim newLineJson As String = "{""actqtt2"": false, ""amostra"": false, ""armazem"": 0, ""articleAutoCreationCode"": 0, ""avencano"": 0, ""avencastamp"": """", ""bistamp"": """", ""ccstamp"": """", ""cliref"": """", ""codigo"": """", ""codmotiseimp"": """", ""componente"": false, ""compound"": false, ""cpoc"": 0, ""davencaft"": ""1900-01-01 00:00:00Z"", ""desc2"": 0, ""desc3"": 0, ""desc4"": 0, ""desc5"": 0, ""desc6"": 0, ""desconto"": 0, ""design"": ""Caixa e tamboril"", ""ecusto"": 0, ""elucro"": 0, ""emargem"": 0, ""epv"": 14.99, ""etiliquido"": 14.99, ""ettiva"": 0, ""evalcomissao"": 0, ""facturaFt"": false, ""familia"": """", ""fechabo"": false, ""firefs"": [], ""fistamp"": """", ""ftstamp"": ""d08-4a6a-a07f-b6eed883678"", ""iva"": 23, ""ivadata"": ""1900-01-01 00:00:00Z"", ""ivaincl"": true, ""ivarec"": 0, ""litem"": """", ""litem2"": """", ""lordem"": 0, ""lrecno"": """", ""maxQttRefund"": 0, ""miseimpstamp"": """", ""motiseimp"": """", ""nvol"": 0, ""ofistamp"": """", ""ofnstamp"": """", ""oftstamp"": """", ""oref"": """", ""originalMaxQttRefund"": 0, ""pbuni"": 0, ""pluni"": 0, ""pvmoeda"": 0, ""qtt"": 1, ""rdata"": ""1900-01-01 00:00:00Z"", ""rdstamp"": """", ""ref"": ""C001"", ""stns"": false, ""sujirs"": false, ""tabiva"": 0, ""tmoeda"": 0, ""tnvol"": 0, ""tpbrut"": 0, ""tpliq"": 0, ""treestamp"": """", ""tvol"": 0, ""unidade"": """", ""usr1"": """", ""usr2"": """", ""vuni"": 0 }"
Dim newLine = JObject.Parse(newLineJson)
' Add new line into the invoice data (assuming a "fis" array exists)
invoiceData("fis") = New JArray(newLine)
Return invoiceData
End Function
' Associates the client to the invoice and clears financial discounts.
Function UpdateInvoiceWithClient(invoiceData As JObject, clientNumber As String) As JObject
invoiceData("no") = clientNumber
invoiceData("efinv") = 0
invoiceData("fin") = 0
Return invoiceData
End Function
' Called webservice to update the invoice using actEntity.
Async Function ActEntity(client As HttpClient, urlBase As String, token As String, invoiceData As JObject) As Task(Of JObject)
Dim url = urlBase & "REST/FtWS/actEntity"
Dim parameters = New Dictionary(Of String, String) From {
{"entity", invoiceData.ToString()},
{"code", "0"},
{"newValue", "[]"}
}
Dim content As New FormUrlEncodedContent(parameters)
client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Engine-Auth", token)
Dim response = Await client.PostAsync(url, content)
' Assume the invoiceData is updated accordingly.
Return invoiceData
End Function
' Called webservice to save the invoice (FT)
Async Function SaveInvoice(client As HttpClient, urlBase As String, token As String, invoiceData As JObject) As Task(Of JObject)
Dim url = urlBase & "REST/FtWS/Save"
Dim parameters = New Dictionary(Of String, String) From {
{"itemVO", invoiceData.ToString()},
{"runWarningRules", "false"}
}
Dim content As New FormUrlEncodedContent(parameters)
client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Engine-Auth", token)
Dim response = Await client.PostAsync(url, content)
Dim jsonString = Await response.Content.ReadAsStringAsync()
Dim json = JObject.Parse(jsonString)
Return CType(json("result")(0), JObject)
End Function
' Checks if the invoice is still a draft (draftRecord equals 1)
Function IsDraft(invoiceData As JObject) As Boolean
Return invoiceData("draftRecord").ToString() = "1"
End Function
' Called webservice to sign the invoice document
Async Function SignInvoice(client As HttpClient, urlBase As String, token As String, invoiceData As JObject) As Task
Dim url = urlBase & "REST/FtWS/signDocument"
Dim parameters = New Dictionary(Of String, String) From {
{"ftstamp", invoiceData("ftstamp").ToString()}
}
Dim content As New FormUrlEncodedContent(parameters)
client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Engine-Auth", token)
Dim response = Await client.PostAsync(url, content)
Dim jsonString = Await response.Content.ReadAsStringAsync()
Dim json = JObject.Parse(jsonString)
Console.WriteLine(json("result")(0)("nmdoc").ToString() & " #" & json("result")(0)("fno").ToString() & " is signed and inserted in PHC GO")
End Function
End Module
namespace PHCIntegrationExample
{
class Program
{
// The Main entry point – choose between the login branch and the generate-invoice branch.
static async Task Main(string[] args)
{
// Create an HttpClient with a cookie container.
var cookieContainer = new CookieContainer();
var handler = new HttpClientHandler { CookieContainer = cookieContainer, UseCookies = true };
using (var client = new HttpClient(handler))
{
string urlBase = "XXXXXXXXXXXXXXXXXXXXXXX/phcws/";
string username = "XXXXXX";
string password = "XXXXXX";
string appType = "XXXXXXXXXXXXXXXXXXXXXXXXX";
string company = "";
Console.WriteLine("Enter 1 for login and invoice query, 2 for generating invoice:");
string choice = Console.ReadLine();
if (choice == "1")
{
// --- LOGIN BRANCH ---
// Call login endpoint to obtain the token.
string token = await Login(client, urlBase, username, password, appType, company);
if (!string.IsNullOrEmpty(token))
{
// Query available invoice documents (FT, FS, FR).
string invoiceOptions = await QueryInvoiceDocuments(client, urlBase, token);
Console.WriteLine("Available invoice document types:");
Console.WriteLine(invoiceOptions);
// Logout after the query.
await Logout(client, urlBase, token);
}
}
else if (choice == "2")
{
// --- GENERATE INVOICE BRANCH ---
// Re-login to obtain the token.
string token = await Login(client, urlBase, username, password, appType, company);
if (!string.IsNullOrEmpty(token))
{
// 1. Check if the client exists (using NIF) and create one if needed.
string clientNumber = await CheckOrCreateClient(client, urlBase, token);
// 2. Check if the product exists (using reference) and create one if needed.
string productRef = await CheckOrCreateProduct(client, urlBase, token);
// 3. Get a new invoice instance (FT) using the selected invoice type.
string invoiceType = "YOUR_SELECTED_INVOICE_TYPE"; // Replace with your selected value.
JObject invoiceData = await GetNewInvoiceInstance(client, urlBase, token, invoiceType);
// 4. Add a new invoice line (e.g. product, quantity, price).
invoiceData = AddInvoiceLine(invoiceData);
// 5. Associate the client to the invoice and update discount values.
invoiceData = UpdateInvoiceWithClient(invoiceData, clientNumber);
// 6. Update the invoice using actEntity.
invoiceData = await ActEntity(client, urlBase, token, invoiceData);
// 7. Save the invoice.
JObject savedInvoice = await SaveInvoice(client, urlBase, token, invoiceData);
// 8. If the invoice is still a draft, sign it.
if (IsDraft(savedInvoice))
{
await SignInvoice(client, urlBase, token, savedInvoice);
}
// 9. Logout after all operations.
await Logout(client, urlBase, token);
}
}
Console.WriteLine("Process complete. Press any key to exit...");
Console.ReadKey();
}
}
// Called webservice to login into PHC GO.
static async Task<string> Login(HttpClient client, string urlBase, string username, string password, string appType, string company)
{
string url = urlBase + "REST/UserLoginWS/userLoginCompany";
var parameters = new Dictionary<string, string>
{
{ "userCode", username },
{ "password", password },
{ "applicationType", appType },
{ "company", company }
};
var content = new FormUrlEncodedContent(parameters);
var response = await client.PostAsync(url, content);
string jsonString = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(jsonString);
if (json["messages"] != null)
{
Console.WriteLine("Error in login. Please verify your credentials.");
return null;
}
string token = json["result"][0]["token"].ToString();
return token;
}
// Called webservice to query invoice documents (FT, FS, FR).
static async Task<string> QueryInvoiceDocuments(HttpClient client, string urlBase, string token)
{
string url = urlBase + "REST/SearchWS/QueryAsEntities";
string queryJson = "{\"groupByItems\":[],\"lazyLoaded\":false,\"joinEntities\":[],\"orderByItems\":[],\"SelectItems\":[],\"entityName\":\"Td\",\"filterItems\":[{\"comparison\":0,\"filterItem\":\"inactivo\",\"valueItem\":\"0\",\"groupItem\":1,\"checkNull\":false,\"skipCheckType\":false,\"type\":\"Number\"}]}";
var parameters = new Dictionary<string, string>
{
{ "itemQuery", queryJson }
};
var content = new FormUrlEncodedContent(parameters);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Engine-Auth", token);
var response = await client.PostAsync(url, content);
string jsonString = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(jsonString);
var options = new StringBuilder();
foreach (var item in json["result"])
{
string type = item["tiposaft"].ToString();
if (type == "FT" || type == "FS" || type == "FR")
{
options.AppendLine(item["ndoc"].ToString() + " - " + item["nmdoc"].ToString());
}
}
return options.ToString();
}
// Called webservice to logout from PHC GO.
static async Task Logout(HttpClient client, string urlBase, string token)
{
string url = urlBase + "REST/UserLoginWS/userLogout";
await client.GetAsync(url); // Assuming logout is performed via a GET request.
}
// Called webservice to check if the client exists (by NIF) and create one if not.
static async Task<string> CheckOrCreateClient(HttpClient client, string urlBase, string token)
{
string url = urlBase + "REST/SearchWS/QueryAsEntities";
string queryJson = "{\"groupByItems\":[],\"lazyLoaded\":false,\"joinEntities\":[],\"orderByItems\":[],\"SelectItems\":[],\"entityName\":\"Cl\",\"filterItems\":[{\"comparison\":0,\"filterItem\":\"ncont\",\"valueItem\":\"235047660\",\"groupItem\":1,\"checkNull\":false,\"skipCheckType\":false,\"type\":\"Number\"}]}";
var parameters = new Dictionary<string, string>
{
{ "itemQuery", queryJson }
};
var content = new FormUrlEncodedContent(parameters);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Engine-Auth", token);
var response = await client.PostAsync(url, content);
string jsonString = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(jsonString);
if (json["result"] != null && json["result"].HasValues)
{
string clientNo = json["result"][0]["no"].ToString();
Console.WriteLine("Client #" + clientNo + " already exists in PHC GO");
return clientNo;
}
else
{
// Get new instance of client.
url = urlBase + "REST/ClWS/getNewInstance";
parameters = new Dictionary<string, string>
{
{ "ndos", "0" }
};
content = new FormUrlEncodedContent(parameters);
var responseNew = await client.PostAsync(url, content);
jsonString = await responseNew.Content.ReadAsStringAsync();
json = JObject.Parse(jsonString);
// Fill client data.
json["result"][0]["nome"] = "Customer Test wxy";
json["result"][0]["morada"] = "Lagoas Park";
json["result"][0]["local"] = "Lisboa";
json["result"][0]["codpost"] = "1234-123";
json["result"][0]["email"] = "customer3@phc.pt";
json["result"][0]["ncont"] = "212187449";
// Save client.
url = urlBase + "REST/ClWS/Save";
string clientData = json["result"][0].ToString();
parameters = new Dictionary<string, string>
{
{ "itemVO", clientData },
{ "runWarningRules", "false" }
};
content = new FormUrlEncodedContent(parameters);
var responseSave = await client.PostAsync(url, content);
jsonString = await responseSave.Content.ReadAsStringAsync();
json = JObject.Parse(jsonString);
string newClientNo = json["result"][0]["no"].ToString();
Console.WriteLine("Client #" + newClientNo + " is inserted in PHC GO");
return newClientNo;
}
}
// Called webservice to check if the product exists (by reference) and create one if not.
static async Task<string> CheckOrCreateProduct(HttpClient client, string urlBase, string token)
{
string url = urlBase + "REST/SearchWS/QueryAsEntities";
string queryJson = "{\"groupByItems\":[],\"lazyLoaded\":false,\"joinEntities\":[],\"orderByItems\":[],\"SelectItems\":[],\"entityName\":\"St\",\"filterItems\":[{\"comparison\":0,\"filterItem\":\"ref\",\"valueItem\":\"REF_1\",\"groupItem\":1,\"checkNull\":false,\"skipCheckType\":false,\"type\":\"Number\"}]}";
var parameters = new Dictionary<string, string>
{
{ "itemQuery", queryJson }
};
var content = new FormUrlEncodedContent(parameters);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Engine-Auth", token);
var response = await client.PostAsync(url, content);
string jsonString = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(jsonString);
if (json["result"] != null && json["result"].HasValues)
{
string productRef = json["result"][0]["ref"].ToString();
Console.WriteLine("Product ref " + productRef + " already exists in PHC GO");
return productRef;
}
else
{
// Get new instance of product.
url = urlBase + "REST/StWS/getNewInstance";
parameters = new Dictionary<string, string>
{
{ "ndos", "0" }
};
content = new FormUrlEncodedContent(parameters);
var responseNew = await client.PostAsync(url, content);
jsonString = await responseNew.Content.ReadAsStringAsync();
json = JObject.Parse(jsonString);
// Set product details.
json["result"][0]["ref"] = "REF_1";
json["result"][0]["design"] = "Test Product W";
json["result"][0]["epv1"] = "9.99";
json["result"][0]["iva1incl"] = true;
json["result"][0]["inactivo"] = false;
// Save product.
url = urlBase + "REST/StWS/Save";
string productData = json["result"][0].ToString();
parameters = new Dictionary<string, string>
{
{ "itemVO", productData },
{ "runWarningRules", "false" }
};
content = new FormUrlEncodedContent(parameters);
var responseSave = await client.PostAsync(url, content);
jsonString = await responseSave.Content.ReadAsStringAsync();
json = JObject.Parse(jsonString);
string newProductRef = json["result"][0]["ref"].ToString();
Console.WriteLine("Product ref " + newProductRef + " is inserted in PHC GO");
return newProductRef;
}
}
// Called webservice to get a new instance of an invoice (FT).
static async Task<JObject> GetNewInvoiceInstance(HttpClient client, string urlBase, string token, string invoiceType)
{
string url = urlBase + "REST/FtWS/getNewInstance";
var parameters = new Dictionary<string, string>
{
{ "ndos", invoiceType }
};
var content = new FormUrlEncodedContent(parameters);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Engine-Auth", token);
var response = await client.PostAsync(url, content);
string jsonString = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(jsonString);
return (JObject)json["result"][0];
}
// Adds a new line to the invoice document.
static JObject AddInvoiceLine(JObject invoiceData)
{
string newLineJson = "{\"actqtt2\": false, \"amostra\": false, \"armazem\": 0, \"articleAutoCreationCode\": 0, \"avencano\": 0, \"avencastamp\": \"\", \"bistamp\": \"\", \"ccstamp\": \"\", \"cliref\": \"\", \"codigo\": \"\", \"codmotiseimp\": \"\", \"componente\": false, \"compound\": false, \"cpoc\": 0, \"davencaft\": \"1900-01-01 00:00:00Z\", \"desc2\": 0, \"desc3\": 0, \"desc4\": 0, \"desc5\": 0, \"desc6\": 0, \"desconto\": 0, \"design\": \"Caixa e tamboril\", \"ecusto\": 0, \"elucro\": 0, \"emargem\": 0, \"epv\": 14.99, \"etiliquido\": 14.99, \"ettiva\": 0, \"evalcomissao\": 0, \"facturaFt\": false, \"familia\": \"\", \"fechabo\": false, \"firefs\": [], \"fistamp\": \"\", \"ftstamp\": \"d08-4a6a-a07f-b6eed883678\", \"iva\": 23, \"ivadata\": \"1900-01-01 00:00:00Z\", \"ivaincl\": true, \"ivarec\": 0, \"litem\": \"\", \"litem2\": \"\", \"lordem\": 0, \"lrecno\": \"\", \"maxQttRefund\": 0, \"miseimpstamp\": \"\", \"motiseimp\": \"\", \"nvol\": 0, \"ofistamp\": \"\", \"ofnstamp\": \"\", \"oftstamp\": \"\", \"oref\": \"\", \"originalMaxQttRefund\": 0, \"pbuni\": 0, \"pluni\": 0, \"pvmoeda\": 0, \"qtt\": 1, \"rdata\": \"1900-01-01 00:00:00Z\", \"rdstamp\": \"\", \"ref\": \"C001\", \"stns\": false, \"sujirs\": false, \"tabiva\": 0, \"tmoeda\": 0, \"tnvol\": 0, \"tpbrut\": 0, \"tpliq\": 0, \"treestamp\": \"\", \"tvol\": 0, \"unidade\": \"\", \"usr1\": \"\", \"usr2\": \"\", \"vuni\": 0 }";
var newLine = JObject.Parse(newLineJson);
// Add the new line into the "fis" array.
invoiceData["fis"] = new JArray(newLine);
return invoiceData;
}
// Associates the client to the invoice and clears financial discount values.
static JObject UpdateInvoiceWithClient(JObject invoiceData, string clientNumber)
{
invoiceData["no"] = clientNumber;
invoiceData["efinv"] = 0;
invoiceData["fin"] = 0;
return invoiceData;
}
// Called webservice to update the invoice using actEntity.
static async Task<JObject> ActEntity(HttpClient client, string urlBase, string token, JObject invoiceData)
{
string url = urlBase + "REST/FtWS/actEntity";
var parameters = new Dictionary<string, string>
{
{ "entity", invoiceData.ToString() },
{ "code", "0" },
{ "newValue", "[]" }
};
var content = new FormUrlEncodedContent(parameters);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Engine-Auth", token);
var response = await client.PostAsync(url, content);
// Assume invoiceData is updated accordingly.
return invoiceData;
}
// Called webservice to save the invoice (FT).
static async Task<JObject> SaveInvoice(HttpClient client, string urlBase, string token, JObject invoiceData)
{
string url = urlBase + "REST/FtWS/Save";
var parameters = new Dictionary<string, string>
{
{ "itemVO", invoiceData.ToString() },
{ "runWarningRules", "false" }
};
var content = new FormUrlEncodedContent(parameters);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Engine-Auth", token);
var response = await client.PostAsync(url, content);
string jsonString = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(jsonString);
return (JObject)json["result"][0];
}
// Checks if the invoice is still a draft (draftRecord equals "1").
static bool IsDraft(JObject invoiceData)
{
return invoiceData["draftRecord"].ToString() == "1";
}
// Called webservice to sign the invoice document.
static async Task SignInvoice(HttpClient client, string urlBase, string token, JObject invoiceData)
{
string url = urlBase + "REST/FtWS/signDocument";
var parameters = new Dictionary<string, string>
{
{ "ftstamp", invoiceData["ftstamp"].ToString() }
};
var content = new FormUrlEncodedContent(parameters);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Engine-Auth", token);
var response = await client.PostAsync(url, content);
string jsonString = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(jsonString);
Console.WriteLine($"{json["result"][0]["nmdoc"]} # {json["result"][0]["fno"]} is signed and inserted in PHC GO");
}
}
}