UserAuth.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <?php
  2. /**
  3. * 实名认证
  4. */
  5. namespace app\api\controller\v1;
  6. use AlibabaCloud\SDK\Cloudauth\V20190307\Models\CompareFacesResponseBody\data;
  7. use AlibabaCloud\SDK\OSS\OSS\GetBucketRequestPaymentResponse\requestPaymentConfiguration;
  8. use app\api\services\DefaultServices;
  9. use app\common\model\MachineListModel;
  10. use app\common\model\MachineModel;
  11. use app\model\ShopOrderBonusModel as OrderBonus;
  12. use app\model\SocialTerm;
  13. use app\Request;
  14. use jobs\ShopBonusJob;
  15. use jobs\UserJobs;
  16. use think\facade\Db;
  17. use think\facade\Log;
  18. use utils\InitFaceVerify;
  19. use utils\Queue;
  20. use utils\Sample;
  21. class UserAuth
  22. {
  23. protected $RealNameUrl = 'https://cloudauth.aliyuncs.com';
  24. protected $TokenApi = 'DescribeVerifyToken';
  25. protected $VerifyApi = 'VerifyMaterial';
  26. protected $AccessKey;
  27. protected $Secret;
  28. protected $Scene = 'zysmrz';
  29. protected $scene_id = 1000003608; // 认证场景ID 2022-3-3 更换为金融级实名认证
  30. protected $time = '';
  31. protected $error = '';
  32. protected static $user;
  33. public function __construct ()
  34. {
  35. $this->AccessKey = env('aliyun.ACCESS_KEY_FACE');
  36. $this->Secret = env('aliyun.SECRET_KEY_FACE');
  37. }
  38. /**
  39. * 支付状态
  40. * @param Request $request
  41. * @return mixed
  42. * @throws \think\db\exception\DataNotFoundException
  43. * @throws \think\db\exception\DbException
  44. * @throws \think\db\exception\ModelNotFoundException
  45. */
  46. public function authPayStatus (Request $request)
  47. {
  48. $uid = $request->uid;
  49. return api_succ_return('已支付');
  50. $result = self::_before($uid);
  51. if (!$result['flag'])
  52. return api_error_return(['msg'=>$result['msg'], 'code'=>$result['code']]);
  53. return api_succ_return('已支付');
  54. }
  55. /**
  56. * 获取支付宝token
  57. * @param Request $request
  58. * @return mixed
  59. * @throws \think\db\exception\DataNotFoundException
  60. * @throws \think\db\exception\DbException
  61. * @throws \think\db\exception\ModelNotFoundException
  62. */
  63. public function aliToken (Request $request)
  64. {
  65. $uid = $request->uid;
  66. $result = self::_before($uid);
  67. if (!$result['flag'])
  68. return api_error_return(['msg'=>$result['msg'], 'code'=>$result['code']]);
  69. $data = array( // 请求参数
  70. 'BizId' => md5($uid),
  71. 'BizType' => $this->Scene,
  72. 'AccessKey' => $this->AccessKey,
  73. 'Secret' => $this->Secret
  74. );
  75. try {
  76. // $aliyun = new InitFaceVerify();
  77. // $client = InitFaceVerify::createClient('', env('aliyun.ACCESS_KEY'), env('aliyun.SECRET_KEY'));
  78. $initface = new InitFaceVerify();
  79. $initface::get_token($data);
  80. // /** @var Sample $aliyun */
  81. $aliyun = new Sample();
  82. $rpm = $aliyun::get_token($data);
  83. //
  84. // if (!empty($rpm['body']['verifyToken'])) {
  85. // return api_succ_return(['token' => $rpm['body']['verifyToken']]);
  86. // }
  87. } catch (\Exception $e) {
  88. return api_error_return($e->getMessage());
  89. }
  90. }
  91. // 获取支付宝token金融级别
  92. public function aliFinanceToken (Request $request)
  93. {
  94. if (!$request->post('meta_info')){
  95. return api_error_return('参数错误');
  96. }
  97. $uid = $request->uid;
  98. $result = self::_before($uid);
  99. // return $result;
  100. if (!$result['flag'])
  101. return api_error_return(['msg'=>$result['msg'], 'code'=>$result['code']]);
  102. // return app('json')->json_error($result['msg'], $result['code']);
  103. $rz_nonce_str = md5(nonce_str() . '_' . $uid); // 认证随机字符串
  104. $data = array( // 请求参数
  105. 'outerOrderNo' => $rz_nonce_str,
  106. 'sceneId' => $this->scene_id,
  107. 'AccessKey' => $this->AccessKey,
  108. 'Secret' => $this->Secret,
  109. 'metaInfo' => html_entity_decode($request->data['meta_info']),
  110. 'CertName'=>$request->post('cert_name'),
  111. 'CertNo'=>$request->post('cert_no')
  112. );
  113. $cur_user = Db::name('user_data')->where('idcard', $request->post('cert_no'))->find();
  114. // return $cur_user;
  115. if ($cur_user) {
  116. // 被其他暂用 没认证 清除
  117. $user = Db::name('user')->where('id', $cur_user['uid'])->find();
  118. if ($user){
  119. if (!($user['is_auth'] == 1)){
  120. Db::name('user_data')->where('idcard', $request->post('cert_no'))->save(['idcard'=>'', 'idname'=>'']);
  121. Db::name('user_data')->where('uid', $uid)->update(['idcard' => $request->post('cert_no'), 'idname' => $request->post('cert_name'), 'bank_no' => '']);
  122. }else{
  123. return api_error_return('该身份证已被其他账号认证了');
  124. }
  125. }else{
  126. Db::name('user_data')->where('idcard', $request->post('cert_no'))->save(['idcard'=>'', 'idname'=>'']);
  127. }
  128. }else{
  129. Db::name('user_data')->where('uid', $uid)->update(['idcard' => $request->post('cert_no'), 'idname' => $request->post('cert_name'), 'bank_no' => '']);
  130. }
  131. // 判断是否失败过多直接报错
  132. // $count = Db::name('getali_token')->whereDay('create_time', 'today')->where('uid', $request->uid)->count();
  133. // if ($count > 3){
  134. // return api_error_return('失败次数过多,请联系客服');
  135. // }
  136. try {
  137. /** @var Sample $aliyun */
  138. $aliyun = app()->make(Sample::class);
  139. $rpm = $aliyun::get_finance_token($data);
  140. if (!empty($rpm['body']['resultObject']['certifyId'])) {
  141. Db::name('user_data')->where('uid', $uid)->save(['rz_nonce_str' => $rz_nonce_str, 'ali_certify_id' => $rpm['body']['resultObject']['certifyId']]); // 更新随机字符串
  142. return api_succ_return(['msg'=>'success', 'data'=>['token' => $rpm['body']['resultObject']['certifyId']]]);
  143. } else {
  144. // sr_log('实名认证获取token失败【'.$request->uid.'】'.json_encode($rpm));
  145. Db::name('getali_token')->insertGetId([
  146. 'uid'=>$request->uid,
  147. 'content'=>json_encode($rpm),
  148. 'create_time'=>sr_getcurtime(time()),
  149. 'ip'=>$request->ip()
  150. ]);
  151. if (intval($rpm['body']['code']) == 401){
  152. return api_error_return('请检查填写的真实姓名跟身份证号码,(不能输入空格和其他特殊字符,英文字母大写),如还有问题跟客服沟通');
  153. }
  154. if (intval($rpm['body']['code']) == 418){
  155. return api_error_return('当天刷脸认证次数过多,请明天再试。');
  156. }
  157. return api_error_return('获取失败,请提供手机号联系客服');
  158. }
  159. } catch (\Exception $e) {
  160. return api_error_return($e->getMessage());
  161. // return app('json')->json_error($e->getMessage());
  162. }
  163. }
  164. // 获取实名认证结果
  165. public function authFinanceResult (Request $request)
  166. {
  167. $uid = $request->uid;
  168. $result = self::_before($uid);
  169. if (!$result['flag'])
  170. return api_error_return(['msg'=>$result['msg'], 'code'=>$result['code']]);
  171. $data = array( // 请求参数
  172. 'CertifyId' => Db::name('user_data')->where('uid', $uid)->value('ali_certify_id'),
  173. 'SceneId' => $this->scene_id,
  174. 'AccessKey' => $this->AccessKey,
  175. 'Secret' => $this->Secret
  176. );
  177. try {
  178. /** @var Sample $aliyun */
  179. $aliyun = app()->make(Sample::class);
  180. $rpm = $aliyun::get_finance_result($data);
  181. } catch (\Exception $e) {
  182. return api_error_return($e->getMessage());
  183. }
  184. if ($rpm['body']['code'] == '200') {
  185. $rpm = $rpm['body']['resultObject'];
  186. sr_log('shim'. $uid.'---');
  187. $res = self::_afterFinance($uid, $rpm, $result['order_id']);
  188. if (!$res['flag']) {
  189. return api_error_return($res['msg']);
  190. } else {
  191. return api_succ_return('认证成功');
  192. }
  193. }else{
  194. sr_log('获取实名结果失败【uid:'.$request->uid.'】'.json_encode($rpm));
  195. }
  196. return api_error_return('实名认证失败');
  197. }
  198. private static function _afterFinance (int $uid, array $rpm, $pay_order='111', $type = 1): array
  199. {
  200. if (!in_array($rpm['subCode'], [200, 210])) { // 认证未通过
  201. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'type' => $type, 'status' => 2, 'order_id' => $pay_order, 'remarks' => '身份信息错误,认证失败', 'desc' => json_encode($rpm)]);
  202. return ['flag' => false, 'msg' => '身份信息错误,认证失败,请检查实名人脸跟输入身份信息是否匹配'];
  203. }
  204. $materialInfo = json_decode($rpm['materialInfo'], true);
  205. $data = $materialInfo; // 身份信息
  206. // sr_log($data);
  207. $score = $materialInfo['facialPictureFront']['verifyScore']; // 相似度
  208. $header = $materialInfo['facialPictureFront']['pictureUrl']; // 照片
  209. // [$real_name, $idcard, $img, $pay_order] = [$data['certName'], $data['certNo'], $header, $pay_order];
  210. [$img, $pay_order] = [ $header, $pay_order];
  211. // if (Db::name('user_data')->where('idcard', $idcard)->value('idcard')) {
  212. // Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'type' => $type, 'status' => 2, 'order_id' => $pay_order, 'remarks' => '该身份证已被其他账号认证了', 'desc' => json_encode($rpm)]);
  213. // return ['flag' => false, 'msg' => '该身份证已被其他账号认证了'];
  214. // }
  215. if ($type == 4) {
  216. if (Db::name('user_data')->where('bankno', $data['bankno'])->value('bankno')) {
  217. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'type' => $type, 'status' => 2, 'order_id' => $pay_order, 'remarks' => '该银行卡已被绑定', 'desc' => json_encode($rpm)]);
  218. return ['flag' => false, 'msg' => '该银行卡已被绑定'];
  219. }
  220. }
  221. Db::startTrans();
  222. try {
  223. // $bankno = isset($data['bankno']) ? $data['bankno'] : '';
  224. // Db::name('user_data')->where('uid', $uid)->update(['idcard' => $idcard, 'idname' => $real_name, 'bank_no' => $bankno]);
  225. Db::name('user')->where('id', $uid)->update(['is_auth' => 1]);
  226. $userinfo = Db::name('user')->where('id', $uid)->find();
  227. // 实名赠送一个优先勋章
  228. edit_user_medal(3,$uid, 1);
  229. incTeamStatic($uid, 2, $userinfo['path']);
  230. incTodayTeamStatic($uid, 2, $userinfo['path']);
  231. // Db::name('user_shouxuefeilog')->insert([
  232. // 'uid'=>$userinfo['pid'],
  233. // 'type'=>2,
  234. // 'create_time'=>sr_getcurtime(time()),
  235. // 'count'=>1
  236. // ]);
  237. Db::name('auth_log')->insert(['uid' => $uid, 'pid' => $userinfo['pid'], 'type' => $type, 'auth_time' => time(), 'status' => 1, 'order_id' => $pay_order, 'remarks' => '实名认证成功', 'desc' => json_encode($rpm), 'img' => '', 'score' => $score]);
  238. // 新手矿机
  239. $info = MachineModel::where('mlevel', 999)->find();
  240. $m_machinelist = new MachineListModel();
  241. $time = time();
  242. // $m_machinelist->insert([
  243. // 'mid'=>$info['id'],
  244. // 'create_time'=>sr_getcurtime($time),
  245. // 'expire_time'=> sr_getcurtime(strtotime("+ ".$info['valid_day']." days")),
  246. // 'back_count'=>$info['cycle'],
  247. // 'once_back'=>number_format($info['total_number']/$info['cycle'], '4', '.', ''),
  248. // 'over_count'=>$info['cycle'],
  249. // 'get_type'=>2,
  250. // 'uid'=>$uid
  251. // ]);
  252. edit_user_active(2, $uid, $info['add_active']);
  253. Db::commit();
  254. return ['flag' => true, 'msg' => '认证成功'];
  255. } catch (\Exception $e) {
  256. Db::rollback();
  257. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'status' => 2, 'order_id' => $pay_order, 'remarks' => '实名认证失败' . $e->getMessage() . 'Line:' . $e->getLine()]);
  258. // return ['flag' => false, 'msg' => '实名认证失败'];
  259. return ['flag' => false, 'msg' => $e->getMessage()];
  260. }
  261. }
  262. /**
  263. * 认证结果
  264. * @param Request $request
  265. * @param DefaultServices $services
  266. * @return mixed
  267. * @throws \think\db\exception\DataNotFoundException
  268. * @throws \think\db\exception\DbException
  269. * @throws \think\db\exception\ModelNotFoundException
  270. */
  271. public function authResult (Request $request, DefaultServices $services)
  272. {
  273. $uid = $request->uid;
  274. $result = self::_before($uid);
  275. if (!$result['flag'])
  276. return api_error_return(['msg'=>$result['msg'], 'code'=>$result['code']]);
  277. $data = array( // 请求参数
  278. 'BizId' => md5($uid),
  279. 'BizType' => $this->Scene,
  280. 'AccessKey' => $this->AccessKey,
  281. 'Secret' => $this->Secret
  282. );
  283. try {
  284. /** @var Sample $aliyun */
  285. $aliyun = app()->make(Sample::class);
  286. $rpm = $aliyun::get_result($data);
  287. } catch (\Exception $e) {
  288. return api_error_return('error');
  289. }
  290. if ($rpm['body']['verifyStatus'] == 1) {
  291. $res = self::_after($uid, $rpm, $result['order_id'], $services);
  292. if (!$res['flag']) {
  293. return api_error_return($res['msg']);
  294. } else {
  295. return api_succ_return('认证成功');
  296. }
  297. }
  298. return api_error_return('实名认证失败');
  299. }
  300. /**
  301. * 前置验证
  302. * @param int $uid
  303. * @return array
  304. * @throws \think\db\exception\DataNotFoundException
  305. * @throws \think\db\exception\DbException
  306. * @throws \think\db\exception\ModelNotFoundException
  307. */
  308. private static function _before (int $uid)
  309. {
  310. self::$user = Db::name('user')->field('id,is_auth,pid')->find(['id' => $uid]);
  311. if (self::$user['is_auth'])
  312. return ['flag' => false, 'code' => 400, 'msg' => '你已经认证过了'];
  313. $pay_order = Db::name('payment')->where([
  314. ['uid', '=', $uid],
  315. ['order_type', '=', 2],
  316. ['state', '=', 6],
  317. ['pay_at', '<>', '']
  318. ])->order('pay_at', 'desc')->value('id');
  319. if (!$pay_order)
  320. // return ['flag' => false, 'code' => 300, 'msg' => '你还未支付实名认证费用'];
  321. if (Db::name('auth_log')->where('uid', $uid)->where('order_id', $pay_order)->count() >= 3) { // 认证次数
  322. return ['flag' => false, 'code' => 300, 'msg' => '重复认证,每个身份信息只能提交3次'];
  323. }
  324. return ['flag' => true, 'order_id' => $pay_order];
  325. }
  326. /**
  327. * 后置操作
  328. * @param int $uid
  329. * @param array $rpm
  330. * @param int $pay_order
  331. * @param $services
  332. * @return array
  333. */
  334. private static function _after (int $uid, array $rpm, int $pay_order, $services): array
  335. {
  336. $data = $rpm['body']['material'];
  337. $score = $rpm['body']['authorityComparisionScore']; // 相似度
  338. [$real_name, $idcard, $img, $pay_order] = [$data['idCardName'], $data['idCardNumber'], $data['faceImageUrl'], $pay_order];
  339. if (Db::name('user_data')->where('idcard', $idcard)->value('idcard')) {
  340. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'status' => 2, 'order_id' => $pay_order, 'remarks' => '该身份证已被其他账号认证了', 'desc' => json_encode($data)]);
  341. return ['flag' => false, 'msg' => '该身份证已被其他账号认证了'];
  342. }
  343. Db::startTrans();
  344. try {
  345. Db::name('user_data')->where('uid', $uid)->update(['idcard' => $idcard, 'idname' => $real_name]);
  346. Db::name('user')->where('id', $uid)->update(['is_auth' => 1]);
  347. Db::name('auth_log')->insert(['uid' => $uid, 'pid' => self::$user['pid'], 'auth_time' => time(), 'status' => 1, 'order_id' => $pay_order, 'remarks' => '实名认证成功', 'desc' => json_encode($data), 'img' => $img, 'score' => $score]);
  348. /** @var DefaultServices $services */
  349. $services->incTeamStatic($uid);
  350. /**
  351. * 自动加入新人社区,加入市场部创建的新手社区
  352. */
  353. // if (self::$user['market_uid'] && self::$user['market_uid'] != self::$user['id']) {
  354. // $social = Db::name('social')->where(['uid' => self::$user['market_uid'], 'term_id' => 0, 'type' => 0])->findOrEmpty();
  355. // if (!empty($social)) {
  356. // Db::name('social_join')->insert(['uid' => self::$user['id'], 's_id' => $social['id'], 'term_id' => $social['term_id'], 'type' => 2]);
  357. // }
  358. // }
  359. /**
  360. * 首码扶持奖励
  361. */
  362. // if (self::$user['firstcode_uid'] && self::$user['firstcode_uid'] != self::$user['id']) {
  363. // Db::name('user')->where('id', self::$user['firstcode_uid'])->inc('support_money', 1.5)->update();
  364. // Db::name('support_money_log')->insert([
  365. // 'uid' => self::$user['support_money'],
  366. // 'money' => 1.5,
  367. // 'from_id' => self::$user['id'],
  368. // 'before_money' => self::$user['support_money'],
  369. // 'after_money' => self::$user['support_money'] + 1.5,
  370. // ]);
  371. // }
  372. Db::commit();
  373. if (self::$user['pid']) // 上级获得邀新奖励
  374. {
  375. Queue::instance()->log('邀新执行成功')->job(UserJobs::class)->do('inviteRewards')->push([self::$user['pid'], $uid]);
  376. Queue::instance()->log('上级订单加速执行成功')->job(ShopBonusJob::class)->do('ShopBonusInviteQuickenJob')->push([self::$user['pid']]);
  377. }
  378. return ['flag' => true, 'msg' => '认证成功'];
  379. } catch (\Exception $e) {
  380. Db::rollback();
  381. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'status' => 2, 'order_id' => $pay_order, 'remarks' => '实名认证失败',]);
  382. return ['flag' => false, 'msg' => '实名认证失败'];
  383. }
  384. }
  385. }