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:
- Einlesen der Avis-Datei des PSPs
- Mapping der eingelesenen Daten auf eine an den ELKO angelehnte SAP Zwischenstruktur
- Abspeichern der Zwischenstrukturen als elektronische Kontoauszüge
- 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.
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.
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:
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.
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.
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(hlp) = in.
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.
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.