Overblog
Folge diesem Blog Administration + Create my blog
SAPManDoo - SAP Resource

Der vorliegende Blog enthält von mir im Laufe meiner beruflichen Tätigkeit als SAP-Berater zusammengetragene Informationen / Beispiel-Codings zum Themenkreis SAP, speziell FI/CO.

Integration von Zahlungsmitteldienstleistern in die SAP Finanzbuchhaltung

Veröffentlicht am 3. Juli 2018 von sapmandoo in Basis-Entwicklung allg., FI

In den Workshops zur Bankbuchhaltung kommt bei den meisten Kunden (zumindest im Handels-Sektor) irgendwann die Frage nach der Integration von Zahlungsmitteldienstleistern ("Payment Service Provider", kurz PSP) wie PayPal oder Amazon Payments auf.

Mit "Integration" ist dabei üblicherweise das Einlesen und Verbuchen der Avise der verschiedenen PSPs gemeint. Die Antwort darauf lautete bis dato meist: Individualentwicklung.

Mit der Komponente Web Channel Experience Management hat SAP nun ein entsprechendes Framework zur Verfügung gestellt, um neben vielen anderen Funktionen auch diese lästige, aber oft nachgefragte Aufgabe zu bewerkstelligen.

Wer nun aber denkt, dass die Integration wenigstens der gängigsten PSPs per Customizing eingestellt werden kann, wird ähnlich enttäuscht sein, wie über das Abschneiden der deutschen Elf bei den beiden zurückliegenden Weltmeisterschaften. Immerhin für PayPal habe ich mir die Mühe gemacht, dass entsprechende Prozedere genau aufzuschreiben, so dass es Ihnen erspart bleibt.

Es handelt sich dabei um einen Lösungsansatz, der die Funktionen des elektronischen Kontoauszugs (ELKO) verwendet. Im Kern wird so getan, als ob die jeweiligen PSPs (Haus-)Banken sind, die Kontoauszüge anliefern. Der Ablauf des Verfahrens ist dabei wie folgt:

  1. Einlesen der Avis-Datei des PSPs
  2. Mapping der eingelesenen Daten auf eine an den ELKO angelehnte SAP Zwischenstruktur
  3. Abspeichern der Zwischenstrukturen als elektronische Kontoauszüge
  4. Aufruf der Buchungsfunktion des ELKO

Die oben beschriebenen Punkte werden durch die Transaktion FEBPS (Report RFEBKAPSP) initiiert. Hört sich alles im Grunde nicht schlecht an, bis man merkt, dass die (natürlich aufwändigsten) Punkte 1. und 2. komplett selber in Form einer BADI-Implementierung zu entwickeln sind, zu der es auch keinerlei Standard-Implementierung gibt...

Aber nun ja - hilft ja nix, also zunächst sind folgende Business Functions zu aktivieren:

  • LOG_SD_SIMP_02 Vereinfachte Verkaufsprozesse im Vertrieb 2
  • LOG_SD_CI_02 Sales & Distribution 2
  • ERP_WEB_CHANNEL_1 SAP Web Channel Experience Management für SAP ERP
  • ERP_WEB_CHANNEL_2 SAP Web Channel Experience Management 2.0
  • ERP_WEB_CHANNEL_3 SAP Web Channel Experience Management 3.0

Ich habe keinerlei unerwünschte Seiteneffekte der o.g. BF feststellen können, die Aktivierung kann also m.E. bedenkenlos durchgeführt werden.

Customizing

U.a. wird dadurch der folgende Customizing-Pfad eingeblendet: IMG - Vertrieb - SAP Web Channel Experience Management...

Im Abschnitt Zahlungsdienstleister können nun die benötigten PSPs dem System bekannt gemacht werden. Unter Business Add-Ins (BAdIs) - BAdI: Import der Abrechnungsdatei pro Zahlungsdienstleister erfolgt die Implementierung der weiter oben genannten Teilfunktionen 1. & 2. (Mustercoding s.u.).

Alles weitere Customizing ist das kleine Einmaleins des elektronischen Kontoauszugs. Im Customizing des ELKO werden nun für jeden PSP ein Vorgangstyp, die entsprechenden externen Vorgangscodes (Details siehe Abschnitt "Mapping") nebst Zuweisung der Buchungsregeln und abschließend die Zuordnung der Pseudobank des PSP zum entsprechenden Vorgangstyp hinterlegt. Diese Pseudobank muss auch als Hausbank mit Zuordnung zum entsprechenden Verrechnungskonto angelegt werden.

Ich habe zur Definition der Pseudobank einfach den Namen des PSP als Bankschlüssel und die Vertragsnummer als Kontonummer verwendet. Für die Anlage solcher Pseudo- bzw. internen Banken gibt es die Transaktion FIPS, mit der die länderspezifischen Prüfungen der BLZ ignoriert werden. Auf diese Weise lässt sich also bspw. auch ein nicht-numerischer Bankschlüssel anlegen.

Nachfolgend ist ein Beispiel-Customizing für den Zahlungsdienstleister PayPal aufgeführt:

Legen Sie zunächst mithilfe der Transaktion FIPS die Pseudo-Hausbank des PSP an:

Geben Sie unbedingt den Bankschlüssel auch unter SWIFT/BIC an, sonst findet die Eingangsverarbeitung des Kontoauszuges die Pseudobank nicht.

Prägen Sie in der FI12 die Pseudobank als Hausbank aus und legen Sie ein entsprechendes Hausbankkonto dazu an. Im vorliegenden Beispiel wurde die Vertragskontonummer als Kontonummer verwendet.

Die Hinterlegung einer IBAN ist natürlich nicht zwingend. Geben Sie das zu verwendende Hauptbuchkonto an. Denken Sie daran, auch ein entsprechendes Bankunterkonto anzulegen, welches später im Customizing des elektronischen Kontoauszugs zu hinterlegen ist.

Hinterlegen Sie im Customizing (OBXK) ein Konto für die Bankspesen, auf das die PayPal Gebühren zu buchen sind. Sofern es sich dabei um eine Kostenart handelt, muss ggf. eine CO Vorschlagskontierung (OKB9) zur Kostenart gepflegt werden.

 

Definieren und aktiveren Sie dann in der Komponente Web Channel Experience Management, die benötigen Zahlungsdienstleister
(IMG: Vertrieb - SAP Web Channel Experience Management - Zahlungsdienstleister - Zahlungsdienstleister definieren / Zahlungsdienstleister aktivieren (mandantenabhängig))

 

Fügen Sie abschließend das Customizing für den elektronischen Kontoauszug hinzu. Legen Sie zunächst die benötigten Kontosymbole an und ordnen Sie die entsprechenden Konten zu. Im vorliegenden Beispiel genügt die Angabe des Bankkontos sowie des korrespondierenden Bankunterkontos:

 

 

Legen Sie die Buchungsregeln und deren konkrete Ausgestaltung an. Im vorliegenden Fall sind es die Buchungsregeln für die Geschäftsvorfälle "Zahlungseingang" und "Rückerstattung":

Die Buchungsregeln buchen im Hauptbuch (Buchungsbereich 1) PayPal-Bank an PayPal Unterkonto bzw. umgekehrt und versuchen im Nebenbuch einen debitorischen Ausgleich gegen das PayPal Unterkonto:

 

Legen Sie einen Vorgangstyp namens PAYPAL an und weisen Sie die die externen Vorgangsschlüssel T0006  (Zahlungseingänge) und T1107 (Rückerstattungen) mit ihren korrespondierenden Buchungsregeln und einem passenden Interpretationsalgorithmus zu.

Ordnen Sie abschließend das Pseudo-Hausbankkonto dem Vorgangstyp zu.

Buchungslogik

Für die Ausgestaltung des Customizings des elektr. Kontoauszugs ist natürlich die gewünschte Buchungslogik maßgeblich. Eine mögliche Ausprägung könnte wie folgt aussehen:

Überblick Buchungslogik im Prozess "Direktverkauf mit Bezahlung per Zahlkarte"

Überblick Buchungslogik im Prozess "Direktverkauf mit Bezahlung per Zahlkarte"

Im obenstehenden Beispiel wird ein Filialverkauf mit direkter Bezahlung bei Mitnahme des Artikels per Kreditkarte dargestellt.

Aus der Filiale wird der Verkauf mit Angabe des verwendeten Zahlungsmittels an die Finanzbuchhaltung gemeldet.

In regelmäßigen Abständen sendet der Zahlungsmittelprovider Avise über abgerechnete Zahlungen an den Händler üblicherweise unter Angabe sämtlicher Transaktionsdaten und der angefallenen Gebühren. Diese Avise werden über die FEBPS eingelesen und verbucht. Für diese Verbuchung sind die entsprechenden Buchungsregeln auszuprägen und ggf. Suchmuster oder Userexits zu verwenden, um bspw. der Gebührenposition das passende Steuerkennzeichen und ggf. eine Kostenstelle zuzuführen (vgl. hier).

Der tatsächliche Zahlungseingang wird dann über den "echten" Kontoauszug desjenigen Bankkontos verbucht, auf welches der PSP reguliert hat.

Mapping

Elementarer Bestandteil des Prozesses ist natürlich, das Mapping der externen Daten des PSP auf die internen Kontoauszugsstrukturen herzustellen. Die internen Strukturen haben den Typ

FPS_HEADER - Auszugskopf

FPS_ITEM - Umsätze

Für das Mapping habe ich mir eine Excel-Tabelle angelegt, in der in einfacher Form Quelle, Ziel und Verarbeitungshinweise aufgeführt sind.

 

Mapping Auszugskopf

Mapping Auszugskopf

Mapping Umsatzdaten

Mapping Umsatzdaten

In das Feld GCODE der Umsatztabelle ist also der externe Vorgangscode abzufüllen, zu dem im Customizing d. elektr. Kontoauszugs auch die entsprechenden Buchungsregeln hinterlegt werden.

Nach dem Mapping kann dann die BadI-Implementierung erfolgen. Eine mögliche Ausprägung des Codings könnte so aussehen:

**************************************************************************
*   Upload und Mapping der Datei vom PSP in SAP-Strukturen
**************************************************************************
*   Bsp: PAYPAL
**************************************************************************
  METHOD if_ex_fps_import_paysp_file~read_paysp_settlement_file.

    DATA: lt_paypal TYPE ltt_paypal,
          lt_buf    TYPE TABLE OF string.

     CASE i_flt_vl.
      WHEN 'ZPP'.   "PayPal
        CHECK i_pfname IS NOT INITIAL.

        lt_buf = upload_data( i_pfname ).
        structurize_data_paypal( EXPORTING it_buf = lt_buf
                                 IMPORTING et_paypal = lt_paypal ).

        map_data_paypal( EXPORTING i_bank    = i_bank
                                   i_account = i_account
                                   it_paypal = lt_paypal
                         IMPORTING et_header = et_header
                                   et_items  = et_items
                         CHANGING  ct_return = et_return ).

    ENDCASE.

  ENDMETHOD.

 

Im ersten Schritt wird die Datei vom Zahlungsdienstleister in eine Puffer-Tabelle geladen (in diesem Fall CSV-Format) und anschließend strukturiert in eine interne Arbeitstabelle (hier vom Typ ltt_paypal, Satzbett PayPal-Umsätze) abgelegt (Methode STRUCTURIZE_DATA_<psp>). Dieser Abschnitt ist natürlich wesentlich vom Format und Inhalt der PSP-Datei abhängig.

Die entscheidende Verarbeitung erfolgt jedoch in der Methode MAP_DATA_<psp>, in der die zuvor strukturiert abgelegte Datei des PSP in die internen SAP Tabellen ET_HEADER und ET_ITEMS überführt werden.

Nachfolgend das komplette Mustercoding für den Upload der Avise des PSP PayPal:

Datendeklaration PayPal-Satzbett

PROTECTED SECTION.

  TYPES:
    BEGIN OF lty_paypal,
      section(2)          TYPE c,
      transaction         TYPE string,
      invoice(14)         TYPE c,
      reference(16)       TYPE c,
      type(3)             TYPE c,
      code(5)             TYPE c,
      start_date(25)      TYPE c,
      end_date(25)        TYPE c,
      debit_credit(2)     TYPE c,
      amount              TYPE string,
      currency(3)         TYPE c,
      com_debit_credit(2) TYPE c,
      amount_com          TYPE string,
      com_currency(3)     TYPE c,
      no_use(2)           TYPE c,
      id(13)              TYPE c,
      follow_up_nb        TYPE string,
      shop                TYPE string,
      bank_id             TYPE string,
    END OF lty_paypal.

  TYPES: ltt_paypal TYPE STANDARD TABLE OF lty_paypal.

Methode upload_data:

Importing I_PFNAME           TYPE STRING     Dateiname
Returning value( RT_BUF )    TYPE STR_TAB    String Tabelle

 

 METHOD upload_data.
    CALL METHOD cl_gui_frontend_services=>gui_upload
      EXPORTING
        filename = i_pfname
        filetype = 'ASC'
      CHANGING
        data_tab = rt_buf[].
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
  ENDMETHOD.

Methode structurize_data_paypal

Importing IT_BUF       TYPE STR_TAB     String Tabelle
Exporting ET_PAYPAL    TYPE LTT_PAYPAL  Satzbett PayPal  



  METHOD STRUCTURIZE_DATA_PAYPAL.
    DATA: ls_paypal TYPE lty_paypal,
          lv_rec    TYPE string.

    LOOP AT it_buf INTO lv_rec.
      CLEAR ls_paypal.
      TRANSLATE lv_rec USING '" '.  
      CONDENSE lv_rec NO-GAPS.
      SPLIT lv_rec AT ',' INTO
          ls_paypal-section
          ls_paypal-transaction
          ls_paypal-invoice
          ls_paypal-reference
          ls_paypal-type
          ls_paypal-code
          ls_paypal-start_date
          ls_paypal-end_date
          ls_paypal-debit_credit
          ls_paypal-amount
          ls_paypal-currency
          ls_paypal-com_debit_credit
          ls_paypal-amount_com
          ls_paypal-com_currency
          ls_paypal-no_use
          ls_paypal-id
          ls_paypal-follow_up_nb
          ls_paypal-shop
          ls_paypal-bank_id.
      APPEND ls_paypal TO et_paypal.
    ENDLOOP.

  ENDMETHOD.

Methode map_data_paypal

Importing I_BANK       TYPE BANKK         Bank
Importing I_ACCOUNT    TYPE BANKN         Konto
Importing IT_PAYPAL    TYPE LTT_PAYPAL    Paypal Records
Exporting ET_HEADER    TYPE FPS_T_HEADER  Auszug
Exporting ET_ITEMS     TYPE FPS_T_ITEMS   Umsatz
Changing  CT_RETURN    TYPE BAPIRET2_T    Returntabelle

 

  METHOD map_data_paypal.
*--------------------------------------------------------------------
*   PayPal-Daten in SAP Kontoauszugsdaten mappen
*--------------------------------------------------------------------

    DATA: ls_paypal    TYPE lty_paypal,
          ls_header    LIKE LINE OF et_header,
          ls_item      LIKE LINE OF et_items,
          ls_return    LIKE LINE OF ct_return,
          ls_t028b     TYPE t028b,
          lv_t028b_key TYPE absnd_eb.

*--------------------------------------------------------------------
*   HEADER
*--------------------------------------------------------------------
    CLEAR ls_header.

*   Bankdaten
    IF i_bank IS NOT INITIAL.
      ls_header-bank = i_bank.
    ENDIF.
    IF i_account IS NOT INITIAL.
      ls_header-ktonr = i_account.
    ENDIF.
    IF ls_header-bank IS INITIAL OR ls_header-ktonr IS INITIAL.
      "Pseuobank/Konto des PSP ermitteln
      SELECT * FROM t028b UP TO 1 ROWS INTO ls_t028b WHERE vgtyp = 'PAYPAL'.
      ENDSELECT.
      IF sy-subrc = 0.
        ls_header-bank  = ls_t028b-bankl.
        ls_header-ktonr = ls_t028b-ktonr.
      ELSE.
        "Fehler: keine Pseudo-Bank ermittelbar
        ls_return-type       = 'E'.
        ls_return-id         = 'ZFIC_PSP'.
        ls_return-number     = '001'.
        ls_return-message_v1 = 'PAYPAL'.
        APPEND ls_return TO ct_return.
      ENDIF.
    ENDIF.

*   Auszugsnummer
    CONCATENATE ls_header-bank '%' ls_header-ktonr '%' INTO lv_t028b_key.
    SELECT aznum FROM febko INTO ls_header-aznum UP TO 1 ROWS
           WHERE absnd LIKE lv_t028b_key
           ORDER BY aznum DESCENDING.
    ENDSELECT.
    IF sy-subrc = 0.
      ADD 1 TO ls_header-aznum.
    ELSE.
      ls_header-aznum = 1.
    ENDIF.

*   Auszugsdatum
    READ TABLE it_paypal INTO ls_paypal
         WITH KEY section = 'RH'.
    IF sy-subrc = 0.
      ls_header-azdat(4)   = ls_paypal-transaction(4).
      ls_header-azdat+4(2) = ls_paypal-transaction+5(2).
      ls_header-azdat+6(2) = ls_paypal-transaction+8(2).
    ELSE.
      ls_header-azdat = sy-datum.
    ENDIF.

*   Auszugs-Währung
    ls_header-waers = 'EUR'.

*   Start-Saldo
    "n/a

*   End-Saldo
    "n/a

*--------------------------------------------------------------------
*   ITEMS
*--------------------------------------------------------------------
    LOOP AT it_paypal INTO ls_paypal WHERE section = 'SB'.    "Die Einzelpos. tragen Satzart SB

      CHECK ls_paypal-code NE 'T0400'.        "GVC 'interne Umbuchungen' ignorieren

*     Bankdaten
      ls_item-bank  = ls_header-bank.
      ls_item-ktonr = ls_header-ktonr.
      ls_item-aznum = ls_header-aznum.

*     Valutadatum & Zeit
      ls_item-valut(4)   = ls_paypal-end_date(4).
      ls_item-valut+4(2) = ls_paypal-end_date+5(2).
      ls_item-valut+6(2) = ls_paypal-end_date+8(2).
      ls_item-uzeit(2)   = ls_paypal-end_date+10(2).
      ls_item-uzeit+2(2) = ls_paypal-end_date+13(2).
      ls_item-uzeit+4(2) = ls_paypal-end_date+16(2).
      ls_item-bvdat      = ls_item-valut.

*     Beträge
      ls_item-waers = ls_paypal-currency.
      _convert( EXPORTING in  = ls_paypal-amount
                IMPORTING out = ls_item-wrbtr ).
      DIVIDE ls_item-wrbtr BY 100.
      IF ls_paypal-debit_credit = 'DR'.
        MULTIPLY ls_item-wrbtr BY -1.
      ENDIF.

      "Gebühren
      _convert( EXPORTING in  = ls_paypal-amount_com
                IMPORTING out = ls_item-spesk ).
      DIVIDE ls_item-spesk BY 100.
      IF ls_paypal-debit_credit = 'DR'.
        MULTIPLY ls_item-spesk BY -1.
      ENDIF.

*     Verwendungszweck & Buchungstexte
      ls_item-vwz01 = ls_paypal-invoice.

*     GVC extern
      ls_item-gcode = ls_paypal-code.
      TRANSLATE ls_item-gcode TO UPPER CASE.

*     Header-Infos aktualisieren
      ADD 1 TO ls_header-anzum.

      IF ls_paypal-debit_credit = 'CR'.
        ADD ls_item-wrbtr TO ls_header-sumso.
      ENDIF.
      IF ls_paypal-debit_credit = 'DR'.
        ADD ls_item-wrbtr TO ls_header-sumha.
      ENDIF.

      APPEND ls_item TO et_items.

    ENDLOOP.

    APPEND ls_header TO et_header.

  ENDMETHOD.

Methode _convert

Hilfsmethode zum Konvertieren von Werten in Strings in CURR-Felder:

Importing IN  TYPE STRING

Exporting out TYPE KWBTR_EB.

  METHOD _convert.
    DATA(hlpin.
    out 0.
    IF hlp CO '0123456789,. '.
      TRANSLATE hlp USING ',.'.
      CONDENSE hlp NO-GAPS.
      out hlp.
    ENDIF.
  ENDMETHOD. 

 

Zunächst werden im Auszugskopf Bank und Kontonummer mit der Pseudobank des PSP gefüllt, sowie Auszugsnummer, -Datum und Währung gesetzt.

Bei den Umsätzen werden Betrag und Gebühr gefüllt sowie das Valutadatum und Verwendungszweckinformationen eingesetzt. Als externen GVC setze ich hier den in der PSP-Datei enthaltenen Vorgangscode in diesem Fall 'T0006' (Zahlung) bzw. 'T1107' (Rückerstattung). Im Customizing des ELKO muss dann zu diesen GVCs eine geeignete Buchungsregel hinterlegt werden.

Nach Durchlauf des BadI erzeugt der Standardreport RFEBKAPSP aus den so gemappten Tabellen einen Kontoauszug (Tab. FEBKO, FEBEP, FEBRE) und übergibt diesen an die Standard-Kontoauszugsverarbeitung (RFEBBU01).

Der Report RFEBKAPSP wird mithilfe der Transaktion FEBPS gestartet. Das Selektionsbild ähnelt dabei stark der Starttransaktion des elektronischen Kontoauszuges FF_5.

 

Verbuchung von Gebühren (Rückerstattungsfall)

Für die Verbuchung der Gebühren ist ggf. noch eine weitere BadI-Implementierung notwendig. Im Falle von Rückerstattungen kann es vorkommen, dass der Gebührenanteil negativ wird. In diesen Fällen steigt die Standard-Kontoauszugsverbuchung mit der Fehlermeldung aus, dass das Feld BSEG-WRBTR einen Formatfehler aufweist. Wer schonmal eine FI-Buchung manuell durchgeführt hat, weiß, dass Beträge nur positiv eingegeben werden können und das Vorzeichen durch den Buchungsschlüssel bestimmt wird.

Für diese Fälle empfiehlt es sich in einer Implementierung zur BadI-Definition FEB_BADI die Kontoauszugsbuchung zu beeinflussen bzw. in diesem Fall zu korrigieren:

FEB_BADI, Methode CHANGE_POSTING_DATA:

 

METHOD if_ex_feb_badi~change_posting_data.
  FIELD-SYMBOLS: <lf_ftpost> TYPE ftpost.

  CHECK i_febko-anwnd = '0001'.                    "nur Elko
  CHECK NOT t_ftpost[] IS INITIAL.                 "Buchungen?

* S.Rohde Consenso 01/2024
* PayPal Gebühren richtig kontieren
  IF i_febko-hbkid  = 'PAYP'  AND  "Pseusobank Paypal
     i_febko-hktid  = 'PAYP1' AND  "Pseudokonto PayPal
     i_posting_area = '2'     AND  "Nebenbuch
     i_febep-vgint  = 'APP2'. "<<< hier die Buchungsregel für Rückerstattung angeben

    LOOP AT t_ftpost ASSIGNING <lf_ftpost>.
      CHECK <lf_ftpost>-count = '002' AND <lf_ftpost>-stype = 'P'.
      CASE <lf_ftpost>-fnam.
        WHEN 'BSEG-WRBTR'.  "Minuszeichen rausschmeissen
          IF <lf_ftpost>-fval CA '-'.
            TRANSLATE <lf_ftpost>-fval USING '- '.
            CONDENSE <lf_ftpost>-fval.
          ENDIF.
        WHEN 'BSEG-BSCHL'.  "Buchungsschlüssel drehen
          IF <lf_ftpost>-fval = '40'.
            <lf_ftpost>-fval = '50'.
          ENDIF.
      ENDCASE.
    ENDLOOP.
  ENDIF.

ENDMETHOD.
Kommentare