url 将 php 数据编码为 json 对象 [英] url encoding php data into json object

查看:32
本文介绍了url 将 php 数据编码为 json 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请阅读 - 这不仅仅是将 json_encode 从 php 转换为 javascript.

Please read - this isn't just simply doing json_encode from php to javascript.

我们的计费系统使用 Authorize.net.使用 Authorize.net API,我们在 PHP 中创建了一个令牌请求.请求中的数据传递客户信息、余额、帐单地址等 - 这些数据直接通过 PHP 发送.作为响应,我们得到一个要在 PHP 中处理的令牌 - 然后将该令牌嵌入到 HTML 表单输入中.

Our billing system uses Authorize.net. Using the Authorize.net API, in PHP we create a token request. The data in the request passes customer info, balance, billing address, etc - that data is sent directly with PHP. In response we get a token to be processed in PHP - and then that token is embedded into the HTML form input.

信用卡表单提交后,我们得到一个javascript json响应返回给表单,由其他JS函数处理.一切正常,直到我们的客户在公司名称中包含 &(即:Bar & Grill)

After the credit card form is submitted, we get a javascript json response back to the form to be processed by other JS functions. All works fine until we have a customer with the & in their company name (IE: Bar & Grill)

& 仅在返回表单的 json 响应中触发错误 - 特别是我们得到的错误是:unexpected end of json input 导致其余的要出错的脚本.

The & triggers an error only in the json response back to the form - specifically the error we get is: unexpected end of json input which causes the rest of the scripts to error out.

那么,问题是,PHP 令牌请求中的客户数据是否需要进行 urlencoded - 或者是否有特殊的方式来处理 json 响应?据我所知,授权只是在 json 响应中返回确切的客户数据 - 所以如果我们在前端对其进行 url 编码(在发送令牌请求之前),那么这是否意味着我们还需要对 json 响应进行 url 解码.

So, the issue is, does the customer data in the PHP token request need to be urlencoded - or is there a special way to handle the json response? From what I can tell, Authorize simply returns the exact customer data in the json response - so if we url encode it on the front end (before the token request is sent), then does that mean we also need to url decode the json response.

第一个问题是先有鸡还是先有蛋.

Its kind of a chicken and an egg which came first problem.

Authorize.net 令牌请求(在 PHP 中):

Authorize.net Token Request (in PHP):

    $customerData = new AnetAPICustomerDataType();
    $customerData->setType("business");
    $customerData->setId($ss['authCustID']);
    $customerData->setEmail($ii['cEmail']);
    
    // Set the Bill To info for new payment type
    $billTo = new AnetAPICustomerAddressType();
    $billTo->setFirstName($ii['cFirstName']);
    $billTo->setLastName($ii['cLastName']);
    $billTo->setCompany($ii['cName']);            // #1  <----- IE: "Bar & Grill"
    $billTo->setAddress($ii['cAddress']. " " .$ii['cAddress1']);
    $billTo->setCity($ii['cCity']);
    $billTo->setState($ii['cState']);
    $billTo->setZip($ii['cZip']);
    $billTo->setCountry("USA");

    // set shipping profile
    $shipTo = clone $billTo ;

    // extend billTop profile
    $billTo->setFaxNumber('8005551212') ;
    $billTo->setPhoneNumber($ii['cPhone']);
    
    //create a transaction
    $transactionRequestType = new AnetAPITransactionRequestType();
    $transactionRequestType->setTransactionType("authCaptureTransaction");
    $transactionRequestType->setAmount($ss['balance']);
    $transactionRequestType->setCustomer($customerData) ;
    $transactionRequestType->setOrder($order) ;
    $transactionRequestType->setBillTo($billTo) ;
    $transactionRequestType->setShipTo($shipTo) ;

    // Build transaction request
    $request = new AnetAPIGetHostedPaymentPageRequest();
    $request->setMerchantAuthentication($merchantAuthentication);
    $request->setRefId($refId);
    $request->setTransactionRequest($transactionRequestType);

//execute request
    $controller = new AnetControllerGetHostedPaymentPageController($request);
    $response = $controller->executeWithApiResponse(
etauthorizeapiconstantsANetEnvironment::PRODUCTION);  // SANDBOX or PRODUCTION
    
    $gToken=[] ;
    if (($response != null) && ($response->getMessages()->getResultCode() == "Ok")) {
        //echo $response->getToken()."
";
        $gToken["Error"]  = 0 ;
        $gToken["Token"] = $response->getToken() ;
    } else {
        //echo "ERROR :  Failed to get hosted payment page token
";
        $errorMessages = $response->getMessages()->getMessage();
        //echo "RESPONSE : " . $errorMessages[0]->getCode() . "  " .$errorMessages[0]->getText() . "
";
        $gToken["Error"]  = 1 ;
        $gToken["errMsg"] = $errorMessages[0]->getCode() . ":  " .$errorMessages[0]->getText() ;
    }

表单/JSON 响应处理程序:

Form/JSON response handler:

AuthorizeNetPopup.onReceiveCommunication = function (querystr) {
  var params = parseQueryString(querystr);
  //console.log(params) ;
  switch (params["action"]) {
    case "successfulSave":
      AuthorizeNetPopup.closePopup();
      break;
    case "cancel":
      AuthorizeNetPopup.closePopup();
      break;
    case "transactResponse":
      // 'response' is a string value
      // encode it as an object, to be passed to global function
      // that will decode it again for PHP
      console.log(params["response"]) ;
      var response = JSON.parse(params["response"]);  // #2 <--- ERROR: unexpected end of json input
      //var response = params["response"];
      httpReceipt(response) ;
      AuthorizeNetPopup.closePopup();
      break;
    case "resizeWindow":
      var w = parseInt(params["width"]);
      var h = parseInt(params["height"]);
      var ifrm = document.getElementById("iframeAuthorizeNet");
      ifrm.style.width = w.toString() + "px";
      ifrm.style.height = h.toString() + "px";
      centerPopup();
      break;
  }
};

我是在 #1(在 php 部分)对数据进行 url 编码还是在处理它之前对 json 响应进行 url 编码(在 #2) - 还是两者兼而有之?对如何处理这个问题非常困惑.我们是否需要对添加到令牌请求中的每个参数的数据进行编码 - 或者我们可以在提交之前对整个请求进行编码吗?无论通信的哪一端应用编码/解码,正确的编码/解码调用是什么?

Do I url encode data at #1 (in php section) or do I url encode the json response before processing it (at #2) - or both? Very confused on how to handle this. Do we need to encode the data of eachparameter being added to the token request - or can we just encode the entire request before its submitted? Regardless of which end of the communication gets encoding/decoding applied, what are the proper encoding/decoding calls?

为了说明流程:

  1. paymentPage.html ->PHP 生成token,将token嵌入到页面表单中,还有用于paymentPageFrame.html
  2. 的iframe
  3. paymentPageFrame.html ->iFrame 通信器页面,在 paymentPage.html 和 authorize.net 之间中继消息
  4. paymentPage.html ->javascript onReceiveCommunication 处理来自 paymentPageFrame.html 的消息
  1. paymentPage.html ->PHP generates token, embeds token into page form, also has iframe for paymentPageFrame.html
  2. paymentPageFrame.html -> iFrame communicator page, relays msgs between paymentPage.html and authorize.net
  3. paymentPage.html -> javascript onReceiveCommunication to process messages coming from paymentPageFrame.html

结果是 authorize.net 将 URL 字符串返回到 paymentPageFrame.html - 该字符串不是 urlencoded.然后将该字符串传递回父 onReceiveCommunication,此时它被自定义解析器解析:

Turns out that authorize.net is returning a URL string to paymentPageFrame.html - the string is not urlencoded. The string is then getting passed back to the parent onReceiveCommunication at which point its being parsed with a custom parser:

function parseQueryString(str) {
  var vars = [];
  var arr = str.split('&');
  var pair;
  for (var i = 0; i < arr.length; i++) {
    pair = arr[i].split('=');
    vars.push(pair[0]);
    vars[pair[0]] = unescape(pair[1]);
  }
  return vars;
}

此自定义解析器然后导致其中包含 & 的数据值(即:company":Bar & Grill")将名称一分为二,最终导致到 json 输入的无效/意外结尾.

This custom parser is then causing a data value that has the & in it (IE: "company" : "Bar & Grill") to split the name in half ultimately leading to the invalid/unexpected end of json input.

传递回 iFrame 的 string 依次传递给父对象是:

The string being passsed back to the iFrame, which in turn gets passed to the parent is:

action=transactResponse&response={"accountType":"Visa","accountNumber":"XXXX0623","transId":"62830720474","responseCode":"1","authorization":"185778","shipTo":{"firstName":"Bob","lastName":"Jones","company":"Backyard Bar & Grill","address":"123 Main St ","city":"Tampa","state":"FL","zip":"33606","country":"USA"},"orderDescription":"2020-12-01 bill for All Regions/All Sites","customerId":"1002-0","totalAmount":"1.50","orderInvoiceNumber":"11386-0","dateTime":"2/2/2021 4:57:53 PM","refId":"ref1612285039"}

既然字符串在父页面中,我正在尝试找出对其进行编码的最佳方法,然后对其进行解析,以便在数据值具有 & 时不会在解析时中断它(即:Backyard Bar & Grill)

Now that the string is in the parent page, I am trying to figure the best way to encode it then parse it so it won't break on parsing when a data value has & in it (IE: Backyard Bar & Grill)

到目前为止我正在尝试,但没有成功:

So far I am trying, without sucess:

var urlstr = encodeURIComponent(response) ;  // encode it first
var newUrl = new URLSearchParams(urlstr) ; // then proper parse it

但是当我尝试访问参数时,它返回空值:

But when I try to access the parameters, it returns null:

consoole.log(newUrl.get('action')) ;  
> null 

推荐答案

经过一番折腾,我终于写出了自己的解析器:

After much tinkering around, i finally wrote my own parser that:

A:如果存在,首先捕获响应JSON

A: if exists, capture the response JSON first

B:然后解析 URL 参数的其余部分:

B: then parse the remainder of the URL params:

C: 将所有参数和响应对象作为单个对象返回

C: return all params and response object as a single object

var str = 'action=transactResponse&response={"accountType":"Visa","accountNumber":"XXXX0623","transId":"62830720474","responseCode":"1","authorization":"185778","shipTo":{"firstName":"Preston","lastName":"Rolinger","company":"Backyard & Grill","address":"2808 W Foster Ave S ","city":"Tampa","state":"FL","zip":"33611","country":"USA"},"orderDescription":"2020-12-01 bill for All Regions/All Sites","customerId":"1002-0","totalAmount":"1.50","orderInvoiceNumber":"11386-0","dateTime":"2/2/2021 4:57:53 PM","refId":"ref1612285039"}&moreKey="other value"' ;

  function parseResponse(str) {
    var resInfo = [], res = {} ;
    if (str.match("&response=")) {
      var params = str.split("&response=") ; // leading params & response obj
      if (params[1].match("}&")) {
        resInfo = params[1].split("}&") ;  // splits off anything at end of obj
        res.response = JSON.parse(resInfo[0] + "}") ;  // add } to complete obj string again
      } else {
        res.response = JSON.parse(params[1]) ;  // else it already is the json string
      }
      if (resInfo[1]) {
        params = params[0]+ "&" +resInfo[1] ;  // join url params back together  
      } else {
        params = params[0] ;
      }
    }  else {
      params = str ;  // else the str has no "response" in it, process just params
    }
    params = new URLSearchParams(encodeURI(params)) ;  //encode then parse
    params.forEach(function(value, key) {
      res[key] = value ;
    }) ;

    return res ;
  }     
var response = parseResponse(str) ;
console.log(response) ;

这篇关于url 将 php 数据编码为 json 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆