POST verileriyle PHP Yönlendirme


241

Bu konuda biraz araştırma yaptım ve bunun mümkün olmadığını söyleyen bazı uzmanlar var , bu yüzden alternatif bir çözüm istemek istiyorum.

Benim durumum:

Sayfa A: [checkout.php] Müşteri fatura ayrıntılarını dolduruyor.

Sayfa B: [process.php] Bir fatura numarası oluşturun ve müşteri bilgilerini veritabanında saklayın.

Sayfa C: [thirdparty.com] Üçüncü Ödeme Ağ Geçidi (SADECE POSTA VERİLERİNİ KABUL ET).

Müşteri, ayrıntılarını doldurur ve A Sayfasında alışveriş sepetlerini sonra da B Sayfasına POST yapar. Process.php içinde, POSTed verilerini veritabanında saklar ve bir fatura numarası oluşturur. Bundan sonra, müşteri verilerini ve fatura numarasını POSTParty.com ödeme ağ geçidine GÖNDERİN. Sorun B sayfasında POST yapıyor. CURL verileri C Sayfasına POST yapabilir, ancak sorun sayfanın C sayfasına yönlendirmediğidir. Müşterinin C Sayfasındaki Kredi Kartı ayrıntılarını doldurması gerekir.

Üçüncü taraf ödeme ağ geçidi bize API örneğini verdi, örnek müşteri detaylarıyla birlikte fatura numarasını POST. Sistemin istenmeyen fatura numaraları aşmasını istemiyoruz.

Bunun için herhangi bir çözüm var mı? Mevcut çözümümüz, müşterinin A Sayfasındaki ayrıntıları doldurmasıdır, ardından B Sayfasında, kullanıcının C Sayfasına POST yapmak için ONAYLA düğmesini tıklatabileceği tüm müşteri ayrıntılarını gösteren başka bir sayfa oluştururuz.

Hedefimiz, müşterilerin yalnızca bir kez tıklamak zorunda kalmalarıdır.

Umarım sorum açıktır :)


Bunun için yinelenen olduğunu düşünmüyorum, çünkü amacım bir PHP sayfasının içinde, POST verilerini iletmek ve yönlendirmek. cURL Bunu yapmanın mümkün olduğunu düşünmüyorum. Bunun için herhangi bir alternatif uzman arayın
Shiro

ʜᴛᴛᴘ 308 yönlendirme kodu?
user2284570

Yanıtlar:


212

Sayfa B'de gerekli tüm veriler ve eylem Sayfa C olarak ayarlanmış bir form oluşturun ve sayfa yüklendiğinde JavaScript ile gönderin. Verileriniz kullanıcıya çok fazla uğraşmadan Sayfa C'ye gönderilecektir.

Bunu yapmanın tek yolu bu. Yönlendirme, http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html adresinde okuyabileceğiniz 303 HTTP üstbilgisidir , ancak bazılarını alıntılayacağım:

İsteğe yanıt farklı bir URI altında bulunabilir ve bu kaynaktaki bir GET yöntemi kullanılarak alınmalıdır. Bu yöntem öncelikle, POST tarafından etkinleştirilen bir komut dosyasının çıktısının kullanıcı aracısını seçilen bir kaynağa yönlendirmesine izin vermek için vardır. Yeni URI, başlangıçta istenen kaynağın yerini alan bir başvuru değil. 303 yanıtı önbelleğe EDİLMEMELİDİR, ancak ikinci (yeniden yönlendirilen) istek yanıtı önbelleğe alınabilir.

Yaptığınız şeyi elde etmenin tek yolu, kullanıcıyı Sayfa C'ye gönderen bir ara sayfa kullanmaktır.

<form id="myForm" action="Page_C.php" method="post">
<?php
    foreach ($_POST as $a => $b) {
        echo '<input type="hidden" name="'.htmlentities($a).'" value="'.htmlentities($b).'">';
    }
?>
</form>
<script type="text/javascript">
    document.getElementById('myForm').submit();
</script>

Ayrıca, Javascript içermeyen kullanıcıların hizmetinizi kullanabildiğinden emin olmak için bir noscript etiketi içinde basit bir "onayla" formuna sahip olmalısınız.


2
amacım A Sayfası -> C Sayfasında, B Sayfası denetleyicinin (iş mantığı) fatura numarasını oluşturmasıdır. Sistem görünümünden Sayfa A-> Sayfa B-> Sayfa C'dir, ancak kullanıcı görünümünden Sayfa A-> Sayfa B olmalıdır, hiçbir zaman Sayfa B'yi serbest bırakmamalıdır.
Shiro

3
@Peeter: akıllı öneri +1. Tek sorun C Sayfası itme geri düğmesi daha kullanıcı Sayfa C'ye yeniden gönderilecektir edildiğinde Üstelik kodlamanızı unuttuğunu olduğunu $ave $bkullanarak htmlentities/htmlspecialchars, bkz stackoverflow.com/questions/6180072/php-forward-data-post/...
Marco DeMaio

8
soru burada istemcide Javascript devre dışı bırakılırsa? B Sayfası C sayfasına yönlendirilmez, değil mi?
Imran Omar Bukhsh

24
<noscript><input type="submit" value="Click here if you are not redirected."/></noscript>içinde<form>
nullability

3
languagenitelik olması gerektiği itiraz edildi,<script type="text/javascript">...</script>
Alex W

34
/**
 * Redirect with POST data.
 *
 * @param string $url URL.
 * @param array $post_data POST data. Example: array('foo' => 'var', 'id' => 123)
 * @param array $headers Optional. Extra headers to send.
 */
public function redirect_post($url, array $data, array $headers = null) {
    $params = array(
        'http' => array(
            'method' => 'POST',
            'content' => http_build_query($data)
        )
    );
    if (!is_null($headers)) {
        $params['http']['header'] = '';
        foreach ($headers as $k => $v) {
            $params['http']['header'] .= "$k: $v\n";
        }
    }
    $ctx = stream_context_create($params);
    $fp = @fopen($url, 'rb', false, $ctx);
    if ($fp) {
        echo @stream_get_contents($fp);
        die();
    } else {
        // Error
        throw new Exception("Error loading '$url', $php_errormsg");
    }
}

17
İlk başta bu kabul edilen cevaptan daha iyi görünse de, $urlverilene yönlendirmediğini unutmayın - Sadece mevcut sayfanın içeriğini sayfanın içeriğiyle değiştirir $url. Önemlisi , $urlsayfadaki php kodu değerlendirilmez.
iPadDeveloper2011

@ iPadDeveloper2011, URL'de bir PHP kodunuz yok! PHP kodu istemcide değil, SERVER'de yürütülür.
Eduardo Cuomo

1
redirect_post()sunucu tarafı olan php kodu, SUNUCU'ya bir istek gönderir $url. Eğer $urlbir olduğunu .phphtml hala içinde php etiketleri ile döndürülür - sayfa, ben php değerlendirilir unutmayın. Bütün mesele POST verilerini bir sunucu tarafı komut dosyasına göndermek değil mi?
iPadDeveloper2011

2
@EduardoCuomo bu yöntem sadece absoulte urls ile çalışır, çünkü fopen () nasıl çalışır: php.net/manual/en/function.fopen.php Hala oldukça şık bir cevap.
Omn

@Omn haklısın! "Bu göreli URL ile çalışmıyor mu?" bir soru değil, bir ifadedir. Karışıklık için üzgünüm
Eduardo Cuomo

25

Bunu mümkün kılan başka bir çözümüm var. İstemcinin Javascript çalıştırmasını gerektirir (bu günlerde adil bir gereklilik olduğunu düşünüyorum).

Fatura numaranızı ve müşteri ayrıntılarınızı arka planda (önceki Sayfa B'niz) oluşturmak için A Sayfasında bir AJAX isteği kullanın, ardından istek doğru bilgilerle başarılı bir şekilde geri döndüğünde - ödeme ağ geçidinize form gönderme işlemini tamamlamanız yeterlidir (Sayfa C).

Bu, kullanıcının sonucunu yalnızca bir düğmeyi tıklayıp ödeme ağ geçidine geçerek elde edecektir. Aşağıda bazı sahte kodlar var

HTML:

<form id="paymentForm" method="post" action="https://example.com">
  <input type="hidden" id="customInvoiceId" .... />
  <input type="hidden" .... />

  <input type="submit" id="submitButton" />
</form>

JS (kolaylık sağlamak için jQuery kullanarak ancak saf Javascript yapmak önemsizdir):

$('#submitButton').click(function(e) {
  e.preventDefault(); //This will prevent form from submitting

  //Do some stuff like build a list of things being purchased and customer details

  $.getJSON('setupOrder.php', {listOfProducts: products, customerDetails: details }, function(data) {
  if (!data.error) {
    $('#paymentForm #customInvoiceID').val(data.id);
    $('#paymentForm').submit();   //Send client to the payment processor
  }
});

1
Bu çözümün bir sorunu var, birisi bu sayfadaki JavaScript'i kapatır, yeniler ve gönderirse, hiçbir şey kaydetmeden ödeme sayfasına gidecektir. bu boşluk olabilir.
caoglish

2
Daha sonra sadece Javascript ile paymentForm eylemini ayarlayın? JS devre dışı bırakılırsa form gönderilmez.
MikeMurko

JS'yi kapatan kullanıcı bize bir soruna neden olmamalıdır - B Sayfasına gitmemiz gereken neden muhtemelen bir parmak izi oluşturmak veya bir sipariş kodu eklemek, vb. sonuç sipariş kodu olmadan 3. taraftan bize geri geldiğinde, siparişi kabul etmemeliyiz. JS kabul edilebilirse bu genel olarak iyi bir çözümdür.
Coder

19

Javascript ile uğraşmak istemiyorsanız $ _SESSION arkadaşınızdır

Diyelim ki bir e-posta iletmeye çalışıyorsunuz:

A sayfasında:

// Start the session
session_start();

// Set session variables
$_SESSION["email"] = "awesome@email.com";

header('Location: page_b.php');

Ve B Sayfasında:

// Start the session
session_start();

// Show me the session!  
echo "<pre>";
print_r($_SESSION);
echo "</pre>";

Oturumu yok etmek

unset($_SESSION['email']);
session_destroy();

neden javascript sürümünden daha az güvenli olduğunu düşünüyorsunuz?
Adam Baranyai

1
hayır, yani javascript ile karşılaştırılamaz. Sadece genel olarak $ _SESSION, $ _SESSION + çerezinden biraz daha az güvenli olabilir, ancak $ _SESSION kendi başına oldukça güvenlidir. Daha fazla bilgi için: stackoverflow.com/questions/17413480/session-spoofing-php
Robert Sinclair

ve oturumu nasıl kapatabilirim?
Sayed Muhammed Idrees

Oturumu kapatmanız mı gerekiyor?
Ivan P.

6

PHP'nin bir POST yapmasına izin verebilirsiniz, ancak daha sonra php'niz her türlü komplikasyonla geri dönecektir. Bence en basit aslında kullanıcının POST yapmasına izin vermek olurdu.

Yani, önerdiğiniz gibi, gerçekten bu kısmı alacaksınız:

Müşteri A Sayfasındaki ayrıntıları doldurur, ardından B Sayfasında tüm müşteri ayrıntılarını gösteren başka bir sayfa oluştururuz, bir ONAYLA düğmesini ve ardından C Sayfasına POST'u tıklarız.

Ancak aslında B sayfasında javascript gönderimi yapabilirsiniz, bu yüzden bir tıklamaya gerek yoktur. Bir yükleme animasyonu içeren bir "yönlendirme" sayfası yapın ve hazırsınız.


Şimdi bunu yapıyoruz. Bunu çözmek için herhangi bir PHP daha iyi mantık olduğunu düşünüyorum. Teşekkürler. ;)
Shiro

ya, HTTP daha doğru, ama ben PHP ortamında çalışmak, bu yüzden her iki etiket olduğunu düşünüyorum. Teşekkürler! Sütun Şarapnel.
Shiro

6

Bu eski bir soru olduğunu biliyorum, ama jQuery ile başka bir alternatif çözüm var:

var actionForm = $('<form>', {'action': 'nextpage.php', 'method': 'post'}).append($('<input>', {'name': 'action', 'value': 'delete', 'type': 'hidden'}), $('<input>', {'name': 'id', 'value': 'some_id', 'type': 'hidden'}));
actionForm.submit();

Yukarıdaki kod, form alanı oluşturmak, gizli alanları yazı alanları olarak eklemek ve sonunda göndermek için jQuery kullanır. Sayfa, POST verileri eklenmiş olarak form hedef sayfasına yönlendirilir.

ps Bu vaka için JavaScript ve jQuery gereklidir. Diğer cevapların yorumlarının önerdiği gibi, <noscript>JS'nin devre dışı bırakılması durumunda standart bir HTML formu oluşturmak için etiketi kullanabilirsiniz .


5

Basit bir kesmek var, kullanmak $_SESSIONve arrayyayınlanan değerlerden birini oluşturmak , ve bir kez File_C.phpsen-ebilmek kullanma o kullanabilirsiniz sonra onu yok ettikten sonra işleme.


ne demek istediğine küçük bir örnek verebilir misin?
caro

3
Anladığım kadarıyla, Sayfa C harici bir kaynaktır.
Narayan Bhandari

3

Sorunun phpyönlendirildiğinin farkındayım , ancak bir POSTisteği yeniden yönlendirmenin en iyi yolu muhtemelen .htaccess, yani:

RewriteEngine on
RewriteCond %{REQUEST_URI} string_to_match_in_url
RewriteCond %{REQUEST_METHOD} POST
RewriteRule ^(.*)$ https://domain.tld/$1 [L,R=307]

Açıklama:

Varsayılan olarak, isteği POST verileriyle yeniden yönlendirmek istiyorsanız, tarayıcı isteği GET ile yönlendirir 302 redirect. Bu, istekle ilişkili tüm POST verilerini de bırakır . Tarayıcı bunu, POST işleminin istemeden yeniden gönderilmesini önlemek için bir önlem olarak yapar.

Ama POST isteğini yine de verileriyle yönlendirmek isterseniz ne olur? HTTP 1.1'de bunun için bir durum kodu vardır. Durum kodu 307, isteğin aynı HTTP yöntemi ve verileriyle tekrarlanması gerektiğini belirtir . Dolayısıyla, bu durum kodunu kullanırsanız POST isteğiniz verileriyle birlikte tekrarlanır.

SRC


2

GET İsteği benim değişkenlerim vb geçiyorum arka uç üzerinde iyi çalışıyordu POST Talebi ile benzer sorunlarla karşı karşıya.

Yani ben onu çalışma var tek yolu gizli bir form koymak ve sayfa yüklendiğinde bir POST gönderme ile değerleri itmek oldu.

echo
'<body onload="document.redirectform.submit()">   
    <form method="POST" action="http://someurl/todo.php" name="redirectform" style="display:none">
    <input name="var1" value=' . $var1. '>
    <input name="var2" value=' . $var2. '>
    <input name="var3" value=' . $var3. '>
    </form>
</body>';

1

$_POSTVerileri kaydetmek , daha sonra bu verileri almak $_POSTve sonraki istek üzerine ayarlamak için oturumları kullanabilirsiniz .

Kullanıcı /dirty-submission-url.php
Do isteğini gönderir :

if (session_status()!==PHP_SESSION_ACTIVE)session_start();
     $_SESSION['POST'] = $_POST;
}
header("Location: /clean-url");
exit;

Daha sonra tarayıcı /clean-submission-urlsunucunuza yönlendirir ve isteklerini iletir. Bununla ne yapacağınızı anlamak için bazı dahili yönlendirmelere sahip olacaksınız.
İsteğin başında şunları yapacaksınız:

if (session_status()!==PHP_SESSION_ACTIVE)session_start();
if (isset($_SESSION['POST'])){
    $_POST = $_SESSION['POST'];
    unset($_SESSION['POST']);
}

Şimdi, isteğinizin geri kalanında $_POST, ilk istek üzerine olabildiğince erişebilirsiniz .


Alternatif olarak, $_POSTverileri bir sorgu dizesine işleyebilir ve bir sonraki sayfaya bu şekilde aktarabilirsiniz. Ama sonra veriler çok büyük olamaz. Dosya yüklemeleri söz konusu olduğunda bu muhtemelen işe yaramaz, ancak emin değilim.
Reed

0

Bunu dene:

Ağ geçidine yönlendirmek için B sayfasındaki http üstbilgisiyle veri gönderme ve istekte bulunma

<?php
$host = "www.example.com";
$path = "/path/to/script.php";
$data = "data1=value1&data2=value2";
$data = urlencode($data);

header("POST $path HTTP/1.1\\r\
" );
header("Host: $host\\r\
" );
header("Content-type: application/x-www-form-urlencoded\\r\
" );
header("Content-length: " . strlen($data) . "\\r\
" );
header("Connection: close\\r\
\\r\
" );
header($data);
?>

Ek Başlıklar:

Accept: \*/\*
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like 
Gecko) Chrome/74.0.3729.169 Safari/537.36

0

İşte benim için çalışan başka bir yaklaşım var:

başka bir web sayfasına yönlendirmeniz gerekiyorsa ( user.php) ve bir PHP değişkeni ( $user[0]) içeriyorsa :

header('Location:./user.php?u_id='.$user[0]);

veya

header("Location:./user.php?u_id=$user[0]");

Bu alternatifler GET protokolünü kullanmak içindir. İstemcinin tarayıcısındaki değişkenleri ortaya çıkarır. OP, POST ile aynı davranışı istedi.
Sergio A.17

-2
function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.



    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}

Misal:

 post('url', {name: 'Johnny Bravo'});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.