通过Ajax/JSONP调用外部PHP文件跨域写入JSON文件


Cross Domain Writing to a JSON File via Ajax/JSONP calling an external PHP file

更新并解决

感谢@Christofer Eliasson的提示。添加:

header("access-control-allow-origin: *");

到我的PHP文件解决了这个问题。也许这不是处理这个问题的最美丽的方式,但这是有效的。

为了让它更好/更安全:

$http_origin = $_SERVER['HTTP_ORIGIN'];
if ($http_origin == "http://domain1.com")
{  
    header('Access-Control-Allow-Origin: *');
}

这是另一个跨域相关问题。

我在domain1.com上有一个简单的HTML表单,用户可以在其中将他/她的电子邮件添加到邮件列表中,这里有一个位于第二个域(domain2.com(上的简单json文件"mails.json">

当用户提交他/她的电子邮件时,会调用一个JS脚本,其目的是检查电子邮件,并通过ajax GET和JSONP将表单的数据(此处为用户的电子邮件(发送到domain2.com上托管的mails.json文件。

Ajax调用domain2.com上托管的PHP脚本,该脚本应该获取用户的电子邮件并将其写入mails.json。此外,它应该向domain1.com发送一些关于成功或错误的消息,因为用户之前已经输入了他的电子邮件。

目前,电子邮件被发送并保存到mails.json,但我无法让我的PHP脚本将有关其执行的消息发送回domain1。感谢您的建议,请随时检查和修改下面的代码。

HTML表单托管在domain1.com

<div id="mail">
<form method="post" action="http://domain2.com/script.php" class="notifyme">
    <input type="email" value="" name="email" class="email" id="email" placeholder="Type your email here" required>
    <input type="submit" value="Get notified &raquo;" id="submit" name="submit">
    <div class="clear"></div>
</form>
<div class="errmail hide"><span class="uremail"></span> is not a valid email address. Try again :)</div>
<div class="error hide">Ouch :( <span class="uremail"></span> is already registered.</div>
<div class="success hide">Thank You :) <span class="uremail"></span> will be notified once we're ready.</div>
</div>

domain1.com上托管的Javascript文件

//jQuery Initialization
$(function(){
// Form
$('#submit').click(function () { //onSubmit
$('.error,.errmail,.success').hide();       
    var email = $('input[name=email]').val();
    //Email validation      
    var pattern = new RegExp(/^((([a-z]|'d|[!#'$%&''*'+'-'/='?'^_`{'|}~]|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])+('.([a-z]|'d|[!#'$%&''*'+'-'/='?'^_`{'|}~]|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])+)*)|(('x22)(((('x20|'x09)*('x0d'x0a))?('x20|'x09)+)?((['x01-'x08'x0b'x0c'x0e-'x1f'x7f]|'x21|['x23-'x5b]|['x5d-'x7e]|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])|(''(['x01-'x09'x0b'x0c'x0d-'x7f]|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF]))))*((('x20|'x09)*('x0d'x0a))?('x20|'x09)+)?('x22)))@((([a-z]|'d|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])|(([a-z]|'d|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])([a-z]|'d|-|'.|_|~|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])*([a-z]|'d|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])))'.)+(([a-z]|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])|(([a-z]|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])([a-z]|'d|-|'.|_|~|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])*([a-z]|['u00A0-'uD7FF'uF900-'uFDCF'uFDF0-'uFFEF])))'.?$/i);
    var valid = pattern.test(email);
    if (!valid && email !== 'undefined') {  
            $('.errmail').removeClass('hide').show('fast');
            if (!email){$('.uremail').append('This');}
            else{$('.uremail').append(email);}
            return false;
   } else {
        //start Ajax
        $.ajax({
            url: "http://domain2.com/script.php?json_callback=?",
            dataType: "jsonp text",       
            //GET method is used
            type: "GET",
            //pass the data         
            data: 'email=' + email,   
            //Do not cache the page
            cache: false,
            //Cross Domain
            crossDomain: true,
            //success
            success: function (html) {    
                //if list.php returned 1/true (send mail success)
               if (html==1) {                  
                $('.success').removeClass('hide').show('fast');$('.uremail').append(email);              
                } 
                else if (html == 0){
                $('.error').removeClass('hide').show('fast');$('.uremail').append(email); 
                }
                else { alert('Sorry, unexpected error. Please try again later.');  }           
            } 

        });
        }
        //cancel the submit button default behaviours
        return false;
    }); 
});

更新

托管在domain2.com上的PHP"script.PHP"文件

header('content-type: application/json; charset=utf-8');
$http_origin = $_SERVER['HTTP_ORIGIN'];
if ($http_origin == "http://domain1.com")
{  
    header('Access-Control-Allow-Origin: *');
}
$logname    = 'mails.json';
$logcontents = file_get_contents($logname);
//Retrieve form data.
$email = ($_GET['email']) ?$_GET['email'] : $_POST['email'];
//flag to indicate which method it uses. If POST set it to 1
if ($_POST) $post=1;

    if(strpos($logcontents,$email) !== false) {
    if ($_POST) {die('You are already subscribed.');}
    else{ $result = 0;echo $result; }
    } 
    else {
        $filecontents = $email.',';
        $fileopen = fopen($logname,'a+');
        $filewrite = fwrite($fileopen, json_encode($filecontents) );
        $fileclose = fclose($fileopen);
                if(!$fileopen or !$filewrite or !$fileclose) {
                    if ($_POST) {die('Error occured');}
                    else{ $result = 0;echo $result; }
                    } 
                else {
                    if ($_POST) {echo 'Your email has been added.';}
                    else{ $result = 1;echo $result; }
                    }
    }

在脚本开头设置正确的内容类型标头时,可以使用常规echo返回数据。您只需要先准备数据以匹配JSONP格式。类似这样的东西:

<? 
    // Some data to return
    $data = array(1, 2, 3, 4, 5, 6, 7, 8, 9);
    // JSONP response
    echo $_GET['callback'] . '('.json_encode($data).')';
?>
// For this example, the response would be something like this:
// jsonp1277656587731([1,2,3,4,5,6,7,8,9])

当您使用jQuery执行JSONP ajax请求时,jQuery将自动发送一个回调GET变量供您在服务器端使用。如示例所示。

一些附加阅读:http://www.geekality.net/2010/06/27/php-how-to-easily-provide-json-and-jsonp/

我过去也遇到过类似的问题,我确实尝试过在Web服务器(Apache2(上修改跨域设置,但没有成功。通过反复尝试,我从ajax调用的"url"参数中删除了主机名,这对我来说很有效。但我仍然没有完全理解。

你能从快速检查url参数吗

 http://domain2.com/script.php?json_callback=?

仅:

 script.php?json_callback=?.

可能存在其他web服务器配置设置。。但我只是想看看这是否有效。。。。