GzcApiRequest.php 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <?php
  2. declare (strict_types=1);
  3. namespace app\traits;
  4. use think\facade\Log;
  5. /**
  6. * 请求公证处统一请求API
  7. * Trait GzcApiRequest
  8. * @package app\traits
  9. */
  10. trait GzcApiRequest
  11. {
  12. /**
  13. * 发送请求
  14. * @return mixed|string
  15. * @author php迷途小书童
  16. * @created 2021/1/14 14:34
  17. */
  18. public static function request(string $method, string $url, array $params = [], array $options = [])
  19. {
  20. $base_uri = env('GZC.HOSTNAME');
  21. $request_uri = $base_uri.$url;
  22. try {
  23. $data = json_encode($params);
  24. $headerArray =array(
  25. "Content-type:application/json;charset='utf-8'",
  26. "Accept:application/json"
  27. );
  28. if ($url != '/v1/api/third/auth/token') {
  29. $Token = self::getTokenFromServer();
  30. $accessToken = $Token['extendData']['accessToken'];
  31. array_push($headerArray, "token:".$accessToken);
  32. }
  33. Log::info($data);
  34. $curl = curl_init();
  35. curl_setopt($curl, CURLOPT_URL, $request_uri);
  36. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
  37. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
  38. curl_setopt($curl, CURLOPT_POST, 1);
  39. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  40. curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
  41. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  42. $output = curl_exec($curl);
  43. curl_close($curl);
  44. return json_decode($output, true);
  45. } catch (\Throwable $e) {
  46. return $e->getMessage();
  47. }
  48. }
  49. /**
  50. * 查询账户余额
  51. * @author php迷途小书童
  52. * @created 2021/1/14 16:34
  53. */
  54. public static function checkAmount($user)
  55. {
  56. // $data = [
  57. // 'platformNo' => env('GZC.PLATFORM_NO'),
  58. // 'appNo' => env('GZC.APP_NO'),
  59. // 'conName' => $user['user_name'],
  60. // 'conCertType' => 1,
  61. // 'conCertNo' => $user['user_card'],
  62. // ];
  63. // return self::request('POST', '/v1/api/third/in/in30', $data);
  64. $debug = [];
  65. $data = [
  66. 'platformNo' => env('GZC.PLATFORM_NO'),
  67. 'appNo' => env('GZC.APP_NO'),
  68. 'conName' => $user['user_name'] ?? '',
  69. 'conCertType'=> 1,
  70. 'conCertNo' => $user['user_card'] ?? '',
  71. ];
  72. $debug['request'] = $data;
  73. $res1 = self::getAmount($user,$data);
  74. return $res1;
  75. }
  76. private static function getAmount($user,$data)
  77. {
  78. try {
  79. // 记录请求(原有日志可保留或删除)
  80. Log::info('[checkAmount] request', $data);
  81. $res = self::request('POST', '/v1/api/third/in/in30', $data);
  82. $debug['raw_response'] = $res;
  83. // 尝试解析 amount(以分为单位常见)
  84. $amountCents = $res['extendData']['amount'] ?? $res['data']['amount'] ?? $res['amount'] ?? null;
  85. $debug['parsed_amount'] = $amountCents;
  86. // 如果没有 amount 字段或为0,附加简单推测
  87. if ($amountCents === null) {
  88. $debug['note'] = 'missing_amount';
  89. Log::warning('[checkAmount] missing amount', ['user' => $user, 'response' => $res]);
  90. } elseif ($amountCents == 0) {
  91. $msg = $res['msg'] ?? $res['message'] ?? '';
  92. $reasons = [];
  93. if (stripos($msg, '未开户') !== false || stripos($msg, '未实名') !== false) $reasons[] = 'third_party_unopened_or_unverified';
  94. if (stripos($msg, '无账户') !== false) $reasons[] = 'account_not_found';
  95. if (stripos($msg, 'token') !== false) $reasons[] = 'token_issue_possible';
  96. if (empty($reasons)) $reasons[] = 'balance_is_zero';
  97. $debug['zero_reasons'] = $reasons;
  98. Log::warning('[checkAmount] amount is 0', ['user' => $user, 'reasons' => $reasons]);
  99. }
  100. // 把 debug 附加到返回(不破坏原始返回结构)
  101. if (is_array($res)) {
  102. $res['debug'] = $debug;
  103. return $res;
  104. }
  105. // 如果不是数组,包装返回
  106. return ['code' => 200, 'msg' => 'ok', 'extendData' => ['amount' => $amountCents], 'debug' => $debug];
  107. } catch (\Throwable $e) {
  108. $debug['exception'] = $e->getMessage();
  109. Log::error('[checkAmount] exception', ['user' => $user, 'err' => $e->getMessage()]);
  110. return ['code' => 500, 'msg' => 'exception', 'debug' => $debug];
  111. }
  112. }
  113. public function getAmountFromGzc()
  114. {
  115. $uid = $this->request->uid();
  116. $userInfo = Db::name('UserCertification')->where('uid', $uid)->field('user_name,user_card')->find();
  117. if (empty($userInfo['user_name']) || empty($userInfo['user_card'])) {
  118. Log::error('[getAmountFromGzc] 用户实名信息缺失', ['uid' => $uid, 'userInfo' => $userInfo]);
  119. return app('json')->fail('未找到用户实名信息');
  120. }
  121. try {
  122. $res = GzcApiRequest::checkAmount($userInfo);
  123. } catch (\Throwable $e) {
  124. Log::error('[getAmountFromGzc] 调用异常', ['uid' => $uid, 'error' => $e->getMessage()]);
  125. return app('json')->fail('查询失败(第三方异常)');
  126. }
  127. // 提取 amount(兼容多种字段位置)
  128. $amountCents = $res['extendData']['amount'] ?? $res['data']['amount'] ?? $res['amount'] ?? null;
  129. $amount = $amountCents === null ? 0.0 : floatval($amountCents) * 0.01;
  130. $formatted = sprintf('%.2f', $amount);
  131. // 从 checkAmount 返回的 debug(若存在)
  132. $debug = $res['debug'] ?? null;
  133. // 返回 amount 与 debug 给调用方(前端 / 调试)
  134. return app('json')->success([
  135. 'amount' => $formatted,
  136. 'debug' => $debug
  137. ]);
  138. }
  139. /**
  140. * 获取TOKEN
  141. * @return mixed|string
  142. * @author php迷途小书童
  143. * @created 2021/1/14 14:38
  144. */
  145. public static function getTokenFromServer()
  146. {
  147. $timestamp = (int)(microtime(true) * 1000);
  148. $appid = env('GZC.APP_ID');
  149. $data = [
  150. 'appid' => $appid,
  151. 'sign' => self::getSignContent($timestamp, $appid),
  152. 'timestamp' => $timestamp
  153. ];
  154. return self::request('POST', '/v1/api/third/auth/token', $data);
  155. }
  156. /**
  157. * 获取签名
  158. * @return string
  159. * @author php迷途小书童
  160. * @created 2020/10/29 9:35
  161. */
  162. public static function getSignContent(int $timestamp, string $appid) {
  163. $appsecret = md5(env('GZC.APP_SECRET'));
  164. $stringToBeSigned = "appid={$appid}&secret={$appsecret}&timestamp={$timestamp}";
  165. return md5($stringToBeSigned);
  166. }
  167. /**
  168. * @param $user
  169. * @return array|mixed|string
  170. * @author 史晨
  171. * @date 2025/10/22 11:05
  172. * 幸福保账户获取养老金
  173. */
  174. public static function getAmountXfb($user)
  175. {
  176. $debug = [];
  177. $data = [
  178. 'platformNo' => env('XINGFUBAO.PLATFORM_NO'),
  179. 'appNo' => env('XINGFUBAO.APP_NO'),
  180. 'conName' => $user['user_name'] ?? '',
  181. 'conCertType'=> 1,
  182. 'conCertNo' => $user['user_card'] ?? '',
  183. ];
  184. $debug['request'] = $data;
  185. try {
  186. // 记录请求(原有日志可保留或删除)
  187. Log::info('[checkAmount] request', $data);
  188. $res = self::request('POST', '/v1/api/third/in/in30', $data);
  189. $debug['raw_response'] = $res;
  190. // 尝试解析 amount(以分为单位常见)
  191. $amountCents = $res['extendData']['amount'] ?? $res['data']['amount'] ?? $res['amount'] ?? null;
  192. $debug['parsed_amount'] = $amountCents;
  193. // 如果没有 amount 字段或为0,附加简单推测
  194. if ($amountCents === null) {
  195. $debug['note'] = 'missing_amount';
  196. Log::warning('[checkAmount] missing amount', ['user' => $user, 'response' => $res]);
  197. } elseif ($amountCents == 0) {
  198. $msg = $res['msg'] ?? $res['message'] ?? '';
  199. $reasons = [];
  200. if (stripos($msg, '未开户') !== false || stripos($msg, '未实名') !== false) $reasons[] = 'third_party_unopened_or_unverified';
  201. if (stripos($msg, '无账户') !== false) $reasons[] = 'account_not_found';
  202. if (stripos($msg, 'token') !== false) $reasons[] = 'token_issue_possible';
  203. if (empty($reasons)) $reasons[] = 'balance_is_zero';
  204. $debug['zero_reasons'] = $reasons;
  205. Log::warning('[checkAmount] amount is 0', ['user' => $user, 'reasons' => $reasons]);
  206. }
  207. // 把 debug 附加到返回(不破坏原始返回结构)
  208. if (is_array($res)) {
  209. $res['debug'] = $debug;
  210. return $res;
  211. }
  212. // 如果不是数组,包装返回
  213. return ['code' => 200, 'msg' => 'ok', 'extendData' => ['amount' => $amountCents], 'debug' => $debug];
  214. } catch (\Throwable $e) {
  215. $debug['exception'] = $e->getMessage();
  216. Log::error('[checkAmount] exception', ['user' => $user, 'err' => $e->getMessage()]);
  217. return ['code' => 500, 'msg' => 'exception', 'debug' => $debug];
  218. }
  219. }
  220. }