摘要: php通过接口获取到json数据用
最近在接第三方支付公司的一个支付通道,其他过程比较顺利。最后在接通道发送的交易通知的接口时发生了一些问题。期间为解决办法,网上也扒了很多帖子,但都没有解决问题,故而记录一下,以便为遇到类似问题的小伙伴抛砖引玉。
关于交易通知的接口文档,通道(第三方支付公司)写的比较简单,截图如下:
OK,干就是了,代码如下:
1 2 3 4 5 6 7 | $post = file_get_contents("php://input");//接受通道参数 $this->logger->info('post=>'.$post);//打印日志,记录接受参数 $postResult = json_decode($post,true);//转数组 //如果转失败就报错 if(empty($postResult)){ return $this->notifyResponse("FAIL",'无效报文'); } |
之所以用file_get_contents(“php://input”)接收参数,是因为我接收的是同事写一半的代码(他已奔向他的星辰大海),我用的tp5.0的框架,测试用tp的$request->param()是收不到通道的参数的,后来问了下通道,说是采用的Content-type: application/json 形式的报文,具体的各种接收方式,大家可以自行百度。OK,继续调接口,日志如下:
1 2 | [2020-05-12 08:56:37] paynotify.INFO: post=>{"data":"TeqD8BXaWyzWJj3+bahWIffqG09r+RgEPiD74ck2CNsYxwMC9GtOnVChGN1i8ClRNlFBYlAq6o+w +wu4+cZe2dXHTVyad0mEEd8P5pknfy0Cf9hrPz"} {"logKey":"5eb9f445bda1a"} [2020-05-12 08:56:37] paynotify.INFO: 返回通道信息 {"retCode":"FAIL","retMessage":"无效报文"} {"logKey":"5eb9f445bda1a"} |
能接收到通道的请求报文,但是就是转数组失败。先确认自己的代码有没有问题,
1 2 3 4 5 6 7 8 | //$post = file_get_contents("php://input");//接受通道参数 //$this->logger->info('post=>'.$post);//打印日志,记录接受参数 $post = '{"data":"TeqD8BXaWyzWJj3+bahWIffqG09r+RgEPiD74ck2CNsYxwMC9GtOnVChGN1i8ClRNlFBYlAq6o+w +wu4+cZe2dXHTVyad0mEEd8P5pknfy0Cf9hrPz"}'; $postResult = json_decode($post,true);//转数组 //如果转失败就报错 if(empty($postResult)){ return $this->notifyResponse("FAIL",'无效报文'); } |
发现是OK的,可以解密。这就怪了,明明报文可以转成数组,为什么通道的请求过来时就不行呢?OK,可以用json_last_error()(返回int值)或者json_last_error_msg()(返回字符串)函数获取报错:
1 2 3 4 5 6 | $postResult = json_decode($post,true); $jsonError = json_last_error_msg(); $this->logger->info('json_error=>'.$jsonError); if(empty($postResult)){ return $this->notifyResponse("FAIL",'无效报文'); } |
日志:
1 2 3 | [2020-05-12 09:55:40] paynotify.INFO: post=>{"data":"TeqD8BXaWyzWJj3+bahWIffqG09r+RgEPiD74ck2CNsYxwMC9GtOnVChGN1i8ClRNlFBYlAq6o+w +wu4+cZe2dXHTVyad0mEEd8P5pknfy0Cf9hrPz"} {"logKey":"5eba021ce1fde"} [2020-05-12 09:55:40] paynotify.INFO: json_error=>Syntax error {"logKey":"5eba021ce1fde"} [2020-05-12 09:55:40] paynotify.INFO: 返回通道信息 {"retCode":"FAIL","retMessage":"无效报文"} {"logKey":"5eba021ce1fde"} |
那就查导致报4或者Syntax error的可能原因。网上查了很多相关这个报错的处理办法,都没有解决我的问题。然后自己模拟以json报文的方式请求自己也OK,因为通道用的是java,就把通道请求过来的加密报文给公司的java同事,让他们以json方式请求我的接口,发现也没问题。那问题就在通道那里,联系通道,通道说是不是因为报文的body里有回车符和换行符导致?好那就去除回车符、换行符:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $post = file_get_contents("php://input"); $this->logger->info('post=>'.$post); //$post = '{"data":"TeqD8BXaWyzWJj3+bahWIffqG09r+RgEPiD74ck2CNsYxwMC9GtOnVChGN1i8ClRNlFBYlAq6o+w +wu4+cZe2dXHTVyad0mEEd8P5pknfy0Cf9hrPz"}'; //$postArr = explode('"',$post);//这是中间想到的一个方法:报文的结构是固定的,可以用explode()函数把报文内容截出来~!~ //$this->logger->info('postArr',$postArr); $post = str_replace(array("\r\n", "\r", "\n"), "", $post); $postResult = json_decode($post,true); $jsonError = json_last_error_msg(); $this->logger->info('json_error=>'.$jsonError); if(empty($postResult)){ return $this->notifyResponse("FAIL",'无效报文'); }else{ $this->logger->info('postResult=>',$postResult); } |
日志:
1 2 3 | [2020-05-12 10:47:18] paynotify.INFO: post=>{"data":"TeqD8BXaWyzWJj3+bahWIffqG09r+RgEPiD74ck2CNsYxwMC9GtOnVChGN1i8ClRNlFBYlAq6o+w +wu4+cZe2dXHTVyad0mEEd8P5pknfy0Cf9hrPz"} {"logKey":"5eba0e36322d5"} [2020-05-12 10:47:18] paynotify.INFO: json_error=>No error {"logKey":"5eba0e36322d5"} [2020-05-12 10:47:18] paynotify.INFO: postResult=> {"data":"TeqD8BXaWyzWJj3+bahWIffqG09r+RgEPiD74ck2CNsYxwMC9GtOnVChGN1i8ClRNlFBYlAq6o+w +wu4+cZe2dXHTVyad0mEEd8P5pknfy0Cf9hrPz"} {"logKey":"5eba0e36322d5"} |
至此,问题解决。其实想想一开始,有想过可能是报文中一些符号的问题,但是当时只是用trim()去一下报文两边的空格,发现不行,就没再考虑回车符、换行符这边,后面就走偏了(T_T),外加跟公司java同事的通信一直很正常,就有点太相信通道的接口。