Showing posts with label GSX. Show all posts
Showing posts with label GSX. Show all posts

Friday, November 19, 2021

Passing a URL to a PHP to Call GSX

 GSSX requires user site to be white listed before allowing access. Since our customer are using multiple applications that access GSX. The whitelisted server is not on the same server as our web program. User need to post data to the web server which in turn send a request to a central server which then send the request to GSX. 

Sending normal requests is simple but since GSX has many APIs that have a mix of "GET and POST"., The sending of data to GSX become complex as we have to send specific URL to get the right result. Now sending a POST/GET that contains URL as parameter is not that simple especially when the URL is mixed with other parameters. It need to be url-encoded properly.

PHP CURL uses query method to do both POST/GET thus the query works on both.

Luckily, there is a PHP function that could compose the post parameters. It is called HTTP_BUILD_QUERY. You just need to send an array of the parameters and it will compose the parameters properly. This including sending a URL as data.

The following is an example 

$data= array(

"id" => "1234567"

,"address" => "https://gsxserver.com/returns"

);

$params = http_build_query($data);

In your CURL request you simply use 

curl_setopt($ch, CURLOPT_POSTFIELDS, $param);

The central server PHP just need to get $_POST['xx'] to get the specific parameters.





Sunday, December 13, 2020

Communicating with Apple Web Services (GSX) via Filemaker 3

 My previous blog talks about communicating with GSX using JSON. There is one area which is not mentioned. This area concerns with security. GSX requires client certificate issued by them and a white-listed IP. They require user to be certified and communicating from an approved IP address.

The white-listing is easy to achieve. Just designate your server/computer as the channel to communicate with GSX. All API requests have to be send from the server/computer. This means that if you require multiple user access, then you must provide a means for all of them to communicate with GSX from the white-listed server/computer from Filemaker using the "Insert from URL" function.

Getting a cert from GSX is done by sending a properly filled CSR to GSX. Note that the Common Name is defined by GSX. It is used to identify user according to GSX format. With the cert, you need to prepare it for use by the server/computer so that you can use it. The following is example done in PHP. The method used is via CURL in PHP.  It is not advisable to use Filemaker to communicate directly with GSX as each "execute from server" means one connection used. You may soon find out you run out of connection on your server. By using "Insert from URL" and calls a PHP server, there is no limit.

Before you could start coding the PHP, you need to prepare your cert for use in CURL. CURL works best with certs in the PEM format. You need to combine the cert and private key into one file by copying and pasting the cert and key into a single pem file.

The following is a typical CURL setting

$ch = curl_init();

curl_setopt($ch, CURLOPT_HEADER, false);

curl_setopt($ch, CURLOPT_VERBOSE, true);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);

curl_setopt($ch, CURLOPT_VERIFYHOST, 0);

curl_setopt($ch, CURLOPT_VERIFYPEER, 0);

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

curl_setopt($ch, CURLOPT_HEASDER_OUT, true);

curl_setopt($ch, CURLOPT_SSSLCERTTYPE, 'pem');

curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'pem');

curl_setopt($ch, CURLOPT_SSLCERT, 'your cert');

curl_setopt($ch, CURLOPT_SSLKEY, 'your key');

curl_setopt($ch, CURLOPT_SSLKEYPASSWD, 'your pass');

You will have to check the documents to see what are the headers required to be sent to GSX. I suggest you send the header settings from your user to the server/computer as JSON then convert the JSON as array with variable name as $headers as shown above. In addition, not all GSX API calls are POST. You need to get user to indicate whether the request is POST or GET.

If it is post then you will need to set the following

curl_setopt($ch, CURLOPT_POST, true);

curl_setopt($ch, CURLOPT_POSTFIELDS, $content);

curl_setopt($ch, CURLOPT_URL, 'your url');

Since a GET requires CURL GET request, you need to define it with the following.

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

Each API requires the API to be defined as part of the URL. You need to define the URL for each API call. Compose the URL from the user side and send it as a parameter to the server.

curl_setopt($ch, CURLOPT_URL, 'your url');

Finally execute the CURL

$output = curl_exec($ch);

It is a good practice to always close the CURL after every thing is done.

Now CURL may return two different errors. One from CURL itself, the other is from GSX. Your error message have to distinguish between the two.

Before you even start to test the PHP coding, you need to obtain an initial ID from GSX. Therefore, you have to visit https://gsx2.apple.com/gsx/login to sign in and get the ID. This id will be used to obtain the proper ID for subsequent GSX API request by calling the "authenticate token" api then copy the ID returned for subsequent use.

A final oddities is that if you, or your users, use more than one app or one computer that access GSX. Please be reminded that only one ID is provided at anytime. You need to use the same ID for all requests. It is up to you and your user to store such ID in one secure place and use it to consume APIs.







Sunday, June 23, 2019

GSX Questions

It was something that was started quite sometime ago but wasn't made compulsory. Questions are a set of data that was posted as questions and user is supposed to answer it accordingly. Its as simple as that.

However, the Questions are nested questions and no fixed pattern. Previously, a pointer is used if there are nested questions. It could not work that well. Recently GSX changed the data format to JSON and the Questions were set in nested JSON format. This makes it much easier to follow as we just need to traverse the nesting structure typical of JSON.

Fortunately, Questions uses fixed format in the form of Questions and Answers. The nesting is always at the Answers array or as a array in the Questions level.

This blog talks about how to traverse through the list and nested questions using FileMaker. As it is, GSX returns a JSON. Since FileMaker has JSON functions that can read nodes from JSON stored in fields or variables and the format (path) of reading the nodes is like "XX.YY.ZZ". If it is an array, just add the array number after the node name like "XX[0]".

The method of traversing the nodes is simple. The path is stored in a variable.  We start off with $trees="questionDetails[0].trees[0].questions[0].answers[0]". Using JSONListKeys($json;$trees) we can get a list of keys. If there is no answers, we remove the last node and add 1 to the previous level array then repeats to find the answer keys.

Upon finding the answer, we post the question and gets an answer from user. Depends on answer type, user have to respond accordingly. Once finished answering then we look for nested questions in the answer. If there are nested questions, we add one new level after answers and go to the first question in the nested questions.

In the nesting, if there are more items in the array, we go into the next item in the array and look for questions or answers. If there is no more or no questions/answers. we back up one level and see if there are more items in that level.

In this way, we could go into the nesting systematically and back up to the higher level if there are no more array item.

GSX requires you provide the question ID when you answers. So you must create an answer JSON that corresponds to the Questions. Every time you add a question/answer level you need to add the array first so that when you answer, you can write the answers using the same $trees array.

I won't be diving into showing examples of traversing. Do figure out how to do it yourself.




Sunday, February 01, 2015

Communicating with Apple Web Services (GSX) via Filemaker

Web services according to WikiPedia is "a method of communication between two electronic devices over a network." There are websites that provide information as a service. Sites like Google Language API which allows you to translate your website directly without you having to create the translation yourself. This means you could translate your web site to hundreds of languages just with the web services code.

In plain language, web services allows you to call a web site from your website by providing a request, or consuming a request ( a most confusing term), with some data. The web site will then provide you with the result. For example, I send a request to Google Language API with "Japanese" as the required language and "How to speak Japanese" as the data. Google Language API will understand your request and responds with the result as "日本語を話す方法". When you change the language to Korean, and use back the same data, the API will respond with "일본어를하는 방법". Isn't that easier than you writing three different pages each with a different language?

Some web sites provide more than just one functionality. You can actually use the service to perform various actions by using it like a "function" with "parameters". In layman language, it means you need to tell the web service what you want to do with the data provided by you. The web services will understand your request and perform the exact action then return you the result. For example, I can go to a plant information web site and do search, update, create, delete, etc. just by calling the same address with different info.

In a web page, we will normally use Javascript to do the calling and showing the response using the technique call AJAX and a newer technique called JSON as data. It has all the functionality available to do it. You just need to compose what to send and get what is returned.

I have the opportunity to write programs using Filemaker (A database program owned by Apple). It has very good interface that allow very easy creation of database interfaces and web pages. However, its scripting facility is a bit lacking. This is especially true when trying to use the technology above to do translation. You practically have to write a code to do the functionality then write the code that make use of the functionality. That is double the work. Luckily there are plug-in that expand the capability of the application.

The following is a description of what I did to call a Web Service from Apple itself using Filemaker. It is a web service provided by Apple to its agents that provide repair services to its customers. The service provides a number of requests with its associated data. For example, if I need to order a spare part, I will call the web services with the request "orderPart" and "xxxxxx" as part number. Apple will then create an entry in its database that records your request and then send the part to you.

The request is send as a XML that contains the "request action" and the data. The response is also a XML that contains the result of the request. In this way user will see the same display yet the transaction is made in the back ground. The Filemaker program will then display the respond data so that user can see the result of the transaction.

Actually it is easier said than done. There is no such functionality available to talk to web services. Filemaker does have a "insert from URL" function that could call a web site and display the result in a field (a place where you can type in a form). However, it only shows the XML returned from Apple directly which is mostly not understood by user. Its XML facility is also not suited for manipulation with XML in this way. Thus the task is to create a code that could call the web services, send the request in XML format and translate the result to user in a readable format.

The very first task is to create the proper XML. Since there is no such function, it has to be created. XML node is generally in the form "<node>value</node>". As you can see, creating it is not a problem. So instead of typing the "node" and the "value" manually, you just need to call the subscript and pass it with the correct parameters.

Problem is that Filemaker (FMP) cannot pass multiple parameters. It does not have arrays too. There is, however, a "List" function that you can use like "list(value1,value2)". Thus you must combine the two information into one by using "list" before passing it as a parameter. You can even create a sort of array by creating a list within a list.

The XML example above is the basic format. XML, like HTML, also can contain properties. It is in the form "<node property='xxxx'>value</node>". Obviously these nodes can be nested. Setting the property nodes aside (as it is normally not used in "body"). There are four ways to create the XML.

1. The beginning node ("<node>"). With this and the ending node, you can create a nested node to what ever level you want.
2. The ending node ("</node>")
3. The complete node with value ("<node>value</node>").
4. The NULL node ("<node/>")

It is very easy to take the first parameter and treat it as a node by enclosing it with "<" and ">". The value is placed next then the first parameter is used again by enclosing it with "<" and ">
".

For those that only need the node name like 1,2, 4 above. It is constructed accordingly.

The value must not contain characters used by XML itself like "<" and ">". Therefore all the values have to be filtered or modified to ensure that the value does not end up as the XML itself. This is called "escaping". With this we are able to construct any XML body. This script will then be store as a script by itself. It always write to a global variable like $$xml so that it does not even need to return a value. The script then becomes a function that create xml nodes.

How then should we add headers. It is very simple. Since we always access to the same address, the header seldom changes. Why not just store it as a plain variable? This is exactly what I did.

In another script we will assemble the xml step by step. Fist we store the header into the variable $$xml. Then we use "run script" to run the script that creates the xml by passing the appropriate values beginning with a code that define what type of nodes we are creating. Repeat the subscript till the whole xml is complete. The result is then a well formed xml. You could even test the output by storing the $$xml in a field or just a custom dialog to ensure that the xml is correctly form by copying and pasting the result in a xml editor.

With the xml available, the next task is to send it to the Apple web services (GSX). Luckily, this functionality is available as a plug-in. BaseElements has the plug-in that could do a post to a website and get a respond into a variable instead of a input field. This functionality is exactly what we need to talk to the server.

The last part is to get the result out of the xml. This functionality is again not available. However, BaseElements does have the functionality to extract values from the xml. It may not be the functionality that I am looking at but at least it can be done. The best way is to transform the whole response xml into something  that is humanly manageable like an array without having to write long codes to do it. But then with the limitations, it is still better than nothing.

The conclusion is that Filemaker can talk to web services. With the database capability, getting chunks data out of the web services is a possibility.

MBS has an excellent example of communicating with GSX. MBS Blog.

Apple will be changing the format used for sending and receiving data.  Please go to part 2 to see how it could be done.