ModPay支付网关如何

时间:2014-07-13 03:02:43

标签: php jquery ajax payment

更新:我已将其缩小到Ajax通话范围。我可以使用正常的表单提交后,仍然使用相同的PHP代码,它的工作原理。 Ajax没有。所以如果熟悉Ajax的人有一个想法......或者如果你更好地了解如何在没有用户交互的情况下从代码中执行POST ...

更新2: 如果我用下面的代码替换GetPaymentSetup()函数,它也可以使用PostTo。它似乎与重定向有关......

    public function GetPaymentSetup() {
        $script1 = "<script type=\"text/javascript\">
            function post_to_url() {
                var form = document.createElement('form');
                form.action = '" . self::PROXY_URL . "';
                form.method = 'POST';

                var input = document.createElement('input');
                input.type = 'hidden';
                input.name = 'clientId';
                input.value = '" . self::CLIENTID . "';
                document.body.appendChild(input);
                form.appendChild(input);

                var input1 = document.createElement('input');
                input1.type = 'hidden';
                input1.name = 'clientCode';
                input1.value = '" . self::CLIENTCODE . "';
                document.body.appendChild(input1);
                form.appendChild(input1);

                var input2 = document.createElement('input');
                input2.type = 'hidden';
                input2.name = 'postTo';
                input2.value = '" . self::POSTTO_URL . "';
                document.body.appendChild(input2);
                form.appendChild(input2);

                var input3 = document.createElement('input');
                input3.type = 'hidden';
                input3.name = 'target';
                input3.value = 'GetPaymentSetup';
                document.body.appendChild(input3);
                form.appendChild(input3);

                form.submit();
            }
        </script>";
        $html2 = "<br><button id='hidformbtn' onclick=\"post_to_url()\">Click 3</button><br>";

        echo $script1;
        echo $html2;
}

我想这会奏效。在某些情况下我需要自动化它,但这不是问题。我想知道jQuery / Ajax失败的原因。


我到处搜索,但找不到与此系统有关的任何问题。所以我需要一些指导,也许作为未来使用它的人的参考。我的任务是与ModPay.com的支付系统集成。它也被称为TotalTransact。出于测试目的,他们有一个足够简单的页面,您可以执行POST并在没有任何实际数据交换的情况下获取响应。我编写了可以使用此代码的代码,但是当我向&#34; PostTo添加一个选项时,我不会回复一个响应。首先,以下是API文档中如何描述该选项:

  

如果提供PostTo = URL参数,则调用结果   xxxxx页面会将结果发布到提供的网址而不是   返回包含结果的网页。

我想将结果发布到不同的网址,以便更轻松地拆分解析。如果我不使用此参数,我会从发出请求的页面中获得结果。如果我使用参数,我仍然可以获得成功的POST,但没有回复。他们的开发人员摸不着头脑,所以我更倾向于认为这与我的代码有关。

我已经确认他们可以直接发布到我的PostTo网址。所以我知道这不是问题。我还添加了#34; Access-Control-Allow-Origin&#34;标题,以确保他们可以回发确定,以避免跨域问题。

以下是PHP中的相关代码:

function post($url, $data) {
    $header = array("Content-Type: application/x-www-form-urlencoded");
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

    //curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ;
    //curl_setopt($curl, CURLOPT_SSLVERSION,3);
    //curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    //curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($curl, CURLOPT_HEADER, true);  //This option returns some data to the screen
    curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
    //curl_setopt($curl, CURLOPT_COOKIEFILE, ''); //write cookies.  empty string to ignore.
    //curl_setopt($curl, CURLOPT_COOKIEJAR, ''); //read cookies
    //curl_setopt($curl, CURLOPT_VERBOSE, '1');
    //curl_setopt($curl, CURLOPT_NOPROXY, 1); // causes POST to fail
    //curl_setopt($curl, CURLOPT_HTTPHEADER,array("Expect:"));
    //curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);

    $response = curl_exec($curl);
    curl_close($curl);
    return $response;
}

其中

$data = http_build_query($_POST, '', '&');

和$ _POST来自另一个页面上的AJAX调用(代理以避免浏览器CORS问题):

public function GetPaymentSetup($useButton) {
    $script = "<script type=\"text/javascript\">";
    if($useButton == true) {
        $script .= "
        $(document).ready(function() {
        $(\"button\").click(function() {
        ";
    }
    $script .= "
        var request = jQuery.ajax ({
            type:   'POST',
            url:    '" . self::PROXY_URL . "',
            crossDomain: true,
            data:       { \"clientId\"      : \"" . self::CLIENTID . "\",
                          \"clientCode\"    : \"" . self::CLIENTCODE . "\",
                          \"postTo\"        : \"" . self::POSTTO_URL . "\" 
                        }
            success: function(responseData, textStatus, jqXHR) {
                        $('#dresponse').html(responseData);
                     },
            error:   function(responseData, textStatus, errorThrown) {
                        $('#dresponse').html('Error. POST failed.');
                     }
        });";
    if($useButton == true) {
        $script .= "
        });});";
    }
    $script .= " </script>";
    if($useButton == true)
        $html = "<button>click</button><div id='dresponse'></div>";
    else
        $html = "<div id='dresponse'></div>";
    echo $script;
    echo $html;
}

任何人都可以解释为什么我使用这一行:

                      \"postTo\"        : \"" . self::POSTTO_URL . "\" 

POSTTO_URL页面永远不会得到任何回报。但如果我删除该行,我会得到回复?再次,使用POSTTO_URL,我也不会在原始的AJAX调用中收到错误,因此它可以成为一个成功的POST。我可以通过将CLIENTID更改为其他内容来验证这一点,然后我就会失败。

这是我正在做的事情,还是结果不正确的事情?有没有人有任何与他们融合的经验?

提前致谢!

1 个答案:

答案 0 :(得分:0)

没有人对原始Ajax / jQuery失败的原因有任何了解。但我确实有一个可行的解决方案,所以在这里,对于未来寻找TotalTransact / ModPay集成的任何人来说都是如此:

创建一个文件:modPayProcessing.php:

<?php
class modPayProcessing {
    const CLIENTCODE = "xxxxxxx";
    const CLIENTID = "xxxxxx";
    const PROXY_URL = "https://....modPayProxy.php";
    const POSTTO_URL = "https://....modPayReceive.php";

    public function GetPaymentSetup($useButton=false, $usePostTo=false) {
        $script = "<script type=\"text/javascript\">
            function post_to_url() {
                var form = document.createElement('form');
                form.action = '" . self::PROXY_URL . "';
                form.method = 'POST';

                var input = document.createElement('input');
                input.type = 'hidden';
                input.name = 'clientId';
                input.value = '" . self::CLIENTID . "';
                document.body.appendChild(input);
                form.appendChild(input);

                var input1 = document.createElement('input');
                input1.type = 'hidden';
                input1.name = 'clientCode';
                input1.value = '" . self::CLIENTCODE . "';
                document.body.appendChild(input1);
                form.appendChild(input1);
        ";
        if($usePostTo === true) {
            $script .= "
                var input2 = document.createElement('input');
                input2.type = 'hidden';
                input2.name = 'postTo';
                input2.value = '" . self::POSTTO_URL . "';
                document.body.appendChild(input2);
                form.appendChild(input2);
            ";
        }
        $script .= "
                var input3 = document.createElement('input');
                input3.type = 'hidden';
                input3.name = 'target';
                input3.value = 'GetPaymentSetup';
                document.body.appendChild(input3);
                form.appendChild(input3);

                form.submit();
            }
        ";
        if($useButton == true) {
            $html = "<button id='hidformbtn' onclick=\"post_to_url()\">Submit</button>";
            $script .= "</script>";
        }
        else {
            $html = "";
            $script .= "
            if(window.onload) {
                var currOnload = window.onload;
                var newOnload = function() {
                    currOnload();
                    post_to_url();
                };
                window.lonload = newOnload;
            }
            else {
                window.onload = post_to_url();
            }
        </script>";
        }

        echo $script;
        echo $html;
    }

    public function PostPayment($useButton, $usePostTo=false) {
    // Same as the above function, but change the input.name/value to be for whatever you want to submit
    // Implementations of how to retrieve the data vary, so I am not listing it exactly here, but the basic format is the same.
    }

创建一个文件:modPayProxy.php:

//You can use Curl, or you can use php Streams.  Below is a function for each:
<?php
    function postCurl($url, $data) {
        $header = array("Content-Type: application/x-www-form-urlencoded");
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_POST, 3);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_HEADER, false);  //This option returns some data to the screen
        curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);

        $response = curl_exec($curl);
        curl_close($curl);
        return $response;
    }

    function postStreams($url, $data) {
        $params = array(
            'http' => array(
                'method'=>'POST',
                'content'=>$data,
                'header'=>array("Content-Type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($data) . "\r\n"),
                'user_agent'=>"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"
            )
        );
        $ctx = stream_context_create($params);
        $fp = @fopen($url, 'rb', false, $ctx);
        if(!$fp) {
            throw new Exception("Problem with $url, $php_errormsg");
        }
        $response = @stream_get_contents($fp);
        fclose($fp);
        if($response === false) {
            throw new Exception("Problem reading data from $url, $php_errormsg");
        }
        return $response;
    }

    if(array_key_exists('target', $_POST)) {
        if($_POST['target'] == 'GetPaymentSetup')
            $url = GETSETUP_URL;
        elseif($_POST['target'] == 'PostPayment')
            $url = POST_URL;
        else
            $url = "";

        unset($_POST['target']);
        $data = http_build_query($_POST, '', '&');

        echo(postStreams($url, $data)); //change to postCurl if you prefer
    }
    else {  // if POSTTO_URL is not used in the calling function.
        $postdata = file_get_contents("php://input");
        parse_str($postdata, $output);
        // Do whatever you want with $output now.
    }

创建一个文件modPayReceive.php:

<?php
    $postdata = file_get_contents("php://input");
    parse_str($postdata, $output);
    // Now do whatever you want with $output now.

要发起呼叫,请确保您需要modPayProcessing.php,然后:

$cc = new modPayProcessing();
$cc->GetPaymentSetup(true, false);

如果第二个参数为false,则不会使用POSTTO_URL / modPayReceive.php文件。 第一个参数可以设置为true,以将其作为表单上的按钮。或者假的直接处理(更好的想法,所以你不暴露你的clientID等)