POST crashes the script and does not execute the code after form Ubmit

Asked

Viewed 125 times

0

I have a problem at hand. I have a credit card form, where the customer will fill in the data and be submitted to the bank evaluation. However, it should perform some operations before to arrive at the function that will send your data to the payment gateway. I will exemplify a step by step of what should be happening:

  1. User fills in card data;
  2. Send the form;
  3. Receives the answer "Wait, analyzing data";
  4. User receives the reply "Payment approved" or "Payment denied";

But step 3 is not running at all. Here is my code:

$('#credit_card_form').submit(function() {
    $.post($("#credit_card_form").attr('action'), $("#credit_card_form").serialize(), function(data){
        $("#retorno_form").html(data);
    }); 
    return false;
});

The POST is dealt with here:

if ($_POST['f'] == 'pay_credit_card') {
    $bandeira_cartao = $_POST['card_brand'];
    $numero_cartao = $_POST['card_number'];
    $vecto_mes = $_POST['card_valid_month'];
    $vecto_ano = $_POST['card_valid_year'];
    $cod_seguranca = $_POST['card_security'];
    $nome_cartao = $_POST['card_name'];

    if ($_POST['card_number'] == '') {
        echo "Preencha o campo X"
        return false;
    }

    // d_none = display: none;
    echo "<script>$('#aviso_carregando_cartao').removeClass('d_none'); $('#div_formulario_cartao').addClass('d_none');</script>";
    $retorno_pagamento = CS_MundiPagg($bandeira_cartao, $numero_cartao, $vecto_mes, $vecto_ano, $cod_seguranca, $nome_cartao);
    if ($retorno_pagamento == 'Captured') {     
        echo "<script>$('#sucesso_cartao').removeClass('d_none'); $('#modal-close').addClass('d_none');</script>";
    }
}

It turns out that it already goes through the "echo" above Cs_mundipagg() and goes straight to the answer at the end of the script. As if it "hangs" the script after the user submits the form and brings only the final answer (payment approved or not).

I have tried almost everything, I am not finding a solution. There is hope at the end of the tunnel?

2 answers

1

If you pass through it is because the conditional does not return true.

Besides, it’s a very weak, inconsistent, redundant parole.

It is inconsistent because it does not validate the input. It only checks if it is equal to empty and then interrupts. This means that if the user enters an empty space or anything invalid, the validation will pass.

It’s also just doing a superficial check of the card number and leaves other parameters untreated. At least you should also check the month, year and code.

Redundancy is in the misuse of variables. Declares and assigns variables that are not even used.

$bandeira_cartao = $_POST['card_brand'];
$numero_cartao = $_POST['card_number'];
$vecto_mes = $_POST['card_valid_month'];
$vecto_ano = $_POST['card_valid_year'];
$cod_seguranca = $_POST['card_security'];
$nome_cartao = $_POST['card_name'];

Then makes:

if ($_POST['card_number'] == '') {

And at no time used any of the above variables.

Check with isset() if each of the parameters exists.

After that make the appropriate validations for each one.

Below is an example for the credit card number:

function numbers_only($str, $exception = '')
{
    return preg_replace('#[^0-9'.$exception.']#', '', mb_convert_kana($str, 'n'));
}

$c = 'card_number';
if (isset($_POST[$c])) {
    $numero_cartao = trim($_POST[$c]);

    // Verifica se não está vazio
    if (empty($numero_cartao)) {
        echo 'Número do cartão não pode ser vazio';
        exit;
    }

    // Sanitiza removendo tudo que não for numérico
    // Sanitizar é opcional. Depende da política da sua empresa.
    $s = numbers_only($s);

    // Verifica a qunatidade de caracteres. A anatomia de um cartão é mínimo 12 e máximo 19. Note que esse padrão varia de acordo com a operadora e pode surgir uma nova operadora com padrão que modifique essa regra.
    $s = strlen($numero_cartao);
    if ($s < 12 || $s > 19) {
        echo 'Número do cartão é inválido';
        exit;
    }
}

It’s a rather simple example but it’s the least that should be done.

For the other fields, follow the same logic. The month and year fields check the entry if it is not empty and if it is numeric. After this check whether the date is valid.

A minimum check also in the name field is always good to do.

And to save request to the gateway, you can also detect by the number which the card operator is and thus create a validation rule for the security code because each carrier has a format. This item is not required. It would only be to refine the system and avoid unnecessary requests to the gateway.

In fact you can even send the data without any processing because the gateway API will do the validations anyway. That’s acting in bad faith and in a way it’s stupid.

The validations are to avoid unnecessary requests, as commented above and is also important for UX (user Experience). The user gets annoyed when he expects a request and receives an error. Depending on the case, he even gives up the purchase.
It is smarter to handle common and predicted errors, avoiding time-consuming requests and processing. The ideal is to already handle this data with Javascript and for precaution, ALWAYS should handle in the backend (PHP).

  • Doesn’t it work? Strange, here it is working. For when it hits the return false it does not perform the rest. So much so that the data is not sent to the gateway.

  • I understand Daniel, thank you. But tell me why in your opinion this is a very weak, inconsistent and redundant parole? She somehow doesn’t keep her promises?

  • Added an example of how to treat more consistently.

  • I understand Daniel, thank you for the explanations.

0

I recommend that you pass this part of the code to javascript/jquery, using the $.ajax() in place of $.post():

$.ajax({
    type: "POST",
    url: $("#credit_card_form").attr('action'),
    data: $("#credit_card_form").serialize(),
    dataType: 'json',
    beforeSend: function(){
        $('#aviso_carregando_cartao').removeClass('d_none');
        $('#formulario_cartao').addClass('d_none');
    },
    complete: function(){
        $('#aviso_carregando_cartao').addClass('d_none');
        $('#formulario_cartao').removeClass('d_none');
    },
    success: function(html){
       if(html.success)
       {
         $('#sucesso_cartao').removeClass('d_none');
         $('#modal-close').addClass('d_none');
       }
       else
       {
         $("#retorno_form").html(html.errormsg);
       }
    }
});

and your PHP would look something like this:

if ($_POST['f'] == 'pay_credit_card') {
    $bandeira_cartao = $_POST['card_brand'];
    $numero_cartao = $_POST['card_number'];
    $vecto_mes = $_POST['card_valid_month'];
    $vecto_ano = $_POST['card_valid_year'];
    $cod_seguranca = $_POST['card_security'];
    $nome_cartao = $_POST['card_name'];
    $status = ['success' => false, 'errormsg' => ''];

    if ($_POST['card_number'] == '') {
        $status['success'] = false;
        $status['errormsg'] = "Preencha o campo X";
        echo json_encode($status);
        return false;
    }

    $retorno_pagamento = CS_MundiPagg($bandeira_cartao, $numero_cartao, $vecto_mes, $vecto_ano, $cod_seguranca, $nome_cartao);
    if ($retorno_pagamento == 'Captured') {
        $status['success'] = true;
        echo json_encode($status);
    }
}

I didn’t test the code, but see if it works.

  • Well, it does the whole process, but for example, it does not return the error in the check if ($_POST['card_number'] == '') and does not run Cs_mundipagg().

  • I edited the answer, see if it worked.

  • Almost there. I actually had to comment on the whole key of complete: function() because the way I was removing the #formulario_card then put it back together with the success message. I didn’t quite understand the logic there. But now he doesn’t show me the error in $("#retorno_form").html(html.errormsg); (if the user for example stops filling the "card_number"). Only the message of the $('#aviso_carregando_cartao').removeClass('d_none');. I’ve tried editing here in some ways but I’m not succeeding.

  • It no longer shows the error after you comment all part of the complete:? The complete runs always, regardless of whether the ajax request was successful or unsuccessful. If you don’t want the #formulary_card to reappear after the request is finished, just take that part of the complete: ('#formulario_cartao').removeClass('d_none');

Browser other questions tagged

You are not signed in. Login or sign up in order to post.