Part1 - Get ready for Form Service by Adobe API in BTP <- This blog |
Part2 - Wrapping Form Service API into your own consumable API |
Part3 - Create No-Code PDF generation app in SAP Build Apps(AppGyver App) |
Go to BTP subaccount -> Service Marketplace and choose Create from Forms Service by Adobe tile. Choose "default" as the service instance plan. Follow the same step with Forms Service by Adobe API, but choose "standard" as the service instance plan.
From left side pane, go to Destination under Connectivity and create a new destination from a blank template. Use OAuth2ClinetCrendentials and enter the client credentials from the service key created from the previous step.
Name | ADS_SRV |
Type | HTTP |
Description | Adobe API destination |
URL | uri from service key https://adsrestapi-formsprocessing.cfapps.<your region>.hana.ondemand.com |
Proxy type | Internet |
Authentication | OAuth2ClientCredentials |
Client ID | Client ID from service key |
Client Secret | Client Secret from service key |
Token Service URL | URL from service key + /oauth/token |
Form service configuration page | https://<your subdomain>-ads.formsprocessing.cfapps.<your region>.hana.ondemand.com/ui/customer/index.html | ||||||||||||
Form service template store | https://<your subdomain>-ads.formsprocessing.cfapps.<your region>.hana.ondemand.com/adsrestapi/ui.html |
Let's bind the fields. Click on the field Company, for example, and on the right side pane you can find Data Binding field. Choose "Use Data Connection" and choose "Company". After this, you will able to see red and green arrow on the right side of the field on the Data View tab. This means the field on the PDF is bound to the field in data connection.
Save the template as Adobe XML Form (*xdp).
Now go to the Template Store(https://<your subdomain>-ads.formsprocessing.cfapps.<your region>.hana.ondemand.com/adsrestapi/ui.html). Create a Form called "Invoice". In the form, click the + button to upload a template. You will be prompted to choose .xdp file so upload the one created in Adobe LiveCycle Designer.
CLASS zcl_fp_client DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
DATA:
mo_http_destination TYPE REF TO if_http_destination,
mv_client TYPE REF TO if_web_http_client.
TYPES :
BEGIN OF ty_template_body,
xdp_Template TYPE xstring,
template_Name TYPE c LENGTH 30,
description TYPE c LENGTH 280,
note TYPE c LENGTH 280,
locale TYPE c LENGTH 6,
language TYPE c LENGTH 280,
master_Language TYPE c LENGTH 280,
business_Area TYPE c LENGTH 280,
business_Department TYPE c LENGTH 280,
END OF ty_template_body,
BEGIN OF ty_form_body,
form_Name TYPE c LENGTH 30,
description TYPE c LENGTH 280,
note TYPE c LENGTH 30,
END OF ty_form_body,
tt_forms TYPE STANDARD TABLE OF ty_form_body WITH KEY form_Name,
tt_templates TYPE STANDARD TABLE OF ty_template_body WITH KEY template_Name.
METHODS:
constructor
IMPORTING
iv_name TYPE string
iv_service_instance_name TYPE string OPTIONAL,
get_template_by_name
IMPORTING
iv_get_binary TYPE abap_boolean DEFAULT abap_false
iv_form_name TYPE string
iv_template_name TYPE string
RETURNING VALUE(rs_template) TYPE ty_template_body,
reder_pdf
IMPORTING
iv_xml TYPE string
RETURNING VALUE(rv_response) TYPE string.
PROTECTED SECTION.
PRIVATE SECTION.
METHODS:
__get_request
RETURNING VALUE(ro_request) TYPE REF TO if_web_http_request,
__json2abap
IMPORTING
ir_input_data TYPE data
CHANGING
cr_abap_data TYPE data,
__execute
IMPORTING
i_method TYPE if_web_http_client=>method
RETURNING VALUE(ro_response) TYPE REF TO if_web_http_response.
ENDCLASS.
CLASS zcl_fp_client IMPLEMENTATION.
METHOD constructor.
TRY.
mo_http_destination = cl_http_destination_provider=>create_by_cloud_destination(
i_service_instance_name = CONV #( iv_service_instance_name )
i_name = iv_name
i_authn_mode = if_a4c_cp_service=>service_specific
).
mv_client = cl_web_http_client_manager=>create_by_http_destination( mo_http_destination ).
CATCH
cx_web_http_client_error
cx_http_dest_provider_error.
ENDTRY.
ENDMETHOD.
METHOD __execute.
TRY.
ro_response = mv_client->execute( i_method = i_method ).
DATA(response_body) = ro_response->get_text( ).
DATA(response_headers) = ro_response->get_header_fields( ).
CATCH cx_web_message_error.
CATCH cx_web_http_client_error INTO DATA(lo_http_error).
ENDTRY.
ENDMETHOD.
METHOD __json2abap.
DATA(lo_input_struct) = CAST cl_abap_structdescr( cl_abap_structdescr=>describe_by_data( p_data = ir_input_data ) ).
DATA(lo_target_struct) = CAST cl_abap_structdescr( cl_abap_structdescr=>describe_by_data( p_data = cr_abap_data ) ).
LOOP AT lo_input_struct->components ASSIGNING FIELD-SYMBOL(<ls_component>).
IF line_exists( lo_target_struct->components[ name = <ls_component>-name ] ).
ASSIGN COMPONENT <ls_component>-name OF STRUCTURE ir_input_data TO FIELD-SYMBOL(<field_in_data>).
ASSIGN COMPONENT <ls_component>-name OF STRUCTURE cr_abap_data TO FIELD-SYMBOL(<field_out_data>).
IF lo_target_struct->components[ name = <ls_component>-name ]-type_kind = cl_abap_typedescr=>typekind_xstring.
<field_out_data> = cl_web_http_utility=>decode_x_base64( <field_in_data>->* ).
ELSE.
<field_out_data> = <field_in_data>->*.
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD get_template_by_name.
DATA(lo_request) = __get_request( ).
lo_request->set_uri_path( |/v1/forms/{ iv_form_name }/templates/{ iv_template_name }| ).
IF iv_get_binary = abap_true.
lo_request->set_query( |select=xdpTemplate,templateData| ).
ELSE.
lo_request->set_query( |select=templateData| ).
ENDIF.
DATA(lo_response) = __execute(
i_method = if_web_http_client=>get
).
DATA(lv_json_response) = lo_response->get_text( ).
DATA lr_data TYPE REF TO data.
lr_data = /ui2/cl_json=>generate(
json = lv_json_response
pretty_name = /ui2/cl_json=>pretty_mode-camel_case
).
IF lr_data IS BOUND.
ASSIGN lr_data->* TO FIELD-SYMBOL(<data>).
__json2abap(
EXPORTING
ir_input_data = <data>
CHANGING
cr_abap_data = rs_template
).
ENDIF.
ENDMETHOD.
METHOD __get_request.
ro_request = mv_client->get_http_request( ).
ro_request->set_header_fields( VALUE #(
( name = 'Accept' value = 'application/json, text/plain, */*' )
( name = 'Content-Type' value = 'application/json;charset=utf-8' )
) ).
ENDMETHOD.
METHOD reder_pdf.
TYPES :
BEGIN OF struct,
xdp_Template TYPE string,
xml_Data TYPE string,
form_Type TYPE string,
form_Locale TYPE string,
tagged_Pdf TYPE string,
embed_Font TYPE string,
END OF struct.
CONSTANTS: cns_storage_name TYPE string VALUE 'templateSource=storageName',
cns_template_name TYPE string VALUE 'Invoice/InvoiceTemplate'.
DATA lr_data TYPE REF TO data.
DATA(lo_request) = __get_request( ).
lo_request->set_query( query = cns_storage_name ).
lo_request->set_uri_path( i_uri_path = '/v1/adsRender/pdf' ).
DATA(ls_body) = VALUE struct( xdp_Template = cns_template_name
xml_Data = iv_xml
form_Type = 'print'
form_Locale = 'en_US'
tagged_Pdf = '0'
embed_font = '0' ).
DATA(lv_json) = /ui2/cl_json=>serialize( data = ls_body compress = abap_true
pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
lo_request->append_text(
EXPORTING
data = lv_json
).
TRY.
DATA(lo_response) = __execute(
i_method = if_web_http_client=>post
).
DATA(lv_json_response) = lo_response->get_text( ).
FIELD-SYMBOLS:
<data> TYPE data,
<field> TYPE any,
<pdf_based64_encoded> TYPE any.
"lv_json_response has the following structure `{"fileName":"PDFOut.pdf","fileContent":"JVB..."}
lr_data = /ui2/cl_json=>generate( json = lv_json_response ).
IF lr_data IS BOUND.
ASSIGN lr_data->* TO <data>.
ASSIGN COMPONENT `fileContent` OF STRUCTURE <data> TO <field>.
IF sy-subrc EQ 0.
ASSIGN <field>->* TO <pdf_based64_encoded>.
* rv_response = <pdf_based64_encoded>.
rv_response = lv_json_response.
ENDIF.
ENDIF.
ENDTRY.
ENDMETHOD.
ENDCLASS.
CLASS ztest_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
DATA:
mo_http_destination TYPE REF TO if_http_destination,
mv_client TYPE REF TO if_web_http_client.
INTERFACES: if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ztest_class IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
TRY.
"Initialize Template Store Client
DATA(lo_client) = NEW zcl_fp_client(
iv_name = 'ADS_SRV'
).
"Get form template data
DATA(ls_template) = lo_client->get_template_by_name(
iv_get_binary = abap_true
iv_form_name = 'Invoice'
iv_template_name = 'InvoiceTemplate'
).
out->write( ls_template-template_name ).
ENDTRY.
ENDMETHOD.
ENDCLASS.
CLASS ztest_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
DATA:
mo_http_destination TYPE REF TO if_http_destination,
mv_client TYPE REF TO if_web_http_client.
INTERFACES: if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ztest_class IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
TRY.
"Initialize Template Store Client
DATA(lo_client) = NEW zcl_fp_client(
iv_name = 'ADS_SRV'
).
"create xml string
DATA(lv_xml_raw) = |<form1>| &&
|<InvoiceNumber>Ego ille</InvoiceNumber>| &&
|<InvoiceDate>20040606T101010</InvoiceDate>| &&
|<OrderNumber>Si manu vacuas</OrderNumber>| &&
|<Terms>Apros tres et quidem</Terms>| &&
|<Company>| && 'My company ABCDE' && |</Company>| &&
|<Address>| && '1234 Ice cream street' && |</Address>| &&
|<StateProvince>| && 'Alaska' && |</StateProvince>| &&
|<ZipCode>Am undique</ZipCode>| &&
|<Phone>| && '1234567' && |</Phone>| &&
|<Fax>Vale</Fax>| &&
|<ContactName>Ego ille</ContactName>| &&
|<Item>| && 'ICE111' && |</Item>| &&
|<Description>| && 'Vanilla ice cream' && |</Description>| &&
|<Quantity>| && '1' && |</Quantity>| &&
|<UnitPrice>| && '10' && |</UnitPrice>| &&
|<Amount>| && '10' && |</Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Item></Item>| && |<Description></Description>| && |<Quantity></Quantity>| && |<UnitPrice></UnitPrice>| && |<Amount></Amount>| &&
|<Subtotal></Subtotal>| &&
|<StateTaxRate></StateTaxRate>| &&
|<StateTax></StateTax>| &&
|<FederalTaxRate></FederalTaxRate>| &&
|<FederalTaxRate></FederalTaxRate>| &&
|<FederalTax></FederalTax>| &&
|<ShippingCharge></ShippingCharge>| &&
|<GrandTotal></GrandTotal>| &&
|<Comments></Comments>| &&
|<AmountPaid></AmountPaid>| &&
|<DateReceived></DateReceived>| &&
|</form1>|.
DATA(lv_xml) = cl_web_http_utility=>encode_base64( lv_xml_raw ).
"Render PDF by caling REST API
data(lv_rendered_pdf) = lo_client->reder_pdf( iv_xml = lv_xml ).
ENDTRY.
ENDMETHOD.
ENDCLASS.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
5 | |
5 | |
4 | |
4 | |
4 | |
4 | |
4 | |
4 | |
3 | |
3 |