AopClient.php 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334
  1. <?php
  2. require_once 'AopEncrypt.php';
  3. require_once 'EncryptParseItem.php';
  4. require_once 'EncryptResponseData.php';
  5. require_once 'SignData.php';
  6. require_once 'AlipayConfig.php';
  7. class AopClient
  8. {
  9. //应用ID
  10. public $appId;
  11. //私钥文件路径
  12. public $rsaPrivateKeyFilePath;
  13. //私钥值
  14. public $rsaPrivateKey;
  15. //网关
  16. public $gatewayUrl = "https://openapi.alipay.com/gateway.do";
  17. //返回数据格式
  18. public $format = "json";
  19. //api版本
  20. public $apiVersion = "1.0";
  21. // 表单提交字符集编码
  22. public $postCharset = "UTF-8";
  23. //使用文件读取文件格式,请只传递该值
  24. public $alipayPublicKey = null;
  25. //使用读取字符串格式,请只传递该值
  26. public $alipayrsaPublicKey;
  27. public $debugInfo = false;
  28. private $fileCharset = "UTF-8";
  29. private $RESPONSE_SUFFIX = "_response";
  30. private $ERROR_RESPONSE = "error_response";
  31. private $SIGN_NODE_NAME = "sign";
  32. //加密XML节点名称
  33. private $ENCRYPT_XML_NODE_NAME = "response_encrypted";
  34. private $needEncrypt = false;
  35. //签名类型
  36. public $signType = "RSA";
  37. //加密密钥和类型
  38. public $encryptKey;
  39. public $encryptType = "AES";
  40. private $targetServiceUrl = "";
  41. protected $alipaySdkVersion = "alipay-sdk-PHP-4.19.101.ALL";
  42. function __construct() {
  43. //根据参数个数和参数类型 来做相应的判断
  44. if(func_num_args()==1 && func_get_arg(0) instanceof AlipayConfig){
  45. $config = func_get_arg(0);
  46. $this->appId = $config->getAppId();
  47. $this->format = $config->getFormat();
  48. $this->gatewayUrl = $config->getServerUrl();
  49. $this->signType = $config->getSignType();
  50. $this->postCharset = $config->getCharset();
  51. $this->rsaPrivateKey = $config->getPrivateKey();
  52. $this->alipayrsaPublicKey = $config->getAlipayPublicKey();
  53. }
  54. }
  55. public function generateSign($params, $signType = "RSA")
  56. {
  57. $params = array_filter($params);
  58. $params['sign_type'] = $signType;
  59. return $this->sign($this->getSignContent($params), $signType);
  60. }
  61. public function rsaSign($params, $signType = "RSA")
  62. {
  63. return $this->sign($this->getSignContent($params), $signType);
  64. }
  65. public function getSignContent($params)
  66. {
  67. ksort($params);
  68. unset($params['sign']);
  69. $stringToBeSigned = "";
  70. $i = 0;
  71. foreach ($params as $k => $v) {
  72. if ("@" != substr($v, 0, 1)) {
  73. // 转换成目标字符集
  74. $v = $this->characet($v, $this->postCharset);
  75. if ($i == 0) {
  76. $stringToBeSigned .= "$k" . "=" . "$v";
  77. } else {
  78. $stringToBeSigned .= "&" . "$k" . "=" . "$v";
  79. }
  80. $i++;
  81. }
  82. }
  83. unset ($k, $v);
  84. return $stringToBeSigned;
  85. }
  86. //此方法对value做urlencode
  87. public function getSignContentUrlencode($params)
  88. {
  89. ksort($params);
  90. $stringToBeSigned = "";
  91. $i = 0;
  92. foreach ($params as $k => $v) {
  93. if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
  94. // 转换成目标字符集
  95. $v = $this->characet($v, $this->postCharset);
  96. if ($i == 0) {
  97. $stringToBeSigned .= "$k" . "=" . urlencode($v);
  98. } else {
  99. $stringToBeSigned .= "&" . "$k" . "=" . urlencode($v);
  100. }
  101. $i++;
  102. }
  103. }
  104. unset ($k, $v);
  105. return $stringToBeSigned;
  106. }
  107. protected function sign($data, $signType = "RSA")
  108. {
  109. if ($this->checkEmpty($this->rsaPrivateKeyFilePath)) {
  110. $priKey = $this->rsaPrivateKey;
  111. $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
  112. wordwrap($priKey, 64, "\n", true) .
  113. "\n-----END RSA PRIVATE KEY-----";
  114. } else {
  115. $priKey = file_get_contents($this->rsaPrivateKeyFilePath);
  116. $res = openssl_get_privatekey($priKey);
  117. }
  118. ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置');
  119. var_dump('last_sign_data');
  120. var_dump($data);
  121. var_dump('last_sign_$res');
  122. var_dump($res);
  123. if ("RSA2" == $signType) {
  124. openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
  125. } else {
  126. openssl_sign($data, $sign, $res);
  127. }
  128. if (!$this->checkEmpty($this->rsaPrivateKeyFilePath)) {
  129. openssl_free_key($res);
  130. }
  131. $sign = base64_encode($sign);
  132. return $sign;
  133. }
  134. /**
  135. * RSA单独签名方法,未做字符串处理,字符串处理见getSignContent()
  136. * @param $data 待签名字符串
  137. * @param $privatekey 商户私钥,根据keyfromfile来判断是读取字符串还是读取文件,false:填写私钥字符串去回车和空格 true:填写私钥文件路径
  138. * @param $signType 签名方式,RSA:SHA1 RSA2:SHA256
  139. * @param $keyfromfile 私钥获取方式,读取字符串还是读文件
  140. * @return string
  141. */
  142. public function alonersaSign($data, $privatekey, $signType = "RSA", $keyfromfile = false)
  143. {
  144. if (!$keyfromfile) {
  145. $priKey = $privatekey;
  146. $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
  147. wordwrap($priKey, 64, "\n", true) .
  148. "\n-----END RSA PRIVATE KEY-----";
  149. } else {
  150. $priKey = file_get_contents($privatekey);
  151. $res = openssl_get_privatekey($priKey);
  152. }
  153. ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置');
  154. if ("RSA2" == $signType) {
  155. openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
  156. } else {
  157. openssl_sign($data, $sign, $res);
  158. }
  159. if ($keyfromfile) {
  160. openssl_free_key($res);
  161. }
  162. $sign = base64_encode($sign);
  163. return $sign;
  164. }
  165. protected function curl($url, $postFields = null)
  166. {
  167. $ch = curl_init();
  168. curl_setopt($ch, CURLOPT_URL, $url);
  169. curl_setopt($ch, CURLOPT_FAILONERROR, false);
  170. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  171. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  172. $postBodyString = "";
  173. $encodeArray = Array();
  174. $postMultipart = false;
  175. if (is_array($postFields) && 0 < count($postFields)) {
  176. foreach ($postFields as $k => $v) {
  177. if ("@" != substr($v, 0, 1)) //判断是不是文件上传
  178. {
  179. $postBodyString .= "$k=" . urlencode($this->characet($v, $this->postCharset)) . "&";
  180. $encodeArray[$k] = $this->characet($v, $this->postCharset);
  181. } else //文件上传用multipart/form-data,否则用www-form-urlencoded
  182. {
  183. $postMultipart = true;
  184. $encodeArray[$k] = new \CURLFile(substr($v, 1));
  185. }
  186. }
  187. unset ($k, $v);
  188. curl_setopt($ch, CURLOPT_POST, true);
  189. if ($postMultipart) {
  190. curl_setopt($ch, CURLOPT_POSTFIELDS, $encodeArray);
  191. } else {
  192. curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
  193. }
  194. }
  195. if (!$postMultipart) {
  196. $headers = array('content-type: application/x-www-form-urlencoded;charset=' . $this->postCharset);
  197. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  198. }
  199. $reponse = curl_exec($ch);
  200. if (curl_errno($ch)) {
  201. throw new \Exception(curl_error($ch), 0);
  202. } else {
  203. $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  204. if (200 !== $httpStatusCode) {
  205. throw new \Exception($reponse, $httpStatusCode);
  206. }
  207. }
  208. curl_close($ch);
  209. return $reponse;
  210. }
  211. protected function getMillisecond()
  212. {
  213. list($s1, $s2) = explode(' ', microtime());
  214. return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
  215. }
  216. protected function logCommunicationError($apiName, $requestUrl, $errorCode, $responseTxt)
  217. {
  218. $logData = array(
  219. date("Y-m-d H:i:s"),
  220. $apiName,
  221. $this->appId,
  222. PHP_OS,
  223. $this->alipaySdkVersion,
  224. $requestUrl,
  225. $errorCode,
  226. str_replace("\n", "", $responseTxt)
  227. );
  228. echo json_encode($logData);
  229. }
  230. /**
  231. * 生成用于调用收银台SDK的字符串
  232. * @param $request SDK接口的请求参数对象
  233. * @param $appAuthToken 三方应用授权token
  234. * @return string
  235. */
  236. public function sdkExecute($request, $appAuthToken = null)
  237. {
  238. $this->setupCharsets($request);
  239. $params['app_id'] = $this->appId;
  240. $params['method'] = $request->getApiMethodName();
  241. $params['format'] = $this->format;
  242. $params['sign_type'] = $this->signType;
  243. $params['timestamp'] = date("Y-m-d H:i:s");
  244. $params['timestamp'] = '2023-05-15 12:07:00';
  245. $params['alipay_sdk'] = $this->alipaySdkVersion;
  246. $params['charset'] = $this->postCharset;
  247. $version = $request->getApiVersion();
  248. $params['version'] = $this->checkEmpty($version) ? $this->apiVersion : $version;
  249. if ($notify_url = $request->getNotifyUrl()) {
  250. $params['notify_url'] = $notify_url;
  251. }
  252. $params['app_auth_token'] = $appAuthToken;
  253. $dict = $request->getApiParas();
  254. $params['biz_content'] = $dict['biz_content'];
  255. ksort($params);
  256. $params['sign'] = $this->generateSign($params, $this->signType);
  257. foreach ($params as &$value) {
  258. $value = $this->characet($value, $params['charset']);
  259. }
  260. return http_build_query($params);
  261. }
  262. /**
  263. * 页面提交执行方法
  264. * @param $request 跳转类接口的request
  265. * @param string $httpmethod 提交方式,两个值可选:post、get;
  266. * @param null $appAuthToken 三方应用授权token
  267. * @return 构建好的、签名后的最终跳转URL(GET)或String形式的form(POST)
  268. * @throws Exception
  269. */
  270. public function pageExecute($request, $httpmethod = "POST", $appAuthToken = null)
  271. {
  272. $this->setupCharsets($request);
  273. if (strcasecmp($this->fileCharset, $this->postCharset)) {
  274. // writeLog("本地文件字符集编码与表单提交编码不一致,请务必设置成一样,属性名分别为postCharset!");
  275. throw new \Exception("文件编码:[" . $this->fileCharset . "] 与表单提交编码:[" . $this->postCharset . "]两者不一致!");
  276. }
  277. $iv = null;
  278. if (!$this->checkEmpty($request->getApiVersion())) {
  279. $iv = $request->getApiVersion();
  280. } else {
  281. $iv = $this->apiVersion;
  282. }
  283. //组装系统参数
  284. $sysParams["app_id"] = $this->appId;
  285. $sysParams["version"] = $iv;
  286. $sysParams["format"] = $this->format;
  287. $sysParams["sign_type"] = $this->signType;
  288. $sysParams["method"] = $request->getApiMethodName();
  289. $sysParams["timestamp"] = date("Y-m-d H:i:s");
  290. $sysParams["alipay_sdk"] = $this->alipaySdkVersion;
  291. if (!$this->checkEmpty($request->getTerminalType())) {
  292. $sysParams["terminal_type"] = $request->getTerminalType();
  293. }
  294. if (!$this->checkEmpty($request->getTerminalInfo())) {
  295. $sysParams["terminal_info"] = $request->getTerminalInfo();
  296. }
  297. if (!$this->checkEmpty($request->getProdCode())) {
  298. $sysParams["prod_code"] = $request->getProdCode();
  299. }
  300. if (!$this->checkEmpty($request->getNotifyUrl())) {
  301. $sysParams["notify_url"] = $request->getNotifyUrl();
  302. }
  303. if (!$this->checkEmpty($request->getReturnUrl())) {
  304. $sysParams["return_url"] = $request->getReturnUrl();
  305. }
  306. $sysParams["charset"] = $this->postCharset;
  307. if (!$this->checkEmpty($appAuthToken)) {
  308. $sysParams["app_auth_token"] = $appAuthToken;
  309. }
  310. //获取业务参数
  311. $apiParams = $request->getApiParas();
  312. if (method_exists($request, "getNeedEncrypt") && $request->getNeedEncrypt()) {
  313. $sysParams["encrypt_type"] = $this->encryptType;
  314. if ($this->checkEmpty($apiParams['biz_content'])) {
  315. throw new \Exception(" api request Fail! The reason : encrypt request is not supperted!");
  316. }
  317. if ($this->checkEmpty($this->encryptKey) || $this->checkEmpty($this->encryptType)) {
  318. throw new \Exception(" encryptType and encryptKey must not null! ");
  319. }
  320. if ("AES" != $this->encryptType) {
  321. throw new \Exception("加密类型只支持AES");
  322. }
  323. // 执行加密
  324. $enCryptContent = encrypt_new($apiParams['biz_content'], $this->encryptKey);
  325. $apiParams['biz_content'] = $enCryptContent;
  326. }
  327. //print_r($apiParams);
  328. $totalParams = array_merge($apiParams, $sysParams);
  329. //待签名字符串
  330. $preSignStr = $this->getSignContent($totalParams);
  331. //签名
  332. $totalParams["sign"] = $this->generateSign($totalParams, $this->signType);
  333. if ("GET" == strtoupper($httpmethod)) {
  334. //value做urlencode
  335. $preString = $this->getSignContentUrlencode($totalParams);
  336. //拼接GET请求串
  337. $requestUrl = $this->gatewayUrl . "?" . $preString;
  338. return $requestUrl;
  339. } else {
  340. //拼接表单字符串
  341. return $this->buildRequestForm($totalParams);
  342. }
  343. }
  344. /**
  345. * 建立请求,以表单HTML形式构造(默认)
  346. * @param $para_temp 请求参数数组
  347. * @return 提交表单HTML文本
  348. */
  349. protected function buildRequestForm($para_temp)
  350. {
  351. $sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='" . $this->gatewayUrl . "?charset=" . trim($this->postCharset) . "' method='POST'>";
  352. while (list ($key, $val) = $this->fun_adm_each($para_temp)) {
  353. if (false === $this->checkEmpty($val)) {
  354. //$val = $this->characet($val, $this->postCharset);
  355. $val = str_replace("'", "&apos;", $val);
  356. //$val = str_replace("\"","&quot;",$val);
  357. $sHtml .= "<input type='hidden' name='" . $key . "' value='" . $val . "'/>";
  358. }
  359. }
  360. //submit按钮控件请不要含有name属性
  361. $sHtml = $sHtml . "<input type='submit' value='ok' style='display:none;''></form>";
  362. $sHtml = $sHtml . "<script>document.forms['alipaysubmit'].submit();</script>";
  363. return $sHtml;
  364. }
  365. protected function fun_adm_each(&$array)
  366. {
  367. $res = array();
  368. $key = key($array);
  369. if ($key !== null) {
  370. next($array);
  371. $res[1] = $res['value'] = $array[$key];
  372. $res[0] = $res['key'] = $key;
  373. } else {
  374. $res = false;
  375. }
  376. return $res;
  377. }
  378. public function execute($request, $authToken = null, $appInfoAuthtoken = null, $targetAppId = null)
  379. {
  380. $this->setupCharsets($request);
  381. //如果两者编码不一致,会出现签名验签或者乱码
  382. if (strcasecmp($this->fileCharset, $this->postCharset)) {
  383. // writeLog("本地文件字符集编码与表单提交编码不一致,请务必设置成一样,属性名分别为postCharset!");
  384. throw new \Exception("文件编码:[" . $this->fileCharset . "] 与表单提交编码:[" . $this->postCharset . "]两者不一致!");
  385. }
  386. $iv = null;
  387. if (!$this->checkEmpty($request->getApiVersion())) {
  388. $iv = $request->getApiVersion();
  389. } else {
  390. $iv = $this->apiVersion;
  391. }
  392. //组装系统参数
  393. $sysParams["app_id"] = $this->appId;
  394. $sysParams["version"] = $iv;
  395. $sysParams["format"] = $this->format;
  396. $sysParams["sign_type"] = $this->signType;
  397. $sysParams["method"] = $request->getApiMethodName();
  398. $sysParams["timestamp"] = date("Y-m-d H:i:s");
  399. if (!$this->checkEmpty($authToken)) {
  400. $sysParams["auth_token"] = $authToken;
  401. }
  402. $sysParams["alipay_sdk"] = $this->alipaySdkVersion;
  403. if (!$this->checkEmpty($request->getTerminalType())) {
  404. $sysParams["terminal_type"] = $request->getTerminalType();
  405. }
  406. if (!$this->checkEmpty($request->getTerminalInfo())) {
  407. $sysParams["terminal_info"] = $request->getTerminalInfo();
  408. }
  409. if (!$this->checkEmpty($request->getProdCode())) {
  410. $sysParams["prod_code"] = $request->getProdCode();
  411. }
  412. if (!$this->checkEmpty($request->getNotifyUrl())) {
  413. $sysParams["notify_url"] = $request->getNotifyUrl();
  414. }
  415. $sysParams["charset"] = $this->postCharset;
  416. if (!$this->checkEmpty($appInfoAuthtoken)) {
  417. $sysParams["app_auth_token"] = $appInfoAuthtoken;
  418. }
  419. if (!$this->checkEmpty($targetAppId)) {
  420. $sysParams["target_app_id"] = $targetAppId;
  421. }
  422. if (!$this->checkEmpty($this->targetServiceUrl)) {
  423. $sysParams["ws_service_url"] = $this->targetServiceUrl;
  424. }
  425. //获取业务参数
  426. $apiParams = $request->getApiParas();
  427. if (method_exists($request, "getNeedEncrypt") && $request->getNeedEncrypt()) {
  428. $sysParams["encrypt_type"] = $this->encryptType;
  429. if ($this->checkEmpty($apiParams['biz_content'])) {
  430. throw new \Exception(" api request Fail! The reason : encrypt request is not supperted!");
  431. }
  432. if ($this->checkEmpty($this->encryptKey) || $this->checkEmpty($this->encryptType)) {
  433. throw new \Exception(" encryptType and encryptKey must not null! ");
  434. }
  435. if ("AES" != $this->encryptType) {
  436. throw new \Exception("加密类型只支持AES");
  437. }
  438. // 执行加密
  439. $enCryptContent = encrypt_new($apiParams['biz_content'], $this->encryptKey);
  440. $apiParams['biz_content'] = $enCryptContent;
  441. }
  442. //签名
  443. $sysParams["sign"] = $this->generateSign(array_merge($apiParams, $sysParams), $this->signType);
  444. var_dump('before_sign:'.$this->signType.' after_sign:'.$sysParams["sign"]);var_dump(array_merge($apiParams, $sysParams));
  445. //系统参数放入GET请求串
  446. $requestUrl = $this->gatewayUrl . "?";
  447. foreach ($sysParams as $sysParamKey => $sysParamValue) {
  448. if ($sysParamValue != null) {
  449. $requestUrl .= "$sysParamKey=" . urlencode($this->characet($sysParamValue, $this->postCharset)) . "&";
  450. }
  451. }
  452. $requestUrl = substr($requestUrl, 0, -1);
  453. //发起HTTP请求
  454. try {
  455. $resp = $this->curl($requestUrl, $apiParams);
  456. } catch (Exception $e) {
  457. $this->logCommunicationError($sysParams["method"], $requestUrl, "HTTP_ERROR_" . $e->getCode(), $e->getMessage());
  458. return false;
  459. }
  460. print('$resp:'.$requestUrl);
  461. var_dump($apiParams);
  462. print($resp);
  463. //解析AOP返回结果
  464. $respWellFormed = false;
  465. // 将返回结果转换本地文件编码
  466. $r = iconv($this->postCharset, $this->fileCharset . "//IGNORE", $resp);
  467. $signData = null;
  468. if ("json" == strtolower($this->format)) {
  469. $respObject = json_decode($r);
  470. if (null !== $respObject) {
  471. $respWellFormed = true;
  472. $signData = $this->parserJSONSignData($request, $resp, $respObject);
  473. }
  474. } else if ("xml" == $this->format) {
  475. $disableLibxmlEntityLoader = libxml_disable_entity_loader(true);
  476. $respObject = @ simplexml_load_string($resp);
  477. if (false !== $respObject) {
  478. $respWellFormed = true;
  479. $signData = $this->parserXMLSignData($request, $resp);
  480. }
  481. libxml_disable_entity_loader($disableLibxmlEntityLoader);
  482. }
  483. //返回的HTTP文本不是标准JSON或者XML,记下错误日志
  484. if (false === $respWellFormed) {
  485. var_dump(333);
  486. $this->logCommunicationError($sysParams["method"], $requestUrl, "HTTP_RESPONSE_NOT_WELL_FORMED", $resp);
  487. return false;
  488. }
  489. // 验签
  490. $this->checkResponseSign($request, $signData, $resp, $respObject);
  491. // 解密
  492. if (method_exists($request, "getNeedEncrypt") && $request->getNeedEncrypt()) {
  493. if ("json" == strtolower($this->format)) {
  494. $resp = $this->encryptJSONSignSource($request, $resp);
  495. // 将返回结果转换本地文件编码
  496. $r = iconv($this->postCharset, $this->fileCharset . "//IGNORE", $resp);
  497. $respObject = json_decode($r);
  498. } else {
  499. $resp = $this->encryptXMLSignSource($request, $resp);
  500. $r = iconv($this->postCharset, $this->fileCharset . "//IGNORE", $resp);
  501. $disableLibxmlEntityLoader = libxml_disable_entity_loader(true);
  502. $respObject = @ simplexml_load_string($r);
  503. libxml_disable_entity_loader($disableLibxmlEntityLoader);
  504. }
  505. }
  506. return $respObject;
  507. }
  508. /**
  509. * 转换字符集编码
  510. * @param $data
  511. * @param $targetCharset
  512. * @return string
  513. */
  514. function characet($data, $targetCharset)
  515. {
  516. if (!empty($data)) {
  517. $fileType = $this->fileCharset;
  518. if (strcasecmp($fileType, $targetCharset) != 0) {
  519. $data = mb_convert_encoding($data, $targetCharset, $fileType);
  520. // $data = iconv($fileType, $targetCharset.'//IGNORE', $data);
  521. }
  522. }
  523. return $data;
  524. }
  525. public function exec($paramsArray)
  526. {
  527. if (!isset ($paramsArray["method"])) {
  528. trigger_error("No api name passed");
  529. }
  530. $inflector = new LtInflector;
  531. $inflector->conf["separator"] = ".";
  532. $requestClassName = ucfirst($inflector->camelize(substr($paramsArray["method"], 7))) . "Request";
  533. if (!class_exists($requestClassName)) {
  534. trigger_error("No such api: " . $paramsArray["method"]);
  535. }
  536. $session = isset ($paramsArray["session"]) ? $paramsArray["session"] : null;
  537. $req = new $requestClassName;
  538. foreach ($paramsArray as $paraKey => $paraValue) {
  539. $inflector->conf["separator"] = "_";
  540. $setterMethodName = $inflector->camelize($paraKey);
  541. $inflector->conf["separator"] = ".";
  542. $setterMethodName = "set" . $inflector->camelize($setterMethodName);
  543. if (method_exists($req, $setterMethodName)) {
  544. $req->$setterMethodName ($paraValue);
  545. }
  546. }
  547. return $this->execute($req, $session);
  548. }
  549. /**
  550. * 校验$value是否非空
  551. * if not set ,return true;
  552. * if is null , return true;
  553. **/
  554. protected function checkEmpty($value)
  555. {
  556. if (!isset($value))
  557. return true;
  558. if ($value === null)
  559. return true;
  560. if (trim($value) === "")
  561. return true;
  562. return false;
  563. }
  564. /** rsaCheckV1 & rsaCheckV2
  565. * 验证签名
  566. * 在使用本方法前,必须初始化AopClient且传入公钥参数。
  567. * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。
  568. **/
  569. public function rsaCheckV1($params, $rsaPublicKeyFilePath, $signType = 'RSA')
  570. {
  571. $sign = $params['sign'];
  572. unset($params['sign']);
  573. unset($params['sign_type']);
  574. return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath, $signType);
  575. }
  576. public function rsaCheckV2($params, $rsaPublicKeyFilePath, $signType = 'RSA')
  577. {
  578. $sign = $params['sign'];
  579. unset($params['sign']);
  580. return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath, $signType);
  581. }
  582. function verify($data, $sign, $rsaPublicKeyFilePath, $signType = 'RSA')
  583. {
  584. if ($this->checkEmpty($this->alipayPublicKey)) {
  585. $pubKey = $this->alipayrsaPublicKey;
  586. $res = "-----BEGIN PUBLIC KEY-----\n" .
  587. wordwrap($pubKey, 64, "\n", true) .
  588. "\n-----END PUBLIC KEY-----";
  589. } else {
  590. //读取公钥文件
  591. $pubKey = file_get_contents($rsaPublicKeyFilePath);
  592. //转换为openssl格式密钥
  593. $res = openssl_get_publickey($pubKey);
  594. }
  595. ($res) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
  596. //调用openssl内置方法验签,返回bool值
  597. $result = FALSE;
  598. if ("RSA2" == $signType) {
  599. $result = (openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256) === 1);
  600. } else {
  601. $result = (openssl_verify($data, base64_decode($sign), $res) === 1);
  602. }
  603. if (!$this->checkEmpty($this->alipayPublicKey)) {
  604. //释放资源
  605. openssl_free_key($res);
  606. }
  607. return $result;
  608. }
  609. /**
  610. * 在使用本方法前,必须初始化AopClient且传入公私钥参数。
  611. * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。
  612. **/
  613. public function checkSignAndDecrypt($params, $rsaPublicKeyPem, $rsaPrivateKeyPem, $isCheckSign, $isDecrypt, $signType = 'RSA')
  614. {
  615. $charset = $params['charset'];
  616. $bizContent = $params['biz_content'];
  617. if ($isCheckSign) {
  618. if (!$this->rsaCheckV2($params, $rsaPublicKeyPem, $signType)) {
  619. echo "<br/>checkSign failure<br/>";
  620. exit;
  621. }
  622. }
  623. if ($isDecrypt) {
  624. return $this->rsaDecrypt($bizContent, $rsaPrivateKeyPem, $charset);
  625. }
  626. return $bizContent;
  627. }
  628. /**
  629. * 在使用本方法前,必须初始化AopClient且传入公私钥参数。
  630. * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。
  631. **/
  632. public function encryptAndSign($bizContent, $rsaPublicKeyPem, $rsaPrivateKeyPem, $charset, $isEncrypt, $isSign, $signType = 'RSA')
  633. {
  634. // 加密,并签名
  635. if ($isEncrypt && $isSign) {
  636. $encrypted = $this->rsaEncrypt($bizContent, $rsaPublicKeyPem, $charset);
  637. $sign = $this->sign($encrypted, $signType);
  638. $response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$encrypted</response><encryption_type>RSA</encryption_type><sign>$sign</sign><sign_type>$signType</sign_type></alipay>";
  639. return $response;
  640. }
  641. // 加密,不签名
  642. if ($isEncrypt && (!$isSign)) {
  643. $encrypted = $this->rsaEncrypt($bizContent, $rsaPublicKeyPem, $charset);
  644. $response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$encrypted</response><encryption_type>$signType</encryption_type></alipay>";
  645. return $response;
  646. }
  647. // 不加密,但签名
  648. if ((!$isEncrypt) && $isSign) {
  649. $sign = $this->sign($bizContent, $signType);
  650. $response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$bizContent</response><sign>$sign</sign><sign_type>$signType</sign_type></alipay>";
  651. return $response;
  652. }
  653. // 不加密,不签名
  654. $response = "<?xml version=\"1.0\" encoding=\"$charset\"?>$bizContent";
  655. return $response;
  656. }
  657. /**
  658. * 在使用本方法前,必须初始化AopClient且传入公私钥参数。
  659. * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。
  660. **/
  661. public function rsaEncrypt($data, $rsaPublicKeyFilePath, $charset)
  662. {
  663. if ($this->checkEmpty($this->alipayPublicKey)) {
  664. //读取字符串
  665. $pubKey = $this->alipayrsaPublicKey;
  666. $res = "-----BEGIN PUBLIC KEY-----\n" .
  667. wordwrap($pubKey, 64, "\n", true) .
  668. "\n-----END PUBLIC KEY-----";
  669. } else {
  670. //读取公钥文件
  671. $pubKey = file_get_contents($rsaPublicKeyFilePath);
  672. //转换为openssl格式密钥
  673. $res = openssl_get_publickey($pubKey);
  674. }
  675. ($res) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
  676. $blocks = $this->splitCN($data, 0, 30, $charset);
  677. $chrtext = null;
  678. $encodes = array();
  679. foreach ($blocks as $n => $block) {
  680. if (!openssl_public_encrypt($block, $chrtext , $res)) {
  681. echo "<br/>" . openssl_error_string() . "<br/>";
  682. }
  683. $encodes[] = $chrtext ;
  684. }
  685. $chrtext = implode(",", $encodes);
  686. return base64_encode($chrtext);
  687. }
  688. /**
  689. * 在使用本方法前,必须初始化AopClient且传入公私钥参数。
  690. * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。
  691. **/
  692. public function rsaDecrypt($data, $rsaPrivateKeyPem, $charset)
  693. {
  694. if ($this->checkEmpty($this->rsaPrivateKeyFilePath)) {
  695. //读字符串
  696. $priKey = $this->rsaPrivateKey;
  697. $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
  698. wordwrap($priKey, 64, "\n", true) .
  699. "\n-----END RSA PRIVATE KEY-----";
  700. } else {
  701. $priKey = file_get_contents($this->rsaPrivateKeyFilePath);
  702. $res = openssl_get_privatekey($priKey);
  703. }
  704. ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置');
  705. //转换为openssl格式密钥
  706. $decodes = explode(',', $data);
  707. $strnull = "";
  708. $dcyCont = "";
  709. foreach ($decodes as $n => $decode) {
  710. if (!openssl_private_decrypt($decode, $dcyCont, $res)) {
  711. echo "<br/>" . openssl_error_string() . "<br/>";
  712. }
  713. $strnull .= $dcyCont;
  714. }
  715. return $strnull;
  716. }
  717. function splitCN($cont, $n = 0, $subnum, $charset)
  718. {
  719. //$len = strlen($cont) / 3;
  720. $arrr = array();
  721. for ($i = $n; $i < strlen($cont); $i += $subnum) {
  722. $res = $this->subCNchar($cont, $i, $subnum, $charset);
  723. if (!empty ($res)) {
  724. $arrr[] = $res;
  725. }
  726. }
  727. return $arrr;
  728. }
  729. function subCNchar($str, $start = 0, $length, $charset = "gbk")
  730. {
  731. if (strlen($str) <= $length) {
  732. return $str;
  733. }
  734. $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
  735. $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
  736. $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  737. $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
  738. preg_match_all($re[$charset], $str, $match);
  739. $slice = join("", array_slice($match[0], $start, $length));
  740. return $slice;
  741. }
  742. function parserResponseSubCode($request, $responseContent, $respObject, $format)
  743. {
  744. if ("json" == strtolower($format)) {
  745. $apiName = $request->getApiMethodName();
  746. $rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
  747. $errorNodeName = $this->ERROR_RESPONSE;
  748. $rootIndex = strpos($responseContent, $rootNodeName);
  749. $errorIndex = strpos($responseContent, $errorNodeName);
  750. if ($rootIndex > 0) {
  751. // 内部节点对象
  752. $rInnerObject = $respObject->$rootNodeName;
  753. } elseif ($errorIndex > 0) {
  754. $rInnerObject = $respObject->$errorNodeName;
  755. } else {
  756. return null;
  757. }
  758. // 存在属性则返回对应值
  759. if (isset($rInnerObject->sub_code)) {
  760. return $rInnerObject->sub_code;
  761. } else {
  762. return null;
  763. }
  764. } elseif ("xml" == $format) {
  765. // xml格式sub_code在同一层级
  766. return $respObject->sub_code;
  767. }
  768. }
  769. function parserJSONSignData($request, $responseContent, $responseJSON)
  770. {
  771. $signData = new SignData();
  772. $signData->sign = $this->parserJSONSign($responseJSON);
  773. $signData->signSourceData = $this->parserJSONSignSource($request, $responseContent);
  774. return $signData;
  775. }
  776. function parserJSONSignSource($request, $responseContent)
  777. {
  778. $apiName = $request->getApiMethodName();
  779. $rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
  780. $rootIndex = strpos($responseContent, $rootNodeName);
  781. $errorIndex = strpos($responseContent, $this->ERROR_RESPONSE);
  782. if ($rootIndex > 0) {
  783. return $this->parserJSONSource($responseContent, $rootNodeName, $rootIndex);
  784. } else if ($errorIndex > 0) {
  785. return $this->parserJSONSource($responseContent, $this->ERROR_RESPONSE, $errorIndex);
  786. } else {
  787. return null;
  788. }
  789. }
  790. function parserJSONSource($responseContent, $nodeName, $nodeIndex)
  791. {
  792. $signDataStartIndex = $nodeIndex + strlen($nodeName) + 2;
  793. $signIndex = strrpos($responseContent, "\"" . $this->SIGN_NODE_NAME . "\"");
  794. // 签名前-逗号
  795. $signDataEndIndex = $signIndex - 1;
  796. $indexLen = $signDataEndIndex - $signDataStartIndex;
  797. if ($indexLen < 0) {
  798. return null;
  799. }
  800. return substr($responseContent, $signDataStartIndex, $indexLen);
  801. }
  802. function parserJSONSign($responseJSon)
  803. {
  804. return $responseJSon->sign;
  805. }
  806. function parserXMLSignData($request, $responseContent)
  807. {
  808. $signData = new SignData();
  809. $signData->sign = $this->parserXMLSign($responseContent);
  810. $signData->signSourceData = $this->parserXMLSignSource($request, $responseContent);
  811. return $signData;
  812. }
  813. function parserXMLSignSource($request, $responseContent)
  814. {
  815. $apiName = $request->getApiMethodName();
  816. $rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
  817. $rootIndex = strpos($responseContent, $rootNodeName);
  818. $errorIndex = strpos($responseContent, $this->ERROR_RESPONSE);
  819. // $this->echoDebug("<br/>rootNodeName:" . $rootNodeName);
  820. // $this->echoDebug("<br/> responseContent:<xmp>" . $responseContent . "</xmp>");
  821. if ($rootIndex > 0) {
  822. return $this->parserXMLSource($responseContent, $rootNodeName, $rootIndex);
  823. } else if ($errorIndex > 0) {
  824. return $this->parserXMLSource($responseContent, $this->ERROR_RESPONSE, $errorIndex);
  825. } else {
  826. return null;
  827. }
  828. }
  829. function parserXMLSource($responseContent, $nodeName, $nodeIndex)
  830. {
  831. $signDataStartIndex = $nodeIndex + strlen($nodeName) + 1;
  832. $signIndex = strrpos($responseContent, "<" . $this->SIGN_NODE_NAME . ">");
  833. // 签名前-逗号
  834. $signDataEndIndex = $signIndex - 1;
  835. $indexLen = $signDataEndIndex - $signDataStartIndex + 1;
  836. if ($indexLen < 0) {
  837. return null;
  838. }
  839. return substr($responseContent, $signDataStartIndex, $indexLen);
  840. }
  841. function parserXMLSign($responseContent)
  842. {
  843. $signNodeName = "<" . $this->SIGN_NODE_NAME . ">";
  844. $signEndNodeName = "</" . $this->SIGN_NODE_NAME . ">";
  845. $indexOfSignNode = strpos($responseContent, $signNodeName);
  846. $indexOfSignEndNode = strpos($responseContent, $signEndNodeName);
  847. if ($indexOfSignNode < 0 || $indexOfSignEndNode < 0) {
  848. return null;
  849. }
  850. $nodeIndex = ($indexOfSignNode + strlen($signNodeName));
  851. $indexLen = $indexOfSignEndNode - $nodeIndex;
  852. if ($indexLen < 0) {
  853. return null;
  854. }
  855. // 签名
  856. return substr($responseContent, $nodeIndex, $indexLen);
  857. }
  858. /**
  859. * 验签
  860. * @param $request
  861. * @param $signData
  862. * @param $resp
  863. * @param $respObject
  864. * @throws Exception
  865. */
  866. public function checkResponseSign($request, $signData, $resp, $respObject)
  867. {
  868. if (!$this->checkEmpty($this->alipayPublicKey) || !$this->checkEmpty($this->alipayrsaPublicKey)) {
  869. if ($signData == null || $this->checkEmpty($signData->sign) || $this->checkEmpty($signData->signSourceData)) {
  870. throw new \Exception(" check sign Fail! The reason : signData is Empty");
  871. }
  872. // 获取结果sub_code
  873. $responseSubCode = $this->parserResponseSubCode($request, $resp, $respObject, $this->format);
  874. if (!$this->checkEmpty($responseSubCode) || ($this->checkEmpty($responseSubCode) && !$this->checkEmpty($signData->sign))) {
  875. $checkResult = $this->verify($signData->signSourceData, $signData->sign, $this->alipayPublicKey, $this->signType);
  876. if (!$checkResult) {
  877. if (strpos($signData->signSourceData, "\\/") > 0) {
  878. $signData->signSourceData = str_replace("\\/", "/", $signData->signSourceData);
  879. $checkResult = $this->verify($signData->signSourceData, $signData->sign, $this->alipayPublicKey, $this->signType);
  880. if (!$checkResult) {
  881. throw new \Exception("check sign Fail! [sign=" . $signData->sign . ", signSourceData=" . $signData->signSourceData . "]");
  882. }
  883. } else {
  884. throw new \Exception("check sign Fail! [sign=" . $signData->sign . ", signSourceData=" . $signData->signSourceData . "]");
  885. }
  886. }
  887. }
  888. }
  889. }
  890. private function setupCharsets($request)
  891. {
  892. if ($this->checkEmpty($this->postCharset)) {
  893. $this->postCharset = 'UTF-8';
  894. }
  895. $str = preg_match('/[\x80-\xff]/', $this->appId) ? $this->appId : print_r($request, true);
  896. $this->fileCharset = mb_detect_encoding($str, "UTF-8, GBK") == 'UTF-8' ? 'UTF-8' : 'GBK';
  897. }
  898. // 获取加密内容
  899. private function encryptJSONSignSource($request, $responseContent)
  900. {
  901. $parsetItem = $this->parserEncryptJSONSignSource($request, $responseContent);
  902. $bodyIndexContent = substr($responseContent, 0, $parsetItem->startIndex);
  903. $bodyEndContent = substr($responseContent, $parsetItem->endIndex, strlen($responseContent) + 1 - $parsetItem->endIndex);
  904. $bizContent = decrypt($parsetItem->encryptContent, $this->encryptKey);
  905. return $bodyIndexContent . $bizContent . $bodyEndContent;
  906. }
  907. private function parserEncryptJSONSignSource($request, $responseContent)
  908. {
  909. $apiName = $request->getApiMethodName();
  910. $rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
  911. $rootIndex = strpos($responseContent, $rootNodeName);
  912. $errorIndex = strpos($responseContent, $this->ERROR_RESPONSE);
  913. if ($rootIndex > 0) {
  914. return $this->parserEncryptJSONItem($responseContent, $rootNodeName, $rootIndex);
  915. } else if ($errorIndex > 0) {
  916. return $this->parserEncryptJSONItem($responseContent, $this->ERROR_RESPONSE, $errorIndex);
  917. } else {
  918. return null;
  919. }
  920. }
  921. private function parserEncryptJSONItem($responseContent, $nodeName, $nodeIndex)
  922. {
  923. $signDataStartIndex = $nodeIndex + strlen($nodeName) + 2;
  924. $signIndex = strpos($responseContent, "\"" . $this->SIGN_NODE_NAME . "\"");
  925. // 签名前-逗号
  926. $signDataEndIndex = $signIndex - 1;
  927. if ($signDataEndIndex < 0) {
  928. $signDataEndIndex = strlen($responseContent) - 1;
  929. }
  930. $indexLen = $signDataEndIndex - $signDataStartIndex;
  931. $encContent = substr($responseContent, $signDataStartIndex + 1, $indexLen - 2);
  932. $encryptParseItem = new EncryptParseItem();
  933. $encryptParseItem->encryptContent = $encContent;
  934. $encryptParseItem->startIndex = $signDataStartIndex;
  935. $encryptParseItem->endIndex = $signDataEndIndex;
  936. return $encryptParseItem;
  937. }
  938. // 获取加密内容
  939. private function encryptXMLSignSource($request, $responseContent)
  940. {
  941. $parsetItem = $this->parserEncryptXMLSignSource($request, $responseContent);
  942. $bodyIndexContent = substr($responseContent, 0, $parsetItem->startIndex);
  943. $bodyEndContent = substr($responseContent, $parsetItem->endIndex, strlen($responseContent) + 1 - $parsetItem->endIndex);
  944. $bizContent = decrypt($parsetItem->encryptContent, $this->encryptKey);
  945. return $bodyIndexContent . $bizContent . $bodyEndContent;
  946. }
  947. private function parserEncryptXMLSignSource($request, $responseContent)
  948. {
  949. $apiName = $request->getApiMethodName();
  950. $rootNodeName = str_replace(".", "_", $apiName) . $this->RESPONSE_SUFFIX;
  951. $rootIndex = strpos($responseContent, $rootNodeName);
  952. $errorIndex = strpos($responseContent, $this->ERROR_RESPONSE);
  953. // $this->echoDebug("<br/>rootNodeName:" . $rootNodeName);
  954. // $this->echoDebug("<br/> responseContent:<xmp>" . $responseContent . "</xmp>");
  955. if ($rootIndex > 0) {
  956. return $this->parserEncryptXMLItem($responseContent, $rootNodeName, $rootIndex);
  957. } else if ($errorIndex > 0) {
  958. return $this->parserEncryptXMLItem($responseContent, $this->ERROR_RESPONSE, $errorIndex);
  959. } else {
  960. return null;
  961. }
  962. }
  963. private function parserEncryptXMLItem($responseContent, $nodeName, $nodeIndex)
  964. {
  965. $signDataStartIndex = $nodeIndex + strlen($nodeName) + 1;
  966. $xmlStartNode = "<" . $this->ENCRYPT_XML_NODE_NAME . ">";
  967. $xmlEndNode = "</" . $this->ENCRYPT_XML_NODE_NAME . ">";
  968. $indexOfXmlNode = strpos($responseContent, $xmlEndNode);
  969. if ($indexOfXmlNode < 0) {
  970. $item = new EncryptParseItem();
  971. $item->encryptContent = null;
  972. $item->startIndex = 0;
  973. $item->endIndex = 0;
  974. return $item;
  975. }
  976. $startIndex = $signDataStartIndex + strlen($xmlStartNode);
  977. $bizContentLen = $indexOfXmlNode - $startIndex;
  978. $bizContent = substr($responseContent, $startIndex, $bizContentLen);
  979. $encryptParseItem = new EncryptParseItem();
  980. $encryptParseItem->encryptContent = $bizContent;
  981. $encryptParseItem->startIndex = $signDataStartIndex;
  982. $encryptParseItem->endIndex = $indexOfXmlNode + strlen($xmlEndNode);
  983. return $encryptParseItem;
  984. }
  985. function echoDebug($content)
  986. {
  987. if ($this->debugInfo) {
  988. echo "<br/>" . $content;
  989. }
  990. }
  991. }