Posts Tagged ‘web service’

API เบื้องต้น และแนวคิดของ API

API นั้นเราอาจจะได้ยินกันบ่อยๆ ช่วงนี้ เอ่ หรือเราได้ยินไปเองหว่า 555 และช่วงหลังๆ เองก็มีการจัดงาน camp เกี่ยวกับ API อีกด้วย

API นั้น ย่อมาจาก application programming interface ซึ่งหมายถึง ตัวเชื่อมกับ application นั้นเอง

ในความจริงแล้ว API นั้นถ้าจะคิดง่ายๆ แล้วก็เหมือนกับ function หนึ่งๆ นะให้คิดว่าเป็นแบบนี้ (ถึงจะสื่อความหมายผิดเพี้ยนไป) เพราะ Interface นั้นก็คือ สิ่งที่เราใส่ input ลงไปแล้วได้ผลลัพธ์ ออกมานั่นเอง

ถ้าให้คิดว่าเป็นเหมือน function แล้วแม้แต่เด็กที่เริ่มเขียนโปรแกรมใหม่ๆ เองก็ยังพอเข้าใจ เพราะความจริงแล้วมันก็ไม่ได้ยากอย่างที่คิดหรอก

API นั้นมีหลายแบบและแตกต่างกันมาก ทั้งในเรื่องของภาษาในการเขียนโปรแกรมออกมาและการเรียกใช้งาน และอย่างอื่นอีกมากมาย แต่ที่ใหญ่ๆ ก็ 2 ตัวที่บอกไปเนี่ยแหละ

API เองถูกประยุกต์ใช้มาตั้งแต่นานนมมาแล้ว ติดปัญหาที่ภาษาในการเรียกใช้ซะมาก การที่จะเรียกใช้ API ที่เขียนขึ้นมาได้จึงต้องเขียนภาษาเดียวกันจึงจะเรียกใช้กันได้ ข้ามสายพันธ์ไม่ได้่เลยทีเดียว

ช่วงหลังๆ ได้มี XML ซึ่งเป็นภาษาในการแลกเปลี่ยนข้อมูลทำให้ข้อจำกัดพวกนี้หายไป เขียนอะไรก็ได้ gen ออกมาให้เป็น XML ให้ได้ก็พอ ส่วนอีกฝ่ายก็จะเขียนโปรแกรมสำหรับอ่าน XML แล้วนำ data เอาไปใช้ แค่นั้นเอง

การเรียกใช้ API นั้นอย่าคิดว่าเป็นการเรียกกันข้ามเครื่อง หรือ เรียกๆกันผ่านเว็บอย่างเดียวนะ เพราะ ก่อนที่จะมีเว็บ ก็มีการใช้ API กันแล้ว โดย API ที่ออกมาเป็นชุดๆ สำหรับใช้งานได้เลย ก็คือ library นั้นเอง แต่ จะเป็นขั้นก่อนนิดนึง ตรงที่ library เองจะทำงานด้วยตัวเองไม่ได้แค่นั้น
ตัวอย่างของ API ที่เรา(อาจ)เห็นกันบ่อยๆ ก็เช่น เราติดต่อไปหา mysql นั่นแหละ ให้คิดดูดีๆ ว่า กว่ามันจะไปเรียก ข้อมูลมาจาก mysql ต้องทำอะไรบ้าง

ถ้า้เป็น PHP เองก็ต้องเขียน

mysql_connect(xxx,xxx,xxx,xxx);

ซึ่งตรงนี้หมายถึงอะไร ก็หมายถึง เราเรียก function นั่นเอง แต่ว่าเป็น function มาตราฐานแค่นั้นเอง เลยเหมือนกับมีมาให้แต่ต้นไม่ต้องไปเอา library มาจากที่อื่นแค่นั้นเอง แล้ว API มันอยู่ตรงใหน นั่นซิ ก็ใน function นี้ยังไงล่ะครับ

คิดว่าอยู่ๆ เรียก mysql_connect แล้วมันติดต่อได้เลยเหรอ ไม่ใช่แบบนั้นหรอกนะ มีทั้ง code ที่ต้อง connect กัน แล้วให้รู้กันได้ รูปแบบข้อมูลในการส่ง ว่าจะต้องส่งอะไรไปก่อนหลัง การ authenication กัน ว่ามีสิทธ์ที่จะผ่านเข้ามาได้หรือไม่ได้ โอ้ย เพียบไปหมด แต่นั้นเราไม่จำเป็นต้องรู้ นั่นแหละคือ API

เรารออยู่อย่างเดียวคือ return value ก็พอแล้ว

ตัวอย่างข้างบนก็เป็นตัวอย่างที่ให้พอได้เข้าใจเฉยๆ นะ API นั้นจะว่าให้ลึกๆ สลับซับซ้อนแล้วก็ หลากหลายรูปแบบมาก ยกตัวอย่าง API ใหม่ๆ เช่น Web Service เป็นต้น Web Service เองจะว่าไปก็ API ดีๆ นี่เอง แต่การเรียกใช้ การติดต่อนั้นต่างกันฟ้ากับก้นเหวเลย

ปตท web service

วันๆ ว่างๆ ไม่รู้จะทำอะไร เหลือบมองเห็นช่องราคาน้ำมันจากหน้าเว็บเลย เข้าไปดู กลายเป็น Iframe ซึ่งไม่ค่อยชอบเท่าใหร่ เลยไปดูว่าเอาข้อมูลมาจาใหน ที่แท้เป็น frame ที่ได้จากเว็บของ ปตทเลยนี่เอง เลื่อนลงมาล่างๆ หน่อยมี web service ให้ยริการด้วย เลยแก้ว่างด้วยการเขียน web service เรียกราคาน้ำมันซะเลย

ในการเขียนครั้งนี้ก็ไม่ได้ เวอร์ หลูหลา สะแมนแตน อะไรมากมาย แค่PHP+ lib ของ nusoup ตัวเดียวเท่านั้น ถ้าไม่มี lib ตัวนี้อยู่ก็เข้า google แล้วหาคำว่า nosoap รับลองเจอ

php เองจะว่าว่าเป็นของเด็กๆ ก็ทำอะไรที่ Enterprise กับเข้าได้เหมือนกันนะ ที่เห็นว่าเป็นเด็กๆ หรือ Basic เพราะอะไรหลายๆ อย่างไม่บอกดีกว่า มาเขียนกันดีกว่า

เริ่มแรกก็ เข้าไปที่ http://www.pttplc.com/th/nc_oi.aspx ซะก่อน บอกแล้วว่าล่างๆ จะบอกว่า web service ด้วย และก็มีมาให้ครบเลยทั้ง WSDL และเอกสารด้วย อ่านกันได้ตามสบาย

ทีนี้เรารมาดูวิธีการเขียนด้วย nusoap กันดีกว่า

require_once('./lib/nusoap.php');
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
$client = new nusoap_client('http://www.pttplc.com/pttinfo.asmx?wsdl',</code>

<code> 'wsdl', $proxyhost, $proxyport, $proxyusername, $proxypassword);
$err = $client-&gt;getError();
if ($err) {
echo '
</code>
<h2>Constructor error</h2>
<pre>' . $err . '</pre>
';
}

$operation = 'CurrentOilPrice';
$client-&gt;decodeUTF8(false);
$result = $client-&gt;call(
$operation,
array('Language' =&gt; 'TH')
);

// Check for a fault
if ($client-&gt;fault) {
echo '
<h2>Fault</h2>
<pre>';

print_r($result);

echo '</pre>
';
exit();
}

// Check for errors
$err = $client-&gt;getError();
if ($err) {
// Display the error
echo '
<h2>Error</h2>
<pre>' . $err . '</pre>
';
exit();
}

$result = $result['CurrentOilPriceResult'];
$content = new xx_xml($result, 'contents');
$PRICE_DATE = $content-&gt;data['PTT_DS|Table|PRICE_DATE']['data'];
$PRODUCT = $content-&gt;data['PTT_DS|Table|PRODUCT']['data'];
$PRICE = $content-&gt;data['PTT_DS|Table|PRICE']['data'];

?&gt;

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<style> table{  width:350px;  border:1px solid #999999; }

table th{  background-color:#3f3f3f;  color:#FFFFFF; }

.hl{  background-color:#EFEFEF; }

</style>
<table>
<tr>
<th>Type</th>
<th>Price</th>
<th>Update date</th>
</tr>
<tr>
<td></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</table>
class xx_xml {

// XML parser variables
var $parser;
var $name;
var $attr;
var $data  = array();
var $stack = array();
var $keys;
var $path;

// either you pass url atau contents.
// Use 'url' or 'contents' for the parameter
var $type;

// function with the default parameter value
function xx_xml($url='http://www.opocot.com', $type='url') {
$this-&gt;type = $type;
$this-&gt;url  = $url;
$this-&gt;parse();
}

// parse XML data
function parse()
{
$data = '';
$this-&gt;parser = xml_parser_create();
xml_set_object($this-&gt;parser, $this);
xml_set_element_handler($this-&gt;parser, 'startXML', 'endXML');
xml_set_character_data_handler($this-&gt;parser, 'charXML');

xml_parser_set_option($this-&gt;parser, XML_OPTION_CASE_FOLDING, false);

if ($this-&gt;type == 'url') {
// if use type = 'url' now we open the XML with fopen

if (!($fp = @fopen($this-&gt;url, 'rb'))) {
$this-&gt;error("Cannot open {$this-&gt;url}");
}

while (($data = fread($fp, 8192))) {
if (!xml_parse($this-&gt;parser, $data, feof($fp))) {
$this-&gt;error(sprintf('XML error at line %d column %d',
xml_get_current_line_number($this-&gt;parser),
xml_get_current_column_number($this-&gt;parser)));
}
}
} else if ($this-&gt;type == 'contents') {
// Now we can pass the contents, maybe if you want
// to use CURL, SOCK or other method.
$lines = explode("\n",$this-&gt;url);
foreach ($lines as $val) {
if (trim($val) == '')
continue;
$data = $val . "\n";
if (!xml_parse($this-&gt;parser, $data)) {
$this-&gt;error(sprintf('XML error at line %d column %d',
xml_get_current_line_number($this-&gt;parser),
xml_get_current_column_number($this-&gt;parser)));
}
}
}
}

function startXML($parser, $name, $attr)    {
$this-&gt;stack[$name] = array();
$keys = '';
$total = count($this-&gt;stack)-1;
$i=0;
foreach ($this-&gt;stack as $key =&gt; $val)    {
if (count($this-&gt;stack) &gt; 1) {
if ($total == $i)
$keys .= $key;
else
$keys .= $key . '|'; // The saparator
}
else
$keys .= $key;
$i++;
}
if (array_key_exists($keys, $this-&gt;data))    {
$this-&gt;data[$keys][] = $attr;
}    else
$this-&gt;data[$keys] = $attr;
$this-&gt;keys = $keys;
}

function endXML($parser, $name)    {
end($this-&gt;stack);
if (key($this-&gt;stack) == $name)
array_pop($this-&gt;stack);
}

function charXML($parser, $data)    {
if (trim($data) != '')
$this-&gt;data[$this-&gt;keys]['data'][] = trim(str_replace("\n", '', $data));
}

function error($msg)    {
echo "
<p align="\">             <font color="#00ed00"><strong>Error: $msg</strong></font></p>
";
exit();
}
}

?>

อันนี้ที่เห็นเป็น Code คร่าวๆ นะ จะได้หน้าตาแบบ หน้านี้ ครับ ไปที่นี่เลย http://www.meteenee.com/pttservice/index.php

จะว่าไปแล้วก็ขอบคุณ ปตท. นะ เพราะว่า บ้านเรานี้ไม่ค่อยมี service ให้ใช้เลย เฮ้อ รอต่อไป รอหน่วยงานที่เห็นถึงความสำคัญ