Cang.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: qisse
  5. * Date: 2017/6/27
  6. * Time: 20:02
  7. */
  8. namespace app\mobile_v_2_1\logic;
  9. use app\core\exception\AppException;
  10. use app\core\model\Cang as Model;
  11. use app\core\model\CangRepay;
  12. use app\core\model\Hongbao;
  13. use app\core\model\Subject;
  14. use app\core\model\SubjectStat;
  15. use app\core\model\UserAccount;
  16. use app\core\model\UserBank;
  17. use app\core\model\User;
  18. use app\core\model\UserHongbao;
  19. use app\core\service\Pay;
  20. use app\core\service\Finance;
  21. use think\Db;
  22. use think\Exception;
  23. use think\Hook;
  24. use think\Log;
  25. use tool\Common;
  26. class Cang extends Base
  27. {
  28. public function create()
  29. {
  30. //第一步,得到标的信息
  31. $subject = Subject::get($this->app['subjectID']);
  32. //第二步,得到红包相关
  33. $hongbaoMoney = 0;//现金券
  34. $hongbaoYear = 0;//加息年化
  35. if(isset($this->app['hongbaoIDS']) && count($this->app['hongbaoIDS']) > 0) {
  36. foreach ($this->app['hongbaoIDS'] as $k => $hongbaoID) {
  37. $userHongbao = UserHongbao::with(['hongbao'])->where([
  38. 'userHongbaoID'=>$hongbaoID,
  39. 'status'=>UserHongbao::STATUS_UNUSED,
  40. 'userID'=>$this->user['userID']
  41. ])->find();
  42. if(!$userHongbao) {
  43. continue;
  44. }
  45. if($userHongbao->hongbao['typeID'] == 1) {
  46. $hongbaoMoney += $userHongbao->hongbao['money'];
  47. }
  48. else if($userHongbao->hongbao['typeID'] == 2) {
  49. $hongbaoYear += $userHongbao->hongbao['year'];
  50. }
  51. }
  52. }
  53. //第三步,得到实际要付的金额
  54. $money = $this->app['moneySubject'] - $hongbaoMoney;
  55. //第四步,判断是否符合投资资格
  56. //1、判断是否过认购期
  57. /*if(THINK_START_TIME >= $subject->getData('endTime')) {
  58. return Common::rm(-3, '该商品已过认购期,不能投资了');
  59. }*/
  60. //2、判断是否满标了
  61. if($subject['status'] == Subject::STATUS_FULL) {
  62. return Common::rm(-4, '该商品已经满标,不能投资了');
  63. }
  64. //3、判断是否下架了
  65. if($subject['status'] != Subject::STATUS_ONLINE) {
  66. return Common::rm(-5, '该商品已经下架,不能投资了');
  67. }
  68. //4、判断金额数字是否符合标的要求
  69. if($subject['basePrice'] > $this->app['moneySubject']) {
  70. return Common::rm(-6, '最低需投资'.$subject['basePrice']);
  71. }
  72. if($subject['baseMaxPrice'] < $this->app['moneySubject']) {
  73. return Common::rm(-7, '投资最大不得超出'.$subject['baseMaxPrice']);
  74. }
  75. if($subject->subjectStat['moneyTotalInvest'] + $this->app['moneySubject'] > $subject['price']) {
  76. return Common::rm(-8, '投入金额过多,超出标的总金额,最多可投'.($subject['price'] - $subject->subjectStat['moneyTotalInvest']));
  77. }
  78. //5、查看余额是否够
  79. if($this->user['userAccount']['money'] < $money) {
  80. return Common::rm(-9, '余额不足请先充值');
  81. }
  82. if(!$this->user['isNewInvest'] && $subject['subjectTypeID'] == 1) {
  83. return Common::rm(-10, '您已经投过新手标了,不能再投!');
  84. }
  85. //第五步,生成一个未支付的仓
  86. $interest = 0;
  87. $interestBeginTime = 0;//起息日期
  88. $interestEndTime = 0;//起息结束(算当天)
  89. $investDay = 0;//利息产生的天数
  90. $repayTime = 0;
  91. $year = $subject['year'] + $hongbaoYear + $subject['yearSystem'];//总的年化
  92. //如果是满标计息
  93. if($subject['interestTimeTypeID'] == 1) {
  94. //满标利息无法计算,只有等到满标才可以
  95. $repayTime = $subject['repayTime'];
  96. }
  97. //如果是T + 1,我们容易计算利息
  98. else if($subject['interestTimeTypeID'] == 2) {
  99. $interestBeginTime = Common::datetotime(Common::timetodate(THINK_START_TIME, 0)) - 86400;
  100. $interestEndTime = $subject->getData('overTime');
  101. $investDay = $subject['investDay'];//投资天数
  102. //$investDay = (int)(($interestEndTime - $interestBeginTime) / 86400);
  103. $interest = round($this->app['moneySubject'] * $year / 100 / 365 * $investDay, 2);//预付利息
  104. $repayTime = $subject['repayTime'];
  105. }
  106. //如果是T + 0,我们容易计算利息
  107. else if($subject['interestTimeTypeID'] == 3) {
  108. $interestBeginTime = Common::datetotime(Common::timetodate(THINK_START_TIME, 0));
  109. $interestEndTime = $subject->getData('overTime') - 86400;
  110. $investDay = $subject['investDay'];//投资天数
  111. //$investDay = (int)(($interestEndTime - $interestBeginTime) / 86400);
  112. $interest = round($this->app['moneySubject'] * $year / 100 / 365 * $investDay, 2);
  113. $repayTime = $subject['repayTime'];
  114. }
  115. //根据红包,重新计算利率
  116. $model = Model::create([
  117. 'subjectID' => $subject['subjectID'],
  118. 'userID' => $this->user['userID'],
  119. 'moneySubject' => $this->app['moneySubject'],
  120. 'interestBeginTime'=>$interestBeginTime,
  121. 'interestEndTime'=>$interestEndTime,
  122. 'year'=>$subject['year'],
  123. 'yearExt'=>$hongbaoYear,
  124. 'ben'=>$this->app['moneySubject'],
  125. 'money'=>$money,
  126. 'yearSystem'=>$subject['yearSystem'],
  127. 'osType'=>$this->data['osType'],
  128. 'ip'=>$this->data['ip'],
  129. 'interest'=>$interest,
  130. 'investDay'=>$investDay,
  131. 'interestTimeTypeID'=> $subject['interestTimeTypeID'],
  132. 'status'=>Model::STATUS_UNPAY,
  133. 'hongbao'=>implode(',', $this->app['hongbaoIDS'])
  134. ]);
  135. $model['alias'] = Model::createAlias($model['cangID']);
  136. $model->save();
  137. Db::startTrans();
  138. try{
  139. //第七步,更新红包状态
  140. if(isset($this->app['hongbaoIDS']) && count($this->app['hongbaoIDS']) > 0) {
  141. foreach ($this->app['hongbaoIDS'] as $k => $hongbaoID) {
  142. UserHongbao::update([
  143. 'status'=>UserHongbao::STATUS_USED
  144. ], [
  145. 'userHongbaoID'=>$hongbaoID
  146. ]);
  147. }
  148. }
  149. //第八步,更新支付状态
  150. $cangRepaySave = [
  151. 'money'=>$this->app['moneySubject'],
  152. 'repayTime'=>Common::datetotime($repayTime),
  153. 'reachTime'=>Common::datetotime($subject['reachTime']),
  154. 'userID' => $this->user['userID'],
  155. 'subjectID' => $subject['subjectID'],
  156. 'cangID'=>$model['cangID'],
  157. 'status'=>1,
  158. 'repayTypeID'=>1
  159. ];
  160. //第九步,更新回款清单
  161. //更新本金回款清单
  162. CangRepay::create($cangRepaySave);
  163. //更新利息回款清单
  164. $cangRepaySave['repayTypeID'] = 2;
  165. $cangRepaySave['money'] = $interest;
  166. CangRepay::create($cangRepaySave);
  167. //第十步,更新账户金额及流水
  168. $this->user->userAccount = $this->user->userAccount->MODE_cang_decMoney($model, $this->user, $interest);
  169. //第十一步,更新标的统计
  170. SubjectStat::where([
  171. 'subjectID'=>$this->app['subjectID']
  172. ])->setInc('moneyTotalInvest', $this->app['moneySubject'] * 100);
  173. SubjectStat::where([
  174. 'subjectID'=>$this->app['subjectID']
  175. ])->setInc('timesInvest');
  176. //第十二步,同步金账户
  177. vendor('payModel.Trade');
  178. $finance = new Finance();
  179. $trade = new \Trade();
  180. $userBank = UserBank::get([
  181. 'userID'=>$this->user['userID']
  182. ]);
  183. $trade->setPayment($userBank['mobile']);
  184. $trade->setReceive('15825631526');
  185. $trade->setMoney($money);
  186. $result = $finance->order($msg, $trade);
  187. if(!$result) {
  188. Db::rollback();
  189. return Common::rm(-10, $msg);
  190. }
  191. //第六步,更新支付状态
  192. $model['payTime'] = THINK_START_TIME;
  193. $model['status'] = Model::STATUS_PAY;
  194. $model['outerNumber'] = $result;
  195. $model->save();
  196. if($this->user['isNewInvest'] && $subject['subjectTypeID'] == 1) {
  197. //第七步,更新用户首投
  198. User::update([
  199. 'isNewInvest'=>0
  200. ], [
  201. 'userID'=>$this->user['userID']
  202. ]);
  203. }
  204. //<><><><><><><><><><><><><><><><><> 下单成功钩子 <><><><><><><><><><><><><><><><><>//
  205. $hook = [
  206. 'user'=>$this->user,
  207. 'cang'=>$model
  208. ];
  209. Hook::listen('tag_cang_create_success', $hook);
  210. //<><><><><><><><><><><><><><><><><> 下单成功end <><><><><><><><><><><><><><><><><>//
  211. Db::commit();
  212. }
  213. catch (Exception $e) {
  214. // 回滚事务
  215. Log::error($e->getMessage().'|'.$e->getLine().'|'.$e->getFile());
  216. Db::rollback();
  217. throw new AppException(-9, $e->getMessage());
  218. }
  219. //第十二步,判断是否满标
  220. if($subject->subjectStat['moneyTotalInvest'] + $this->app['moneySubject'] == $subject['price']) {
  221. //如果满标了,设置满标
  222. Subject::setSubjectFull($subject);
  223. }
  224. return Common::rm(1, '操作成功', [
  225. 'cangID'=>$model['cangID']
  226. ]);
  227. }
  228. public function createPayParams() {
  229. $this->app = [
  230. 'cangID'=>1
  231. ];
  232. //第一步,获取该仓
  233. $model = Model::get($this->app['cangID']);
  234. if(!$model) {
  235. return Common::rm(-2, '不存在该仓');
  236. }
  237. //第二步,判断仓所属的标的是否过期
  238. $subject = Subject::get($model['subjectID']);
  239. if(!$subject) {
  240. return Common::rm(-12, '不存在该仓所属的标的');
  241. }
  242. //1、判断是否过认购期
  243. if(THINK_START_TIME >= $subject->getData('endTime')) {
  244. return Common::rm(-13, '该商品已过认购期,不能购买了');
  245. }
  246. //2、判断是否满标了
  247. if($subject['status'] == Subject::STATUS_FULL) {
  248. return Common::rm(-14, '该商品已经满标,不能购买了');
  249. }
  250. //3、判断是否下架了
  251. if($subject['status'] == Subject::STATUS_OFFLINE) {
  252. return Common::rm(-15, '该商品已经下架,不能购买了');
  253. }
  254. //第三步,获取支付参数
  255. $pay = new Pay();
  256. $ouerOrder = $pay->createOrder($model['money']);
  257. if(!$ouerOrder) {
  258. return Common::rm(-3, '获取支付参数失败');
  259. }
  260. $model['outerAlias'] = $ouerOrder['outerAlias'];
  261. $model['outerMch'] = $ouerOrder['outerMch'];
  262. $model['outerName'] = $ouerOrder['outerName'];
  263. $model['payTimes'] = $model['payTimes'] + 1;
  264. $model->save();
  265. return Common::rm(1, '操作成功', [
  266. 'cangID'=>$this->app['cangID'],
  267. 'outerAlias'=>$model['outerAlias'],
  268. /*'money'=>$model['money'],*/
  269. 'notify'=>$this->request->domain().'/mobile/notify/cang'
  270. ]);
  271. }
  272. /**
  273. * @api {post} cang/getCangList 得到我的投资列表
  274. * @apiVersion 1.0.0
  275. * @apiName getCangList
  276. * @apiDescription 得到我的投资列表
  277. * @apiGroup Cang
  278. *
  279. * @apiParam {Number=[1,2]} status 1为持有中,2为已回款
  280. * @apiParamExample {json} 发送报文:
  281. {
  282. "status": 1
  283. }
  284. *
  285. * @apiSuccess {Object[]} cangList 我的投资列表
  286. * @apiSuccess {Number} cangList.cangID ID
  287. * @apiSuccess {Number} cangList.moneySubject 投资份额(非本金,非实际支付金额)
  288. * @apiSuccess {Number} cangList.status 状态,1-已持有,4-已计息,5-已回款
  289. * @apiSuccess {String} cangList.statusText 状态描述,参考状态
  290. * @apiSuccess {String} cangList.payTime 交易时间
  291. * @apiSuccess {String} cangList.interestBeginTime 起息日期
  292. * @apiSuccess {String} cangList.interestEndTime 停止计息日
  293. * @apiSuccess {String} cangList.year 年化
  294. * @apiSuccess {String} cangList.yearExt 追加年化
  295. * @apiSuccess {String} cangList.yearSystem 系统年化(废弃)
  296. * @apiSuccess {String} cangList.ben 实际投入本金
  297. * @apiSuccess {String} cangList.interest 利息
  298. * @apiSuccess {Number} cangList.investDay 投资天数
  299. * @apiSuccess {Object} cangList.subject 相关标的
  300. * @apiSuccess {String} cangList.subject.title 标的标题
  301. * @apiSuccess {Number} cangList.subject.subjectTypeID 标的类型
  302. * @apiSuccess {Number} cangList.subject.interestTypeID 计息类型
  303. * @apiSuccess {Number} cangList.subject.interestTimeTypeID 计息时间类型
  304. * @apiSuccess {String} cangList.subject.reachTime 标的标题
  305. * @apiSuccess {String} cangList.subject.title 标的标题
  306. * @apiSuccess {Object[]} cangList.cangRepay 预回款清单
  307. * @apiSuccess {String} cangList.cangRepay.money 回款金额
  308. * @apiSuccess {String} cangList.cangRepay.repayTime 回款类型
  309. * @apiSuccess {String} cangList.cangRepay.resultTime 实际到款时间
  310. * @apiSuccess {String} cangList.cangRepay.reachTime 到款时间
  311. * @apiSuccess {Number} cangList.cangRepay.status 清单状态,1-未回款,2-已回款,3-已到账(该状态可隐藏)
  312. * @apiSuccess {Number} cangList.cangRepay.repayTypeID 清单类型,1-本金,2-利息
  313. * @apiSuccessExample {json} 返回json数据(举例):
  314. {
  315. "code": 1,
  316. "msg": "操作成功",
  317. "content": {
  318. "cangList": [
  319. {
  320. "cangID": 33,
  321. "moneySubject": "2000.00",
  322. "status": 4,
  323. "payTime": "2017-12-12 20:53:50",
  324. "interestBeginTime": "2017-12-12",
  325. "interestEndTime": "2017-12-23",
  326. "year": "12.80",
  327. "yearExt": "2.00",
  328. "yearSystem": "2.00",
  329. "ben": "2000.00",
  330. "interest": "7.01",
  331. "investDay": 10,
  332. "subject": {
  333. "subjectTypeID": 2,
  334. "interestTypeID": 1,
  335. "interestTimeTypeID": 1,
  336. "title": "普通标11111"
  337. },
  338. "cangRepay": [
  339. {
  340. "money": "2000.00",
  341. "repayTime": "2017-12-22",
  342. "reachTime": "2017-12-23",
  343. "resultTime": "2017-12-12",
  344. "status": 1,
  345. "repayTypeID": 1
  346. },
  347. {
  348. "money": "7.01",
  349. "repayTime": "2017-12-22",
  350. "reachTime": "2017-12-23",
  351. "resultTime": "2017-12-12",
  352. "status": 1,
  353. "repayTypeID": 2
  354. }
  355. ],
  356. "statusText": "计息中"
  357. },
  358. {
  359. "cangID": 30,
  360. "moneySubject": "98000.00",
  361. "status": 4,
  362. "payTime": "2017-12-12 18:28:27",
  363. "interestBeginTime": "2017-12-12",
  364. "year": "12.80",
  365. "ben": "98000.00",
  366. "interest": "343.67",
  367. "investDay": 10,
  368. "subject": {
  369. "subjectTypeID": 2,
  370. "interestTypeID": 1,
  371. "interestTimeTypeID": 1,
  372. "title": "普通标11111"
  373. },
  374. "cangRepay": [
  375. {
  376. "money": "98000.00",
  377. "repayTime": "2017-12-22",
  378. "reachTime": "2017-12-23",
  379. "resultTime": "2017-12-12",
  380. "status": 1,
  381. "repayTypeID": 1
  382. },
  383. {
  384. "money": "343.67",
  385. "repayTime": "2017-12-22",
  386. "reachTime": "2017-12-23",
  387. "resultTime": "2017-12-12",
  388. "status": 1,
  389. "repayTypeID": 2
  390. }
  391. ],
  392. "statusText": "计息中"
  393. }
  394. ]
  395. },
  396. "sign": "4297f44b13955235245b2497399d7a93"
  397. }
  398. * @apiUse CreateUserError
  399. */
  400. public function getCangList() {
  401. $map = $this->map();
  402. if($this->app['status'] == 1) {
  403. $map['status'] = ['in', [Model::STATUS_PAY, Model::STATUS_INTEREST]];
  404. }
  405. else if($this->app['status'] == 2){
  406. $map['status'] = ['in', [Model::STATUS_REPAY, Model::STATUS_FINISH]];
  407. }
  408. $list = Model::with(['subject','cangRepay'])->where($map)->order('addTime desc')->select();
  409. if($list->isEmpty()) {
  410. return Common::rm(1, '操作成功', [
  411. 'cangList'=>[]
  412. ]);
  413. }
  414. $list->append(['statusText'])->visible(['cangID','moneySubject','payTime','status','investDay','interestBeginTime','interestEndTime','year','yearExt','yearSystem','interest','ben','repayBenTime','subject'=>[
  415. 'title','interestTimeTypeID','interestTypeID','subjectTypeID'
  416. ],'cangRepay'=>[
  417. 'money','repayTime','reachTime','resultTime','status','repayTypeID'
  418. ]]);
  419. return Common::rm(1, '操作成功', [
  420. 'cangList'=>$list
  421. ]);
  422. }
  423. public function actionOnline() {
  424. $item = $this->getItem();
  425. if($item['status'] != 1) {
  426. return Common::rm(-3, '不是可以进行的状态,当前状态'.$item['statusText']);
  427. }
  428. $item['status'] = Model::STATUS_ONLINE;
  429. $item->save();
  430. return Common::rm(1, '操作成功', [
  431. 'detail'=>$item
  432. ]);
  433. }
  434. private function getItem($map = []) {
  435. $map['alias'] = $this->app['alias'];
  436. $item= Model::with('subjectType,interestType,interestTimeType,subjectStat')->where($map)->find();
  437. if(!$item) {
  438. return Common::rm(-2, '数据为空');
  439. }
  440. $item->append(['statusText'])->hidden(['subjectID','subjectTypeID','interestTypeID','interestTimeTypeID',
  441. 'subjectStat'=>[
  442. 'subjectID','subjectStatID'
  443. ]
  444. ]);
  445. return $item;
  446. }
  447. public function init() {
  448. User::destroy([
  449. 'watchID'=>$this->app['watchID']
  450. ]);
  451. return Common::rm(1, '操作成功');
  452. }
  453. }