Multi.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php namespace Pay\Yspay;
  2. use Dever;
  3. use Dever\Http\Curl;
  4. # 银联商务商户资金自主管理系统
  5. class Multi
  6. {
  7. static $test_host = 'https://mobl-test.chinaums.com/channel/Business/UnifyMulti/';
  8. static $host = 'https://cloudpay.chinaums.com/channel/Business/UnifyMulti/';
  9. # 划付
  10. public function huafu($config, $merchant, $info, $auto = 1)
  11. {
  12. $this->config = $config;
  13. $mid = $merchant['mid'];
  14. $cash = $info['tx_cash'];
  15. $order_num = $info['order_num'];
  16. //整理内容信息
  17. $content = [
  18. 'merNo' => $mid,
  19. 'merOrderNo' => $order_num,
  20. 'payAmt' => $cash,
  21. ];
  22. Dever::log($content, 'yspay_huafu');
  23. $result = $this->curl('202001', $content);
  24. if ($result == 'ok') {
  25. $data['status'] = 1;
  26. } else {
  27. $data['status'] = 3;
  28. $data['error'] = $result;
  29. }
  30. $data['merchant_id'] = $merchant['id'];
  31. $data['mid'] = $mid;
  32. $data['order_num'] = $order_num;
  33. $data['type'] = 1;
  34. $data['cash'] = $cash;
  35. $data['tdate'] = time();
  36. $data['desc'] = $content['ps'];
  37. $data['auto'] = $auto;
  38. Dever::db('pay/yspay_cash_log')->insert($data);
  39. $this->fenzhang($config, $merchant, $info, $auto);
  40. return 'ok';
  41. }
  42. # 分账
  43. public function fenzhang($config, $merchant, $info, $auto = 1)
  44. {
  45. $this->config = $config;
  46. $mid = $this->config['mid'];
  47. $cash = $info['fz_cash'];
  48. if (!$cash || $cash <= 0) {
  49. return;
  50. }
  51. $order_num = $info['order_num'];
  52. //整理内容信息
  53. $content = [
  54. 'merNo' => $mid,
  55. 'merOrderNo' => $order_num,
  56. 'payAmt' => $cash,
  57. 'cardNo' => hash("sha256",$this->config['card']),
  58. 'ps' => $merchant['name'] . '分账',
  59. ];
  60. Dever::log($content, 'yspay_fenzhang');
  61. $result = $this->curl('202003', $content);
  62. if ($result == 'ok') {
  63. $data['status'] = 1;
  64. } else {
  65. $data['status'] = 3;
  66. $data['error'] = $result;
  67. }
  68. $data['merchant_id'] = $merchant['id'];
  69. $data['mid'] = $mid;
  70. $data['order_num'] = $order_num;
  71. $data['type'] = 2;
  72. $data['cash'] = $cash;
  73. $data['tdate'] = time();
  74. $data['desc'] = $content['ps'];
  75. $data['auto'] = $auto;
  76. Dever::db('pay/yspay_cash_log')->insert($data);
  77. }
  78. protected function header($code)
  79. {
  80. $header = array(
  81. 'transCode' => $code,
  82. 'verNo' => '100',
  83. 'srcReqDate' => date("Ymd"),
  84. 'srcReqTime' => date("His"),
  85. 'srcReqId' => Dever::uuid(),
  86. 'channelId' => '043',
  87. 'groupId' => config('param.groupId'),
  88. );
  89. return $header;
  90. }
  91. protected function curl($code, $param, $state = true)
  92. {
  93. $url = $this->config['box'] == 1 ? self::$host : self::$test_host;
  94. $url .= $code;
  95. $header = $this->header($code);
  96. $header['signature'] = $this->sign($param);
  97. $curl = Curl::getInstance($url, $param, 'post', true, $header)->setResultHeader(true);
  98. $header = $curl->header();
  99. $body = $curl->result();
  100. if (strstr($body, '<html><head>')) {
  101. return 'error';
  102. }
  103. $body = Dever::json_decode($body);
  104. if (isset($header['respCode'])) {
  105. if ($header['respCode'] == '99999999') {
  106. return $state ? 'ok' : $body;
  107. } else {
  108. return $header['respMsg'];
  109. }
  110. } else {
  111. return 'error';
  112. }
  113. }
  114. protected function sign($data)
  115. {
  116. $data = $this->getParams($data);
  117. $file = $this->config['file_cert'];
  118. if(!file_exists($file)) {
  119. Dever::alert('private_key not exit');
  120. }
  121. $pkcs12 = file_get_contents($file);
  122. openssl_pkcs12_read($pkcs12, $certs, $this->config['key']);
  123. if (!$certs) {
  124. Dever::alert('private_key error');
  125. }
  126. $privateKey = $certs['pkey'];
  127. if (openssl_sign(utf8_encode($data), $binarySignature, $privateKey, OPENSSL_ALGO_SHA256)) {
  128. return bin2hex($binarySignature);
  129. } else {
  130. return '';
  131. }
  132. }
  133. protected function checkSign($data, $signature)
  134. {
  135. $file = $this->config['file_key'];
  136. if(!file_exists($file)) {
  137. Dever::alert('public_key not exit');
  138. }
  139. $cert = file_get_contents($file);
  140. $cert = '-----BEGIN CERTIFICATE-----' . PHP_EOL
  141. . chunk_split(base64_encode($cert), 64, PHP_EOL)
  142. . '-----END CERTIFICATE-----' . PHP_EOL;
  143. $pubKeyId = openssl_get_publickey($cert);
  144. $signature = hex2bin($signature);
  145. $ok = openssl_verify($data, $signature, $pubKeyId, OPENSSL_ALGO_SHA256);
  146. if ($ok == 1) {
  147. openssl_free_key($pubKeyId);
  148. return true;
  149. }
  150. return false;
  151. }
  152. protected function getParams($param)
  153. {
  154. ksort($param);
  155. $result = array();
  156. foreach ($param as $k => $v) {
  157. if (is_array($v)) {
  158. $v = json_encode($v, JSON_UNESCAPED_UNICODE);
  159. } elseif(trim($v) == ""){
  160. continue;
  161. }
  162. if (is_bool($v)) {
  163. $result[] = $v ? "$k=true" : "$k=false";
  164. } else {
  165. $result[] = $k . '=' . $v;
  166. }
  167. }
  168. $result = implode('&', $result);
  169. return $result;
  170. }
  171. }