Custom connection to Xero using Oracle PL/SQL - xero-api

I am having a problem with Xero API when the API establishes the connection, in the first attempt to establish the connection, it returns an error of Unexpected character "<" while in the very 2nd attempt to establish a connection gets successful.
The Code I am using is in the form of a Function as below:
function base64encode(t in varchar2) return varchar2
is
begin
return translate(utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(t))), 'd'||CHR(10)||CHR(13), 'd');
end base64encode;
function get_access_token return varchar2
is
g_client varchar2(200);
v_secret varchar2(200);
l_result clob;
token_not_found exception;
l_token clob;
begin
g_client := mis_system_parameters.get_string_value('XERC');
v_secret := mis_system_parameters.get_string_value('XERS');
g_xero_revenue_account_code := mis_system_parameters.get_string_value('XENC');
while l_result is null or l_result like '%<%' loop
apex_web_service.g_request_headers.delete();
apex_web_service.g_request_headers(1).name := 'authorization';
apex_web_service.g_request_headers(1).value := 'Basic '|| base64encode(g_client||':'||v_secret);
apex_web_service.g_request_headers(2).name := 'Content-Type';
apex_web_service.g_request_headers(2).value := 'application/x-www-form-urlencoded';
l_result := apex_web_service.make_rest_request(
p_url => 'http://localhost/identity-xero-api-proxy/connect/token'
,p_http_method => 'POST'
,p_body => 'grant_type=client_credentials&scope=accounting.transactions accounting.contacts assets files accounting.settings'
);
end loop;
apex_json.parse(l_result);
l_token := apex_json.get_varchar2('access_token');
if apex_json.get_varchar2('access_token') is null then
raise token_not_found;
end if;
return l_token;
exception
when token_not_found then
mis_errors.ins_err
('mis_xero_customer_api.get_access_token','Token Not Found');
when others then
mis_errors.ins_err
('mis_xero_customer_api.get_access_token',l_result||' - '||SQLERRM);
raise;
end get_access_token;
Any kind of advise and help will be highly appreciated.
Thanks

Related

catch the value of response headers and use it in another api call in pl sql

I would like to ask how can I loop the value of a return in 'url_next' variable into url varible so that I can use the function until the all users imported from the api call .
so the value returned from 'url_next'
into
url := 'https://dev-9466225.okta.com/api/v1/users';
l_http_request := utl_http.begin_request(apex_string.format( url , 'GET', 'HTTP/1.1'));
create or replace function OKTA_API_X
(url IN VARCHAR2)
return varchar2
IS
v_username VARCHAR2(50);
v_email VARCHAR2(50);
v_firstname VARCHAR2(50);
v_last_name VARCHAR2(50);
l_http_request utl_http.req;
l_http_response utl_http.resp;
l_text VARCHAR2(32767);
resp CLOB := '';
l_json_obj json_object_t;
l_json_in json_array_t;
name VARCHAR2(2560);
value VARCHAR2(2024);
url_next VARCHAR2(100);
url VARCHAR2(50);
BEGIN
url := 'https://dev-9466225.okta.com/api/v1/users';
l_http_request := utl_http.begin_request(apex_string.format( url , 'GET', 'HTTP/1.1'));
utl_http.set_wallet('file:c:/okta_wallet_base/', NULL);
utl_http.set_header(l_http_request, 'content-type', 'application/json');
utl_http.set_header(l_http_request, 'authorization', 'SSWS 00mz6_ost-rfegVu5K5I6dEs33JLIFSmcBO8VxzI');
utl_http.set_header(l_http_request, 'Accept', 'application/json');
l_http_response := utl_http.get_response(l_http_request);
-- dbms_output.put_line('HTTP response status code =>' || l_http_response.status_code);
-- dbms_output.put_line('HTTP response reason phrase => ' || l_http_response.reason_phrase);
BEGIN
LOOP
utl_http.read_text(l_http_response, l_text,32766)
resp := resp || l_text;
END LOOP;
END;
--- JASON PARSING
l_json_in := json_array_t(resp);
FOR indx IN 0..l_json_in.get_size - 1 LOOP
l_json_obj := TREAT(l_json_in.get(indx) AS json_object_t);
--GET JSON OBJECT AND STRINGS FROM RESPONSE
v_firstname := l_json_obj.get_object('profile').get_string('firstName');
v_last_name := l_json_obj.get_object('profile').get_string('lastName');
v_email := l_json_obj.get_object('profile').get_string('email');
v_username := l_json_obj.get_object('profile').get_string('login');
-------------------------------
dbms_output.put_line(v_firstname);
--dbms_output.put_line(v_EMAIL);
END LOOP;
---------------------------------------------------------------------------- FOR i IN 1..
utl_http.get_header_count(l_http_response) LOOP
utl_http.get_header(l_http_response, i, name, value);
IF
name = 'link'
AND value LIKE '%rel="next"'
THEN
url_next := ( trim(TRAILING '>' FROM regexp_substr(value, 'http[^>]+>')) );
END IF;
END LOOP;
BEGIN
WHILE url_next IS NOT NULL LOOP
IF url_next <> url THEN
url := url_next;
ELSE
NULL;
END IF;
END LOOP;
END;
EXCEPTION
WHEN OTHERS THEN
BEGIN
utl_http.end_response(l_http_response);
dbms_output.put_line('ERROR →' || sqlerrm);
END;
END;

Bypass the JSON object using PL / SQL, and output all data in key value format in Oracle

I have JSON, I want to bypass it and display all the data that is in it. But the problem is that I can't know what data will be there. I made the code, but it only looks for top-level objects. And the rest are not. I will be grateful for your help.
DECLARE
l_object json_object_t;
l_key_list json_key_list;
v_clob CLOB;
tv apex_json.t_values;
BEGIN
-- JSON_OBJECT can figure out what keys it has...
v_clob := '{"devices":{"id":"d652f632-0835-871b-a140-58701f019000","scale_id":"88348A32BD3D149FE055000000000001"},"data":{"external_id":"40023"},"data_weight":{"weight":"20322","prevWeight":"1000","prevTransaction":"1607680754361","transaction":"1607680754361","on":"false","transactionDataCount":"1","stable":"false","duration":"12","transactionMaxWeight":"2000","perimetr":"true","driverInCar":"false"}}';
apex_json.parse(tv,v_clob);
l_object := json_object_t.parse (v_clob);
l_key_list := l_object.get_keys;
FOR counter IN 1 .. l_key_list.COUNT
LOOP
DBMS_OUTPUT.put_line (
l_key_list (counter)
|| ' : '
|| apex_json.get_varchar2(p_path => l_key_list (counter), p_values => tv));
END LOOP;
END;
If you take into account only the top level objects, then this code works
DECLARE
l_object json_object_t;
l_key_list json_key_list;
v_clob CLOB;
tv apex_json.t_values;
BEGIN
-- JSON_OBJECT can figure out what keys it has...
v_clob := '{"devices":"3423","data":"okwwwe"}';
apex_json.parse(tv,v_clob);
l_object := json_object_t.parse (v_clob);
l_key_list := l_object.get_keys;
FOR counter IN 1 .. l_key_list.COUNT
LOOP
DBMS_OUTPUT.put_line (
l_key_list (counter)
|| ' : '
|| apex_json.get_varchar2(p_path => l_key_list (counter), p_values => tv));
END LOOP;
END;
RESULT :
devices : 3423
data : okwwwe
And how to deduce the data from the first example, I can not understand. These data must correspond to the hierarchy.
If you have access to the native JSON types (JSON_ELEMENT_T, JSON_ARRAY_T, etc.) you should always use them over using the APEX_JSON package ans they will have much better performance. A package similar to the one below can be used to output the full hierarchy of a JSON object or array. Feel free to tweak the package to change the format of the output.
Package Specification
CREATE OR REPLACE PACKAGE output_json
AS
c_padding_char CONSTANT VARCHAR2 (1) := '-';
c_padding_amount CONSTANT PLS_INTEGER := 1;
PROCEDURE output_scalar (p_element json_element_t,
p_padding PLS_INTEGER,
p_json_key VARCHAR2 DEFAULT NULL);
PROCEDURE output_object (p_object json_object_t, p_padding PLS_INTEGER);
PROCEDURE output_array (p_array json_array_t, p_padding PLS_INTEGER);
PROCEDURE output_element (p_element json_element_t,
p_padding PLS_INTEGER,
p_json_key VARCHAR2 DEFAULT NULL);
END;
/
Package Body
CREATE OR REPLACE PACKAGE BODY output_json
AS
PROCEDURE output_scalar (p_element json_element_t,
p_padding PLS_INTEGER,
p_json_key VARCHAR2 DEFAULT NULL)
IS
BEGIN
DBMS_OUTPUT.put_line (
LPAD (c_padding_char, p_padding, c_padding_char)
|| CASE WHEN p_json_key IS NOT NULL THEN p_json_key || ' : ' END
|| CASE
WHEN p_element.is_boolean
THEN
CASE WHEN p_element.to_boolean THEN 'TRUE' ELSE 'FALSE' END || ' (boolean)'
WHEN p_element.is_date
THEN
TO_CHAR (p_element.TO_DATE, 'YYYY-MM-DD') || ' (date)'
WHEN p_element.is_number
THEN
p_element.TO_NUMBER || ' (number)'
WHEN p_element.is_string
THEN
p_element.TO_STRING || ' (string)'
END);
END;
PROCEDURE output_object (p_object json_object_t, p_padding PLS_INTEGER)
IS
l_keys json_key_list;
l_element json_element_t;
BEGIN
l_keys := p_object.get_keys;
FOR i IN 1 .. l_keys.COUNT
LOOP
l_element := p_object.get (l_keys (i));
output_element (l_element, p_padding, l_keys (i));
END LOOP;
END;
PROCEDURE output_array (p_array json_array_t, p_padding PLS_INTEGER)
IS
BEGIN
FOR i IN 0 .. p_array.get_size - 1
LOOP
output_element (p_array.get (i), p_padding);
END LOOP;
END;
PROCEDURE output_element (p_element json_element_t,
p_padding PLS_INTEGER,
p_json_key VARCHAR2 DEFAULT NULL)
IS
BEGIN
DBMS_OUTPUT.put_line (
CASE
WHEN p_json_key IS NOT NULL AND NOT p_element.is_scalar THEN p_json_key || ' : '
END);
IF p_element.is_scalar
THEN
output_scalar (p_element, p_padding, p_json_key);
ELSIF p_element.is_object
THEN
output_object (TREAT (p_element AS json_object_t), p_padding + c_padding_amount);
ELSIF p_element.is_array
THEN
output_array (TREAT (p_element AS json_array_t), p_padding + c_padding_amount);
END IF;
END;
END;
/
Example Call
DECLARE
l_clob CLOB;
BEGIN
l_clob :=
'{"arr":[1,2,3],"devices":{"id":"d652f632-0835-871b-a140-58701f019000","scale_id":"88348A32BD3D149FE055000000000001"},"data":{"external_id":"40023"},"data_weight":{"weight":"20322","prevWeight":"1000","prevTransaction":"1607680754361","transaction":"1607680754361","on":"false","transactionDataCount":"1","stable":"false","duration":"12","transactionMaxWeight":"2000","perimetr":"true","driverInCar":"false"}}';
output_json.output_element (json_element_t.parse (l_clob), 0);
END;
/
Example Output
arr :
--1 (number)
--2 (number)
--3 (number)
devices :
--id : "d652f632-0835-871b-a140-58701f019000" (string)
--scale_id : "88348A32BD3D149FE055000000000001" (string)
data :
--external_id : "40023" (string)
data_weight :
--weight : "20322" (string)
--prevWeight : "1000" (string)
--prevTransaction : "1607680754361" (string)
--transaction : "1607680754361" (string)
--on : "false" (string)
--transactionDataCount : "1" (string)
--stable : "false" (string)
--duration : "12" (string)
--transactionMaxWeight : "2000" (string)
--perimetr : "true" (string)
--driverInCar : "false" (string)
I also made my own version, but it is limited to 2 levels of objects, and does not take into account arrays.
DECLARE
l_object json_object_t;
l_key_obj json_key_list;
v_clob CLOB;
tv apex_json.t_values;
obj_in_obj JSON_OBJECT_T;
l_key_list json_key_list;
BEGIN
v_clob := '{
"devices":{
"id":"d652f632-0835-871b-a140-58701f019000",
"scale_id":"88348A32BD3D149FE055000000000001"
},
"data":{
"external_id":"40023"
},
"data_weight":{
"weight":"20322",
"prevWeight":"1000",
"prevTransaction":"1607680754361",
"transaction":"1607680754361",
"on":"false",
"transactionDataCount":"1",
"stable":"false",
"duration":"12",
"transactionMaxWeight":"2000",
"perimetr":"true",
"driverInCar":"false"
}
}';
apex_json.parse(tv,v_clob);
l_object := json_object_t.parse (v_clob);
l_key_list := l_object.get_keys;
FOR counter IN 1 .. l_key_list.COUNT
LOOP
obj_in_obj := l_object.get_object(l_key_list (counter));
l_key_obj := obj_in_obj.get_keys;
FOR counter_all_obj IN 1 .. l_key_obj.COUNT
LOOP
DBMS_OUTPUT.put_line (
l_key_list (counter)||'.'||l_key_obj (counter_all_obj)
|| ' : '
|| apex_json.get_varchar2(p_path => l_key_list (counter)||'.'|| l_key_obj (counter_all_obj), p_values => tv));
END LOOP;
END LOOP;
END;

passing sys_refcursor from function to sys_refcursor out parameter in procedure

I have problem with outputting results from the sys_refcursor returned from the function stored in the variable crs_scenarios. I then want to pass this collection of data to the output parameter pout_result. I get the error PLS-00487: Invalid reference to variable 'POUT_RESULT'. Can you advise me please, how to solve this issue?
Thanks a lot!
declare
pin_scenarioName scenarios.scen_name%TYPE := 'zz_berlin_testen';
pin_scenarioRegion inf_ausbaugebiete.ausg_name%TYPE DEFAULT NULL;
pin_scenarioCutOffDate scenarios.scen_cut_off_date%TYPE DEFAULT NULL;
pin_scenarioStatus scenario_status.scst_name%TYPE DEFAULT NULL;
pout_result SYS_REFCURSOR;
pout_strerrorcode VARCHAR2(1000);
pout_strerrormessage VARCHAR2(1000);
BEGIN
pout_result := funk30.pbi$capi_export_pck.cfn_getscenarios(pin_scenarioName => pin_scenarioName,
pin_scenarioRegion => pin_scenarioRegion,
pin_scenarioCutOffDate => pin_scenarioCutOffDate,
pin_scenarioStatus => pin_scenarioStatus,
pout_strerrorcode => pout_strerrorcode,
pout_strerrormessage => pout_strerrormessage);
dbms_output.put_line(pout_result.ID || ' ' ||pout_result.NAME || ' ' ||pout_result.CUT_OFF || ' ' ||pout_result.STATUS ||
' ' || pout_result.PRIORITY || ' ' ||pout_result.PARENT_SCENARIO|| ' ' ||pout_result.REGION|| ' ' || pout_result.REMARK);
END cpr_getscenarios;
Function:
FUNCTION mfn_getscenarios(pin_scenarioName IN scenarios.scen_name%TYPE DEFAULT NULL,
pin_scenarioRegion IN inf_ausbaugebiete.ausg_name%TYPE DEFAULT NULL,
pin_scenarioCutOffDate IN scenarios.scen_cut_off_date%TYPE DEFAULT NULL,
pin_scenarioStatus IN scenario_status.scst_name%TYPE DEFAULT NULL,
pout_strerrorcode OUT VARCHAR2,
pout_strerrormessage OUT VARCHAR2)
RETURN SYS_REFCURSOR IS
crs_scenarios SYS_REFCURSOR;
n_cnt_exists NUMBER;
ex_scennotexists EXCEPTION;
strprocedurename VARCHAR2(128) := package_name || '.mfn_getScenarios';
BEGIN
BEGIN
SELECT 1 INTO n_cnt_exists FROM scenarios WHERE rownum = 1;
EXCEPTION
WHEN no_data_found THEN
RAISE ex_scennotexists;
END;
OPEN crs_scenarios FOR
SELECT scen.scen_id id,
scen.scen_name NAME,
scen.scen_cut_off_date cut_off,
scst.scst_name STATUS,
scen.scen_priority PRIORITY,
parent.scen_name PARENT_SCENARIO,
ausg.ausg_name REGION,
scen.scen_comment REMARK
FROM scenarios scen,
scenarios parent,
scenario_status scst,
inf_ausbaugebiete ausg
WHERE scen.scen_scst_id = scst.scst_id
AND scen.scen_parent_scen_id = parent.scen_id(+)
AND scen.scen_ausg_id= ausg.ausg_id(+)
AND lower(scen.scen_name) like nvl(lower('%'||pin_scenarioName||'%'), lower(scen.scen_name))
AND NVL(ausg.ausg_name, 'xxxxx') = nvl(pin_scenarioRegion, NVL(ausg.ausg_name, 'xxxxx'))
AND scen.scen_cut_off_date = nvl(pin_scenarioCutOffDate, scen.scen_cut_off_date)
AND scst.scst_name = nvl(pin_scenarioStatus, scst.scst_name);
pout_strerrorcode := '0';
pout_strerrormessage := '';
RETURN crs_scenarios;
EXCEPTION
WHEN ex_scennotexists THEN
pout_strerrorcode := 'API-00239';
pout_strerrormessage := rtrim(api_err_pck.apierrormsg('API-00239', strprocedurename), ' #');
RETURN NULL;
WHEN OTHERS THEN
pout_strerrorcode := '-1';
pout_strerrormessage := substr(SQLERRM, instr(SQLERRM, 'ORA') + 11, length(SQLERRM));
RETURN NULL;
END mfn_getscenarios;
Sys_refcursor is only a SQL definition. If you want to run it, you have to FETCH data.
So pout_result varible has no data itself.
-------- function -----
create or replace FUNCTION mfn
RETURN SYS_REFCURSOR IS
crs_scenarios SYS_REFCURSOR;
BEGIN
OPEN crs_scenarios FOR
SELECT dummy from dual;
RETURN crs_scenarios;
END ;
-- execution
set serveroutput on
declare
pout_result SYS_REFCURSOR;
type pout_result_tab is table of dual%rowtype; -- cursor datatype
pout_result_t pout_result_tab;
BEGIN
pout_result := mfn;
fetch pout_result bulk collect into pout_result_t; -- bulk collect because I assume you have recordset, not one record
dbms_output.put_line(pout_result_t(1).dummy);
END ;
/
--- Result
X
PL/SQL procedure successfully completed.

Extract a base64binary from a WebService in ORACLE and use it as a BLOB

I made this WebService in .NET which response is a byte[] which is a base64binary. I need to receive this in ORACLE (10.2.0).
I already have the response stored in a CLOB variable, I can read the value of the response this way:
SELECT EXTRACT(XMLTYPE(l_clob),
'//GetBlobResponse/GetBlobResult/text()',
'xmlns="http://tempuri.org/"')
FROM DUAL;
This throws me something like "JVBERi0xLjMNCiX5+prnDQo1IDAgb2JqDQo8PA0KL..." and so on, all this on a XMLTYPE CLOB COLUMN.
What I want to do is something like this:
DECLARE
VAR BLOB;
BEGIN
SELECT EXTRACT(XMLTYPE(l_clob),
'//GetBlobResponse/GetBlobResult/text()',
'xmlns="http://tempuri.org/"')
INTO VAR
FROM DUAL;
END;
I tried to do "VAR CLOB" with no luck.
I don't want to insert this on a TABLE, I want to use it with another Procedure that receives a BLOB.
And for the record is a PDF file.
Well i hitted the answer,after doin this:
DECLARE
l_xml XMLTYPE;
l_clob CLOB;
x_clob CLOB;
l_blob BLOB;
BEGIN
x_clob := '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetBlobResponse xmlns="http://tempuri.org/">
<GetBlobResult>[BASE64BINARY]</GetBlobResult>
</GetBlobResponse>
</soap:Body>
</soap:Envelope>';
SELECT EXTRACT(XMLTYPE(x_clob),
'//GetBlobResponse/GetBlobResult/text()',
'xmlns="http://tempuri.org/"')
INTO l_xml
FROM DUAL;
l_clob := l_xml.getClobVal();
l_blob := F_DECODE_BASE64(l_clob);
END;
With the function doin this:
FUNCTION F_DECODE_BASE64(p_clob_in in clob) return blob is
v_blob blob;
v_result blob;
v_offset integer;
v_buffer_size binary_integer := 48;
v_buffer_varchar varchar2(48);
v_buffer_raw raw(48);
BEGIN
IF p_clob_in is null then
return null;
END IF;
dbms_lob.createtemporary(v_blob, true);
v_offset := 1;
FOR i in 1 .. ceil(dbms_lob.getlength(p_clob_in) / v_buffer_size) LOOP
dbms_lob.read(p_clob_in, v_buffer_size, v_offset, v_buffer_varchar);
v_buffer_raw := utl_raw.cast_to_raw(v_buffer_varchar);
v_buffer_raw := utl_encode.base64_decode(v_buffer_raw);
dbms_lob.writeappend(v_blob, utl_raw.length(v_buffer_raw), v_buffer_raw);
v_offset := v_offset + v_buffer_size;
END LOOP;
v_result := v_blob;
dbms_lob.freetemporary(v_blob);
RETURN v_result;
END f_decode_base64;
This gave me the answer i was lookin for.

Sending CLOB data of length 32000 in utl_http.req throws ORA:06052 POST method

I am trying to send an XML as a URL parameter from PL/SQL.
But when I try to send it the error "ORA:06052" occurs. Below is the PL/SQL code
CREATE OR REPLACE FUNCTION EMASDB.ESIGN(TY IN VARCHAR2,DATA1 IN CLOB,DATA2 IN CLOB) RETURN clob
IS
XML CLOB;
v_data_post CLOB;
resp utl_http.resp;
req utl_http.req;
v_txt CLOB;
BEGIN
IF TY='REGISTER' THEN
XML:='<register><uniqueid>'||DATA2||'</uniqueid><DATA1>'||DATA1||'</DATA1><userEnable>true</userEnable><originalContent>'||DATA2||'</originalContent></register>';
ELSIF TY='AUTHENTICATE' THEN
XML :='<AuthenticateDet><uniqueId>'||DATA2||'</uniqueId><DATA1>'||DATA1||'</DATA1><originalContent>'||DATA2||'</originalContent><referenceNo></referenceNo></AuthenticateDet>';
ELSE
XML :='<verifyDet><dataType>pkcs7</dataType><DATA1>'||DATA1||'</DATA1><originalContent>'||DATA2||'</originalContent><responseFormat>plain</responseFormat></verifyDet>';
DBMS_OUTPUT.PUT_LINE('A');
END IF;
req := UTL_HTTP.begin_request ('url','POST','HTTP/1.1');
utl_http.set_header(req, 'Content-Type', 'application/x-www-form-urlencoded');
utl_http.set_header(req, 'Content-Length', length(XML));
v_data_post :='xml='||XML;
/*utl_http.write_text(req, v_data_post);
resp := UTL_HTTP.get_response(req);
utl_http.read_text(resp,v_txt);
utl_http.end_response(resp);
RETURN v_txt;*/
RETURN 'done';
END;
/
When you need write (and read) more than 32k in utl_http, it done a bit differently.
For example:
l_data := 'fill with some sample piece of text';
http_req := utl_http.begin_request(url => 'http://example.com', method => 'POST');
utl_http.set_header (http_req, 'Content-Length', length(l_data));
utl_http.set_header (http_req, 'Content-Type', 'text/xml;charset=UTF-8');
utl_http.set_header (http_req, 'Transfer-Encoding', 'chunked');
loop
l_chunkData := null;
l_chunkData := substr(l_data, l_chunkStart, l_chunkLength);
utl_http.write_text(http_req, l_chunkData);
if (length(l_chunkData) < l_chunkLength) then exit; end if;
l_chunkStart := l_chunkStart + l_chunkLength;
end loop;
See: http://www.kurzhals.info/2012/03/using-chunked-transfer-with-plsql-utl_http-write_text.html
And for a clob example see: http://blog.optiosys.com/?p=246
You should NEVER send Transfer-Encoding: chunked , alongside Content-Length , its either the one of the other. –
Jelman
Jan 21, 2020 at 13:54
helped me!
For all of you who are struggling with similar issues, this solution also resolved the following Oracle errors:
Error: ORA-29273: fallo de la solicitud HTTP
ORA-12547: TNS:contacto perdido
for those who still need it, you can try this way :
begin
declare
v_req utl_http.req;
v_res utl_http.resp;
vn_tam_clob PLS_INTEGER;
vn_tam_buffer PLS_INTEGER;
vn_pos_inicial PLS_INTEGER;
v_buffer varchar2(32000);
v_body clob := va_content_clob; -- Your JSON (XML)
begin
-- Set connection.
vn_tam_clob := DBMS_LOB.GETLENGTH(va_content_clob);
v_req := utl_http.begin_request('http://your.api/operation', 'POST');
utl_http.set_authentication(v_req, 'your_username','your_password');
utl_http.set_header(v_req, 'content-type', 'application/json');
utl_http.set_header(v_req, 'Content-Length', vn_tam_clob);
-- Set error to exception
utl_http.set_response_error_check(true);
-- Invoke REST API.
vn_pos_inicial := 1;
vn_tam_buffer := 32000;
while vn_pos_inicial <= vn_tam_clob -- least( vn_tam_clob, vn_tam_buffer ) )
loop
utl_http.write_text( v_req, dbms_lob.substr( v_body, vn_tam_buffer, vn_pos_inicial ) );
vn_pos_inicial := vn_pos_inicial + vn_tam_buffer ;
end loop;
-- Get response para retorno OK ou analise do problema.
v_res := utl_http.get_response(v_req);
-- if you don't set : utl_http.set_response_error_check(true);
-- you can get the return structure
-- IF (v_res.status_code = 202) THEN
-- dbms_output.put_line('v_response is okay');
-- ELSE
-- dbms_output.put_line('v_resPONSE CODE IS '||v_res.status_code);
--
-- begin
-- loop
-- utl_http.read_line(v_res, v_buffer);
--
-- -- display or log in table v_buffer;
--
--
-- end loop;
-- utl_http.end_response(v_res);
-- exception
-- when utl_http.end_of_body then
-- utl_http.end_response(v_res);
-- end;
--
-- END IF;
END;
EXCEPTION
WHEN OTHERS THEN
utl_http.end_response(v_res);
RAISE;
END;