Welcome to Philippine Ports Authority
Web API RESTful Services
Online Ports Charges Exemption

Change Log
Recent Update: Tue 20-Aug-2019 | Previous: Mon, 11-Jun-2018
Developer's and Track Changes Guide — For OPCE Release Version 1.5.30136


Document Changes
Date Change
Friday 29/Nov/2019 Added minor feature to detect if the external PPA Central Database where OPCE depends is offline.
A message will be displayed on top of the page. The Login button is not shown if the database is offline.
Tue 20/Aug/2019 Added the field/member CONFIRMED_TRANSACTION to class OpceExemptionRequestHeaderDto for single request
Added the field/member BATCH_REQUEST_ID to class OpceBatchExemptionRequestHeaderDto for batch request
Added the field/member CONFIRMED_TRANSACTION to class OpceCommodityDto for batch request

Deployed new module Customers' Request
Deployed new module Commodity Approval
Deployed new module Administration/Helpdesk
Updated system version to 1.5.x
Mon 11/Jun/2018
Publicly Available Commodity Listings - As requested over PPA and ICTSI meeting dated May 22, 2018. PPA will provie a public listing where all the commodities can be accessed at anytime by customers.

The page is accessible using link the URL address at:
•   https://api.ppa.com.ph/PublicService/CommodityListing

This page provides the following features:
  • List all the commodities
  • Filter or search using commodity code
  • Filter or search using commodity description
  • Click to copy Commodity Code or Description to clipboard
  • Printing - all or based on filter result

NOTE: This endpoint is publicly accessible. No authorization is needed.
Mon 01/May/2018
Commodity and Party/Customer track changes - In connection with the previously added "versioning" of the commodity lists and party lists, the client, e.g. ICTSI is unaware of the records changed in our part. To further introduce verifiable and accuracy of data being exchanged on both ends, OPCE now provides the client to query the history of the changes made on these items.
See the new endpoint added (item #6, marked as * New) in the online documentation of OPCE at API Endpoint Documentation.

This is accomplished using the new endpoint at :
•   https://api.ppa.com.ph/api/OpceReportingApi/GetVerChanges?t=

NOTE: This endpoint is only accessible if the client is logged-on and authorized.
Mon 11/Dec/2017
Commodity and Party/Customer Versioning - This new API endpoint provides synchronization of commodity and party/customer lists on both client and server records for counter checking validity of commodity post exemption requests.
See the new endpoint added (item #2 and #3) in the online documentation of OPCE at API Endpoint Documentation.

NOTE: This endpoint is only accessible if the client is logged-on and authorized.
Mon 07/August/2017
Commodity Batch Request - The Web API system now supports batch request. A single request contains a client's/party's list of commodities in one post. Please see on how to use this endpoint by clicking Posting a Batch Request for Exemption (* New) above.

This is accomplished using the new endpoint at :
•   https://api.ppa.com.ph/api/opce/PostBatchExemptionRequestAsync

NOTE: This endpoint is only accessible if the client is logged-on and authorized.
Mon 20/Mar/2017
Deprecated Endpoints - The following end points for acquiring the updated list of parties and commodities are now disabled and out of service. This is due to the ambiguity of how the client/consumer development designs or program their consumer app.
• https://api.ppa.com.ph/api/opce/GetPezaAccreditedCompaniesTinAsync/?tin=
• https://api.ppa.com.ph/api/opce/GetPezaAccreditedCompanies/?startsWith=p

New Endpoints - Use the following GET endpoints for updating your local database repository for Party lists and Commodity lists, respectively.
NOTE: The endpoints are only accessible if the client is logged-on and authorized.
• https://api.ppa.com.ph/api/opce/GetPartyClientListAsync
• https://api.ppa.com.ph/api/opce/GetCommodityListAsync
Wed 18/Jan/2017
Completely REMOVED PEZA information members/fields from the validation/condition AND from the class/entity request. Please modify codebase to remove these two class members in your class OpceExemptionRequestHeaderDto codebase. If you are using REST Client for testing, remove these two form members from the form/json request.
public string REQ_PU_EXEMP_CODE { get; set; } //19 - Data Validation Request for PEZA Code
public string REQ_PU_EXEMP_ZONE { get; set; } //20 - Data Validation Request for Port client zone info

Sun 20/Mar/2016
REMOVED PEZA information members/fields from the validation/condition check ONLY for posting exemption request as all PEZA zones are exempted regardless of zone. Please NOTE however that these two fields are still required during each exemption request. Retaining these members in the codebase lessens the code modification.
public string REQ_PU_EXEMP_CODE { get; set; } //19 - Data Validation Request for PEZA Code
public string REQ_PU_EXEMP_ZONE { get; set; } //20 - Data Validation Request for Port client zone info

Tue 16/Feb/2016 Added Endpoint for acquiring PEZA accredited companies with TAX Number as reference/parameter.
NOTE: Requested by ICTSI.
1) List/Acquire Commodity List accredited by PEZA - This feature needs the member to be authorized or logged-in.
a) Using the account/credential, log in using this website, or automate login using your backend code.
b) Use https://api.ppa.com.ph/api/opce/GetPezaAccreditedCompaniesTinAsync/?tin= for acquiring the list.
where: tin is a parameter indicating the TAX number of the PEZA company being queried.

example: https://api.ppa.com.ph/api/opce/GetPezaAccreditedCompaniesTinAsync/?tin=400-263-290-0000
Sun 20/Dec/2015 Two major features added: (These are OPTIONAL helpers/methods for the subscriber to easily acquire and insert records to their backing database instead of parsing from the Excel file list being sent by PPA.)
1) List/Acquire Commodity List accredited by PEZA - This feature needs the member to be authorized or logged-in.
a) Using the account/credential, log in using this website.
b) After logging in, click the My Account [youremail@somewhere.com] on the upper right corner of this site.
c) The Manage your account page will be displayed.
d) Select from the list of links indicating "| View PEZA Accredited List of Exemptions".
To access the API that returns a JSON list of records, please use the endpoint:

https://api.ppa.com.ph/api/opce/GetPezaAccreditedCompanies/?startsWith=p

where: startsWith is a parameter indicating all the companies starting with such a letter or word. In the sample above, it gets the parties starting with letter "p". The casing is not sensitive. The value of the parameter can be a word as well, for example "house", indicating search all the party names starting with the word "house".

2) List Down Submitted Requests - follow instruction as above until step c). From the list, select | View My Exemption Requests
Sat 19/Dec/2015 Added two critical members/fields for OpceExemptionRequestHeaderDto. Below are the two fields added:
public string REQ_PU_EXEMP_CODE { get; set; } //19 - Data Validation Request for PEZA Code
public string REQ_PU_EXEMP_ZONE { get; set; } //20 - Data Validation Request for Port client zone info

Please see the latest definition of the data transformation class object OpceExemptionRequestHeaderDto. Again, the order of the fields are VERY IMPORTANT for hash code generation.
16/Dec/2015 The value of member/field REQ_ENTITY_ID will no longer accept any valid email format, instead, the the email of the currently logged-in or authorized user during a post exemption request.
07/Dec/2015 Registration/Membership is now in effect. Any request to the api endpoint at http://api.ppa.com.ph/api/opce/PostExemptionRequestAsync is now closed for public access. Please read the Registration Account Registration to be able to continue the posting of exemption requests.
  Installed Server Certificate for SSL/SLT access.
Signature Algo : sha256RSA; Public Key : RSA (2048-Bit); Expires: Friday, December 07, 2018
CN = Go Daddy Secure Certificate Authority - G2 OU = http://certs.godaddy.com/repository/ O = GoDaddy.com, Inc. L = Scottsdale S = Arizona C = US
03/Dec/2015 Members data type changes to data transformation object class OpceExemptionRequestHeaderDto. All members are now string for more precise serialization for hashing. Please change your class definition to exactly match the serialization and request. Click here to see the changes
For the member REQ_EX_REFERENCE_DATE valid date format are only:
{"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", "M/d/yyyy h:mm", "M/d/yyyy h:mm", "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"}
02/Dec/2015
When using the ASP.Net 4.5.x using async request via HttpClient, ALL the DECIMAL members of OpceExemptionRequestHeaderDto should be sent as with two precise decimal numbers. i.e.
For the following members of decimal type, please assign numbers with two precision decimal numbers. If you opted to input 0, please put 0.00. Use rounding of two decimal places strictly.
REQ_EX_WEIGHT = 0.00
REQ_EX_VOLUME = 0.00
REQ_EX_QTY = 11.26
REQ_EX_PPA_AMT = 100.96
29/Nov/2015
var serializedPostData = JsonSerializerUtility<OpceApiResponseHeaderDto>.SerializeToJson(postData);
SHOULD BE:

var serializedPostData = JsonSerializerUtility<OpceExemptionRequestHeaderDto>.SerializeToJson(postData);
  OpceApiResponseHeaderDto member: string ATTRIBUTE4 member now contains requesting entity IP Address
18/Nov/2015 OpceApiResponseHeaderDto member: int REQ_REMARK_ID changed to string REQ_REMARK_CODE
13/Nov/2015 Added authorization procedure in document
12/Nov/2015 Modification to second sentence at section, Option 1 : Via Asp.Net WebRequest (.NET 4 and below)
11/Nov/2015 Changes to Response Class Object (OpceApiResponseHeaderDto), use of members ATTRIBUTE1, ATTRIBUTE2 and ATTRIBUTE3. See new definition for details. See also sample response data for the values.
11/Nov/2015 Changes to Response Class Object (OpceApiResponseHeaderDto), added the field REQ_EX_REFERENCE_NO as part of response
11/Nov/2015 Thrid Draft, Version 0.0.3; HTML Format (this website document page).
Changes to Request Class Object (OpceExemptionRequestHeaderDto), omitted unnecessary field members. It now contains 18 member/attributes. See definition for more details.
10/Nov/2015 Second Draft Submitted, Version 0.0.2; Adobe PDF format via email.
04/Nov/2015 First Draft Submitted, Version 0.0.1; Adobe PDF format via email.

Getting Started

Prerequisite
The set of API endpoints served by PPA API Server will only accept JSON and/or XML posts via HTTP. The methods defined in each endpoint return varrying data objects from JSON/XML and sometimes, the standard W3C HTTP Response together with the standard response codes.
 
The requests may originate from varying sources or platforms, such as LINUX, Windows Server, DB2 to name a few. And can originate from any desktop, mobile and specific OS apps from PHP to JAVA to .NET/C#, MONGO, including mobile applications, etc. -- as long as it sends the standard JSON/XML Format under the HTTP protocol.

Account Registration

Required
Please contact PPA Helpdesk on how to acquire an account for posting commodity requests against this system.
 

Authorizing Post Exemption Request

Introduction

Based from the previous meet-up with PPA and ICTSI, a security authorization code will be provided in order for ICTSI to send and authorize request with the PPA Server. This, together with the request every time a post is made with the API Server. However, we found this to be insecure, because it is based on older Basic Authentication offered by Membership provider, long ago being used in the market. As well, it does not scale, since, this is just a basic type of authentication. The authorization code can be compromised should there be a breach of information shared with unauthorized person(s) in the long run.

To remedy the problem, we are designing a more secured and scalable approach on authorizing requests from clients. This method will be derived and based from a newer authorization method from Microsoft Identity Core, OWIN or Open Web Interface for .NET, providing two-factor authentication and heightened security measure. This will be available for testing starting 24th of November, 2015.

Registration

By means of account registration, the owner of the business, i.e. ICTSI can change credentials at will, at anytime for a more secure approach of posting request to PPA API Server, rather than a fixed authorization code given for authority and access.

During account registration, two-factor authentication will be applied, email confirmation, expiring credential resets, and/or SMS verification method. The latter, if PPA can provide will be validated but of course, in the code base, ready and can be tested provided the SMS service subscription is granted by PPA. For now, only e-mail verification is required, PLUS the administrator approval of the membership.

Credentials

The e-mail you will provide will serve as the user name when authenticating during a post request together with the password over https. The Password can be changed at any given point in time for tighter security measure.

Once the registration is successful, an email message will be sent to the email provided during registration. The confirmation of said registration will expire in 7 (seven) days right after the email has been sent by PPA API Server. Once confirmed, PPA Management will be notified. You cannot login even if the account is confirmed in the email. PPA still needs to approve your registration. Once this is approved, you will receive a confirmation email for account activation. Only then you can login, and use the credential for posting request with PPA API Server.

The credential information, especifically the email/username and password will be used with the endpoint at https://api.ppa.com.ph/api/signin/AuthorizeLogInAsync before a request can be made to https://api.ppa.com.ph/api/opce/PostExemptionRequestAsync.

However, as of this writing, authorization is not yet effected to the current endpoint for posting. Testing will commence first without the authorization before this feature is applied. This module will be available and can be tested starting 24th of November, 2015. The feature for Registration and Authorization is now in effect (Dec 06, 2015).

Posting and Logging-In Credential
This feature is now ready (Dec 06, 2015).

Once you have registered, confirmed the e-mail confirmation, and have receive the PPA Admin approval, the next step is to authorize/login to the endpoint https://api.ppa.com.ph/api/signin/AuthorizeLogInAsync.

NOTE: Depending on how your organization wanted to authorize, there are a lot of ways on how to do this. This is a matter of security and of course flexibility. You can automate the login/authorization, but keep in mind that this is insecure if you do not create a flexible way of sending the password during automated authorization even if the request is travelling via HTTPS.
Option 1: Automated Authorization

The User Name (email) during registration and password is the key for the authorization. Depending on how you will automate the submission of the authorization request, is beyond the scope of this document. It is your responsibility to safe keep the password, either storing it in a configuration file encrypted, and decrypting it during a request is being made to the authorize endpoint address. Also, bear in mind that the password can be changed at anytime using this website using the Forgot Password link. So it is advisable to put the password (encrypted by your encryption utility) in the configuration file which can also be changed at any time.

Below is a straight forward approach for automating the authorization request. It uses the following simple class to store the result status

public class LoginResponseDto {
public string StatusCode { get; set; }
public string Description { get; set; }
}
//Automated Authorization inside a code
//Somewhere in your PostRequestHeaderData() method...
public async Task<OpceApiResponseHeaderDto> PostRequestHeaderData() {
....
....
Do the authorization once. not for every post exemption request. please :)
var authorizeRequest = await LogonToOpceApiAsync();
....
....
if (authorizeRequest.StatusCode == "200") {
//access is granted. you can post the request now.
} else {
//authorizeRequest.StatusCode will return either of the following statuses:
//"401" - Unauthorized/Access Denied
//"4001" - Account is Locked
//"4002" - Requires Verification
//"4003" - Failure
//"500" - Internal Server Error
//"503" - Service Unavailable
}
}

public async Task<LoginResponseDto> LogonToOpceApiAsync() {

var responseData = new LoginResponseDto();
const string PPA_BASE_API_DOMAIN = @"https://api.ppa.com.ph";
const string PPA_API_END_POINT = @"/api/signin/AuthorizeLogInAsync";

//declare anonymous type of {...}, this is optional. You can use your own object as long as it has the property members, "Email" and "Password".
var logonCredentials = new {
Email = //mock code: Utility.WebConfigEntry.OpceEmailUserName,
Password = //mock code: Utility.DecryptViaAes256(Utitlity.WebConfigEntry.OpcePassword)
};

using (var client = new System.Net.Http.HttpClient()) {
client.BaseAddress = new Uri(PPA_BASE_API_DOMAIN);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

using (var response = await client.PostAsJsonAsync(PPA_API_END_POINT, logonCredentials)) {
if (response.IsSuccessStatusCode) {
responseData = await response.Content.ReadAsAsync<LoginResponseDto>();
} else {
responseData.Description = "Something went wrong.";
responseData.StatusCode = "0";
//your code stuffs to handle the status
}
}
}
return responseData;
}
 
Option 2: Authorization via a Web Form Login

Depending on how you will use the API service of OPCE, the automation of authorizing an account is very straight forward. However, as said, it is your responsibility as the developer to secure the login credentials for automating the authorization procedure.

By using a login UI (let's say a web form or win form) for authorization is more safer and secure than automating it. Because of course, the credentials are manually inputted rather than storing it somewhere in your configuration file. The challenge here is/are, if you are automating request to PPA Server and you are also receiving automated requests from a third party subscriber of your service as well. In that manner, the dilemma is beyond this document can cover. We only provide how the API can be accessed in different manners. The work around for solving the problem as stated earlier is for you as the developer to solve.

Implementing the web form login either Web Form or MVC Razor form is simple. Just use the code above and supply the Email and Password with the textbox entries inside your login form. In addition, you can also do this via a JQuery AJAX post request.


Posting Request and Receiving Response

Updated: 20-Aug-2019 | Added field/member CONFIRMED_TRANSACTION
Preparation
Once you have performed authentication with the web api system as discussed in the previous section, you can now begin the request. Please see the prerequisites below.

Define class definitions for 'posting a request', and a class that will 'receive the response'. The class names doesn't matter as long as the member name definitions are exactly the same, such as casing (upper/lower cases). The content of each member is not case sensitive.
 
Request Class Definition
This object will be used as the Request class to the PPA endpoint method. NOTE: Below code is C#. You can also use other languages of your choice as long as the definitions and types are the same.
//NOTE: All the string members below are 1,000 characters in length
public class OpceExemptionRequestHeaderDto {
public string REQ_ENTITY_ID { get; set; } //1 - Requesting Entity ID
public string REQ_ENTITY_LOGIN { get; set; } //2 - Requesting Client Entity Authorization Login
public string HASH_CODE { get; set; } //3 - Request Exemption Info 64-char hash code for accuracy of data sent
public string REQ_EX_COM_CODE { get; set; } //4 - Data Validation Request for commodity code
public string REQ_EX_COM_DSC { get; set; } //5 - Data Validation Request for commodity description
public string REQ_EX_PU_NAME { get; set; } //6 - Data Validation Request for Port client User name Info
public string REQ_EX_PU_ADDR { get; set; } //7 - Data Validation Request for Port client User Address Info
public string REQ_EX_PU_TIN { get; set; } //8 - Data Validation Request for Port client User TIN Info

//Begin Added: Saturday, December 19, 2015
//Begin Removed: Thu, Jan 19, 2017 -- all PEZA locations are exempted regardless of zone
public string REQ_PU_EXEMP_CODE { get; set; } //19 - Data Validation Request for PEZA Code
public string REQ_PU_EXEMP_ZONE { get; set; } //20 - Data Validation Request for Port client zone info
//End Added: Saturday, December 19, 2015

public string REQ_EX_VOYAGE_NO { get; set; } //9 - Voyage Number
public string REQ_EX_REFERENCE_NO { get; set; } //10 - Request Exemption Reference No
public string REQ_EX_REFERENCE_DATE { get; set; } //11 - Request Exemption Reference Date
public string REQ_EX_BLNO { get; set; } //12 - Bill of Lading Number
public string REQ_EX_WEIGHT { get; set; } //13 - Weight
public string REQ_EX_VOLUME { get; set; } //14 - Volume
public string REQ_EX_CARGO_TYPE { get; set; } //15 - Cargo Type
public string REQ_EX_UOM { get; set; } //16 - Unit of Measurement
public string REQ_EX_QTY { get; set; } //17 - Quantity
public string REQ_EX_PPA_AMT { get; set; } //18 - Computed Amount (only PPA Share)
public int CONFIRMED_TRANSACTION { get; set; } //19 - Determines if the request is confirmed (1) | (0) Inquiry only
}
Response Class Definition
Below class object will be used as the Response class from the PPA endpoint method. NOTE: Below code is C#. You can also use other languages of your choice as long as the definitions and types are the same.
//NOTE: All the string members below are 1,000 characters in length
public class OpceApiResponseHeaderDto {
public string APPD_REFERENCE_NO { get; set; } //1 - PPA Response Reference Number
public string REQ_EX_REFERENCE_NO { get; set; } //2 - Post Request Reference Number
public string REQ_REMARK_CODE { get; set; } //3 - PPA Response Remark Code
public string REQ_PPA_REMARKS { get; set; } //4 - PPA Response Remark Description
public string REQ_STATUS_ID { get; set; } //5 - Request Exemption info Status
//6 - ATTRIBUTE1; Server Received the request at this time stamp, hh:mm:ss.fff (milliseconds)
public string ATTRIBUTE1 { get; set; }
//7 - ATTRIBUTE2; Server Process Time – the time it took for the PPA server to validate the request, record/insert, cross validations, etc. in format of [hour:minutes:seconds:fff (milliseconds)]
public string ATTRIBUTE2 { get; set; }
//8 - ATTRIBUTE3; Server Departure – the time when the response left the PPA Server to send to subscriber
public string ATTRIBUTE3 { get; set; }
public string ATTRIBUTE4 { get; set; } //9 - Reserved
public string RESPONSE_HASH { get; set; } //10 - Optional Data validation for subscriber
}
Methods of Posting Request

There are quite a few ways on how to send a request to an endpoint being served by an ASP.NET MVC API. This will depend on the platform, i.e., PHP or ASP.NET or Java, or JQuery to send (POST) request to PPA Web API service, but they are all approximately or identically the same. PPA Central API Services is compatible with all the REST formats in the market, web and mobiles.
 
Option 1 : Via Asp.Net WebRequest (.NET 4 and below)
This method is most preferred if you are using ASP.Net platform and you don’t want to use a JQuery AJAX request to post/send a request. However, since this will be coming from within the program instead of a Jquery script AJAX request, you must serialize the request object to JSON before sending it to PPA Web API Server.
 
Below is a basic example of how to request using ASP.Net’s System.Net.WebRequest. Code shows all the fully qualified namespaces so developers will easily identify which classes or methods a particular call came from what namespace. The version of ASP.Net C# used below is 4.0. Another example follows written under .NET 4.5.x for asynchronous request.
 
//Using ASP.NET C# 4.0 and lower
public OpceApiResponseHeaderDto PostRequestHeaderData() {
//below is the data request header. The method GetRequestHeaderData will return a class object of type OpceExemptionRequestHeaderDto the actual data can be acquired from your own implementation of service or any kind of data acquisition already built in your code.
var postData = _service.GetRequestHeaderData(1); //let’s say record Id in DB is 1.
postData.HASH_CODE = string.Empty;
//hash the postData request for verifiability of data to be sent. For the HashUtility helper method, please see Hashing Request for Posting. It SHOULD be strictly the code to be used for hashing so it is compatible with PPA’s code during re-hash. The object must be serialized to string then bytes for hashing
var serializedPostData =
JsonSerializerUtility<OpceExemptionRequestHeaderDto>.SerializeToJson(postData);
var hashCode = HashUtility.ComputeHash(serializedPostData);
//after hashing, assign the hashcode to the member "HASH_CODE". PPA Web API will not include this value during the re-hash of the data to check for accuracy.
postData.HASH_CODE = hashCode;
//prepare the variable for storing the response coming from the PPA API service.
var responseData = new OpceApiResponseHeaderDto();
//Serialize your request data to json to send as API parameter to ppa API endpoint. The sample JsonSerializerUtility sample code can be seen here: Serializing Request to JSON, but you can create or write a code of your own as long as it serializes to JSON string object.
var dataString = JsonSerializerUtility<OpceExemptionRequestHeaderDto>.SerializeToJson(postData);
//prepare the resources needed for the response
var responseFromServer = string.Empty;
var ppaApiEndPoint = "https://api.ppa.com.ph/api/opce/PostExemptionRequestAsync";
//create the request. Please strictly use utf-8 as shown below
var request = System.Net.WebRequest.Create(ppaApiEndPoint);
request.ContentType = "application/json; charset=utf-8";
request.Method = "POST";
byte[] byteData = Encoding.UTF8.GetBytes(dataString);
request.ContentLength = byteData.Length;
using (Stream dataStream = request.GetRequestStream()) {
dataStream.Write(byteData, 0, byteData.Length);
}
//acquire the request data from the endpoint, then deserialize it to the original object definition of OpceApiResponseHeaderDto
using (var response = request.GetResponse()) {
using (Stream dataStream = response.GetResponseStream()) {
StreamReader reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
responseData = JsonSerializerUtility<OpceApiResponseHeaderDto>
.DeserializeJson(responseFromServer);
}
}
//responseData now contains the dictionary values returned by the PPA endpoint. //further operation is on the subscriber side (ICTSI)
return responseData; //use the responseData and its members/attributes for checking the response.
}
Option 2: Using HttpClient under ASP.Net C# 4.5.x Async Request
Posting Data using .Net/C# 4.5.x and above via HttpClient and Asynchronous Request
 
public async Task<OpceApiResponseHeaderDto> PostRequestHeaderDataViaHttpClientAsync() {

var postData = await _service.GetRequestHeaderDataAsync(recordId: 1);
var serializedPostData = JsonSerializerUtility<OpceExemptionRequestHeaderDto>
.SerializeToJson(postData);

//IMPORTANT: Hash the post request data before assigning it to post request data itself
var hashCode = Domain.Utilities.HashUtility.ComputeHash(serializedPostData);
postData.HASH_CODE = hashCode;

var responseData = new OpceApiResponseHeaderDto();
const string ppaBaseApiDomain = @"https://api.ppa.com.ph";
const string ppaApiEndPoint = @"/api/opce/PostExemptionRequestAsync";

//create the request
using (var client = new System.Net.Http.HttpClient()) {
client.BaseAddress = new Uri(ppaBaseApiDomain);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue(@"application/json"));

using (var response = await client.PostAsJsonAsync(ppaApiEndPoint, postData)) {
if (response.IsSuccessStatusCode) {
responseData = await response.Content.ReadAsAsync<OpceApiResponseHeaderDto>();
} else {
//do your stuffs here...
}
}
}
//use the return data after acquiring it from PPA API endpoint and AFTER disposing client and reponse objects with using statement as above.
return responseData;
} //end async method
Option 3: Via Jquery AJAX POST Request
If you are using JQuery to post/get requests from an API or Webservice endpoint, below is a straight forward sample code to demonstrate how to request to PPA’s API.
 
$(document).ready(function () {
var btnRequest = $("#btnRequest"); //sample button id. Replace with your own
if (btnRequest.length) {
btnRequest.off().on("click", function (e) {
e.preventDefault(); // comment this if your form requires a postback
var ppaApiEndPoint = "https://api.ppa.com.ph/api/opce/PostExemptionRequestAsync";
//it's up to the subscriber to fill-out all the request JSON data below.
var requestHdr = { //name of variable does not matter. Use your own if you prefer.
// you may create another service or API in your project to fill-in the hashcode or during the request in your asp.net/PHP/Java code. NOTE: hash the requestHdr first before assigning a hashcode here. OR, inside your MVC/page request, generate the hashcode there using the utility in Appendix 1, then assign the hash after completely hashing the request data.
"HASH_CODE": "691a671e9caa98ac894fbb379cd8cc9747cbcab8617008514bf2bfbc434e6bce"
, "REQ_ENTITY_ID" : "opceUser@ictsi.com.ph" //ictsi user id in PPA Api membership registration
, "REQ_ENTITY_LOGIN" : "ictsi-client-01@something.com" //ictsi's client user id
, "REQ_EX_COM_CODE": "COM-CODE-01"
, "REQ_EX_COM_DSC": "Textiles"
, "REQ_EX_PU_NAME": "PU-TEXTILES"
, "REQ_EX_PU_ADDR": "Manila City"
, "REQ_EX_PU_TIN": "912-304-177"
, "REQ_EX_VOYAGE_NO": "VOYAGE-001"
, "REQ_EX_REFERENCE_NO": "REF-01"
, "REQ_EX_REFERENCE_DATE": "30/10/2015 9:46:09 AM"
, "REQ_EX_BLNO": "BLN-01" , "REQ_EX_WEIGHT": "100"
, "REQ_EX_VOLUME": "123.56"
, "REQ_EX_CARGO_TYPE": "CARGO-01"
, "REQ_EX_UOM": "UOM-01"
, "REQ_EX_QTY": "12"
, "REQ_EX_PPA_AMT": "45000"
};

var jRequest = $.ajax({
method: "POST",
url: ppaApiEndPoint,
data: requestHdr,
type: "application/json; charset=utf-8",
dataType: 'json', cache: false,
success: function (responseData) {
//process and validate result based on your needs.
var result = responseData;
if (result.REQ_REMARK_CODE === 200) { //OK, request successful and authorized
//determine commodity request
if (result.REQ_STATUS_ID === 1) {
// 1 = Commodity Exempted
// 0 = Commodity NOT Exempted
// n = awaiting for PPA for other status
} else {
//... Further processing
}
} else {
//there is/are some errors in the request data //Codes will be provided by PPA for the errors, awaiting as of this writing. //e.g. 401 – Unauthorized, 402, 403, etc.
}
}, error: function (req, status, errorObj) {
alert("req: " + req + " status: " + status + " errorObj: " + errorObj);
}
});
//optional, if request has failed
jRequest.fail(function (jqXhr, textStatus) {
alert("Request failed: " + textStatus);
});
}); //end button click
} //end test button length
});
Sample Response Data (JSON) after a successful post
"OpceApiResponseHeaderDto": {
"APPD_REFERENCE_NO" : "PPA-REF-00000001"
,"REQ_EX_REFERENCE_NO" : "ICTSI-REF-000001"
,"REQ_REMARK_CODE" : "200"
,"REQ_PPA_REMARKS" : "ALL ENTRIES VALID"
,"REQ_STATUS_ID" : "1"
,"ATTRIBUTE1" : "SVR-RCVD-12:50:57.240" //Server Received the request at this time stamp
,"ATTRIBUTE2" : "SVR-PTM-0:00:00.290" //PPA Server Process Time
,"ATTRIBUTE3" : "SVR-DPRTR-12:50:57.240" //Server Departure Time for returning the request
,"ATTRIBUTE4" : "na"
}

Posting a Batch Request for Exemption (* New)

Updated: 20-Aug-2019 | Added field/member CONFIRMED_TRANSACTION
This method is requested to accomodate batch exemption request and validating each commodity contained in the request.
How does a batch request works?
In a certain scenario, a party/client has different commodities being exported/imported. If a batch request for example contains three commodities of different types, the system will:

  • Accept the request from the new endpoint at: https://api.ppa.com.ph/api/opce/PostBatchExemptionRequestAsync
  • In the three commodities contained in the batch request, if one fails to be exempted, only the two commodities will be accepted as exempted and recorded in PPA records.
  • The failed commodity for exemption will as well be recorded in the PPA records under Invalid Requests.
  • The web API endpoint will return a list of statuses for each commodity contained in the batch request.
New C# classes for requesting a batch request.

The three classes below should be defined in your codebase to be able to use the endpoint. NOTE: The casing of each property in the class, their order and names should be followed. This is a requirement when generating a serial number or hash to the request.

The content or value however of each property is not case sentive during posting.


public class OpceBatchExemptionRequestHeaderDto {
public string BATCH_REQUEST_ID { get; set; } //1 * new as of 2019
public string REQ_ENTITY_ID { get; set; } //2
public string REQ_ENTITY_LOGIN { get; set; } //3
public string HASH_CODE { get; set; } //4
public string REQ_EX_PU_NAME { get; set; } //5
public string REQ_EX_PU_ADDR { get; set; } //6
public string REQ_EX_PU_TIN { get; set; } //7
public List<OpceCommodityDto> BatchCommodityList { get; set; } //8
}
public class OpceCommodityDto {
public string REQ_EX_COM_CODE { get; set; } //1
public string REQ_EX_COM_DSC { get; set; } //2
public string REQ_EX_VOYAGE_NO { get; set; } //3
public string REQ_EX_REFERENCE_NO { get; set; } //4
public string REQ_EX_REFERENCE_DATE { get; set; } //5
public string REQ_EX_BLNO { get; set; } //6
public string REQ_EX_WEIGHT { get; set; } //7
public string REQ_EX_VOLUME { get; set; } //8
public string REQ_EX_CARGO_TYPE { get; set; } //9
public string REQ_EX_UOM { get; set; } //10
public string REQ_EX_QTY { get; set; } //11
public string REQ_EX_PPA_AMT { get; set; } //12
public int CONFIRMED_TRANSACTION { get; set; } //13 *new as of 20-Aug-2019
}
public class OpceApiBatchResponse {
public int REQ_STATUS_ID { get; set; }
public int ERROR_COUNT { get; set; }
public string REQ_REMARK_CODE { get; set; }
public string REQ_PPA_REMARKS { get; set; }
public string REQUEST_IP { get; set; }
public string RESPONSE_HASH { get; set; }
public string ATTRIBUTE1 { get; set; }
public string ATTRIBUTE2 { get; set; }
public string ATTRIBUTE3 { get; set; }
public string ATTRIBUTE4 { get; set; }
// The generic list below of type OpceApiResponseHeaderDto
// is a original class existing in the previous codebase used in posting single request.
public List<OpceApiResponseHeaderDto> CommodityListResponse { get; set; }
}
Posting Batch Request to the web API
The method of posting a batch request is similar to making a single commodity request for exemption. However, this time you submit the request to the endpoint at https://api.ppa.com.ph/api/opce/PostBatchExemptionRequestAsync instead of https://api.ppa.com.ph/api/opce/PostExemptionRequestAsync
Sample batch request graphical representation of OpceBatchExemptionRequestHeaderDto for posting:

Batch Request
Depending on your codebase design, a sample code snippet below simply shows on how to post the batch request. Of course, the values of the class objects must be processed and derived from your codebase. The code below is written in C# under .NET 4.5.x, it's compatible up to .NET 4.7

var batchHeader = new OpceBatchExemptionRequestHeaderDto() {
HASH_CODE = string.Empty,
BATCH_REQUEST_ID = 'B-08202019030322'
REQ_ENTITY_ID = "opceuser001@ictsi.com.ph",
REQ_ENTITY_LOGIN = "housetech@something.com",
REQ_EX_PU_ADDR = @"BLK 25 PH IV EXP. AREA, CEPZ ROSARIO CAVITE CAVITE ROSARIO CAVITE",
REQ_EX_PU_NAME = @"HOUSE TECHNOLOGY INDUSTRIES PTE LTD",
REQ_EX_PU_TIN = @"004-692-492-0000",
BatchCommodityList = new List<OpceCommodityDto> {
new OpceCommodityDto() { REQ_EX_COM_CODE = "23970",
REQ_EX_COM_DSC = "Cutting, shaping and finishing of stone",
REQ_EX_VOYAGE_NO = "VYG-0001",
REQ_EX_REFERENCE_NO = "ICTSI-0001-B451",
REQ_EX_REFERENCE_DATE = "07/27/2017 08:51:00 AM",
REQ_EX_BLNO = "BLNO-01-203-APX",
REQ_EX_WEIGHT = "1.5",
REQ_EX_VOLUME = "60.20",
REQ_EX_CARGO_TYPE = "CRR-TYPE-00023",
REQ_EX_UOM = "TON",
REQ_EX_QTY = "1",
REQ_EX_PPA_AMT = "500.50",
CONFIRMED_TRANSACTION = 0 },

//just a sample, let's invalidate the second item by adding "AND STUFFS" to description
new OpceCommodityDto() { REQ_EX_COM_CODE = "23969",
REQ_EX_COM_DSC = "Manufacture of articles of concrete, cement and plaster AND STUFFS",
REQ_EX_VOYAGE_NO = "VYG-0001",
REQ_EX_REFERENCE_NO = "ICTSI-0001-B452",
REQ_EX_REFERENCE_DATE = "07/27/2017 08:51:00 AM",
REQ_EX_BLNO = "BLNO-01-203-APX",
REQ_EX_WEIGHT = "1.50",
REQ_EX_VOLUME = "123.20",
REQ_EX_CARGO_TYPE = "CRR-TYPE-00023",
REQ_EX_UOM = "TON",
REQ_EX_QTY = "2",
REQ_EX_PPA_AMT = "100.50",
CONFIRMED_TRANSACTION = 0 }
}
};

// put a serial number (hash) to the request;
var serializedPostData = JsonSerializerUtility<OpceBatchExemptionRequestHeaderDto>.SerializeToJson(batchHeader);
var hashCode = HashUtility.ComputeHash(serializedPostData);
batchHeader.HASH_CODE = hashCode;

using (var client = new HttpClient()) {
client.BaseAddress = new Uri("https://api.ppa.com.ph");
// use line below if your app is Android, Windows app or iOS. for web application, there is no need for this.
// client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "[token value from authorization]");
try {
using (var response = await client.PostAsJsonAsync("/api/opce/PostBatchExemptionRequestAsync", batchHeader)) {
if (response.IsSuccessStatusCode) {
var responseData = await response.Content.ReadAsAsync<OpceApiBatchResponse>();
//responseData now contains the list of status for each commodity processed by PPA
....
value of responseData
} else {
....
....
}
} catch Exception(ex) { ... }
}

Hashing Request for Posting

Hash Utility Method
Below is a simple hashing method for generating request hash. Please strictly use this method for hashing as PPA will use this for re-hash.
 
using System.Web.Extensions;
using System.Security.Cryptography;

namespace Domain.Utilities {
public class HashUtility {
public static string ComputeHash(string inputText) {
var bytes = Encoding.UTF8.GetBytes(inputText);
var sha256Managed = new SHA256Managed();
var sBuilder = new StringBuilder();
var hashByte = sha256Managed.ComputeHash(bytes);

//[byte by 8-bit hexadecimal val] by [64-byte characters] = 512-bit length hash code
foreach (var b in hashByte) {
//convert byte data to hexa decimal small letter format instead of the usual raw base64 string
sBuilder.Append(b.ToString(@"x2"));
}
return sBuilder.ToString();
//sample output: 691a671e9caa98ac894fbb379cd8cc9747cbcab8617008514bf2bfbc434e6bce }
}
}

Serializing Object Class for JSON

Simple Json Serializer
You can use other serializer utility that serializes/deserializes C# objects. But we recommend to use the simple methods below for full compatibility.
NOTE: You don't need this utility if you are posting/getting requests via JQUERY. This utility is needed during the hash of the request, as the hash value is derived from a string converted to byte array, i.e., an object is serialized to JSON string then converted to byte array.
 
using System.Web.Extensions;

namespace Domain.Utilities {

public class JsonSerializerUtility<T> where T : class {
public static string SerializeToJson(T dataToSerialize) {
var javaScriptSerializer = new
System.Web.Script.Serialization.JavaScriptSerializer();
var result = javaScriptSerializer.Serialize(dataToSerialize);
return result;
}

public static T DeserializeJson(string jsonString) {
var javaScriptSerializer = new
System.Web.Script.Serialization.JavaScriptSerializer();
var result = javaScriptSerializer.Deserialize<T>(jsonString);
return result;
}
}
}