Wallet.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?php
  2. namespace app\common\model;
  3. use think\Model;
  4. use think\Db;
  5. /**
  6. * 货币模型
  7. */
  8. class Wallet extends Model
  9. {
  10. // 日志变动类型
  11. const log_type = [
  12. 1 => '系统调节',//money + -
  13. 10 => '用户充值',//money + -
  14. 20 => '老年大学活动报名',//money + -
  15. ];
  16. // 操作钱包余额类型
  17. const money_type = [
  18. 'money' => '余额',
  19. ];
  20. protected $message = '';
  21. protected $data = [];
  22. /**
  23. * 获取交易类型配置
  24. * @return mixed
  25. */
  26. public function getLogType($type = '')
  27. {
  28. $conf = self::log_type;
  29. if ($type) {
  30. return $conf[$type] ?: $type;
  31. }
  32. return $conf;
  33. }
  34. //获取钱包名称
  35. public function getWalletName($name = '')
  36. {
  37. $conf = self::money_type;
  38. if ($name) {
  39. return $conf[$name] ?: $name;
  40. }
  41. return $conf;
  42. }
  43. /**
  44. * 获取钱包余额
  45. * @param int $user_id 用户编号
  46. * @param string $wallet_name 指定钱包名
  47. * @return array|float
  48. */
  49. public function getWallet($user_id = 0, $wallet_name = '')
  50. {
  51. //所有钱包余额
  52. if (!$wallet = Db::name('user_wallet')->where(['user_id' => $user_id])->find()) {
  53. abort(500, '钱包余额获取失败');
  54. }
  55. if ($wallet_name) { //返回指定钱包
  56. return isset($wallet[$wallet_name]) ? $wallet[$wallet_name] : 0;
  57. } else { //返回所有钱包
  58. return $wallet;
  59. }
  60. }
  61. /**
  62. *
  63. * @param floatval $number 金额(正数进账,负数出账)
  64. * @param $accountType 货币类型,money,score
  65. * @param $logtype 日志的类型
  66. * @param $remark 备注
  67. * @param $user_id 用户id
  68. * @param $table 来源表
  69. * @param $data_id 表id
  70. * @param $isAdmin 是否是管理员处理
  71. * @return array
  72. * @return array[status]
  73. * @return array[msg]
  74. * @return array[log_table]
  75. * @return array[log_id]
  76. */
  77. public function lockChangeAccountRemain($user_id, $accountType = 'money', $number, $logtype = '', $remark = '', $table = '', $table_id = 0, $isAdmin = false)
  78. {
  79. //初始化
  80. $result = array(
  81. 'status' => false,
  82. 'msg' => '',
  83. 'log_table' => '',
  84. 'log_id' => '',
  85. );
  86. //获取小数点
  87. $point = $accountType == 'money' ? 2 : 0;
  88. bcscale($point);
  89. //钱包名称
  90. $wallet_name = $this->getWalletName($accountType);
  91. //检测
  92. $number = floatval($number);
  93. if ($number == 0) {
  94. $result['msg'] = '交易金额:0';
  95. return $result;
  96. }
  97. if (0 === bccomp($number, 0)) {
  98. $result['msg'] = '交易金额:0';
  99. return $result;
  100. }
  101. //检测
  102. $wallet = Db::name('user_wallet')->lock(true)->where(['user_id' => $user_id])->find();
  103. if (!$wallet) {
  104. $result['msg'] = '不存在的用户';
  105. return $result;
  106. }
  107. if (bccomp(bcadd($wallet[$accountType], $number), 0) === -1) {
  108. $result['msg'] = $wallet_name . '余额不足!';
  109. return $result;
  110. } else {
  111. if (0 !== bccomp($number, 0)) {
  112. //钱币记录
  113. $data = array();
  114. $data['user_id'] = $user_id;
  115. $data['log_type'] = $logtype;
  116. // $data['money_type'] = $accountType;
  117. $data['before'] = $wallet[$accountType];
  118. $data['change_value'] = $number;
  119. $data['remain'] = bcadd($wallet[$accountType], $number);
  120. $data['table'] = $table;
  121. $data['table_id'] = $table_id;
  122. $data['remark'] = $remark;
  123. $data['createtime'] = time();
  124. $data['updatetime'] = time();
  125. //新的方式
  126. $rs1 = Db::name('user_wallet')->where(['user_id' => $user_id])->update([$accountType => $data['remain']]);
  127. /////////////
  128. $log_table = 'user_' . $accountType . '_log';
  129. $rs2_id = Db::name($log_table)->insertGetId($data);
  130. if ($rs1 === false || $rs2_id === false) {
  131. $result['msg'] = '更新财务记录失败!';
  132. return $result;
  133. }
  134. if ($rs1 !== false && $rs2_id !== false) {
  135. $result['status'] = true;
  136. $result['msg'] = '账户余额已更新!';
  137. $result['log_table'] = $log_table;
  138. $result['log_id'] = $rs2_id;
  139. return $result;
  140. } else {
  141. $result['msg'] = '更新财务记录失败!';
  142. return $result;
  143. }
  144. } else {
  145. $result['msg'] = '金额不足0.01';
  146. return $result;
  147. }
  148. }
  149. }
  150. /**
  151. * 余额变更
  152. * @param int $user_id 用户id
  153. * @param float $number 金额(正数进账,负数出账)
  154. * @param string $accountType 货币类型 self::money_type
  155. * @param int $log_type 日志的类型 self::log_type
  156. * @param string $remark 备注
  157. * @param string $table 来源表
  158. * @param int $table_id 表id
  159. * @return bool
  160. */
  161. public function change(int $user_id, float $number, string $accountType = 'money', int $log_type = 0, string $remark = '', string $table = '', int $table_id = 0)
  162. {
  163. //获取小数点
  164. $point = $accountType == 'money' ? 2 : 0;
  165. bcscale($point);
  166. //钱包名称
  167. $wallet_name = $this->getWalletName($accountType);
  168. //检测
  169. if ($number == 0 || 0 === bccomp($number, 0)) {
  170. return $this->error('交易金额:0');
  171. }
  172. //检测
  173. if (!$wallet = Db::name('user_wallet')->lock(true)->where(['user_id' => $user_id])->find()) {
  174. return $this->error('不存在的用户');
  175. }
  176. if (bccomp(bcadd($wallet[$accountType], $number), 0) === -1) {
  177. return $this->error("{$wallet_name}余额不足!");
  178. }
  179. //钱币记录
  180. $data = [
  181. 'user_id' => $user_id,
  182. 'log_type' => $log_type,
  183. 'before' => $wallet[$accountType],
  184. 'change_value' => $number,
  185. 'remain' => bcadd($wallet[$accountType], $number),
  186. 'table' => $table,
  187. 'table_id' => $table_id,
  188. 'remark' => $remark,
  189. 'createtime' => time(),
  190. 'updatetime' => time(),
  191. ];
  192. //新的方式
  193. $upWallet = Db::name('user_wallet')->where(['user_id' => $user_id])->update([$accountType => $data['remain']]);
  194. if ($upWallet === false) {
  195. return $this->error("更新账户余额失败!");
  196. }
  197. if (!Db::name("user_{$accountType}_log")->insertGetId($data)) {
  198. return $this->error("更新财务记录失败!");
  199. }
  200. return $this->success("账户余额已更新!");
  201. }
  202. protected function success($message = '', $data = [])
  203. {
  204. $this->message = $message;
  205. $this->data = $data;
  206. return true;
  207. }
  208. protected function error($message = '', $data = [])
  209. {
  210. $this->message = $message;
  211. $this->data = $data;
  212. return false;
  213. }
  214. public function getMessage()
  215. {
  216. return $this->message;
  217. }
  218. public function getData($name = null)
  219. {
  220. $data = $this->data;
  221. !empty($name) && $data = $this->data[$name];
  222. return $data;
  223. }
  224. }