JiaLieService.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <?php
  2. namespace crmeb\services;
  3. use think\Request;
  4. class JiaLieService
  5. {
  6. private static $Url = "https://qrcode.jlpay.com/api/pay/";
  7. private static $zsUrl = "https://qrcode.jlpay.com/api/pay/";
  8. private static $dgurl = "https://qrcode-dev.jlpay.com/api/pay/";
  9. private static $initialize = null;
  10. private static $org_code =null;
  11. private static $mch_id =null;
  12. private static $prikey =null;
  13. private static $pubkey =null;
  14. private static $dubeg =null;
  15. private static $errorMsg = "";
  16. const DEFAULT_ERROR_MSG = '操作失败,请稍候再试!';
  17. const MICROPAY = "micropay"; //付款码支付
  18. const QRCODEPAY = "qrcodepay"; //扫码支付
  19. const REFUND = "refund"; //退款接口
  20. const CANCEL = "cancel"; //撤销接口
  21. const APPPAY = "apppay"; //APP支付接口
  22. const OFFICIALPAY = "officialpay";//微信公众号、小程序支付接口
  23. const WAPH5PAY = "waph5pay"; // 支付宝服务窗、小程序支付接口
  24. const QUERY = "chnquery"; //订单查询接口
  25. const UNIONJSPAY = "unionjspay"; //银联行业码支付接口
  26. const AUTHBIND= "authbind"; //绑定支付目录接口
  27. const GETOPENID = "getopenid";//授权码获取openId或userId接口
  28. const MICROPAYPREAUTH = "micropaypreauth";//付款码预授权
  29. const QRCODEPAYPREAUTH = "qrcodepaypreauth";//扫码预授权
  30. const PREAUTHCOMPLETE= "preauthcomplete"; //预授权完成
  31. const PREAUTHREVIKE = "preauthrevoke"; //预授权撤销
  32. const PREAUTHCLOSE = "preauthclose";//预授权关单
  33. const PREAUTHQUREY = "preauthquery";//预授权查询
  34. /**
  35. * 设置错误信息
  36. * @param string $errorMsg
  37. * @return bool
  38. */
  39. protected static function setErrorInfo($errorMsg = self::DEFAULT_ERROR_MSG, $rollback = false)
  40. {
  41. if ($rollback) self::rollbackTrans();
  42. self::$errorMsg = $errorMsg;
  43. return false;
  44. }
  45. /**
  46. * 获取错误信息
  47. * @param string $defaultMsg
  48. * @return string
  49. */
  50. public static function getErrorInfo($defaultMsg = self::DEFAULT_ERROR_MSG)
  51. {
  52. return !empty(self::$errorMsg) ? self::$errorMsg : $defaultMsg;
  53. }
  54. private function __construct()
  55. {
  56. // TODO 初始化配置
  57. $system = SystemConfigService::more(['jl_org_code', 'jl_mch_id', 'mer_prikey', 'jl_pubkey','jl_dubeg']);
  58. self::$org_code = $system['jl_org_code'] ?? '';
  59. self::$mch_id = $system['jl_mch_id'] ?? '';
  60. self::$prikey = $system['mer_prikey'] ?? '';
  61. self::$pubkey = $system['jl_pubkey'] ?? '';
  62. self::$dubeg = $system['jl_dubeg'] ?? '';
  63. if($system['jl_dubeg']==1)
  64. {
  65. self::$Url = self::$dgurl;
  66. }
  67. else
  68. {
  69. self::$Url = self::$zsUrl;
  70. }
  71. }
  72. /**
  73. * 初始化静态类
  74. *
  75. * @return Test
  76. */
  77. public static function initialize(): JiaLieService
  78. {
  79. if (!self::$initialize instanceof self) {
  80. return new self();
  81. }
  82. return self::$initialize;
  83. }
  84. private static function do_rsaSign($data, $private_key) {
  85. $search = [
  86. "-----BEGIN RSA PRIVATE KEY-----",
  87. "-----END RSA PRIVATE KEY-----",
  88. "\n",
  89. "\r",
  90. "\r\n"
  91. ];
  92. $private_key = str_replace($search, "", $private_key);
  93. $private_key = $search[0] . PHP_EOL . wordwrap($private_key, 64, "\n", true) . PHP_EOL . $search[1];
  94. $res = openssl_get_privatekey($private_key);
  95. if ($res) {
  96. openssl_sign($data, $sign, $res,OPENSSL_ALGO_SHA256);
  97. openssl_free_key($res);
  98. } else {
  99. self::setErrorInfo("私钥格式有误");
  100. }
  101. @file_put_contents("xxx.txt",$sign);
  102. $sign = base64_encode($sign);
  103. return $sign;
  104. }
  105. /**
  106. * RSA验签
  107. * @param $data 待签名数据
  108. * @param $public_key 公钥字符串
  109. * @param $sign 要校对的的签名结果
  110. * return 验证结果
  111. */
  112. public static function do_rsaCheck($data, $public_key, $sign) {
  113. $search = [
  114. "-----BEGIN PUBLIC KEY-----",
  115. "-----END PUBLIC KEY-----",
  116. "\n",
  117. "\r",
  118. "\r\n"
  119. ];
  120. $public_key = str_replace($search, "", $public_key);
  121. $public_key = $search[0] . PHP_EOL . wordwrap($public_key, 64, "\n", true) . PHP_EOL . $search[1];
  122. $res = openssl_get_publickey($public_key);
  123. if ($res) {
  124. $result = (bool) openssl_verify($data, base64_decode($sign), $res,OPENSSL_ALGO_SHA256);
  125. file_put_contents("callback.txt", "\n异步验签原字符串\n", FILE_APPEND);
  126. file_put_contents("callback.txt",$data , FILE_APPEND);
  127. openssl_free_key($res);
  128. } else {
  129. self::setErrorInfo('公钥格式有误');
  130. }
  131. return $result;
  132. }
  133. public static function rsaSign($params) {
  134. $dataStr = self::getJsonStr($params);
  135. return self::do_rsaSign($dataStr, self::$prikey);
  136. }
  137. public static function verify($params) {
  138. if (!isset($params['sign'])) {
  139. throw new Exception("没有sign签名参数");
  140. }
  141. $sign = $params['sign'];
  142. unset($params['sign']);
  143. $dataStr = self::getJsonStr($params);
  144. return self::do_rsaCheck($dataStr, self::$pubkey, $sign);
  145. }
  146. public static function getJsonStr($params) {
  147. if (!is_array($params)) {
  148. return $params;
  149. }
  150. if (count($params) <= 0) {
  151. throw new Exception("检查参数");
  152. }
  153. ksort($params);
  154. return json_encode($params,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
  155. }
  156. public static function getKeyValueStr($params) {
  157. if (!is_array($params)) {
  158. return $params;
  159. }
  160. if (count($params) <= 0) {
  161. throw new Exception("检查参数");
  162. }
  163. $dataStr = "";
  164. ksort($params);
  165. foreach ($params as $key => $value) {
  166. if ($key == "sign") {
  167. continue;
  168. }
  169. if ($value === "" || $value === null) {
  170. continue;
  171. }
  172. $dataStr .= $key . "=" . $value;
  173. $dataStr .= "&";
  174. }
  175. return rtrim($dataStr, "&");
  176. }
  177. public static function checkTradeType($authCode) {
  178. if (empty($authCode)) {
  179. return "";
  180. }
  181. $prefix = substr($authCode, 0, 2);
  182. $aliPayCode = array("25", "26", "27", "28", "29", "30");
  183. $wxPayCode = array("10", "11", "12", "13", "14", "15");
  184. $unionPayCode = array("62");
  185. if (in_array($prefix, $aliPayCode)) {
  186. return "alipay";
  187. } else if (in_array($prefix, $wxPayCode)) {
  188. return "wxpay";
  189. } else if (in_array($prefix, $unionPayCode)) {
  190. return "unionpay";
  191. }
  192. return "";
  193. }
  194. public static function dataRecodes($title, $data) {
  195. $handler = fopen('logs/result.txt', 'a+');
  196. $content = "================" . $title . "===================\n";
  197. if (is_string($data) === true) {
  198. $content .= $data . "\n";
  199. }
  200. if (is_array($data) === true) {
  201. foreach ($data as $k => $v) {
  202. $content .= "key:【" . $k . "】,value: 【" . var_export($v, true) . "】\n";
  203. }
  204. }
  205. $flag = fwrite($handler, $content);
  206. fclose($handler);
  207. return $flag;
  208. }
  209. /**
  210. * 调取支付
  211. * @param string $URL
  212. * @param array $Params
  213. * @return bool|string
  214. */
  215. public static function paymentOrder($URL=self::MICROPAY,$Params=[])
  216. {
  217. $headers = array("Content-Type:application/json");
  218. $config = [
  219. 'org_code' => self::$org_code,
  220. 'mch_id' => self::$mch_id,
  221. 'version' => "1.0.0",
  222. 'charset' => "UTF-8",
  223. 'sign_type' => "RSA",
  224. 'pay_type' => 'wxpay',
  225. 'notify_url'=> sys_config('site_url')."/api/jialie/notify",
  226. ];
  227. $requestParams = array_merge($config, $Params);
  228. $requestParams['sign'] = self::rsaSign($requestParams);
  229. $http = new HttpClient();
  230. $http->setDebug(true);
  231. self::dataRecodes('付款码支付request报文 ', $requestParams);
  232. $rs = $http->post(self::$Url.$URL,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
  233. //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
  234. self::dataRecodes('付款码支付response报文 ', self::$Url.$URL.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
  235. self::dataRecodes('付款码支付response报文 ', $rs);
  236. return $rs;
  237. }
  238. public static function paymentquery($URL=self::QUERY,$Params)
  239. {
  240. $headers = array("Content-Type:application/json");
  241. $config = [
  242. 'org_code' => self::$org_code,
  243. 'mch_id' => self::$mch_id,
  244. 'version' => "1.0.0",
  245. 'charset' => "UTF-8",
  246. 'sign_type' => "RSA",
  247. ];
  248. $requestParams = array_merge($config, $Params);
  249. $requestParams['sign'] = self::rsaSign($requestParams);
  250. $http = new HttpClient();
  251. //$http->setDebug(true);
  252. //self::dataRecodes('订单查询request报文 ', $requestParams);
  253. $rs = $http->post(self::$Url.$URL,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
  254. //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
  255. //self::dataRecodes('订单查询response报文 ', self::$Url.$URL.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
  256. //self::dataRecodes('订单查询response报文 ', $rs);
  257. return $rs;
  258. }
  259. public static function payOrderRefund($orderNo, array $opt)
  260. {
  261. if (!isset($opt['pay_price'])) exception('缺少pay_price');
  262. $totalFee = floatval(bcmul($opt['pay_price'], 100, 0));
  263. $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'], 100, 0)) : null;
  264. $refundReason = isset($opt['desc']) ? $opt['desc'] : '';
  265. $headers = array("Content-Type:application/json");
  266. $config = [
  267. 'org_code' => self::$org_code,
  268. 'mch_id' => self::$mch_id,
  269. 'charset' => "UTF-8",
  270. 'sign_type' => "RSA",
  271. ];
  272. $Params['nonce_str'] = uniqid();
  273. $Params['out_trade_no'] = 'ref'.uniqid();
  274. $Params['ori_out_trade_no'] = $orderNo;
  275. $Params['total_fee'] = intval($refundFee);
  276. $Params['mch_create_ip'] = app('request')->ip();
  277. $Params['remark'] = $refundReason;
  278. $requestParams = array_merge($config, $Params);
  279. $requestParams['sign'] = self::rsaSign($requestParams);
  280. $http = new HttpClient();
  281. $http->setDebug(true);
  282. self::dataRecodes('订单退款request报文 ', $requestParams);
  283. $rs = $http->post(self::$Url.self::REFUND,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
  284. //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
  285. self::dataRecodes('订单退款request报文 ', self::$Url.self::REFUND.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
  286. self::dataRecodes('订单退款request报文 ', $rs);
  287. return $rs;
  288. }
  289. }