Drücke "Enter", um den Text zu überspringen.

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:

1) PayPal Auto Return und Payment Data Transfer muss konfiguriert werden

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

2) 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.

3) 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/wichtige Links:

zu Punk 1)

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 Punk 2)

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

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

zu Punk 3)

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-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 } ?>

Zahlungsbestätigungsseite (success.php):

Diese Seite wird automatisch aufgerufen sobald die Zahlung durchgeführt wurde.
Einen Datenbankeintrag gibt es hier noch nicht, da dies der Paypal IPN Service übernimmt.
Durch diesen Dienst kommt man erst an die verifizierten Daten.

<?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."'");
?>
 Your payment has been successful.
 Please wait a few minutes for the transaction to be verified.<br>
 Then you can directly use your product.
<?php }else{ ?>
 Your payment has failed.
<?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";

12 Comments

  1. Hans März 21, 2018

    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 😉

    • mathias März 21, 2018

      Habe es nun korrigiert. In meinem Fall war der Username und der Datenbankname der selbe

  2. Reinhold Juni 11, 2018

    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

      • Reinhold Juni 11, 2018

        ich habe jetzt die Verbindung mit der Datenbank gelöst aber anscheint werden keine Parameter übergeben wie item_number, tx, amt, cc, st

        Notice: Undefined index: item_number in C:\MAMP\htdocs\einzel-scripte\paypal\success.php on line 15

        Notice: Undefined index: tx in C:\MAMP\htdocs\einzel-scripte\paypal\success.php on line 16

        Notice: Undefined index: amt in C:\MAMP\htdocs\einzel-scripte\paypal\success.php on line 17

        Notice: Undefined index: cc in C:\MAMP\htdocs\einzel-scripte\paypal\success.php on line 18

        Notice: Undefined index: st in C:\MAMP\htdocs\einzel-scripte\paypal\success.php on line 19

        kann man den fertigen Script irgend wo herunterladen ?

        • mathias Juni 11, 2018

          Paypal leitet nach erfolgreichem Kauf auf die success.php weiter.
          Um dies zu testen muss man in der Sandbox tatsächlich eine Bestellung ausführen damit die Variablen gesetzt sind seitens Paypal.
          Direkt darauf zuzugreifen klappt natürlich nicht.

          • Reinhold Juni 13, 2018

            ich führe eine Bestellung aus, von Konto Buyer wird auch Geld abgezogen.
            Bis zu Zahlung ist alles ok.
            Wenn die Zahlung durchgeführt wurde und ich auf den Buttom zurück zum Händler drücke, werde ich auf die success.php weitergeleitet und in der url sind keine paramet mehr enthalten.

  3. mathias Juni 13, 2018

    Stimmen die Variablennamen der ipn und success Datei überein?
    Eventuell mal alle Variablen ausgeben lassen in der ipn:
    print_r($_GET);

  4. Eric Laufer Juli 17, 2018

    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

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.