Selamlar
PHP 'de kurmaya çalıştığım sanal posta aşağıdaki sorunum var.
Panelime kullanıcı adı ve şifre ile login oluyorum (login sessionu oluşturur)
Payment.php ile bilgileri girip > PaymentResult.php sayfasına post ediyorum.
Post edilen sayfa 3D ekranına yönlendiriyor, 3d şifreyi giriyorum
returnURL adresine gelirken
sayfa login ekranına dönüyor ve session silinmiş oluyor. (her işlemde böyle olmuyor, ilk deneme başarılıysa ikincide de login'e dönüyor, veya 3.de dönüyor. )
PaymentResult.php içerisinde hiç bir şekilde unset session vs. bulunmuyor.
session ile ilgili sadece bazı post edilen veriler session da tutuluyor
Çözümü için denediğim yöntemler
1. değişkenleri SESSIONDAN çıkardım bu sefer kart CVV, tutar, kart ay/yıl post edilmiyor.
2. işlem sonunda değişkenleri tek tek unset yaptım
session yoksa login ekranına dönderen kod
if(!isset($_SESSION['login']))
{
$returnUrl = 'Payment';
header('Location: /online/?returnUrl=' . urldecode($returnUrl));
die();
}PaymentResult.php kodu;
if (isset($_POST["secure3d"]) && !empty($_POST["secure3d"]))
{
//echo "Yes, secure3d is set";
// Kredi Kartı formundan gelen post bilgileri:
// *******************************************
// Kart ve sipariş bilgileri:
$secure3d = $_POST["secure3d"];
$KartTipi = $_POST["KartMarka"]; // Visa / Master vs.
$KartNo = str_replace(' ', '', $_POST['KartNo']);
$KartCvv = $_POST["securitycode"];
// Ay ve yılı almak için substring (parçalama) kullanıyoruz
$tarih = $_POST["expirationdate"];
list($KartAy, $KartYil) = explode("/", $tarih);
$KartYil = "20" . $KartYil; // Yılı tam hale getirdik
$KartSonkul = $KartYil[2] . $KartYil[3] . $KartAy; // Yılın son iki hanesi ve ay
//Tutar düzelt
$Tutar = $_POST["Tutar"];
$Tutar = str_replace('.', '', $Tutar); // Binlik ayırıcıyı kaldır
$Tutar = str_replace(',', '.', $Tutar);
$IslemNo = $_POST["IslemNo"]; // Unique olmak zorunda boş bıraklılabilir non3d için(kendi oluşturuyor.) ama 3d için olmak zorunda.
$IslemTipi = $_POST["IslemTipi"]; // Sale - Refund gibi.
$ParaKodu = $_POST["ParaKodu"];
$TaksitSayisi = $_POST["Taksit"];
// Üye iş yeri için bırakılan alan
$SessionInfo = session_id(); // Optional programcılara verilen işaretleme alanı. Session_id ile kontrol sağlanıyor.
$_SESSION['SessionInfo'] = $SessionInfo;
$_SESSION['secure3d'] = $secure3d;
$_SESSION['KartTipi'] = $KartTipi;
$_SESSION['KartNo'] = $KartNo;
$_SESSION['KartSonkul'] = $KartSonkul;
$_SESSION['KartAy'] = $KartAy;
$_SESSION['KartYil'] = $KartYil;
$_SESSION['KartCvv'] = $KartCvv;
$_SESSION['Tutar'] = $Tutar;
$_SESSION['IslemNo'] = $IslemNo;
$_SESSION['IslemTipi'] = $IslemTipi;
$_SESSION['ParaKodu'] = $ParaKodu;
$_SESSION['TaksitSayisi'] = $TaksitSayisi;
$_SESSION['arpCode'] = $_POST["arpCode"];
$_SESSION['comment'] = $_POST["comment"];
$_SESSION['ownerTCKN'] = $_POST["ownerTCKN"];
switch ($secure3d) {
case "3d":
echo "case3d";
$postedilecek = "Pan=$KartNo"
."&ExpiryDate=$KartSonkul"
."&PurchaseAmount=$Tutar"
."&Currency=$ParaKodu"
."&BrandName=$KartTipi"
."&VerifyEnrollmentRequestId=$IslemNo"
."&SessionInfo=$SessionInfo"
."&MerchantId=$IsyeriNo"
."&MerchantPassword=$IsyeriSifre"
."&SuccessUrl=$SuccessURL"
."&FailureUrl=$FailureURL";
if ($taksitSayisi > 1){
$postedilecek.="&InstallmentCount=$TaksitSayisi";
}
file_put_contents("vPos/postedilecek.txt",$postedilecek); // log için
postet3d($mpiServiceUrl,$postedilecek);
break;
case "non3d":
echo "case non3d";
$PosXML = 'prmstr=<VposRequest><MerchantId>'
.$IsyeriNo.'</MerchantId><Password>'
.$IsyeriSifre.'</Password><TerminalNo>'
.$TerminalNo.'</TerminalNo><TransactionType>'
.$IslemTipi.'</TransactionType><TransactionId>'
.$IslemNo.'</TransactionId><CurrencyAmount>'
.$Tutar.'</CurrencyAmount><CurrencyCode>'
.$ParaKodu.'</CurrencyCode><Pan>'
.$KartNo.'</Pan><Cvv>'
.$KartCvv.'</Cvv><Expiry>'
.$KartYil.$KartAy.'</Expiry><TransactionDeviceSource>0</TransactionDeviceSource><ClientIp>'
.$ClientIp.'</ClientIp>';
if ($TaksitSayisi > 1){
$PosXML.='<NumberOfInstallments>$TaksitSayisi</NumberOfInstallments></VposRequest>';
}else {
$PosXML.='</VposRequest>';
}
echo $PosXML;
PoxRequest($PostUrl,$PosXML);
break;
} //Switch case sonu
} else
{
echo "N0, secure3d set edilmedi<br/>";
// ACS (Bankalar arası kart merkezin)den gelen datayı karşılama durumu
// ACS (Bankalar arası kart merkezi)nden gelen post bilgileri:
// *******************************************
$SessionInfo = $_POST["SessionInfo"]; // Optional ek veri. 1024byte
If ($SessionInfo != $_SESSION['SessionInfo'])
{ // Session id ile güvenlik kontrolü yapıyoruz.
echo "gelen sessionid = ".$SessionInfo;
echo "<br>";
echo "sistem sessionid = ".$_SESSION['SessionInfo'];
}
$Durum = $_POST["Status"]; // geri dönen durum:
// Y:Doğrulama başarılı
// A:Doğrulama tamamlanamadı ancak doğrulama denemesini kanıtlayan CAVV üretildi
// U:Doğrulama tamamlanamadı
// E:Doğrulama başarısız.
// N:Doğrulama başarısız, işlem reddedildi
$IslemNo = $_POST["VerifyEnrollmentRequestId"]; // işlem numarası unique
$KartNo = $_POST["Pan"]; // Kredi Kartı numarası
$KartSonkul = $_SESSION['KartYil'].$_SESSION['KartAy']; //$_POST["Expiry"]; // Son kullanma tarihi
$Tutar = $_SESSION['Tutar']; //$_POST["PurchAmount"]; // Sipariş tutarı
$ParaKodu = $_POST["PurchCurrency"]; // Para kodu:
// 949: TRY
// 840: USD
// 978: EUR
// 826: GBP
// JPY: 392
$TaksitSayisi = $_POST["InstallmentCount"]; // Taksit Sayısı
$Xid = $_POST["Xid"]; // MPI tarafından üretilen 20 byte değerindeki alan. İşlem Sanal POS a gönderilir.
$ECI = $_POST["Eci"]; // Bankalar arası kart merkezinden gelen Elektronik ticaret belirteci. Status Y ise 05 A ise 06 döner.
$CAVV = $_POST["Cavv"]; // Bankalar arası kart merkezinden gelen (ACS) 28 byte büyüklüğünde kart sahibi doğrulama değeri.
$KartCvv = $_SESSION['KartCvv'];
// Eğer KARD VISA ise;
// Status Y ve ECI 05:
// Otorizasyon mesajına ECI ve CAVV bilgilerini yerleştirerek işleme devam et.
// Status A ve ECI 06:
// Otorizasyon akışını durdur veya Half Secure Ödeme almak için Otorizasyon mesajına ECI ve CAVV bilgilerini yerleştirerek işleme devam et.
// Status U ve ECI 07:
// Otorizasyon akışını durdur veya İşleme Non Secure olarak devam edilecekse Otorizasyon mesajına ECI bilgisini yerleştirerek işleme devam edilebilir.
// Status E: Otorizasyon akışını durdur!
// Status N: Otorizasyon akışını durdur!
// Eğer KARD MasterCard ise;
// Status Y ve ECI 02:
// Otorizasyon mesajına ECI ve CAVV bilgilerini yerleştirerek işleme devam et.
// Status A ve ECI 01:
// Otorizasyon akışını durdur veya Half Secure Ödeme almak için Otorizasyon mesajına ECI ve CAVV bilgilerini yerleştirerek işleme devam et
// Status U ve ECI 00:
// Otorizasyon akışını durdur veya İşleme Non Secure olarak devam edilecekse Otorizasyon mesajına ECI bilgisini yerleştirerek işleme devam edilebilir.
// Status E: Otorizasyon akışını durdur!
// Status N: Otorizasyon akışını durdur!
// Eğer KARD TROY ise;
// Status Y ve ECI 02:
// Otorizasyon mesajına ECI ve CAVV bilgilerini yerleştirerek işleme devam et
// Status A ve ECI 01:
// Otorizasyon akışını durdur veya Half Secure Ödeme almak için Otorizasyon mesajına ECI ve CAVV bilgilerini yerleştirerek işleme devam et
// Status U ve ECI 00:
// Otorizasyon akışını durdur veya İşleme Non Secure olarak devam edilecekse Otorizasyon mesajına ECI bilgisini yerleştirerek işleme devam edilebilir.
if (isset($_POST["VerifyEnrollmentRequestId"]) && !empty($_POST["VerifyEnrollmentRequestId"]))
{
echo " 3d cevap bilgisi geldi işlemler yap<br/>";
$Pos3dXML = 'prmstr=<VposRequest><MerchantId>'
.$IsyeriNo.'</MerchantId><Password>'
.$IsyeriSifre.'</Password><TerminalNo>'
.$TerminalNo.'</TerminalNo><TransactionType>Sale</TransactionType><CurrencyAmount>'
.$Tutar.'</CurrencyAmount><CurrencyCode>'
.$ParaKodu.'</CurrencyCode><Pan>'
.$KartNo.'</Pan><Expiry>'
.$KartSonkul.'</Expiry><Cvv>'
.$KartCvv.'</Cvv><ECI>'
.$ECI.'</ECI><CAVV>'
.$CAVV.'</CAVV><MpiTransactionId>'
.$IslemNo.'</MpiTransactionId><ClientIp>'
.$ClientIp.'</ClientIp><TransactionDeviceSource>0</TransactionDeviceSource>';
if ($TaksitSayisi > 1)
{
$Pos3dXML.='<NumberOfInstallments>$TaksitSayisi</NumberOfInstallments></VposRequest>';
}else
{
$Pos3dXML.='</VposRequest>';
}
file_put_contents("vPos/Pos3dXML.txt",$Pos3dXML); // log için
PoxRequest($PostUrl,$Pos3dXML);
} // if sonu
} // else sonu
function postet3d($mpiServiceUrl,$postedilecek)
{
// Autherizasyon için MPI(MerchantPlugin3d)'e post eder.
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$mpiServiceUrl);
curl_setopt($ch,CURLOPT_POST,TRUE);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_HTTPHEADER,array("Content-Type"=>"application/x-www-form-urlencoded"));
curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($ch,CURLOPT_POSTFIELDS,$postedilecek);
// İşlem isteği MPI'a gönderiliyor
$resultXml = curl_exec($ch);
$errorCurl = curl_error($ch);
curl_close($ch);
if ($errorCurl){
echo "cURL Error #:" . $errorCurl;
exit();
}
// Sonuç XML'i yorumlanıp döndürülüyor
$result = SonucuOku3d($resultXml);
file_put_contents("vPos/result.txt",$result); // log için
if($result["Status"]=="Y")
{
// Kart 3D-Secure Programına Dahil
echo $result["Status"];
?>
<html>
<head>
<title>Get724 Mpi 3D-Secure İşlem Sayfası</title>
</head>
<body>
<div class="container d-flex justify-content-center align-items-center" style="height: 100vh;">
<form name="downloadForm" action="<?php echo $result['ACSUrl']?>" method="POST">
<div class="text-center position-relative">
<div>
<img src="/uploads/payment.png" alt="Payment Image" width="100px">
<!-- Yuvarlak spinning -->
<div class="spinner-border text-primary position-absolute top-50 start-50 translate-middle" style="width: 3rem; height: 3rem;" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<h1>3-D Secure İşleminiz yapılıyor</h1>
<h2>
Tarayıcınızda Javascript kullanımı engellenmiştir.
</h2>
<h3>
3D-Secure işleminizin doğrulama aşamasına geçebilmek için Gönder butonuna basmanız gerekmektedir.
</h3>
<input type="submit" value="Gönder" class="btn btn-primary">
</div>
<input type="hidden" name="PaReq" value="<?php echo $result['PaReq']?>">
<input type="hidden" name="TermUrl" value="<?php echo $result['TermUrl']?>">
<input type="hidden" name="MD" value="<?php echo $result['MerchantData']?>">
</form>
</div>
<SCRIPT LANGUAGE="Javascript" >
document.downloadForm.submit();
</SCRIPT>
</body>
</html>
<?php
} else {
echo'
3D-Secure Verify Enrollment Sonucu : '.$result["Status"].' <br>
' . $result["MessageErrorCode"] . ' : '.vPOSgetErrorMessage($result["MessageErrorCode"]).' <br>
Girilen tutar: ' . $_SESSION['Tutar'] . ' <br>
İşlem İsteğini Sanal Pos\'a gönderiniz.
' . $_SESSION['KartSonkul'] . '
' . $_SESSION['KartNo'] . '
<a href="/online/Payment">Geri dön</a>
';
}
} // postet3d sonu
include_once('assets/footer.php');
//////////////////////////////////////////////// V P O S S T A R T ////////////////////////////////////
function PoxRequest($PostUrl,$PosXML)
{
// Pos bilgilerini alıp bankaya yollar non3d
// echo '<h1>Vpos Request</h1>';
// echo $PostUrl."<br>";
// echo '<textarea rows="15" cols="60">'.$PosXML.'</textarea><br>';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$PostUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$PosXML);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 59);
curl_setopt($ch, CURLOPT_SSLVERSION,5);
// CURL_SSLVERSION_TLSv1_1 = 5,
// CURL_SSLVERSION_TLSv1_2 = 6
// curl_setopt ($ch, CURLOPT_CAINFO, "c:/php/ext/cacert.pem");
$result = curl_exec($ch);
// Check for errors and display the error message
if($errno = curl_errno($ch)) {
$error_message = curl_strerror($errno);
echo "cURL error ({$errno}):\n {$error_message}";
}
curl_close($ch);
//echo '<h1>Vpos Response</h1>';
//echo '<textarea rows="15" cols="60">'.$result.'</textarea>';
// Parse XML response
$xml = simplexml_load_string($result);
if ($xml === false) {
echo "<b> Error in parsing XML.</b>";
return;
}
// Assign XML data to variables
$MerchantId = (string)$xml->MerchantId;
$TransactionType = (string)$xml->TransactionType;
$TransactionId = (string)$xml->TransactionId;
$ResultCode = (string)$xml->ResultCode;
$ResultDetail = (string)$xml->ResultDetail;
$CardHolderName = (string)$xml->CustomItems->Item['value'];
$AuthCode = (string)$xml->AuthCode;
$HostDate = (string)$xml->HostDate;
$Rrn = (string)$xml->Rrn;
$TerminalNo = (string)$xml->TerminalNo;
$TotalPoint = (float)$xml->TotalPoint;
$CurrencyAmount = (float)$xml->CurrencyAmount;
$CurrencyCode = (string)$xml->CurrencyCode;
$ECI = (string)$xml->ECI;
$ThreeDSecureType = (string)$xml->ThreeDSecureType;
$TransactionDeviceSource = (string)$xml->TransactionDeviceSource;
$BatchNo = (string)$xml->BatchNo;
$TLAmount = (float)$xml->TLAmount;
global $db;
global $currentDateTime;
if($ResultCode == '0000')
{
echo'
<h6>Sayın, '.$CardHolderName.'<br/>
'.number_format($CurrencyAmount, 2, ',', '.').' TRY Ödemeniz başarıyla alınmıştır.</h6>
<br/>OdemeID: '.$TransactionId.'
<br/><a href="/online/Payment?uuid='.$TransactionId.'">Tahsilat makbuzu için tıklayınız</a>
<br/><p><span id="second">15</span> saniye sonra otomatik yönlendiriliyorsunuz</p>
<a href="/online/Payment"><button class="btn btn-primary"><i class="fad fa-turkish-lira-sign"></i> Yeni ödeme yapmak için tıklayınız</button></a>
<script type="text/javascript">toastr.success("'.$ResultCode.', İşlem başarıyla tamamlandı","SAP B2B")</script>
';
$tarih = $currentDateTime;
$tahsilat = $db->query("
INSERT INTO
payments
(kartsahibi, result, status, member_id, date, amount, clientIp, ownerTCKN, comment, uuid) VALUES
('$CardHolderName', '".$ResultCode."', '".$ResultDetail."', '".$_SESSION['arpCode']."', '$tarih', '$CurrencyAmount', '".getRealIpAddr()."', '".$_SESSION['ownerTCKN']."' ,'".$_SESSION['comment']."', '".$TransactionId."') ");
} else
{
echo'
<h6>Ödeme Hatası<br/>
Hata kodu: '.$ResultCode.', '. $ResultDetail.'.</h6>
<a href="/online/Payment"><button class="btn btn-primary"><i class="fad fa-turkish-lira-sign"></i> Tekrar denemek için tıklayınız</button></a>
<script type="text/javascript">toastr.error("'.$ResultCode.' : '.$ResultDetail.' ","SAP B2B")</script>
';
}
}
function SonucuOku3d($result)
{
$resultDocument = new DOMDocument();
$resultDocument->loadXML($result);
//Status Bilgisi okunuyor
$statusNode = $resultDocument->getElementsByTagName("Status")->item(0);
$status = "";
if( $statusNode != null )
$status = $statusNode->nodeValue;
//PAReq Bilgisi okunuyor
$PAReqNode = $resultDocument->getElementsByTagName("PaReq")->item(0);
$PaReq = "";
if( $PAReqNode != null )
$PaReq = $PAReqNode->nodeValue;
//ACSUrl Bilgisi okunuyor
$ACSUrlNode = $resultDocument->getElementsByTagName("ACSUrl")->item(0);
$ACSUrl = "";
if( $ACSUrlNode != null )
$ACSUrl = $ACSUrlNode->nodeValue;
//Term Url Bilgisi okunuyor
$TermUrlNode = $resultDocument->getElementsByTagName("TermUrl")->item(0);
$TermUrl = "";
if( $TermUrlNode != null )
$TermUrl = $TermUrlNode->nodeValue;
//MD Bilgisi okunuyor
$MDNode = $resultDocument->getElementsByTagName("MD")->item(0);
$MD = "";
if( $MDNode != null )
$MD = $MDNode->nodeValue;
//MessageErrorCode Bilgisi okunuyor
$messageErrorCodeNode = $resultDocument->getElementsByTagName("MessageErrorCode")->item(0);
$messageErrorCode = "";
if( $messageErrorCodeNode != null )
$messageErrorCode = $messageErrorCodeNode->nodeValue;
// Sonuç dizisi oluşturuluyor
$result = array
(
"Status"=>$status,
"PaReq"=>$PaReq,
"ACSUrl"=>$ACSUrl,
"TermUrl"=>$TermUrl,
"MerchantData"=>$MD ,
"MessageErrorCode"=>$messageErrorCode
);
return $result;
}
function getRealIpAddr()
{
// Client Ip adresini getir.
if (!empty($_SERVER['HTTP_CLIENT_IP'])) //check ip from share internet
{
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) //to check ip is pass from proxy
{
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else
{
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}