UploadForm.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. namespace common\models\forms;
  3. use common\helpers\Cache;
  4. use common\components\Model;
  5. use common\helpers\Date;
  6. use common\helpers\Excel;
  7. use common\helpers\Form;
  8. use common\helpers\http\RemoteUploadApi;
  9. use common\helpers\LoggerTool;
  10. use common\helpers\ocr\OcrApi;
  11. use common\helpers\Tool;
  12. use common\helpers\user\Info;
  13. use common\models\ExcelAddUser;
  14. use common\models\ExcelImport;
  15. use common\models\InvoiceAudit;
  16. use common\models\Recharge;
  17. use common\models\Uploads;
  18. use common\models\User;
  19. use common\models\Withdraw;
  20. use yii\base\Exception;
  21. /**
  22. * Login form
  23. */
  24. class UploadForm extends Model {
  25. public $file;
  26. public $excelOption; // 导入的excel文件用来干什么,存入excel导入表
  27. public $token;
  28. public $remark;
  29. public $withdrawId;
  30. public $rechargeId;
  31. private $_ocrResult;
  32. private $_remoteScenario = [
  33. // 'idCardFront', 'idCardBack', 'ad', 'invoiceFront','proveFront','goodsImg'
  34. ];
  35. /**
  36. * @inheritdoc
  37. */
  38. public function rules() {
  39. return [
  40. [['remark', 'withdrawId', 'rechargeId'], 'trim'],
  41. [['file', 'token', 'excelOption'], 'required'],
  42. [['token'], 'isToken'],
  43. [['file'], 'file'],
  44. [['file'], 'file', 'mimeTypes' => ['image/jpeg', 'image/png', 'image/x-png'], 'on' => ['idCardFront', 'idCardBack', 'ad']],
  45. // todo 暂时屏蔽
  46. // [['file'], 'file', 'mimeTypes'=>['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'text/csv'], 'on'=>['excel']],
  47. [['file'], 'isIdCardFront', 'on' => ['idCardFront']],
  48. [['file'], 'isInvoiceFront', 'on' => ['invoiceFront']],
  49. //[['file'], 'isIdCardBack', 'on'=>['idCardBack']],
  50. ];
  51. }
  52. /**
  53. * 指定校验场景
  54. * @return array
  55. */
  56. public function scenarios() {
  57. $parentScenarios = parent::scenarios();
  58. $customScenarios = [
  59. 'idCardFront' => ['file', 'token'],
  60. 'idCardBack' => ['file', 'token'],
  61. 'invoiceFront' => ['file', 'token', 'remark', 'withdrawId'],
  62. 'proveFront' => ['file', 'token', 'rechargeId'],
  63. 'ad' => ['file', 'token'],
  64. 'article' => ['file', 'token'],
  65. 'excel' => ['file', 'token', 'excelOption'],
  66. 'goodsImg' => ['file', 'token'],
  67. 'order' => ['file', 'token'],
  68. ];
  69. return array_merge($parentScenarios, $customScenarios);
  70. }
  71. public function attributeLabels() {
  72. return [
  73. 'file' => '文件',
  74. ];
  75. }
  76. /**
  77. * 校验上传token
  78. * @param $attributes
  79. */
  80. public function isToken($attributes) {
  81. if (!Cache::getUploadToken($this->token)) {
  82. $this->addError($attributes, '上传token校验失败');
  83. }
  84. }
  85. /**
  86. * 是否是身份证
  87. * @param $attributes
  88. */
  89. public function isIdCardFront($attributes) {
  90. // 查看该用户是否已经上传过身份证照片
  91. $oneData = User::find()->select('ID_IMAGE')->where('ID=:ID', [':ID' => \Yii::$app->user->id])->asArray()->one();
  92. if ($oneData['ID_IMAGE']) {
  93. $this->addError($attributes, '您已上传过身份证照片');
  94. }
  95. $this->_ocrResult = OcrApi::instance()->idCard($this->file->tempName);
  96. if (!$this->_ocrResult['success']) {
  97. $this->addError($attributes, $this->_ocrResult['message']);
  98. }
  99. }
  100. /**
  101. * 前台上传发票
  102. * @param $attributes
  103. */
  104. public function isInvoiceFront($attributes) {
  105. $this->_ocrResult = OcrApi::instance()->vatInvoice($this->file->tempName);
  106. if (!$this->_ocrResult['success']) {
  107. $this->addError($attributes, $this->_ocrResult['message']);
  108. }
  109. }
  110. /**
  111. * 上传
  112. * @throws \yii\db\Exception
  113. */
  114. public function upload() {
  115. if (!$this->validate()) {
  116. return false;
  117. }
  118. $oneUser = User::findOne(['ID' => \Yii::$app->user->id]);
  119. $db = \Yii::$app->db;
  120. $transaction = $db->beginTransaction();
  121. try {
  122. $fileName = '';
  123. switch ($this->scenario) {
  124. case 'invoiceFront':
  125. $uploadCategory = Uploads::CATEGORY_INVOICE;
  126. $uploadRemark = $this->remark;
  127. break;
  128. case 'idCardFront':
  129. $uploadCategory = Uploads::CATEGORY_ID_CARD;
  130. $uploadRemark = $this->_ocrResult['realName'] . '身份证正面';
  131. break;
  132. case 'idCardBack':
  133. $uploadCategory = Uploads::CATEGORY_ID_CARD;
  134. $uploadRemark = $oneUser['REAL_NAME'] . '身份证背面';
  135. break;
  136. case 'proveFront':
  137. case 'goodsImg':
  138. case 'ad':
  139. $uploadCategory = Uploads::CATEGORY_IMAGE;
  140. $uploadRemark = $this->file->baseName;
  141. break;
  142. case 'excel':
  143. $uploadCategory = Uploads::CATEGORY_EXCEL;
  144. $uploadRemark = $this->file->baseName;
  145. break;
  146. case 'order':
  147. if ($this->file->extension != 'csv') {
  148. LoggerTool::info($this->file->extension);
  149. throw new Exception('只能导入csv文件');
  150. }
  151. $uploadCategory = Uploads::CATEGORY_ORDER;
  152. $fileName = date('YmdHis') . mt_rand(1000, 9999);
  153. $uploadRemark = $this->file->baseName;
  154. break;
  155. default :
  156. $uploadCategory = Uploads::CATEGORY_UN_KNOW;
  157. $uploadRemark = $this->file->baseName;
  158. break;
  159. }
  160. $localPath = '';
  161. // 上传图片到远程服务器
  162. if (in_array($this->scenario, $this->_remoteScenario)) {
  163. $remoteUploadApi = RemoteUploadApi::instance();
  164. if ($uploadResult = $remoteUploadApi->upload($this->file->tempName)) {
  165. $uploadInfo = [
  166. 'fileName' => $uploadResult['name'],
  167. 'category' => $uploadCategory,
  168. 'url' => $uploadResult['url'],
  169. 'fileSize' => $uploadResult['size'] ?? null,
  170. 'md5' => $uploadResult['md5'] ?? null,
  171. ];
  172. } else {
  173. throw new Exception('Remote service error');
  174. }
  175. // 删除本地临时文件
  176. unlink($this->file->tempName);
  177. } else {
  178. // 生成文件名
  179. $fileName = $fileName ?: $this->file->baseName;
  180. // 保存在本地
  181. $localPath = '/ng/Volumes/HDD/workshop/old/ar.upload.ming/files/' . $fileName . '.' . $this->file->extension;
  182. // $localPath = \Yii::getAlias('@common/runtime') . __DS__ . 'excelExport' . __DS__ . 'excel_upload' . __DS__ . $fileName . '.' . $this->file->extension;
  183. if (!$this->file->saveAs($localPath)) {
  184. throw new Exception('Failed');
  185. }
  186. $uploadInfo = [
  187. 'fileName' => $fileName . '.' . $this->file->extension,
  188. 'category' => $uploadCategory,
  189. 'url' => $fileName . '.' . $this->file->extension,
  190. 'fileSize' => null,
  191. 'md5' => null,
  192. 'localPath' => $localPath,
  193. ];
  194. }
  195. // 把上传的文件写入数据库记录中
  196. // 把文件对应的相关资料存入数据库中
  197. $uploads = new Uploads();
  198. $uploads->FILE_NAME = $uploadInfo['fileName'];
  199. $uploads->CATEGORY = $uploadInfo['category'];
  200. $uploads->URL = $uploadInfo['url'];
  201. $uploads->FILE_SIZE = $uploadInfo['fileSize'] ?? null;
  202. $uploads->MD5 = $uploadInfo['md5'] ?? null;
  203. $uploads->REMARK = $uploadRemark;
  204. $uploads->CREATED_AT = Date::nowTime();
  205. if (!$uploads->save()) {
  206. throw new Exception('Save error');
  207. }
  208. // 如果是上传发票,更新发票信息,并绑定提现记录
  209. if ($this->scenario == 'invoiceFront') {
  210. $withdraw = Withdraw::findOne(['ID' => $this->withdrawId]);
  211. //判断金额是否一致
  212. if ($withdraw['AMOUNT'] != $this->_ocrResult['amount']) {
  213. throw new Exception('上传发票金额'.$this->_ocrResult['amount'].'与提现金额【'.$withdraw['AMOUNT'].'】不一致');
  214. }
  215. //发票内容是否与后台预置信息相符
  216. $configName = Cache::getSystemConfig()['invoiceItemName']['VALUE'];
  217. if (!in_array($this->_ocrResult['itemName'], explode("\n",$configName))) {
  218. throw new Exception('上传发票中货物或应税劳务服务名称与后台预置信息【' . $configName . '】不一致');
  219. }
  220. //写入发票数据
  221. if (InvoiceAudit::find()->where('INVOICE_NUM=:INVOICE_NUM AND WITHDRAW_ID!=:WITHDRAW_ID AND AUDIT_STATUS!=:AUDIT_STATUS', [':INVOICE_NUM' => $this->_ocrResult['invoiceNum'], ':WITHDRAW_ID' => $this->withdrawId, ':AUDIT_STATUS' => \Yii::$app->params['auditStatus']['reject']['value']])->exists()) {
  222. throw new Exception('该发票已被使用');
  223. }
  224. if(!$invoiceModel = InvoiceAudit::findOne(['WITHDRAW_ID' => $this->withdrawId])){
  225. $invoiceModel = new InvoiceAudit();
  226. }
  227. $invoiceModel->USER_ID = $oneUser['ID'];
  228. $invoiceModel->WITHDRAW_ID = $this->withdrawId;
  229. $invoiceModel->INVOICE_CODE = $this->_ocrResult['invoiceCode'];
  230. $invoiceModel->INVOICE_NUM = $this->_ocrResult['invoiceNum'];
  231. $invoiceModel->INVOICE_DATE = $this->_ocrResult['invoiceDate'];
  232. $invoiceModel->AMOUNT = $this->_ocrResult['amount'];
  233. $invoiceModel->TAX_RATE = $this->_ocrResult['taxRate'];
  234. $invoiceModel->PURCHASER_NAME = $this->_ocrResult['purchaserName'];
  235. $invoiceModel->PURCHASER_REGISTER_NUM = $this->_ocrResult['purchaserRegisterNum'];
  236. $invoiceModel->PURCHASER_ADDRESS = $this->_ocrResult['purchaserAddress'];
  237. $invoiceModel->PURCHASER_BANK = $this->_ocrResult['purchaserBank'];
  238. $invoiceModel->SELLER_NAME = $this->_ocrResult['sellerName'];
  239. $invoiceModel->SELLER_REGISTER_NUM = $this->_ocrResult['sellerRegisterNum'];
  240. $invoiceModel->SELLER_ADDRESS = $this->_ocrResult['sellerAddress'];
  241. $invoiceModel->SELLER_BANK = $this->_ocrResult['sellerBank'];
  242. $invoiceModel->ITEM_NAME = $this->_ocrResult['itemName'];
  243. $invoiceModel->INVOICE_REMARK = $this->_ocrResult['invoiceRemark'];
  244. $invoiceModel->UPLOAD_ID = $uploads->ID;
  245. $invoiceModel->CREATED_AT = Date::nowTime();
  246. if (!$invoiceModel->save()) {
  247. throw new Exception(Form::formatErrorsForApi($invoiceModel->getErrors()));
  248. }
  249. //写入提现表
  250. $withdraw->INVOICE_ID = $invoiceModel->ID;
  251. $withdraw->AUDIT_STATUS = Withdraw::STATUS_APPLIED;
  252. $withdraw->UPDATED_AT = Date::nowTime();
  253. if (!$withdraw->save()) {
  254. throw new Exception(Form::formatErrorsForApi($withdraw->getErrors()));
  255. }
  256. } // 如果是上传身份证正面的场景,则把识别出来的信息更新当前的会员信息
  257. elseif ($this->scenario == 'idCardFront') {
  258. // 修改用户基本信息
  259. $oneUser->REAL_NAME = $this->_ocrResult['realName'];
  260. $oneUser->ID_CARD = $this->_ocrResult['idCardNo'];
  261. $oneUser->ADDRESS = $this->_ocrResult['address'];
  262. $oneUser->NATION = Info::getNationCode($this->_ocrResult['nation']);
  263. $oneUser->ID_IMAGE = $uploadInfo['url'];
  264. if (!$oneUser->save()) {
  265. // throw new Exception('用户基本资料保存失败');
  266. throw new Exception(Form::formatErrorsForApi($oneUser->getErrors()));
  267. }
  268. // 更新会员信息缓存
  269. User::updateBaseInfoToRedis($oneUser['ID']);
  270. } elseif ($this->scenario == 'excel') {
  271. $excelTableClass = Excel::EXCEL_STRUCTURE[$this->excelOption]['excelTableClass'];
  272. // 把上传的文件写入到导入记录中
  273. $excelImport = new ExcelImport();
  274. $excelImport->OPTION_NAME = $this->excelOption;
  275. $excelImport->TABLE_NAME = $excelTableClass::tableName();
  276. $excelImport->UPLOAD_ID = $uploads->ID;
  277. $excelImport->AUDIT_STATUS = \Yii::$app->params['auditStatus']['true']['value'];
  278. $excelImport->IMPORT_ADMIN_ID = \Yii::$app->user->id;
  279. $excelImport->AUDIT_ADMIN_ID = \Yii::$app->user->id;
  280. $excelImport->CREATED_AT = Date::nowTime();
  281. if (!$excelImport->save()) {
  282. throw new Exception(Form::formatErrorsForApi($excelImport->getErrors()));
  283. }
  284. }elseif ($this->scenario == 'proveFront') {
  285. // 如果是上传充值凭证,绑定充值记录
  286. $recharge = Recharge::findOne(['ID' => $this->rechargeId]);
  287. if(!$recharge){
  288. throw new Exception("缺少参数ID");
  289. }
  290. //写入充值表
  291. $recharge->BANK_PROVE = $uploadInfo['url'];
  292. $recharge->AUDIT_STATUS = Recharge::STATUS_PROVED;
  293. if (!$recharge->save()) {
  294. throw new Exception(Form::formatErrorsForApi($recharge->getErrors()));
  295. }
  296. } elseif ($this->scenario == 'order') {
  297. // 执行订单上传服务
  298. $orderForm = new ExcelOrderForm();
  299. $run = $orderForm->run($uploadInfo['localPath']);
  300. if ($run !== true) {
  301. throw new Exception(Form::formatErrorsForApi($run));
  302. }
  303. // 把上传的文件写入到导入记录中
  304. $excelImport = new ExcelImport();
  305. $excelImport->OPTION_NAME = '订单上传';
  306. $excelImport->TABLE_NAME = '';
  307. $excelImport->UPLOAD_ID = $uploads->ID;
  308. $excelImport->AUDIT_STATUS = \Yii::$app->params['auditStatus']['true']['value'];
  309. $excelImport->IMPORT_ADMIN_ID = \Yii::$app->user->id;
  310. $excelImport->AUDIT_ADMIN_ID = \Yii::$app->user->id;
  311. $excelImport->CREATED_AT = Date::nowTime();
  312. if (!$excelImport->save()) {
  313. throw new Exception(Form::formatErrorsForApi($excelImport->getErrors()));
  314. }
  315. }
  316. $transaction->commit();
  317. } catch (Exception $e) {
  318. $transaction->rollBack();
  319. $this->addError('upload', $e->getMessage());
  320. return false;
  321. }
  322. if ($this->scenario == 'order') {
  323. $uploads->URL = $localPath;
  324. }
  325. return $uploads;
  326. }
  327. }