UserMoney.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <?php
  2. namespace app\models\user;
  3. use app\models\activity\Activity;
  4. use app\models\lala\LalaRatio;
  5. use app\models\system\SystemBill;
  6. use crmeb\services\blockchain\BlockChianService;
  7. use crmeb\traits\ModelTrait;
  8. use crmeb\basic\BaseModel;
  9. use think\db\exception\DataNotFoundException;
  10. use think\db\exception\DbException;
  11. use think\db\exception\ModelNotFoundException;
  12. use think\Model;
  13. class UserMoney extends BaseModel
  14. {
  15. /**
  16. * 数据表主键
  17. * @var string
  18. */
  19. protected $pk = 'id';
  20. /**
  21. * 模型名称
  22. * @var string
  23. */
  24. protected $name = 'user_money';
  25. use ModelTrait;
  26. /**
  27. * @param $uid
  28. * @param $money_type
  29. * @param int $money
  30. * @return array|Model|null
  31. * @throws DataNotFoundException
  32. * @throws DbException
  33. * @throws ModelNotFoundException
  34. */
  35. public static function initialUserMoney($uid, $money_type, $money = 0)
  36. {
  37. $where = compact('uid', 'money_type');
  38. $data = self::where($where)->order('id', 'asc')->find();
  39. if (self::where($where)->count() > 1) {
  40. self::where($where)->where('id', '<>', $data['id'])->delete();
  41. }
  42. if ($data) {
  43. // $money_types = sys_data('money_type');
  44. // $update = [];
  45. // foreach ($money_types as $v) {
  46. // if ($v['code'] == $money_type) {
  47. // if ($v['charge']) {
  48. // //TODO 接入链上充值
  49. // if (!$data['address']) {
  50. // $update = BlockChianService::createAddress($v['code']);
  51. // }
  52. // }
  53. // break;
  54. // }
  55. // }
  56. // if ($update)
  57. // self::where($where)->update($update);
  58. return self::where($where)->find();
  59. } else {
  60. // $money_types = sys_data('money_type');
  61. // foreach ($money_types as $v) {
  62. // if ($v['code'] == $money_type) {
  63. // if ($v['charge']) {
  64. // //TODO 接入链上充值
  65. // $address = BlockChianService::createAddress($v['code']);
  66. // $where['address'] = $address['address'];
  67. // $where['privateKey'] = $address['privateKey'];
  68. // $where['hexAddress'] = $address['hexAddress'];
  69. // }
  70. // break;
  71. // }
  72. // }
  73. return self::create(array_merge($where, ['money' => $money]));
  74. }
  75. }
  76. /**
  77. * @param $uid
  78. * @param $to_uid
  79. * @param $money_type
  80. * @param $money
  81. * @return bool
  82. * @throws DataNotFoundException
  83. * @throws DbException
  84. * @throws ModelNotFoundException
  85. */
  86. public static function tradeMoney($uid, $to_uid, $money_type, $money)
  87. {
  88. $user = self::initialUserMoney($uid, $money_type);
  89. $user_info = User::getUserInfo($uid);
  90. $to_user = self::initialUserMoney($to_uid, $money_type);
  91. $to_user_info = User::getUserInfo($to_uid);
  92. if ($to_uid == $uid) {
  93. return self::setErrorInfo('不能转账给自己');
  94. }
  95. if (bcsub($user['money'], $user['only_pink'], 8) < $money) {
  96. return self::setErrorInfo('可转账' . $money_type . '不足');
  97. }
  98. $balance = bcsub($user['money'], $money, 8);
  99. $to_balance = bcadd($to_user['money'], $money, 8);
  100. $mark = '付款给' . $to_user_info['nickname'] . "({$to_user_info['uid']})" . $money . ' ' . $money_type;
  101. $to_mark = '收到' . $user_info['nickname'] . "({$user_info['uid']})支付" . $money . ' ' . $money_type;
  102. self::beginTrans();
  103. try {
  104. $res2 = UserBill::expend('会员转出', $uid, $money_type, 'expend', $money, 0, $balance, $mark, 1);
  105. $res3 = UserBill::income('会员转入', $to_uid, $money_type, 'income', $money, $res2->id, $to_balance, $to_mark, 1);
  106. $res4 = self::where('uid', $uid)->where('money_type', $money_type)->update(['money' => $balance]);
  107. $res5 = self::where('uid', $to_uid)->where('money_type', $money_type)->update(['money' => $to_balance]);
  108. $res = $res2 && $res3 && $res4 && $res5;
  109. if ($res) {
  110. self::commitTrans();
  111. return true;
  112. } else {
  113. self::rollbackTrans();
  114. return self::setErrorInfo('交易失败');
  115. }
  116. } catch (\Exception $e) {
  117. self::rollbackTrans();
  118. return self::setErrorInfo($e->getMessage());
  119. }
  120. }
  121. /**
  122. * @param $aid
  123. * @param $uid
  124. * @param $to_uid
  125. * @param $layer
  126. * @param $money_type
  127. * @param $money
  128. * @param int $status
  129. * @return bool
  130. * @throws DataNotFoundException
  131. * @throws DbException
  132. * @throws ModelNotFoundException
  133. */
  134. public static function activityTradeMoney($aid, $uid, $to_uid, $link_id, $layer, $money_type, $money, int $status = 1)
  135. {
  136. $activity = Activity::get($aid);
  137. if (!$activity) return self::setErrorInfo('找不到活动');
  138. $user = self::initialUserMoney($uid, $money_type);
  139. $user_info = User::getUserInfo($uid);
  140. if (bcsub($user['money'], $user['only_pink'], 8) < $money) {
  141. return self::setErrorInfo('可转账' . $money_type . '不足');
  142. }
  143. $balance = bcsub($user['money'], $money, 8);
  144. if ($to_uid > 0) {
  145. $to_user = self::initialUserMoney($to_uid, $money_type);
  146. $to_user_info = User::getUserInfo($to_uid);
  147. $to_balance = bcadd($to_user['money'], $money, 8);
  148. $to_mark = '收到' . $user_info['nickname'] . "({$user_info['uid']})" . $activity['name'] . '升级V' . $layer . "支付" . $money . ' ' . $money_type;
  149. }
  150. $mark = $activity['name'] . '升级V' . $layer . ('付款给' . ($to_user_info['nickname'] ?? '系统')) . "({$to_uid})" . $money . ' ' . $money_type;
  151. self::beginTrans();
  152. try {
  153. $res2 = UserBill::expend('互助升级转出', $uid, $money_type, 'activity_expend', $money, $link_id, $balance, $mark, 1, '', $aid, $layer);
  154. if ($to_uid > 0)
  155. $res3 = UserBill::income('互助升级转入', $to_uid, $money_type, 'activity_income', $money, $link_id, $to_balance ?? 0, $to_mark ?? '', $status, '', $aid, $layer);
  156. else $res3 = true;
  157. $res4 = self::where('uid', $uid)->where('money_type', $money_type)->update(['money' => $balance]);
  158. if ($status && $to_uid > 0) $res5 = self::where('uid', $to_uid)->where('money_type', $money_type)->update(['money' => $to_balance ?? 0]);
  159. else $res5 = true;
  160. $res = $res2 && $res3 && $res4 && $res5;
  161. if ($res) {
  162. self::commitTrans();
  163. return true;
  164. } else {
  165. self::rollbackTrans();
  166. return self::setErrorInfo('交易失败');
  167. }
  168. } catch (\Exception $e) {
  169. self::rollbackTrans();
  170. return self::setErrorInfo($e->getMessage());
  171. }
  172. }
  173. /**
  174. * @param $uid
  175. * @param $money_type
  176. * @param $money
  177. * @param $type
  178. * @param string $title
  179. * @param string $mark
  180. * @param int $from_vote
  181. * @param int $from_sub_vote
  182. * @return bool
  183. * @throws DataNotFoundException
  184. * @throws DbException
  185. * @throws ModelNotFoundException
  186. */
  187. public static function expendMoney($uid, $money_type, $money, $type, $title = '会员转出', $mark = '', $link_id = 0, $not_pink = true, $admin_mark = '')
  188. {
  189. $user = self::initialUserMoney($uid, $money_type);
  190. if ($not_pink) {
  191. if (bcsub($user['money'], $user['only_pink'], 8) < $money) {
  192. return self::setErrorInfo('可用余额不足');
  193. }
  194. } else {
  195. if ($user['money'] < $money) {
  196. return self::setErrorInfo('余额不足');
  197. }
  198. }
  199. $balance = bcsub($user['money'], $money, 8);
  200. try {
  201. $res2 = UserBill::expend($title, $uid, $money_type, $type, $money, $link_id, $balance, $mark, 1, $admin_mark);
  202. $res4 = self::where('uid', $uid)->where('money_type', $money_type)->update(['money' => $balance]);
  203. if (!$not_pink && $user['only_pink'] > 0) {
  204. if ($user['only_pink'] >= $money) {
  205. $res4 = $res4 && self::where('uid', $uid)->where('money_type', $money_type)->update(['only_pink' => bcsub($user['only_pink'], $money, 8)]);
  206. } else {
  207. $res4 = $res4 && self::where('uid', $uid)->where('money_type', $money_type)->update(['only_pink' => 0]);
  208. }
  209. }
  210. $res = $res2 && $res4;
  211. if ($res) {
  212. return true;
  213. } else {
  214. return self::setErrorInfo('交易失败');
  215. }
  216. } catch (\Exception $e) {
  217. return self::setErrorInfo($e->getMessage());
  218. }
  219. }
  220. /**
  221. * @param $uid
  222. * @param $money_type
  223. * @param $money
  224. * @param $type
  225. * @param string $title
  226. * @param string $mark
  227. * @param int $from_vote
  228. * @param int $from_sub_vote
  229. * @return bool
  230. * @throws DataNotFoundException
  231. * @throws DbException
  232. * @throws ModelNotFoundException
  233. */
  234. public static function incomeMoney($uid, $money_type, $money, $type, $title = '用户获得', $mark = '', $link_id = 0, $status = 1, $not_pink = true, $admin_mark = '')
  235. {
  236. $user = self::initialUserMoney($uid, $money_type);
  237. $balance = bcadd($user['money'], $money, 8);
  238. try {
  239. $res2 = UserBill::income($title, $uid, $money_type, $type, $money, $link_id, $balance, $mark, $status, $admin_mark);
  240. if ($status) {
  241. $res4 = self::where('uid', $uid)->where('money_type', $money_type)->update(['money' => $balance]);
  242. if (!$not_pink) {
  243. $res4 = $res4 && self::where('uid', $uid)->where('money_type', $money_type)->update(['only_pink' => bcadd($user['only_pink'], $money, 8)]);
  244. }
  245. } else
  246. $res4 = true;
  247. $res = $res2 && $res4;
  248. if ($res) {
  249. return true;
  250. } else {
  251. return self::setErrorInfo('交易失败');
  252. }
  253. } catch (\Exception $e) {
  254. return self::setErrorInfo($e->getMessage());
  255. }
  256. }
  257. public static function sendMoney($id)
  258. {
  259. $info = UserBill::get($id);
  260. if (!$info || $info['status'] != 0) {
  261. return self::setErrorInfo('状态异常');
  262. }
  263. $user = self::initialUserMoney($info['uid'], $info['category']);
  264. $balance = bcadd($user['money'], $info['number'], 8);
  265. try {
  266. $res2 = UserBill::edit(['status' => 1, 'balance' => $balance, 'add_time' => time()], $id);
  267. $res4 = self::where('uid', $info['uid'])->where('money_type', $info['category'])->update(['money' => $balance]);
  268. $res = $res2 && $res4;
  269. if ($res) {
  270. return true;
  271. } else {
  272. return self::setErrorInfo('交易失败');
  273. }
  274. } catch (\Exception $e) {
  275. return self::setErrorInfo($e->getMessage());
  276. }
  277. }
  278. /**
  279. * @param $uid
  280. * @param $origin_money_type
  281. * @param $target_money_type
  282. * @param $money
  283. * @return bool
  284. * @throws DataNotFoundException
  285. * @throws DbException
  286. * @throws ModelNotFoundException
  287. */
  288. public static function exchangeMoney($uid, $origin_money_type, $target_money_type, $money)
  289. {
  290. if ($origin_money_type == $target_money_type) return self::setErrorInfo('相同币种不可兑换');
  291. $origin_money = self::initialUserMoney($uid, $origin_money_type);
  292. $target_money = self::initialUserMoney($uid, $target_money_type);
  293. if (bcsub($origin_money['money'], $origin_money['only_pink'], 8) < $money) {
  294. return self::setErrorInfo('可用' . $origin_money_type . '不足');
  295. }
  296. $money_types = sys_data('money_type');
  297. $origin_ratio = 0;
  298. $target_ratio = 0;
  299. foreach ($money_types as $v) {
  300. if ($v['code'] == $origin_ratio) {
  301. $origin_ratio = $v['usdt_price'];
  302. if ($origin_money_type == 'LALA') {
  303. $origin_ratio = get_lala_ratio();
  304. }
  305. }
  306. if ($v['code'] == $target_money_type) {
  307. $target_ratio = $v['usdt_price'];
  308. if ($target_money_type == 'LALA') {
  309. $target_ratio = get_lala_ratio();
  310. }
  311. }
  312. }
  313. $ratio = bcdiv($origin_ratio, $target_ratio, 14);
  314. $add_money = bcmul($money, $ratio, 8);
  315. $balance = bcsub($origin_money['money'], $money, 8);
  316. $to_balance = bcadd($target_money['money'], $add_money, 8);
  317. $mark = '使用' . $money . ' ' . $origin_money_type . '兑换' . $add_money . ' ' . $target_money_type;
  318. self::beginTrans();
  319. try {
  320. $res2 = UserBill::expend('闪兑', $uid, $origin_money_type, 'exchange', $money, 0, $balance, $mark, 1);
  321. $res3 = UserBill::income('闪兑', $uid, $target_money_type, 'exchange', $add_money, $res2->id, $to_balance, $mark, 1);
  322. $res4 = self::where('uid', $uid)->where('money_type', $origin_money_type)->update(['money' => $balance]);
  323. $res5 = self::where('uid', $uid)->where('money_type', $target_money_type)->update(['money' => $to_balance]);
  324. $res = $res2 && $res3 && $res4 && $res5;
  325. if ($res) {
  326. self::commitTrans();
  327. return true;
  328. } else {
  329. self::rollbackTrans();
  330. return self::setErrorInfo('兑换失败');
  331. }
  332. } catch (\Exception $e) {
  333. self::rollbackTrans();
  334. return self::setErrorInfo($e->getMessage());
  335. }
  336. }
  337. }