UserAuth.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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. $initface = new InitFaceVerify();
  77. $initface::get_token($data);
  78. $aliyun = new Sample();
  79. $rpm = $aliyun::get_token($data);
  80. } catch (\Exception $e) {
  81. return api_error_return($e->getMessage());
  82. }
  83. }
  84. // 获取支付宝token金融级别
  85. public function aliFinanceToken (Request $request)
  86. {
  87. if (!$request->post('meta_info')){
  88. return api_error_return('参数错误');
  89. }
  90. $uid = $request->uid;
  91. $result = self::_before($uid);
  92. if (!$result['flag'])
  93. return api_error_return(['msg'=>$result['msg'], 'code'=>$result['code']]);
  94. $rz_nonce_str = md5(nonce_str() . '_' . $uid); // 认证随机字符串
  95. $data = array( // 请求参数
  96. 'outerOrderNo' => $rz_nonce_str,
  97. 'sceneId' => $this->scene_id,
  98. 'AccessKey' => $this->AccessKey,
  99. 'Secret' => $this->Secret,
  100. 'metaInfo' => html_entity_decode($request->data['meta_info']),
  101. 'CertName'=>$request->post('cert_name'),
  102. 'CertNo'=>$request->post('cert_no')
  103. );
  104. $cur_user = Db::name('user_data')->where('idcard', $request->post('cert_no'))->find();
  105. // return $cur_user;
  106. if ($cur_user) {
  107. // 被其他暂用 没认证 清除
  108. $user = Db::name('user')->where('id', $cur_user['uid'])->find();
  109. if ($user){
  110. if (!($user['is_auth'] == 1)){
  111. Db::name('user_data')->where('idcard', $request->post('cert_no'))->save(['idcard'=>'', 'idname'=>'']);
  112. Db::name('user_data')->where('uid', $uid)->update(['idcard' => $request->post('cert_no'), 'idname' => $request->post('cert_name'), 'bank_no' => '']);
  113. }else{
  114. return api_error_return('该身份证已被其他账号认证了');
  115. }
  116. }else{
  117. Db::name('user_data')->where('idcard', $request->post('cert_no'))->save(['idcard'=>'', 'idname'=>'']);
  118. }
  119. }else{
  120. Db::name('user_data')->where('uid', $uid)->update(['idcard' => $request->post('cert_no'), 'idname' => $request->post('cert_name'), 'bank_no' => '']);
  121. }
  122. try {
  123. /** @var Sample $aliyun */
  124. $aliyun = app()->make(Sample::class);
  125. $rpm = $aliyun::get_finance_token($data);
  126. if (!empty($rpm['body']['resultObject']['certifyId'])) {
  127. Db::name('user_data')->where('uid', $uid)->save(['rz_nonce_str' => $rz_nonce_str, 'ali_certify_id' => $rpm['body']['resultObject']['certifyId']]); // 更新随机字符串
  128. return api_succ_return(['msg'=>'success', 'data'=>['token' => $rpm['body']['resultObject']['certifyId']]]);
  129. } else {
  130. // sr_log('实名认证获取token失败【'.$request->uid.'】'.json_encode($rpm));
  131. Db::name('getali_token')->insertGetId([
  132. 'uid'=>$request->uid,
  133. 'content'=>json_encode($rpm),
  134. 'create_time'=>sr_getcurtime(time()),
  135. 'ip'=>$request->ip()
  136. ]);
  137. if (intval($rpm['body']['code']) == 401){
  138. return api_error_return('请检查填写的真实姓名跟身份证号码,(不能输入空格和其他特殊字符,英文字母大写),如还有问题跟客服沟通');
  139. }
  140. if (intval($rpm['body']['code']) == 418){
  141. return api_error_return('当天刷脸认证次数过多,请明天再试。');
  142. }
  143. return api_error_return('获取失败,请提供手机号联系客服');
  144. }
  145. } catch (\Exception $e) {
  146. return api_error_return($e->getMessage());
  147. }
  148. }
  149. // 获取实名认证结果
  150. public function authFinanceResult (Request $request)
  151. {
  152. $uid = $request->uid;
  153. $result = self::_before($uid);
  154. if (!$result['flag'])
  155. return api_error_return(['msg'=>$result['msg'], 'code'=>$result['code']]);
  156. $data = array( // 请求参数
  157. 'CertifyId' => Db::name('user_data')->where('uid', $uid)->value('ali_certify_id'),
  158. 'SceneId' => $this->scene_id,
  159. 'AccessKey' => $this->AccessKey,
  160. 'Secret' => $this->Secret
  161. );
  162. try {
  163. /** @var Sample $aliyun */
  164. $aliyun = app()->make(Sample::class);
  165. $rpm = $aliyun::get_finance_result($data);
  166. } catch (\Exception $e) {
  167. return api_error_return($e->getMessage());
  168. }
  169. if ($rpm['body']['code'] == '200') {
  170. $rpm = $rpm['body']['resultObject'];
  171. sr_log('shim'. $uid.'---');
  172. $res = self::_afterFinance($uid, $rpm, $result['order_id']);
  173. if (!$res['flag']) {
  174. return api_error_return($res['msg']);
  175. } else {
  176. return api_succ_return('认证成功');
  177. }
  178. }else{
  179. sr_log('获取实名结果失败【uid:'.$request->uid.'】'.json_encode($rpm));
  180. }
  181. return api_error_return('实名认证失败');
  182. }
  183. private static function _afterFinance (int $uid, array $rpm, $pay_order='111', $type = 1): array
  184. {
  185. if (!in_array($rpm['subCode'], [200, 210])) { // 认证未通过
  186. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'type' => $type, 'status' => 2, 'order_id' => $pay_order, 'remarks' => '身份信息错误,认证失败', 'desc' => json_encode($rpm)]);
  187. return ['flag' => false, 'msg' => '身份信息错误,认证失败,请检查实名人脸跟输入身份信息是否匹配'];
  188. }
  189. $materialInfo = json_decode($rpm['materialInfo'], true);
  190. $data = $materialInfo; // 身份信息
  191. // sr_log($data);
  192. $score = $materialInfo['facialPictureFront']['verifyScore']; // 相似度
  193. $header = $materialInfo['facialPictureFront']['pictureUrl']; // 照片
  194. // [$real_name, $idcard, $img, $pay_order] = [$data['certName'], $data['certNo'], $header, $pay_order];
  195. [$img, $pay_order] = [ $header, $pay_order];
  196. // if (Db::name('user_data')->where('idcard', $idcard)->value('idcard')) {
  197. // Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'type' => $type, 'status' => 2, 'order_id' => $pay_order, 'remarks' => '该身份证已被其他账号认证了', 'desc' => json_encode($rpm)]);
  198. // return ['flag' => false, 'msg' => '该身份证已被其他账号认证了'];
  199. // }
  200. if ($type == 4) {
  201. if (Db::name('user_data')->where('bankno', $data['bankno'])->value('bankno')) {
  202. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'type' => $type, 'status' => 2, 'order_id' => $pay_order, 'remarks' => '该银行卡已被绑定', 'desc' => json_encode($rpm)]);
  203. return ['flag' => false, 'msg' => '该银行卡已被绑定'];
  204. }
  205. }
  206. Db::startTrans();
  207. try {
  208. Db::name('user')->where('id', $uid)->update(['is_auth' => 1]);
  209. $userinfo = Db::name('user')->where('id', $uid)->find();
  210. // 实名赠送一个优先勋章
  211. edit_user_medal(3,$uid, 1);
  212. incTeamStatic($uid, 2, $userinfo['path']);
  213. incTodayTeamStatic($uid, 2, $userinfo['path']);
  214. 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]);
  215. // 新手矿机
  216. $info = MachineModel::where('mlevel', 999)->find();
  217. edit_user_active(2, $uid, $info['add_active']);
  218. Db::commit();
  219. return ['flag' => true, 'msg' => '认证成功'];
  220. } catch (\Exception $e) {
  221. Db::rollback();
  222. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'status' => 2, 'order_id' => $pay_order, 'remarks' => '实名认证失败' . $e->getMessage() . 'Line:' . $e->getLine()]);
  223. return ['flag' => false, 'msg' => $e->getMessage()];
  224. }
  225. }
  226. /**
  227. * 认证结果
  228. * @param Request $request
  229. * @param DefaultServices $services
  230. * @return mixed
  231. * @throws \think\db\exception\DataNotFoundException
  232. * @throws \think\db\exception\DbException
  233. * @throws \think\db\exception\ModelNotFoundException
  234. */
  235. public function authResult (Request $request, DefaultServices $services)
  236. {
  237. $uid = $request->uid;
  238. $result = self::_before($uid);
  239. if (!$result['flag'])
  240. return api_error_return(['msg'=>$result['msg'], 'code'=>$result['code']]);
  241. $data = array( // 请求参数
  242. 'BizId' => md5($uid),
  243. 'BizType' => $this->Scene,
  244. 'AccessKey' => $this->AccessKey,
  245. 'Secret' => $this->Secret
  246. );
  247. try {
  248. /** @var Sample $aliyun */
  249. $aliyun = app()->make(Sample::class);
  250. $rpm = $aliyun::get_result($data);
  251. } catch (\Exception $e) {
  252. return api_error_return('error');
  253. }
  254. if ($rpm['body']['verifyStatus'] == 1) {
  255. $res = self::_after($uid, $rpm, $result['order_id'], $services);
  256. if (!$res['flag']) {
  257. return api_error_return($res['msg']);
  258. } else {
  259. return api_succ_return('认证成功');
  260. }
  261. }
  262. return api_error_return('实名认证失败');
  263. }
  264. /**
  265. * 前置验证
  266. * @param int $uid
  267. * @return array
  268. * @throws \think\db\exception\DataNotFoundException
  269. * @throws \think\db\exception\DbException
  270. * @throws \think\db\exception\ModelNotFoundException
  271. */
  272. private static function _before (int $uid)
  273. {
  274. self::$user = Db::name('user')->field('id,is_auth,pid')->find(['id' => $uid]);
  275. if (self::$user['is_auth'])
  276. return ['flag' => false, 'code' => 400, 'msg' => '你已经认证过了'];
  277. $pay_order = Db::name('payment')->where([
  278. ['uid', '=', $uid],
  279. ['order_type', '=', 2],
  280. ['state', '=', 6],
  281. ['pay_at', '<>', '']
  282. ])->order('pay_at', 'desc')->value('id');
  283. if (!$pay_order)
  284. // return ['flag' => false, 'code' => 300, 'msg' => '你还未支付实名认证费用'];
  285. if (Db::name('auth_log')->where('uid', $uid)->where('order_id', $pay_order)->count() >= 3) { // 认证次数
  286. return ['flag' => false, 'code' => 300, 'msg' => '重复认证,每个身份信息只能提交3次'];
  287. }
  288. return ['flag' => true, 'order_id' => $pay_order];
  289. }
  290. /**
  291. * 后置操作
  292. * @param int $uid
  293. * @param array $rpm
  294. * @param int $pay_order
  295. * @param $services
  296. * @return array
  297. */
  298. private static function _after (int $uid, array $rpm, int $pay_order, $services): array
  299. {
  300. $data = $rpm['body']['material'];
  301. $score = $rpm['body']['authorityComparisionScore']; // 相似度
  302. [$real_name, $idcard, $img, $pay_order] = [$data['idCardName'], $data['idCardNumber'], $data['faceImageUrl'], $pay_order];
  303. if (Db::name('user_data')->where('idcard', $idcard)->value('idcard')) {
  304. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'status' => 2, 'order_id' => $pay_order, 'remarks' => '该身份证已被其他账号认证了', 'desc' => json_encode($data)]);
  305. return ['flag' => false, 'msg' => '该身份证已被其他账号认证了'];
  306. }
  307. Db::startTrans();
  308. try {
  309. Db::name('user_data')->where('uid', $uid)->update(['idcard' => $idcard, 'idname' => $real_name]);
  310. Db::name('user')->where('id', $uid)->update(['is_auth' => 1]);
  311. 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]);
  312. /** @var DefaultServices $services */
  313. $services->incTeamStatic($uid);
  314. Db::commit();
  315. if (self::$user['pid']) // 上级获得邀新奖励
  316. {
  317. Queue::instance()->log('邀新执行成功')->job(UserJobs::class)->do('inviteRewards')->push([self::$user['pid'], $uid]);
  318. Queue::instance()->log('上级订单加速执行成功')->job(ShopBonusJob::class)->do('ShopBonusInviteQuickenJob')->push([self::$user['pid']]);
  319. }
  320. return ['flag' => true, 'msg' => '认证成功'];
  321. } catch (\Exception $e) {
  322. Db::rollback();
  323. Db::name('auth_log')->insert(['uid' => $uid, 'auth_time' => time(), 'status' => 2, 'order_id' => $pay_order, 'remarks' => '实名认证失败',]);
  324. return ['flag' => false, 'msg' => '实名认证失败'];
  325. }
  326. }
  327. }