BaseApi.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. <?php
  2. namespace addons\AvoidTax\common\jdk\luyong;
  3. use Exception;
  4. use GuzzleHttp\Client;
  5. use Yii;
  6. use GuzzleHttp\Psr7\Request;
  7. use yii\base\BaseObject;
  8. use yii\helpers\Json;
  9. use GuzzleHttp\Exception\ClientException;
  10. use GuzzleHttp\Psr7\Response;
  11. /**
  12. * luyongAPI
  13. * BaseApi class
  14. * @package addons\AvoidTax\common\jdk\luyong
  15. */
  16. class BaseApi extends BaseObject
  17. {
  18. /**
  19. * 账号
  20. *
  21. * @var string
  22. */
  23. public $email;
  24. /**
  25. * @var string
  26. */
  27. public $pwd;
  28. /**
  29. * @var string
  30. */
  31. public $accountId;
  32. /**
  33. * @var string
  34. */
  35. public $publicKey;
  36. /**
  37. * @var string
  38. */
  39. public $privateKey;
  40. /**
  41. * 是否测试
  42. *
  43. * @var boolean
  44. */
  45. private $test = false;
  46. /**
  47. * 标识当前接口使用的API
  48. *
  49. * @var string
  50. */
  51. private $type = 'sc';
  52. /**
  53. * 测试API域名
  54. *
  55. * @var array
  56. */
  57. protected $testApi = [
  58. // 登录接口
  59. // 打款批次风控接口
  60. // 支付时异步请求接口
  61. // 打款批次支付结果接收接口
  62. 'sc' => 'http://t2.1010jz.wang/',
  63. // 无感电签接口
  64. 'sw' => 'http://t1.1010jz.wang/',
  65. ];
  66. /**
  67. * 正式API域名
  68. *
  69. * @var array
  70. */
  71. protected $devApi = [
  72. // 登录接口
  73. // 打款批次风控接口
  74. // 支付时异步请求接口
  75. // 打款批次支付结果接收接口
  76. 'sc' => 'https://sc.luyong.com/',
  77. // 无感电签接口
  78. 'sw' => 'https://sw.luyong.com/',
  79. ];
  80. /**
  81. * 请求是否包含token
  82. *
  83. * @var boolean
  84. */
  85. protected $token = false;
  86. /**
  87. * 不参与签名字段
  88. *
  89. * @var array
  90. */
  91. protected $notJoinSignFields = [];
  92. /**
  93. * 设置接口是sw
  94. *
  95. * @return void
  96. */
  97. private function setSw()
  98. {
  99. $this->type = 'sw';
  100. }
  101. /**
  102. * 设置接口是sc
  103. *
  104. * @return void
  105. */
  106. private function setSc()
  107. {
  108. $this->type = 'sc';
  109. }
  110. /**
  111. * @return void
  112. */
  113. public function setTest()
  114. {
  115. $this->test = true;
  116. }
  117. /**
  118. * 不需要token
  119. *
  120. * @return void
  121. */
  122. protected function setHasToken()
  123. {
  124. $this->token = true;
  125. }
  126. /**
  127. * 设置不参与签名字段
  128. *
  129. * @param array $fields
  130. * @return void
  131. */
  132. protected function setNotJoinSignFields(array $fields)
  133. {
  134. $this->notJoinSignFields = $fields;
  135. }
  136. /**
  137. * (一) 登录接口
  138. *
  139. * @return void
  140. */
  141. public function signIn()
  142. {
  143. $this->setSc();
  144. $data = $this->sendRequest('/api/sign_in', [
  145. 'email' => $this->email,
  146. 'pwd' => md5($this->pwd),
  147. ]);
  148. return $data['data'];
  149. }
  150. /**
  151. * (二) 打款批次风控接口
  152. *
  153. * @param string $batchNo
  154. * @param array $userPayInfos
  155. * @return array
  156. */
  157. public function riskCheck(string $batchNo, array $userPayInfos)
  158. {
  159. $this->setSc();
  160. return $this->sendRequest('/api/alisafepay/riskCheck', [
  161. 'token' => $this->getToken(),
  162. 'batchNo' => $batchNo,
  163. 'userPayInfos' => Json::encode($userPayInfos),
  164. ]);
  165. }
  166. /**
  167. * (三) 支付时异步请求接口
  168. *
  169. * @param string $batchNo
  170. * @return array
  171. */
  172. public function asyncTransferNotify(string $batchNo)
  173. {
  174. $this->setSc();
  175. return $this->sendRequest('/api/alisafepay/asyncTransferNotify', [
  176. 'token' => $this->getToken(),
  177. 'batchNo' => $batchNo,
  178. ]);
  179. }
  180. /**
  181. * (四) 打款批次支付结果接收接口失败
  182. *
  183. * @param string $batchNo
  184. * @return array
  185. */
  186. public function asyncTransferResultNotifyNo(
  187. string $bizOutNo,
  188. string $payStatus = 'false',
  189. string $message = ''
  190. )
  191. {
  192. $this->setSc();
  193. $this->setNotJoinSignFields(['message']);
  194. return $this->sendRequest('/api/alisafepay/asyncTransferResultNotify', [
  195. 'token' => $this->getToken(),
  196. 'bizOutNo' => $bizOutNo,
  197. 'payStatus' => $payStatus,
  198. 'message' => $message,
  199. ], 'post');
  200. }
  201. /**
  202. * (四) 打款批次支付结果接收接口成功
  203. *
  204. * @param string $batchNo
  205. * @return array
  206. */
  207. public function asyncTransferResultNotifyOk(
  208. string $bizOutNo,
  209. string $pay_fund_order_id,
  210. string $payStatus = 'true',
  211. string $message = ''
  212. )
  213. {
  214. $this->setSc();
  215. $this->setNotJoinSignFields(['message']);
  216. return $this->sendRequest('/api/alisafepay/asyncTransferResultNotify', [
  217. 'token' => $this->getToken(),
  218. 'bizOutNo' => $bizOutNo,
  219. 'payStatus' => $payStatus,
  220. 'message' => $message,
  221. 'pay_fund_order_id' => $pay_fund_order_id
  222. ], 'post');
  223. }
  224. /**
  225. * (五) 无感电签接口
  226. *
  227. * @param string $name
  228. * @param string $phone
  229. * @param string $idCard
  230. * @param string|null $templateId
  231. * @param string|null $email
  232. * @param string|null $callbackUrl
  233. * @param string|null $extraMsg
  234. * @return array
  235. */
  236. public function silentSign(
  237. string $name,
  238. string $phone,
  239. string $idCard,
  240. string $templateId = null,
  241. string $email = null,
  242. string $callbackUrl = null,
  243. string $extraMsg = null
  244. )
  245. {
  246. $this->setSw();
  247. return $this->sendRequest('/sign/silentSign', array_merge(compact(
  248. 'name',
  249. 'phone',
  250. 'idCard',
  251. 'templateId',
  252. 'email',
  253. 'callbackUrl',
  254. 'extraMsg',
  255. ), [
  256. 'accountId' => $this->accountId,
  257. ]), 'get');
  258. }
  259. /**
  260. * (二十一) 查询用户注册信息
  261. *
  262. * @param string $idCard
  263. * @return array
  264. */
  265. public function queryRegisterUser(string $idCard)
  266. {
  267. return $this->sendRequest('/signing/queryRegisterUser', compact('idCard'), 'get');
  268. }
  269. /**
  270. * 手机号查询电签用户信息
  271. *
  272. * @param string $phone
  273. * @return void
  274. */
  275. public function querySignUserByPhone(string $phone)
  276. {
  277. $data = $this->querySignUser(compact('phone'));
  278. }
  279. /**
  280. * 身份证查询电签用户信息
  281. *
  282. * @param string $idCard
  283. * @return array
  284. */
  285. public function querySignUserByIdCard(string $idCard)
  286. {
  287. return $this->querySignUser(compact('idCard'));
  288. }
  289. /**
  290. * (六) 查询电签用户信息
  291. *
  292. * @param array $data
  293. * @return void
  294. */
  295. protected function querySignUser(array $data)
  296. {
  297. return $this->sendRequest('/signing/querySignUser', array_merge($data, [
  298. 'accountId' => $this->accountId,
  299. ]), 'get');
  300. }
  301. /**
  302. * (七) 批量导入签约用户接口
  303. *
  304. * @param string $batchNum
  305. * @param array $signUsers [[idCard name phone]]
  306. * @return array
  307. */
  308. public function importSignUser(string $batchNum, array $signUsers)
  309. {
  310. $this->setSc();
  311. return $this->sendRequest('/api/settlement/batch/importSignUser', [
  312. 'token' => $this->getToken(),
  313. 'batchNum' => $batchNum,
  314. 'signUsers' => Json::encode($signUsers)
  315. ], 'post');
  316. }
  317. /**
  318. * 获取token
  319. *
  320. * @return string
  321. */
  322. private function getToken()
  323. {
  324. $key = 'yl_token_' . $this->email;
  325. $redis = Yii::$app->redis;
  326. if (($cache = $redis->get($key)) == false) {
  327. $token = $this->signIn()['token'];
  328. $redis->setex($key, 3000, $token);
  329. return $token;
  330. }
  331. return $cache;
  332. }
  333. /**
  334. * @return string
  335. */
  336. protected function getUri()
  337. {
  338. return $this->test ? $this->testApi[$this->type] : $this->devApi[$this->type];
  339. }
  340. /**
  341. * 发送请求
  342. *
  343. * @param string $api
  344. * @param array $data
  345. * @param string $method
  346. * @return array
  347. * @throws Exception
  348. */
  349. protected function sendRequest(string $api, array $data = [], string $method = 'post')
  350. {
  351. // 客户端
  352. $client = new Client([
  353. 'base_uri' => $this->getUri(),
  354. 'verify' => false
  355. ]);
  356. try {
  357. $response = $client->send($this->getRequest($api, $data, $method));
  358. } catch (ClientException $e) {
  359. throw new Exception($e->getMessage());
  360. }
  361. $result = $this->getResponseData($response);
  362. // 记录
  363. Yii::$app->custom->logs('当前接口: ' . $api);
  364. Yii::$app->custom->logs('传输参数: ' . Json::encode($data));
  365. Yii::$app->custom->logs('返回结果: ' . Json::encode($result));
  366. return $result;
  367. }
  368. /**
  369. * 获取请求返回内容
  370. *
  371. * @param Response $response
  372. * @return array
  373. * @throws Exception
  374. */
  375. protected function getResponseData(Response $response)
  376. {
  377. if ($response->getStatusCode() == 200) {
  378. $content = Json::decode($response->getBody()->getContents());
  379. return $content;
  380. }
  381. throw new Exception('请求失败');
  382. }
  383. /**
  384. * 获取请求类
  385. *
  386. * @param string $api
  387. * @param array $data
  388. * @param string $method
  389. * @return Request
  390. */
  391. protected function getRequest(string $api, array $data, string $method)
  392. {
  393. $method = strtoupper($method);
  394. if ($method == 'POST') {
  395. return new Request($method, $api, $this->getHeaders(), Json::encode($this->getBody($data)));
  396. } else if ($method == 'GET') {
  397. return new Request($method, $this->getUrlQuery($api, $this->getBody($data)));
  398. }
  399. }
  400. /**
  401. * 获取Query
  402. *
  403. * @param string $api
  404. * @param array $data
  405. * @return string
  406. */
  407. protected function getUrlQuery(string $api, array $data)
  408. {
  409. return $api . '?' . $this->getSignStr($data);
  410. }
  411. /**
  412. * 请求体
  413. *
  414. * @param array $array
  415. * @return array
  416. */
  417. protected function getBody(array $data = [])
  418. {
  419. $data = array_filter($data, function($v) {
  420. // return $v !== null;
  421. return true;
  422. });
  423. ksort($data);
  424. $string = $this->getSignStr($data, true);
  425. // echo $string . "\n";
  426. $signature = $this->getSignature(strtoupper(md5($string)));
  427. // echo ($signature);die;
  428. $data['signature'] = $signature;
  429. return $data;
  430. }
  431. /**
  432. * 拼接字符串
  433. *
  434. * @param array $data
  435. * @return string
  436. */
  437. protected function getSignStr(array $data, bool $is_sign = false)
  438. {
  439. if ($is_sign) {
  440. foreach($this->notJoinSignFields as $field) {
  441. if (isset($data[$field])) unset($data[$field]);
  442. }
  443. }
  444. $pairs = [];
  445. foreach ($data as $k => $v) {
  446. $pairs[] = $k . '=' . $v;
  447. }
  448. return implode('&', $pairs);
  449. }
  450. /**
  451. * 请求头
  452. *
  453. * @return array
  454. */
  455. protected function getHeaders()
  456. {
  457. $headers['Content-Type'] = 'application/json';
  458. return $headers;
  459. }
  460. /**
  461. * 回去签名字符串
  462. *
  463. * @param string $signString
  464. * @return string
  465. */
  466. public function getSignature($signString)
  467. {
  468. $privKeyId = openssl_pkey_get_private($this->getPrivateKey());
  469. openssl_sign($signString, $signature, $privKeyId);
  470. if (PHP_MAJOR_VERSION < 8) {
  471. openssl_free_key($privKeyId);
  472. }
  473. return $this->base64UrlEncode($signature);
  474. }
  475. /**
  476. * @return string
  477. */
  478. protected function base64UrlEncode($data)
  479. {
  480. $base64 = base64_encode($data);
  481. $base64Url = strtr($base64, '+/', '-_');
  482. $base64Url = rtrim($base64Url, '=');
  483. return $base64Url;
  484. }
  485. /**
  486. * 私钥加头尾
  487. *
  488. * @return string
  489. */
  490. protected function getPrivateKey()
  491. {
  492. $begin = '-----BEGIN PRIVATE KEY-----';
  493. $end = '-----END PRIVATE KEY-----';
  494. if (stripos($this->privateKey, $begin) === false) {
  495. return $begin . "\n" . $this->privateKey . "\n" . $end;
  496. }
  497. return $this->privateKey;
  498. }
  499. }