0

我正在使用 rails 3.2 开发一个 webapp。我正在尝试为 Paymill 构建一个回调方法,用于捕获交易成功事件。

这是我的控制器。它非常简单,当我使用 CURL 或 Firefox 插件发出模拟 POST 请求并使用 Paymill 文档所述的 JSON 正文时,它工作正常。

不幸的是,当使用 Paymills 自己的测试脚本(用 PHP 制作)时,它失败了。

class Admin::TransactionsController < ActionController::Base

  def create
    transaction = Transaction.new
    transaction.client_id = params[:event][:event_resource][:client][:id]
    transaction.trans_id = params[:event][:event_resource][:id]
    transaction.amount = params[:event][:event_resource][:amount] 
    transaction.currency = params[:event][:event_resource][:currency] 
    transaction.save
    render :nothing => true
  end

end

这是文档说它将附加到回调事件的 JSON 正文:

{
    "event": {
        "event_type": "transaction.succeeded",
        "event_resource": {
            "id": "tran_d06aae1df72af329c39367cde9ed19",
            "amount": "12345",
            "origin_amount": 12345,
            "status": "closed",
            "description": "test paymill",
            "livemode": false,
            "refunds": null,
            "currency": "USD",
            "created_at": 1375457696,
            "updated_at": 1375457696,
            "response_code": 20000,
            "short_id": null,
            "is_fraud": false,
            "invoices": [],
            "app_id": null,
            "fees": [],
            "payment": {
                "id": "pay_46ee3be859eedb72d325adcb6",
                "type": "creditcard",
                "client": "client_d94e1e3efbc59073629df",
                "card_type": "visa",
                "country": null,
                "expire_month": "1",
                "expire_year": "2014",
                "card_holder": null,
                "last4": "1111",
                "created_at": 1375457695,
                "updated_at": 1375457696,
                "app_id": null
            },
            "client": {
                "id": "client_d941e3efbc59e073629df",
                "email": null,
                "description": null,
                "created_at": 1375457696,
                "updated_at": 1375457696,
                "app_id": null,
                "payment": [],
                "subscription": null
            },
            "preauthorization": null
        }
    }
}

当使用 PHP 测试脚本发出请求时,主体以这种形式到达,Rails 出现错误:

string(1712) ""{\n \"event\": {\n \"event_type\": \"transaction.succeeded\",\n \"event_resource\": {\n \"id\": \"tran_d06aae1f72af329c39367cde9ed19\",\n \"amount\": \"12345\",\n \"origin_amount\": 12345,\n \"status\": \"closed\",\n \"description\": \"test paymill\",\n \"livemode\": false,\n \"refunds\": null,\n \"currency\": \"USD\",\n \"created_at\": 1375457696,\n \"updated_at\": 1375457696,\n \"response_code\": 20000,\n \"short_id\": null,\n \"is_fraud\": false,\n \"invoices\": [],\n \"app_id\": null,\n \"fees\": [],\n \"payment\": {\n \"id\": \"pay_46ee3b85f9eedb72d325adcb6\",\n \"type\": \"creditcard\",\n \"client\": \"client_d941e3effbc59073629df\",\n \"card_type\": \"visa\",\n \"country\": null,\n \"expire_month\": \"1\",\n \"expire_year\": \"2014\",\n \"card_holder\": null,\n \"last4\": \"1111\",\n \"created_at\": 1375457695,\n \"updated_at\": 1375457696,\n \"app_id\": null\n },\n \"client\": {\n \"id\": \"client_d941e3efbc59073629df\",\n \"email\": null,\n \"description\": null,\n \"created_at\": 1375457696,\n \"updated_at\": 1375457696,\n \"app_id\": null,\n \"payment\": [],\n \"subscription\": null\n },\n \"preauthorization\": null\n }\n }\n}""

我从 Rails 得到的错误现在是这样的:

Error occurred while parsing request parameters

NoMethodError - undefined method `each' for #<String:0x007fc820a1fc08>:

到底是怎么回事?就像 Rails 把这个身体当作错误的文本对待?如果我从 PHP 中删除这一行(因此在发送之前不对正文进行 JSON 编码)它工作正常并且我没有收到任何错误。我的 create 方法是否为空也没关系。在调用此方法之前发生了什么?

json_encode($http_body);

感谢所有帮助!我很快就会开始哭泣。

4

1 回答 1

0

你从哪里得到测试脚本?我在这里的那个确实包含纯文本的正文,因此它不再需要 json 编码,这应该可以工作(将 < YOUR_TARGET_URL > 替换为您的 URL):

<?php
    $http_body = '{
        "event" : {
            "event_type" : "transaction.succeeded",
            "event_resource" :
                {"id":"__TRANSACTION_ID__","amount":"12345","origin_amount":12345,"status":"closed","description":"test paymill","livemode":false,"refunds":null,"currency":"SEK","created_at":1375457696,"updated_at":1375457696,"response_code":20000,"short_id":null,"is_fraud":false,"invoices":[],"app_id":null,"fees":[],"payment":{"id":"__PAYMNET_ID__","type":"creditcard","client":"__CLIENT_ID__","card_type":"visa","country":null,"expire_month":"1","expire_year":"2014","card_holder":null,"last4":"1111","created_at":1375457695,"updated_at":1375457696,"app_id":null},"client":{"id":"__CLIENT_ID__","email":null,"description":null,"created_at":1375457696,"updated_at":1375457696,"app_id":null,"payment":[],"subscription":null},"preauthorization":null}
        }
    }';

    $curl           = curl_init();

    $curlOpts = array(
        CURLOPT_URL => '',
        CURLOPT_RETURNTRANSFER  => true,
        CURLOPT_CUSTOMREQUEST   => 'POST',
        CURLOPT_SSL_VERIFYPEER  => false,
        CURLOPT_SSLVERSION      => 3,
        CURLOPT_TIMEOUT         => 60,
        CURLOPT_CONNECTTIMEOUT  => 60,
        CURLOPT_HTTPHEADER      => array('Content-type: application/json'),
        CURLOPT_PROTOCOLS       => CURLPROTO_HTTP | CURLPROTO_HTTPS,
        CURLOPT_MAXREDIRS       => 5
    );

    $curlOpts[CURLOPT_URL] = '<__YOUR_TARGET_URL__>';
    $curlOpts[CURLOPT_POSTFIELDS] = $http_body;
    curl_setopt_array($curl, $curlOpts);
    $result = curl_exec($curl);
    $responseInfo = curl_getinfo( $curl );

    var_dump($responseInfo);
    var_dump($result);
    curl_close($curl);

    exit;
于 2013-08-05T07:49:14.833 回答