1

I am doing a payment module on opencart. The problem is that the payment gateway requires a callback url that can only update the order history but difficult to refresh the browser. What I have done is that, after submitting the payment data via a form, the SweetAlert window is loaded that shows processing for like 40 seconds. I assume this is enough time for the user to make the payment from prompt he receives on the phone to confirm.

After making payment, the payment gateway communicates with my system to confirm if payment was successful or it failed by updating order status if successful.

The problem I have is after the 40 seconds, the SweetAlert closes and the subsequent ajax calls are not made. Here is my code:

<script>
    $(document).ready(function(){

    $(document).on('click', '#mpesaPay', function(e){

     var telephone = document.getElementById("lipanampesa_phone").value;

     SwalConfirm(telephone);
     e.preventDefault();
    });

   });

   function SwalConfirm(telephone){

      var telephone = telephone;
      var message = 'Proceed to make payment with ' + telephone + '?';
      swal({
       title: 'Confirm Mobile Number',
       text: message,
       type: 'warning',
       showCancelButton: true,
       confirmButtonColor: '#3085d6',
       cancelButtonColor: '#d33',
       confirmButtonText: 'Continue',
       showLoaderOnConfirm: true,

       preConfirm: function() {
         return new Promise(function(resolve) {

            $.ajax({
              url: 'index.php?route=extension/payment/mpesa/simulation',
              type: 'POST',
              data: $('#lipa-na-mpesa :input'),
              dataType: 'json',
              cache: false,
            })
            .done(function(response){
              swal({
                title: "Processing, Please Wait",
                text: "Check your phone NOW and enter your M-Pesa PIN to complete payment.",
                showConfirmButton: false,
                allowOutsideClick: false,
                timer: 40000,
                onOpen: function () {
                  swal.showLoading()
                }
              })
              .then(function(json){
                  $.ajax({
                          type: "post",
                          url: "index.php?route=extension/payment/mpesa/confirm",
                          data: $('#lipa-na-mpesa :input'),
                          dataType: 'json',
                          cache: false,
                      })
                      .done(function(json) {
                      if (json['success']) {
                        location = json['success'];
                      }
                      if (json['error']['warning']) {
                          swal({
                              type: 'warning',
                              title: 'Payment Failed',
                              text: 'Please restart the checkout process again or contact us if there is a problem'
                          })
                      }
                    });
                })
            })
            .fail(function(){
              swal('Oops...', 'Something went wrong with ajax !', 'error');
            });
         });
          },
       allowOutsideClick: false     
      }); 
   } 
</script>

The backend code is working successfully to the point of updating the order status on successful payment. I only need a way to redirect the user to the checkout/success action after confirming that order has been paid for.

This is the function that is supposed to be called after 40 seconds elapses to check order status and provide redirect link if successful

public function confirm() {

    $this->load->model('checkout/order');

    if (isset($this->request->post['order_id'])) {

        $order_info = $this->model_checkout_order->getOrder($this->request->post['order_id']);

        $order_status_id = $order_info['order_status_id'];

        if ($order_status_id == $this->config->get('payment_mpesa_order_status_id')) {
            $json['success'] = $this->url->link('checkout/success', '', true);
        } else {
            $json['error']['warning'] = 'Payment not received yet.';
        }
    } else {
        $json['error']['warning'] = 'Payment not received yet.';
    }
    return json_encode($json);
}
japheth
  • 229
  • 5
  • 26

1 Answers1

0

I know this is a late answer but... If I understood your problem correctly the issue is in getting the server status so that you can update the loaded web page. This is a common problem faced by web developers, the issue lies in the fact that http is a request response protocol, what this means is that a server has to wait for a client to make a request and respond to that request after which the connection is closed and the server continues idly waiting for the next request. The result is that a server cannot push updates to the clients unless they ask for it.

What this basically means for you is that you have to use either continuous polling in order to check the status of the operation or use websockets on the client side and a publisher subscriber middleware like mqtt (or AMQP?) on the server side so that the server can push the status change to the channel that the client will subscribe to.

Sorry for the wordy answer and the lack of a quick fix code example. In my opinion the quickest way is to use poll the server continuously until you get a response, however this will be resource intensive on both the clients and server compared to a publisher/subscriber model.