Paypal Integration/Implementierung in PHP

Tutorial: Integration Paypal in PHP (implementieren)

Ich habe gefühlt einen ganzen Monat gebraucht um Paypal in meinem eigenen selbstprogrammierten Shop zu implementieren.
Alle Tutorials haben entweder nicht funktioniert, waren unvollständig, hatten keine Datenbankanbindung, es wurden notwendige Informationen einfach weggelassen und und und…

Daher hier die Lösung.

Damit erspart Ihr euch einige nervenzerreißende Tage/Wochen:

Sandbox Accounts anlegen

Erstellt jeweils einen Account für den Käufer und den Verkäufer.

 Käufer: buyer@DOMAINNAME.de
 Verkäufer: seller@DOMAINNAME.de

Diese beiden Accounts nutzt Ihr für eure Testkäufe.

 Account Type
 Personal (Buyer Account) - bei Käufer
 Business (Merchant Account) - bei Verkäufer
 Paypal Balance: 1000 (Startguthaben)

https://developer.paypal.com/developer/accounts/

Unter folgendem Link könnt Ihr euch auch dort einloggen um die Transaktionen auf beiden Seiten zu begutachten und Einstellungen zu machen:

https://www.sandbox.paypal.com/myaccount/home

Anforderungen

PayPal Auto Return und Payment Data Transfer muss konfiguriert werden

PayPal muss direkt nach der Zahlung automatisch auf die Bestätigungsseite weiterleiten.

IPN muss aktiviert werden (Instant Payment Notification)

Nach der Zahlung sendet Paypal eine Bestätigung an meinen Server, welche dann wiederrum überprüft wird ob die Zahlung auch wirklich stattgefunden hat.

Andere Währungen müssen akzeptiert und umgerechnet werden

Wenn nicht, steht die Zahlung auf „Pending“ und muss manuell bestätigt werden, was das Konzept der Automatisierung wieder komplett auf den Kopf stellt. Deswegen immer die Währung umrechnen lassen in die Zielwährung, oder diverse Währungen im Paypal Konto haben.

Konfiguration

zu Punkt 1 der Anforderungen

Auto Return: On
Return URL: https://DOMAINNAME.de/success.php
Payment Data Transfer: On

https://www.sandbox.paypal.com/cgi-bin/customerprofileweb?cmd=%5fprofile%2dwebsite%2dpayments

zu Punkt 2 der Anforderungen

Notification URL: https://DOMAINNAME.de/ipn.php
Receive IPN messages (Enabled)

https://www.sandbox.paypal.com/cgi-bin/customerprofileweb?cmd=%5fprofile%2dipn%2dnotify

zu Punkt 3 der Anforderungen

Allow payments sent to me in a currency I do not hold:
– Yes, accept and convert them to U.S. Dollars.

https://www.sandbox.paypal.com/us/cgi-bin/webscr?cmd=_profile-pref

Nice to know)

IPN Historie (als Verkäuferaccount abrufbar):
https://www.sandbox.paypal.com/us/cgi-bin/webscr?cmd=_display-ipns-history

Datenbanken anlegen (in z.B. phpmyadmin)

Paypal Integration/Implementierung in PHP
Paypal API in PHP/MYSQL
CREATE TABLE `products` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `image` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `price` float(10,2) NOT NULL,
 `status` tinyint(1) NOT NULL DEFAULT '1',
 PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `payments` (
 `payment_id` int(11) NOT NULL AUTO_INCREMENT,
 `item_number` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `txn_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `payment_gross` float(10,2) NOT NULL,
 `currency_code` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
 `payment_status` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `date` datetime NOT NULL,
 PRIMARY KEY (`payment_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Datenbankverbindung anlegen (dbconnect.php)

<?php

$servername = "localhost";
$username = "XXXXXX";
$password = "XXXXXX";
$database = "XXXXXX";

$mysqli = new mysqli($servername, $username, $password, $database);
$mysqli->set_charset("utf8");

// check connection
if ($mysqli->connect_errno) {
 die("Connect failed: ".$mysqli->connect_error);
}

?>

Produkte in Datenbank manuell anlegen und anzeigen lassen (index.php)

Paypal Button: https://www.paypalobjects.com/en_US/i/btn/btn_buynow_LG.gif

<?php
//Include DB configuration file
include 'dbconnect.php';

//Set useful variables for paypal form
$paypalURL = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; //Test PayPal API URL
$paypalID = 'seller@DOMAINNAME.de'; //Business Email

$usermail = $idarray->email;

?>
<?php
 //Fetch products from the database
 $results = $mysqli->query("SELECT * FROM products");
 while($row = $results->fetch_assoc()){
?>
 Name: <?php echo $row['name']; ?><br>
 Preis: <?php echo $row['price']; ?>€
 <form action="<?php echo $paypalURL; ?>" method="post">
 <!-- Identify your business so that you can collect the payments. -->
 <input type="hidden" name="business" value="<?php echo $paypalID; ?>">

<!-- Specify a Buy Now button. -->
 <input type="hidden" name="cmd" value="_xclick">

<!-- Specify details about the item that buyers will purchase. -->
 <input type="hidden" name="item_name" value="<?php echo $row['name']; ?>">
 <input type="hidden" name="item_number" value="<?php echo $row['id']; ?>">
 <input type="hidden" name="amount" value="<?php echo $row['price'];€ ?>">
 <input type="hidden" name="currency_code" value="EUR">

<!-- Specify URLs -->
 <input type='hidden' name='cancel_return' value='https://DOMAINNAME.de/cancel.php'>
 <input type='hidden' name='return' value='https://DOMAINNAME.de/success.php'>
 <input type='hidden' name='notify_url' value='https://DOMAINNAME.de/ipn.php'>

<!-- Display the payment button. -->
 <input type="image" name="submit" border="0"
 src="images/paypal-button-de.gif" alt="PayPal - The safer, easier way to pay online">
 <img alt="" border="0" width="1" height="1" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" >
 </form><br><br>
<?php } ?>
<?php include 'dbconnect.php'; //Get payment information from PayPal $item_number = $_GET['item_number']; $txn_id = $_GET['tx']; $payment_gross = $_GET['amt']; $currency_code = $_GET['cc']; $payment_status = $_GET['st']; //Get product price from database $productResult = $mysqli->query("SELECT price FROM products WHERE id = ".$item_number); $productRow = mysqli_fetch_object($productResult); $productPrice = $productRow->price; if(!empty($txn_id) && $payment_gross == $productPrice){ //Check if payment data exists with the same TXN ID. $prevPaymentResult = $mysqli->query("SELECT payment_id FROM payments WHERE txn_id = '".$txn_id."'"); ?> <h1>Your payment has been successful.</h1> Please wait a few minutes for the transaction to be verified.<br> Then you can directly use your product. <?php }else{ ?> <h1>Your payment has failed.</h1> <?php } ?>

Seite für Zahlungsabbruch (cancel.php)

<h1>Your PayPal transaction has been canceled.</h1>

Paypal Zahlungsbestätigung (ipn.php)

Nachdem der Kunde bezahlt hat wird ihm die success.php angezeigt.
Paypal IPN sendet nach einiger Zeit eine Anfrage an die ipn.php um die erfolgreiche Zahlung zu übermitteln.
Das heißt es kann ein wenig Dauern, bis der Eintrag in der Datenbank landet.

<?php
//Include DB configuration file
include 'dbconnect.php';

/*
 * Read POST data
 * reading posted data directly from $_POST causes serialization
 * issues with array data in POST.
 * Reading raw POST data from input stream instead.
 */
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
 $keyval = explode ('=', $keyval);
 if (count($keyval) == 2)
 $myPost[$keyval[0]] = urldecode($keyval[1]);
}

// Read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
 $get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
 if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
 $value = urlencode(stripslashes($value));
 } else {
 $value = urlencode($value);
 }
 $req .= "&$key=$value";
}

/*
 * Post IPN data back to PayPal to validate the IPN data is genuine
 * Without this step anyone can fake IPN data
 */
$paypalURL = "https://www.sandbox.paypal.com/cgi-bin/webscr";
$ch = curl_init($paypalURL);
if ($ch == FALSE) {
 return FALSE;
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);

// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: company-name'));
$res = curl_exec($ch);

/*
 * Inspect IPN validation result and act accordingly
 * Split response headers and payload, a better way for strcmp
 */
$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));
date_default_timezone_set('Europe/Berlin');
$date = date("Y-m-d H:i:s");

if (strcmp($res, "VERIFIED") == 0 || strcasecmp($res, "VERIFIED") == 0) {

//Payment data
 $item_number = $_POST['item_number'];
 $txn_id = $_POST['txn_id'];
 $payment_gross = $_POST['mc_gross'];
 $currency_code = $_POST['mc_currency'];
 $payment_status = $_POST['payment_status'];

//Check if payment data exists with the same TXN ID.
 $prevPayment = $mysqli->query("SELECT payment_id FROM payments WHERE txn_id = '".$txn_id."'");
 if($prevPayment->num_rows > 0){
 exit();
 }else{
 //Insert tansaction data into the database
 $insert = $mysqli->query("INSERT INTO payments(item_number,txn_id,payment_gross,currency_code,payment_status,date) VALUES('".$item_number."','".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."','".$date."')");

}

}

Hier kann man noch die Bestätigungsemail einfügen. Entweder einfach das Array ausgeben oder ein eMail Template basteln und die Variablen ausgeben.

Außerdem wird hier die Zahlung in die Datenbank geschrieben. Eine Freigabe der gekauften Ware wird hier auch eingefügt.

Beispielsweise eine SQL Abfrage um dem Nutzer das Geld auf seinem Kundenkonto gutzuschreiben, die virtuelle gekaufte Ware zu übergeben (SQL Insert oder Update), das Versenden einer eMail an den Nutzer mit den Daten, die er gekauft hat (Videolinks, ZIP Archiv, ….. usw….).

Je nach Anwendungsfall des Einsatzgebietes.

Live Modus

In index.php folgendes ersetzen:

$paypalURL = 'https://www.paypal.com/cgi-bin/webscr'; // echte paypal url
$paypalID = 'seller@DOMAINNAME.de'; //echte email vom richtigen paypal account

In der ipn.php folgendes ersetzen:

$paypalURL = "https://www.paypal.com/cgi-bin/webscr";

Paypal Integration/Implementierung in PHP

Bewerte diesen Artikel

0 Bewertung(en), Durchschnitt: 0 von 5

Dieser Artikel wurde noch nicht bewertet.

Es tut uns leid, dass dir der Beitrag nicht gefallen hat.

Lass uns genau diesen Artikel überarbeiten.

Erzähle uns, was wir besser machen können.

Beitrag teilen

18
Hinterlasse einen Kommentar

6 Kommentar Themen
12 Themen Antworten
0 Follower
 
Kommentar, auf das am meisten reagiert wurde
Beliebtestes Kommentar Thema
7 Kommentatoren
  Abonnieren  
neueste älteste meiste Bewertungen
Benachrichtige mich bei
Hans

Datenbank name fehlte und in der mysqli() war dafür nochmal $username

set_charset(„utf8“);

// check connection
if ($mysqli->connect_errno) {
die(„Connect failed: „.$mysqli->connect_error);
}

?>

Danke tolles tutorial 😉

Reinhold

ist dieser Script noch aktuell ?
Irgend wie bekommen ich eine Fehler meldung Warning: mysqli::__construct(): Headers and client library minor version mismatch. Headers:50541 Library:50634 in C:\MAMP\htdocs\einzel-scripte\paypal\dbconnect.php on line 8

Eric Laufer

hay,
das ist super was du hier gebaut hast und funktioniert wunderbar.
kannst du den noch was bauen, das man auch die zahlungen stornieren kann, also so das man kann mit einem mausklick das geld zurückbuchen kann?

mfg eric

meineMeinung

Herzlichen Dank für diesen Leitfaden!

Ich bin nun soweit gekommen, dass die Bestellung durchgeführt und das Script success.php die erfolgreiche Zahlung meldet. Leider wird jedoch in der Tabelle payments kein Datensatz hinzugefügt. In der Verlaufsübersicht der Sofortigen Zahlungsbestätigungen (IPN) werden alle Zahlungen korrekt mit Nachrichten-ID und Transaktionscode aufgelistet.

Ich habe auch hierüber eine erneute Zahlungsbestätigung gesendet, auch diese wird nicht in die MySQL-Tabelle geschrieben. Eine Fehlermeldung erhalte ich aber auch nicht. Ich bin nun etwas ratlos….

Eine IPN-Nachricht füge ich unten an, vielleicht hilft diese bei der Fehlersuche?

Viele Grüße,
Marcus

mc_gross=5.00&protection_eligibility=Eligible&address_status=confirmed&payer_id=U6E2ZJPR9B4LU&address_street=ESpachstr. 1&payment_date=08:32:20 Nov 08, 2018 PST&payment_status=Completed&charset=windows-1252&address_zip=79111&first_name=test&mc_fee=0.45&address_country_code=DE&address_name=test buyer&notify_version=3.9&custom=&payer_status=verified&business=memovest-facilitator@web.de&address_country=Germany&address_city=Freiburg&quantity=1&verify_sign=As8ixQ.poP1sojdamgmb9N5ij9rfACnQJpEA-dRxEcZviZNU2pTa7sQp&payer_email=memovest-buyer@web.de&txn_id=2WK15418J8827620D&payment_type=instant&last_name=buyer&address_state=Empty&receiver_email=memovest-facilitator@web.de&payment_fee=&shipping_discount=0.00&insurance_amount=0.00&receiver_id=VR2W6TMSVSZK2&txn_type=web_accept&item_name=Test2&discount=0.00&mc_currency=EUR&item_number=2&residence_country=DE&test_ipn=1&shipping_method=Default&transaction_subject=&payment_gross=&ipn_track_id=d212c39e98517

Mathias

Wenn das Problem ist, dass kein Datensatz hinzugefügt wird trotz erfolgreicher Bestellung, würde ich in der IPN Datei mal ein Check einbauen ob die Datenbankverbindung erfolgreich ist. Eventuell dort auch alle paar Blöcke mal eine Ausgabe machen (wenn diese denn angezeigt wird – oder eMail senden, je nachdem) um zu schauen wie weit der Code ausgeführt wird.

meineMeinung

Offenbar wird das Skript ipn.php nicht aufgerufen. Die entsprechenden Einstellungen habe ich aber vorgenommen:
comment image

comment image
comment image

Thomas

vielen Dank, für dieses Tutorial…hat mir eine MENGE zeit gespart

Scroll to Top