Enterprise Resource Planning Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
Beykan
Participant
976

Executive Summary 

Organizations face an increasing risk of fraud in vendor payments and financial master data. This blog introduces a lightweight SAP Master Data Governance (MDG) enhancement that integrates CDQ's Bank Account API to validate bank trustworthiness and detect fraud — in real-time — directly within the Change Request process. 

 

Introduction

Data quality in financial master data plays a crucial role in maintaining integrity and trust across the enterprise. Especially with increasing cases of fraud targeting bank account information, it has become vital to validate this data against trusted external sources. This blog post demonstrates how to integrate CDQ's Bank Account Data API into SAP MDG to detect and warn about known fraud cases in real time during the Change Request process. 

 

Background

Corporate Data Quality (CDQ) is a cloud-based platform that enables organizations to access verified, trusted data by connecting to official and commercial registers worldwide. While it is widely used for sourcing company information such as legal names, tax numbers, and registration data, CDQ also offers APIs for verifying bank accounts, which play a growing role in fraud prevention and financial data governance.

In my previous blog post, I demonstrated how to create a custom DPI integration solution in SAP for Business Partner creation using a Custom List UIBB and REST API calls to CDQ. This blog builds on that architectural pattern, extending it to the bank account domain using CDQ’s Bank Account Data API to validate and assess trust levels of banks directly within the Change Request process.

 

Feasible Option - Abstract

SAP MDG Classic Mode does not natively support dynamic bank account validation using external risk intelligence. However, this limitation can be overcome by integrating CDQ’s Bank Account Data API into the Change Request (CR) process via a custom-built API integration. This enables the following capabilities:

  • Fraud Detection: Detect if a bank is blacklisted or associated with a known fraud case.
  • Reputation Scoring: Retrieve and display the bank accounts' trust score for transparency and risk assessment.
  • Real-Time Messaging: Show contextual messages — either warnings (blacklisted) or information (whitelisted) — directly in the UI during CR processing.

For example:
If a blacklisted bank is entered: ⚠️ Bank & is in blacklist, one of fraud case ID: &

image1.png

Figure 1 – Warning message after a bank in the blacklist is entered

 If a whitelisted bank is used with a known trust score: Bank & is in whitelist, trust score: &

image2.png

Figure 2 – Information message after a bank in the whitelist is entered

This solution provides a feasible, low-effort, and value-driven way to bring real-time banking insights into your SAP MDG environment.

 

Some Nice-To-Have Skills

Here are some nice-to-have skills and knowledge areas for handling this topic:

ABAP programming, T-Code: SM59, SM30, STRUST, USMD_RULE_SERVICE BadI Definition, REST API, RFC, MDG

 

Solution in a Nutshell

This solution enhances SAP MDG's Change Request process by verifying bank account data in real time via CDQ’s Bank Account Data API. The goal is to detect potential fraud or confirm the trustworthiness of a bank at the moment it is entered in the Change Request.

Here's how it works:

  1. The user adds a bank account in a CR (only IBAN or bank account number & bank code/number & bank country code).
  2. Upon entry, background logic triggers a call to CDQ’s Bank Account Data API (POST /v2/bankaccounts/confirm).
  3. The response returns whether the bank:
    • Is in the whitelist, along with a trust score (e.g., trustScore: 27).
    • ⚠️Has one or more fraud cases, with related metadata like fraudCaseId.
  4. SAP MDG then displays a contextual message in the UI based on the result:
    • If the bank is whitelisted: Bank 0002 is in whitelist, trust score: 27
    • If the bank is flagged for fraud: ⚠️ Bank 0001 is in blacklist, one of fraud case ID: UUIK5gGCQD

This provides immediate, actionable feedback to master data stewards before the data is activated, reducing the risk of onboarding risky bank accounts.

 

Implementation Steps

For our solution, we pursued the following steps:

  • Create an API Key Instance from CDQ with a Client ID and Client Secret. For more information, please visit this site.
  • Import TLS root certificate for https://api.cdq.com. For more information, check out this blog.
  • Maintain the required RFC Destinations to set up technical communication.
  • Determine the logical port as the DPI’s general RFC Destination. Configure the V_MDQDPI_RFCDEST view in SM30.
  • Create these classes to implement the logic;
    1. API Caller Class (ZCL_CDQ_API_CALLER) -> Handling API requests, communicating with CDQ
    2. Main Integration Class (ZCL_CDQ_BP_INTEGRATION) -> Prepare the request data and trigger the POST method
    3. Validation Class (ZCL_BP_CDQ_VALIDATION) -> Display the outcome of the API in Change Request
    4. Utilities Class (ZCL_BP_CDQ_UTILITIES) -> Collect useful methods that are used several times

Create New API Key;

image3.pngFigure 3 – Generating API Key from CDQ Portal for Secure Integration

To establish secure HTTPS communication with CDQ, the certificate for api.cdq.com must be imported via transaction STRUST. This is depicted in Figure 4, where the certificate is added under the SSL Client (Standard);

saplogon_QLJqaBjQRt.png

Figure 4 – Certification for CDQ API

Set up External Server HTTP Connections;

image5.png

 

 

 

 

 

 

 

 

 

 


Figure 5 – RFC Connections for CDQ

The created RFC Destination Z_DPI_CDQ is assigned as the logical port for DPI’s general operation. You can see this configuration in Figure 6, which shows the entry in the V_MDQDPI_RFCDEST view;

image6.png

 

 

 

 


Figure 6 – Data entry for V_MDQDPI_RFCDEST to determine logical port for general DPI operations

Remark: The following methods will be the main part of the framework, they do not include the whole picture.

The method responsible for communicating with CDQ (ZCL_CDQ_API_CALLER->CALL_API);

  METHOD call_api.

    TRY.
        DATA(rfc_destination) = get_rfc_destination( if_mdqdpi_rfc_dest_constants=>provider-cdq-operation-general-name ).

        IF rest_client IS NOT BOUND.
          DATA(http_client) = get_http_client( rfc_destination ).

          cl_http_utility=>set_request_uri( request = http_client->request
                                            uri     = api_path ).

          rest_client = NEW cl_rest_http_client( http_client ).
        ENDIF.

      CATCH cx_mdqdpi_functional_error.
        rfc_destination = get_rfc_destination( if_mdqdpi_rfc_dest_constants=>provider-cdq-operation-lookup-name ).
        IF rest_client IS NOT BOUND.
          http_client = get_http_client( rfc_destination ).
          rest_client = NEW cl_rest_http_client( http_client ).
        ENDIF.
        IF rest_client IS INITIAL.
          RAISE EXCEPTION NEW cx_mdqdpi_functional_error( textid = cx_mdqdpi_functional_error=>data_provider_setup_error ).
        ENDIF.
    ENDTRY.

    DATA(request) = build_request( payload = payload
                                   mapping = mapping ).
    rest_client->post( request ).
    result = rest_client->get_response_entity( )->get_string_data( ).
    analyze_response(
      EXPORTING
        string_response  = result
        rest_client      = rest_client                 " REST Client
      IMPORTING
        http_status_code = http_status_code
    ).

    rest_client->close( ).
    CLEAR rest_client.

  ENDMETHOD.

 The method responsible for preparing the API response for validation BAdI (ZCL_CDQ_BP_INTEGRATION->BANK_RELIABILITY);

  METHOD bank_reliability.

    DATA:
      ls_abap_format  TYPE zif_cdq_bp_integration=>gty_bank_reliability_response,
      ls_t100_message TYPE scx_t100key.

    CLEAR:
      ev_status,
      es_cdq_bank_response,
      et_t100_message.

    DATA(name_mappings) = VALUE /ui2/cl_json=>name_mappings( ( abap = 'bank_code'      json = 'nationalBankIdentifier' )
                                                             ( abap = 'iban'           json = 'internationalBankAccountIdentifier' )
                                                             ( abap = 'account_number' json = 'nationalBankAccountIdentifier' )
                                                             ( abap = 'bic'            json = 'internationalBankIdentifier' ) ).

    DATA(api_caller) = zcl_cdq_api_caller=>get_instance( ).

    TRY.
        api_caller->call_api(
          EXPORTING
            api_path         = '/sap-odm/v3/bankaccount-data/rest/v2/bankaccounts/confirm'
            payload          = is_cdq_bank_request
            mapping          = name_mappings                 " ABAP<->JSON Name Mapping Table
          IMPORTING
            result           = DATA(http_response)
            http_status_code = ev_status
        ).

      CATCH cx_mdqdpi_functional_error INTO DATA(lx_error).

*     General error message info
        CLEAR ls_t100_message.
        ls_t100_message = lx_error->if_t100_message~t100key.
        go_bp_cdq_utilities->prepare_t100_message(
          EXPORTING
            ix_error        = lx_error                 " Functional Errors
          CHANGING
            cs_t100_message = ls_t100_message                 " T100 key with mapping of parameters to attribute names
        ).
        IF ls_t100_message IS NOT INITIAL.
          APPEND ls_t100_message TO et_t100_message.
        ENDIF.

*     Detailed error message info if exists
        IF lx_error->previous IS NOT INITIAL.
          CLEAR ls_t100_message.
          DATA(lx_previos_error) = CAST cx_mdqdpi_functional_error( lx_error->previous ).
          ls_t100_message = lx_previos_error->if_t100_message~t100key.
          go_bp_cdq_utilities->prepare_t100_message(
            EXPORTING
              ix_error        = lx_previos_error                 " Functional Errors
            CHANGING
              cs_t100_message = ls_t100_message                 " T100 key with mapping of parameters to attribute names
          ).
          IF ls_t100_message IS NOT INITIAL.
            APPEND ls_t100_message TO et_t100_message.
          ENDIF.
        ENDIF.
        EXIT.
    ENDTRY.

    convert_to_abap_format(
      EXPORTING
        iv_data_in_json_format       = http_response
        iv_api_type                  = 'BANK_REL'                 " LOOK_UP / BANK_REL / EMAIL
      IMPORTING
        es_cdq_bank_response = es_cdq_bank_response                 " Bank Reliability Response Type
    ).

*  If the bank account has no trust score or fraud case, the bank account is unknown for CDQ
    IF      es_cdq_bank_response-trust_score            IS INITIAL
        AND es_cdq_bank_response-associated_fraud_cases IS INITIAL.
      es_cdq_bank_response-is_bank_unkown  = abap_true.
    ENDIF.

  ENDMETHOD.

 

Conclusion

As organizations increasingly rely on external banking data for payments, compliance, and onboarding, trusted bank account validation becomes a critical part of financial master data governance. This integration with CDQ’s Bank Account Data API provides SAP MDG users with real-time insights into the trust level and potential fraud risk of a bank—before the data is activated.

By embedding this verification into the Change Request process:

  • Stewards are empowered to act immediately on risks.
  • Fraud-prone banks can be flagged and avoided.
  • Clean, verified bank accounts improve downstream processes like payments and compliance reporting.

This approach not only enhances data quality and integrity but also supports key organizational goals: minimizing risk, preventing fraud, and building a solid foundation for digital finance processes.

Whether in finance, procurement, or vendor onboarding, this solution helps ensure that the bank accounts you rely on are exactly what they claim to be: trusted.

1 Comment
eva753kimson
Newcomer
0 Kudos

Thanks a lot! Glad you liked it and appreciate the support !  DailyPay