From 2213e3df2f24a00322239d442c54bf31039f2588 Mon Sep 17 00:00:00 2001 From: Morten Braten Date: Thu, 24 Sep 2015 19:09:35 +0200 Subject: [PATCH] Added SMS utility package --- demos/sms_util_pkg_demo.sql | 40 +++++++ ora/sms_util_pkg.pkb | 209 ++++++++++++++++++++++++++++++++++++ ora/sms_util_pkg.pks | 54 ++++++++++ setup/install.sql | 2 + setup/synonyms.sql | 1 + 5 files changed, 306 insertions(+) create mode 100644 demos/sms_util_pkg_demo.sql create mode 100644 ora/sms_util_pkg.pkb create mode 100644 ora/sms_util_pkg.pks diff --git a/demos/sms_util_pkg_demo.sql b/demos/sms_util_pkg_demo.sql new file mode 100644 index 0000000..690e9eb --- /dev/null +++ b/demos/sms_util_pkg_demo.sql @@ -0,0 +1,40 @@ + +-- send sms (text message) via gateway +-- the configuration must be adapted to a specific gateway api +-- for example, see http://www.smsglobal.com/http-api/ + +-- sign up with a gateway provider to obtain a username and password + +/* + +-- the following tags can be used in the url template + +#username# +#password# +#message# +#to# +#from# +#attr1# +#attr2# +#attr3# + +*/ + +declare + l_config sms_util_pkg.t_gateway_config; +begin + -- configure gateway + -- remember you may have to open this hostname in the database Network ACL + l_config.send_sms_url := 'http://www.smsglobal.com/http-api.php?action=sendsms&user=#username#r&password=#password#&from=#from#&to=#to#& +text=#message#'; + l_config.username := 'testuser'; + l_config.password := 'secret'; + l_config.response_format := sms_util_pkg.g_format_custom; + l_config.response_error_parser := 'my_package.my_error_parser'; -- this is a function that accepts a clob and returns a varchar2 + sms_util_pkg.set_gateway_config (l_config); + -- if using HTTPS you need to set up an Oracle wallet with the certificate + -- sms_util_pkg.set_wallet (p_wallet_path => '/path/to/wallet/', p_wallet_password => 'somesecret'); + -- send the message + sms_util_pkg.sends_sms (p_message => 'Hello SMS World', p_to => 123456789, p_from => 'BobSacamano'); +end; +/ \ No newline at end of file diff --git a/ora/sms_util_pkg.pkb b/ora/sms_util_pkg.pkb new file mode 100644 index 0000000..5976e6f --- /dev/null +++ b/ora/sms_util_pkg.pkb @@ -0,0 +1,209 @@ +create or replace package body sms_util_pkg +as + + /* + + Purpose: Package handles sending of SMS (Short Message Service) to mobile phones via an SMS gateway + + Remarks: The package provides a generic interface and attempts to support "any" SMS gateway that provides an HTTP(S) (GET) interface + + Who Date Description + ------ ---------- -------------------------------- + MBR 24.08.2014 Created + + */ + + g_gateway_config t_gateway_config; + + g_wallet_path string_util_pkg.t_max_db_varchar2; + g_wallet_password string_util_pkg.t_max_db_varchar2; + + +function make_request (p_url in varchar2, + p_body in clob := null, + p_http_method in varchar2 := 'POST', + p_username in varchar2 := null, + p_password in varchar2 := null) return clob +as + l_returnvalue clob; +begin + + /* + + Purpose: make HTTP request + + Remarks: + + Who Date Description + ------ ---------- -------------------------------- + MBR 23.08.2014 Created + + */ + + debug_pkg.printf('%1 %2', p_http_method, p_url); + + l_returnvalue := apex_web_service.make_rest_request( + p_url => p_url, + p_http_method => p_http_method, + p_body => p_body, + p_username => p_username, + p_password => p_password, + p_wallet_path => g_wallet_path, + p_wallet_pwd => g_wallet_password + ); + + return l_returnvalue; + +end make_request; + + +procedure check_response_for_errors (p_response in clob) +as + l_xml xmltype; + l_error_message string_util_pkg.t_max_pl_varchar2; +begin + + /* + + Purpose: check response for errors + + Remarks: error handling is different for every SMS gateway (API provider) + + Who Date Description + ------ ---------- -------------------------------- + MBR 24.08.2014 Created + + */ + + debug_pkg.printf('response length = %1', length(p_response)); + debug_pkg.printf('first 32K characters of response = %1', substr(p_response,1,32000)); + + if g_gateway_config.response_format = g_format_xml then + + begin + l_xml := xmltype (p_response); + debug_pkg.printf('response converted to valid XML'); + if l_xml.existsnode (g_gateway_config.response_error_path) = 1 then + debug_pkg.printf('error path node found, attempting to retrieve it'); + l_error_message := l_xml.extract(g_gateway_config.response_error_path, g_gateway_config.response_error_namespace).getstringval(); + else + debug_pkg.printf('error path node not found, assuming no errors'); + end if; + exception + when others then + l_error_message := sqlerrm; + end; + + elsif g_gateway_config.response_format = g_format_custom then + + -- parse errors from response based on custom PL/SQL parsing function specified by the user + -- this function should take a single clob parameter (the response from the SMS gateway) and return a varchar2 if an error is found in the response + execute immediate 'begin sms_util_pkg.g_exec_result_string := ' || dbms_assert.sql_object_name(g_gateway_config.response_error_parser) || ' (:b1); end;' using p_response; + l_error_message := g_exec_result_string; + + else + -- TODO: implement JSON parsing using APEX_JSON (if Apex 5+ is installed) + raise_application_error (-20000, 'Response format ' || g_gateway_config.response_format || ' not supported or not implemented!'); + end if; + + if l_error_message is not null then + raise_application_error (-20000, 'The SMS gateway returned an error: ' || l_error_message, true); + end if; + +end check_response_for_errors; + + +procedure set_wallet (p_wallet_path in varchar2, + p_wallet_password in varchar2) +as +begin + + /* + + Purpose: set SSL wallet properties + + Remarks: + + Who Date Description + ------ ---------- -------------------------------- + MBR 23.08.2014 Created + + */ + + g_wallet_path := p_wallet_path; + g_wallet_password := p_wallet_password; + +end set_wallet; + + +procedure set_gateway_config (p_gateway_config in t_gateway_config) +as +begin + + /* + + Purpose: set gateway configuration + + Remarks: + + Who Date Description + ------ ---------- -------------------------------- + MBR 23.08.2014 Created + + */ + + g_gateway_config := p_gateway_config; + +end set_gateway_config; + + +procedure send_sms (p_message in varchar2, + p_to in varchar2, + p_from in varchar2, + p_attr1 in varchar2 := null, + p_attr2 in varchar2 := null, + p_attr3 in varchar2 := null, + p_username in varchar2 := null, + p_password in varchar2 := null) +as + l_url string_util_pkg.t_max_pl_varchar2; + l_response clob; + + function url_escape (p_text in varchar2) return varchar2 + as + begin + return utl_url.escape (p_text, escape_reserved_chars => false, url_charset => 'UTF8'); + end url_escape; + +begin + + /* + + Purpose: send SMS message + + Remarks: + + Who Date Description + ------ ---------- -------------------------------- + MBR 24.08.2014 Created + + */ + + -- TODO: assert that configuration exists + + l_url := string_util_pkg.multi_replace ( + g_gateway_config.send_sms_url, + t_str_array('#username#', '#password#', '#message#', '#to#', '#from#', '#attr1#', '#attr2#', '#attr3#'), + t_str_array(coalesce(p_username, g_gateway_config.username), coalesce(p_password, g_gateway_config.password), url_escape(p_message), url_escape(p_to), url_escape(p_from), p_attr1, p_attr2, p_attr3) + ); + + l_response := make_request (p_url => l_url, p_http_method => 'GET'); + + check_response_for_errors (l_response); + +end send_sms; + + +end sms_util_pkg; +/ + diff --git a/ora/sms_util_pkg.pks b/ora/sms_util_pkg.pks new file mode 100644 index 0000000..5a0f8a3 --- /dev/null +++ b/ora/sms_util_pkg.pks @@ -0,0 +1,54 @@ +create or replace package sms_util_pkg +as + + /* + + Purpose: Package handles sending of SMS (Short Message Service) to mobile phones via an SMS gateway + + Remarks: The package provides a generic interface and attempts to support any SMS gateway that provides an HTTP(S) (GET) interface + + Who Date Description + ------ ---------- -------------------------------- + MBR 24.08.2014 Created + + */ + + -- gateway configuration + type t_gateway_config is record ( + send_sms_url varchar2(4000), + username varchar2(255), + password varchar2(255), + response_format varchar2(30), + response_error_path varchar2(4000), -- either an xpath or jsonpath expression + response_error_namespace varchar2(4000), -- xml namespace + response_error_parser varchar2(4000) -- a custom PL/SQL error parsing function (must accept a clob parameter and return a varchar2 containing error message) + ); + + -- response formats + g_format_xml constant varchar2(255) := 'xml'; + g_format_json constant varchar2(255) := 'json'; + g_format_custom constant varchar2(255) := 'custom'; + + -- internal variable used for dynamic PL/SQL evaluation + g_exec_result_string varchar2(4000); + + -- set SSL wallet properties + procedure set_wallet (p_wallet_path in varchar2, + p_wallet_password in varchar2); + + -- set gateway configuration + procedure set_gateway_config (p_gateway_config in t_gateway_config); + + -- send SMS message + procedure send_sms (p_message in varchar2, + p_to in varchar2, + p_from in varchar2, + p_attr1 in varchar2 := null, + p_attr2 in varchar2 := null, + p_attr3 in varchar2 := null, + p_username in varchar2 := null, + p_password in varchar2 := null); + +end sms_util_pkg; +/ + diff --git a/setup/install.sql b/setup/install.sql index 5d79921..93470c4 100755 --- a/setup/install.sql +++ b/setup/install.sql @@ -39,6 +39,7 @@ prompt Creating package specifications @../ora/raw_util_pkg.pks @../ora/regexp_util_pkg.pks @../ora/rss_util_pkg.pks +@../ora/sms_util_pkg.pks @../ora/soap_server_pkg.pks @../ora/sql_builder_pkg.pks @../ora/sql_util_pkg.pks @@ -89,6 +90,7 @@ prompt Creating package bodies @../ora/raw_util_pkg.pkb @../ora/regexp_util_pkg.pkb @../ora/rss_util_pkg.pkb +@../ora/sms_util_pkg.pkb @../ora/soap_server_pkg.pkb @../ora/sql_builder_pkg.pkb @../ora/sql_util_pkg.pkb diff --git a/setup/synonyms.sql b/setup/synonyms.sql index 39e07c0..159a59f 100755 --- a/setup/synonyms.sql +++ b/setup/synonyms.sql @@ -35,6 +35,7 @@ create synonym ax_random for random_util_pkg; create synonym ax_raw for raw_util_pkg; create synonym ax_regexp for regexp_util_pkg; create synonym ax_rss for rss_util_pkg; +create synonym ax_sms for sms_util_pkg; create synonym ax_sql_builder for sql_builder_pkg; create synonym ax_sql for sql_util_pkg; create synonym ax_string for string_util_pkg;