Efalipay.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <?php
  2. class Efalipay {
  3. //测试环境主扫接口路径
  4. protected $gateway = 'http://test-efps.epaylinks.cn/api/txs/pay/NativePayment';
  5. //测试环境单笔提现接口路径
  6. protected $withdrawalToCard = 'http://test-efps.epaylinks.cn/api/txs/pay/withdrawalToCard';
  7. //进件
  8. protected $apply_url = 'http://test-efps.epaylinks.cn/api/cust/SP/Merchant/apply';
  9. //生产环境接口路径
  10. //protected $gateway = 'https://efps.epaylinks.cn/api/txs/pay/NativePayment';
  11. //私钥文件路径
  12. public $rsaPrivateKeyFilePath = "D:\\certs\\user.pfx";
  13. //易票联公钥
  14. public $publicKeyFilePath = "D:\\certs\\efps.cer";
  15. //证书序列号
  16. public $sign_no='562265003122220001';
  17. //证书密码
  18. public $password='Epaylinks@EFPS2018';
  19. //编码格式
  20. public $charset = "UTF-8";
  21. public $signType = "RSA2";
  22. //商户号
  23. protected $config = array(
  24. 'customer_code' => '562265003122220',
  25. 'notify_url' => 'http://www.baidu.com',
  26. 'return_url' => 'http://www.baidu.com'
  27. );
  28. public function check() {
  29. if (!$this->config['customer_code'] ) {
  30. E("支付设置有误!");
  31. }
  32. return true;
  33. }
  34. //测试主扫
  35. public function buildRequestForm() {
  36. $orderNo = "123456".date('YmdHis');
  37. echo '订单号:'.$orderNo;
  38. echo '<br>';
  39. $client_ip = "127.0.0.1";
  40. if (getenv('HTTP_CLIENT_IP')) {
  41. $client_ip = getenv('HTTP_CLIENT_IP');
  42. } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
  43. $client_ip = getenv('HTTP_X_FORWARDED_FOR');
  44. } elseif (getenv('REMOTE_ADDR')) {
  45. $client_ip = getenv('REMOTE_ADDR');
  46. } else {
  47. $client_ip = $_SERVER['REMOTE_ADDR'];
  48. }
  49. $orderInfo=array();
  50. $orderInfo['Id'] = $orderNo;
  51. $orderInfo['businessType'] = '130001';
  52. $orderInfo['goodsList'] = array(array('name'=>'pay','number'=>'one','amount'=>1));
  53. //$orderInfo = json_encode($orderInfo);
  54. $param = array(
  55. 'outTradeNo' => $orderNo,
  56. 'customerCode' => $this->config['customer_code'],
  57. 'clientIp' => $client_ip,
  58. 'orderInfo' => $orderInfo,
  59. 'payMethod' => 7,
  60. 'payAmount' => 10,
  61. 'payCurrency' => 'CNY',
  62. 'channelType' =>'02',
  63. 'notifyUrl' =>$this->config['notify_url'],
  64. 'redirectUrl' =>$this->config['return_url'],
  65. 'transactionStartTime' =>date('YmdHis'),
  66. 'nonceStr' => 'pay'.rand(100,999),
  67. 'version' => '3.0'
  68. );
  69. $sign = $this->sign(json_encode($param));
  70. echo '发送的参数'.json_encode($param);
  71. echo '<br>签名值'.$sign;
  72. $request = $this->http_post_json($this->gateway,json_encode($param),$sign);
  73. if($request && $request[0] == 200){
  74. // $re_data = json_decode($request[1],true);
  75. // if($re_data['returnCode'] == '0000'){
  76. // $payurl = $re_data['codeUrl'];
  77. // $sHtml="<script language='javascript' type='text/javascript'>window.location.href='{$payurl}';</script>";
  78. echo '<br>'.'获取到的参数:';
  79. // echo $request[1];
  80. return $request[1];
  81. /* }else{
  82. echo $request[1];
  83. exit;
  84. } */
  85. }else{
  86. print_r($request);
  87. exit;
  88. }
  89. exit;
  90. //return "";
  91. }
  92. //测试单笔提现
  93. public function withDraw() {
  94. $orderNo = "tx123".date('YmdHis');
  95. echo '订单号:'.$orderNo;
  96. echo '<br>';
  97. $param = array(
  98. 'outTradeNo' => $orderNo,
  99. 'customerCode' => $this->config['customer_code'],
  100. 'amount' => 10,
  101. 'bankUserName' =>$this->public_encrypt('张三',$this->rsaPrivateKeyFilePath),
  102. 'bankCardNo' => $this->public_encrypt('6214858888883338',$this->rsaPrivateKeyFilePath),
  103. 'bankName' => '招商银行',
  104. 'bankAccountType' =>'2',
  105. 'payCurrency' => 'CNY',
  106. 'notifyUrl' =>$this->config['notify_url'],
  107. 'nonceStr' => 'pay'.rand(100,999),
  108. );
  109. $sign = $this->sign(json_encode($param));
  110. echo '发送的参数'.json_encode($param);
  111. echo '<br>签名值'.$sign;
  112. $request = $this->http_post_json($this->withdrawalToCard,json_encode($param),$sign);
  113. if($request && $request[0] == 200){
  114. echo '<br>'.'获取到的参数:';
  115. return $request[1];
  116. }else{
  117. print_r($request);
  118. exit;
  119. }
  120. exit;
  121. }
  122. //进件
  123. //发起进件
  124. public function apply(){
  125. $paper = '{"certificateName":"李四","contactPhone":"13531231222","email":"test1@test.cn","lawyerCertNo":"430481198104234557","lawyerCertType":"0","merchantType":"3","openBank":"中国银行","openingLicenseAccountPhoto":"https://www.epaylinks.cn/www/wimages/epl_logo.png","settleAccount":"李四","settleAccountNo":"6214830201234567","settleAccountType":"2","settleTarget":"2"}';
  126. $business = array(
  127. array(
  128. "businessCode"=>"WITHDRAW_TO_SETTMENT_DEBIT",
  129. "creditcardsEnabled"=>0,
  130. "refundEnabled"=>1,
  131. "refundFeePer"=>0,
  132. "refundFeeRate"=>0,
  133. "settleCycle"=>"D+0",
  134. "stage"=>array(
  135. array(
  136. "amountFrom"=>0,
  137. "feePer"=>50
  138. )
  139. )
  140. )
  141. );
  142. $param =array(
  143. 'acqSpId' => $this->config['customer_code'],
  144. 'merchantName' => "测试商户20211202",
  145. 'acceptOrder' => 0,
  146. 'openAccount' => 1,
  147. 'paper' => $paper,
  148. 'business' =>$business
  149. );
  150. $sign = $this->sign(json_encode($param));
  151. echo json_encode($param);
  152. $res = $this->http_post_json($this->apply_url,json_encode($param),$sign);
  153. var_dump($res);
  154. die;
  155. }
  156. public function generateSign($params) {
  157. return $this->sign($this->getSignContent($params));
  158. }
  159. public function rsaSign($params) {
  160. return $this->sign($this->getSignContent($params));
  161. }
  162. protected function getSignContent($params) {
  163. ksort($params);
  164. $stringToBeSigned = "";
  165. $i = 0;
  166. foreach ($params as $k => $v) {
  167. if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
  168. // 转换成目标字符集
  169. $v = $this->characet($v, $this->charset);
  170. if ($i == 0) {
  171. $stringToBeSigned .= "$k" . "=" . "$v";
  172. } else {
  173. $stringToBeSigned .= "&" . "$k" . "=" . "$v";
  174. }
  175. $i++;
  176. }
  177. }
  178. unset ($k, $v);
  179. return $stringToBeSigned;
  180. }
  181. protected function sign($data) {
  182. $certs = array();
  183. openssl_pkcs12_read(file_get_contents($this->rsaPrivateKeyFilePath), $certs, $this->password); //其中password为你的证书密码
  184. ($certs) or die('您使用的私钥格式错误,请检查RSA私钥配置');
  185. openssl_sign($data, $sign, $certs['pkey'],OPENSSL_ALGO_SHA256);
  186. $sign = base64_encode($sign);
  187. return $sign;
  188. }
  189. /**
  190. * 校验$value是否非空
  191. * if not set ,return true;
  192. * if is null , return true;
  193. **/
  194. protected function checkEmpty($value) {
  195. if (!isset($value))
  196. return true;
  197. if ($value === null)
  198. return true;
  199. if (trim($value) === "")
  200. return true;
  201. return false;
  202. }
  203. /**
  204. * 针对notify_url验证消息是否是支付宝发出的合法消息
  205. * @return
  206. */
  207. public function verifyNotify($notify) {
  208. $ispost = $notify['ispost'];
  209. unset($notify['ispost']);
  210. $info = array();
  211. if($ispost){
  212. $param = array(
  213. 'amount' => intval($notify['amount']),
  214. 'procedureFee' => intval($notify['procedureFee']),
  215. 'payTime' => intval($notify['payTime']),
  216. 'settCycle' => $notify['settCycle'],
  217. 'settCycleInterval' => $notify['settCycleInterval'],
  218. 'outTradeNo' => $notify['outTradeNo'],
  219. 'transactionNo' => $notify['transactionNo'],
  220. 'customerCode' => $notify['customerCode'],
  221. 'payState' =>$notify['payState'],
  222. 'nonceStr' =>$notify['nonceStr']
  223. );
  224. $fp = fopen(ROOT_PATH."/data/runtime/iossdk/verifyNotify1_log.txt","a");
  225. flock($fp, LOCK_EX) ;
  226. fwrite($fp,"执行日期:".strftime("%Y%m%d%H%M%S",time())."\n".json_encode($param)."\n");
  227. flock($fp, LOCK_UN);
  228. fclose($fp);
  229. $sign = $notify['signature']['x-efps-sign'];
  230. $fp = fopen(ROOT_PATH."/data/runtime/iossdk/verifyNotify2_log.txt","a");
  231. flock($fp, LOCK_EX) ;
  232. fwrite($fp,"执行日期:".strftime("%Y%m%d%H%M%S",time())."\n".$sign."\n");
  233. flock($fp, LOCK_UN);
  234. fclose($fp);
  235. $rs = $this->rsaCheckV2(json_encode($param),$this->publicKeyFilePath,$sign);
  236. if($rs && $notify['payState'] == 00){
  237. $out_trade_no = $notify['outTradeNo'];
  238. //支付宝交易号
  239. $trade_no = $notify['transactionNo'];
  240. //交易状态
  241. $trade_status = $notify['payState'];
  242. $info['status'] = ($trade_status == 00) ? 1 : 0;
  243. $info['trade_no'] = $trade_no;
  244. $info['out_trade_no'] = $out_trade_no;
  245. $info['total_amount'] = $notify['amount']/100;
  246. $info['ispost'] = 1;
  247. return $info;
  248. }
  249. }else{
  250. if($notify['payState'] == 00){
  251. $orderid = $notify['outTradeNo'];
  252. $info['status'] = 1;
  253. $info['out_trade_no'] = $orderid;
  254. return $info;
  255. }
  256. }
  257. $info['status'] = 2;
  258. $info['out_trade_no'] = '';
  259. return $info;
  260. }
  261. public function rsaCheckV2($params, $rsaPublicKeyFilePath,$sign) {
  262. //$sign = $params['sign'];
  263. //$params['sign'] = null;
  264. return $this->verify($params, $sign, $rsaPublicKeyFilePath);
  265. }
  266. //使用易票联公钥验签 //返回的验签字段有中文需要加JSON_UNESCAPED_UNICODE才能验签通过
  267. //$data2 = json_encode($data, JSON_UNESCAPED_UNICODE);
  268. function verify($data, $sign, $rsaPublicKeyFilePath) {
  269. //读取公钥文件
  270. $pubKey = file_get_contents($this->publicKeyFilePath);
  271. $res = openssl_get_publickey($pubKey);
  272. ($res) or die('RSA公钥错误。请检查公钥文件格式是否正确');
  273. //调用openssl内置方法验签,返回bool值
  274. $result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256);
  275. if(!$this->checkEmpty($this->publicKeyFilePath)) {
  276. //释放资源
  277. openssl_free_key($res);
  278. }
  279. return $result;
  280. }
  281. //使用易票联公钥加密
  282. function public_encrypt($data,$rsaPublicKeyFilePath)
  283. {
  284. //读取公钥文件
  285. $pubKey = file_get_contents($this->publicKeyFilePath);
  286. $res = openssl_get_publickey($pubKey);
  287. ($res) or die('RSA公钥错误。请检查公钥文件格式是否正确');
  288. $crypttext = "";
  289. openssl_public_encrypt($data,$crypttext, $res );
  290. if(!$this->checkEmpty($this->publicKeyFilePath)) {
  291. //释放资源
  292. openssl_free_key($res);
  293. }
  294. return(base64_encode($crypttext));
  295. }
  296. /**
  297. * 转换字符集编码
  298. * @param $data
  299. * @param $targetCharset
  300. * @return string
  301. */
  302. function characet($data, $targetCharset) {
  303. if (!empty($data)) {
  304. $fileType = $this->charset;
  305. if (strcasecmp($fileType, $targetCharset) != 0) {
  306. $data = mb_convert_encoding($data, $targetCharset);
  307. // $data = iconv($fileType, $targetCharset.'//IGNORE', $data);
  308. }
  309. }
  310. return $data;
  311. }
  312. protected function getParam($para) {
  313. $arg = "";
  314. while (list ($key, $val) = each($para)) {
  315. $arg.=$key . "=" . $val . "&";
  316. }
  317. //去掉最后一个&字符
  318. $arg = substr($arg, 0, -1);
  319. return $arg;
  320. }
  321. /**
  322. * 获取远程服务器ATN结果,验证返回URL
  323. * @param $notify_id
  324. * @return
  325. * 验证结果集:
  326. * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空
  327. * true 返回正确信息
  328. * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
  329. */
  330. protected function getResponse2($Params) {
  331. $veryfy_url = $this->gateway . "?" . $Params;
  332. $responseTxt = $this->fsockOpen($veryfy_url);
  333. return $responseTxt;
  334. }
  335. protected function http_post_json($url, $jsonStr,$sign)
  336. {
  337. $ch = curl_init();
  338. $headers = array(
  339. 'Content-Type: application/json; charset=utf-8',
  340. 'Content-Length: ' . strlen($jsonStr),
  341. 'x-efps-sign-no:'.$this->sign_no,
  342. 'x-efps-sign-type:SHA256withRSA',
  343. 'x-efps-sign:'.$sign,
  344. 'x-efps-timestamp:'.date('YmdHis'),
  345. );
  346. curl_setopt($ch, CURLOPT_POST, 1);
  347. curl_setopt($ch, CURLOPT_URL, $url);
  348. curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
  349. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  350. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过检查
  351. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 跳过检查
  352. //curl_setopt($ch, CURLOPT_HEADER, true);
  353. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  354. $response = curl_exec($ch);
  355. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  356. return array($httpCode, $response);
  357. }
  358. }
  359. $efalipay = new Efalipay();
  360. echo $efalipay->buildRequestForm();
  361. ?>