UserExtract.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. <?php
  2. /**
  3. *
  4. * @author: xaboy<365615158@qq.com>
  5. * @day: 2018/3/3
  6. */
  7. namespace app\models\user;
  8. use app\models\user\User;
  9. use app\models\user\UserBill;
  10. use app\models\wechat\WechatTemplate;
  11. use app\models\wechat\WechatUser;
  12. use app\models\routine\RoutineTemplate;
  13. use crmeb\basic\BaseModel;
  14. use crmeb\services\WechatTemplateService;
  15. use crmeb\services\workerman\ChannelService;
  16. use crmeb\traits\ModelTrait;
  17. use think\facade\Route as Url;
  18. /**
  19. * TODO 用户提现
  20. * Class UserExtract
  21. * @package app\models\user
  22. */
  23. class UserExtract extends BaseModel
  24. {
  25. /**
  26. * 数据表主键
  27. * @var string
  28. */
  29. protected $pk = 'id';
  30. /**
  31. * 模型名称
  32. * @var string
  33. */
  34. protected $name = 'user_extract';
  35. use ModelTrait;
  36. //审核中
  37. const AUDIT_STATUS = 0;
  38. //未通过
  39. const FAIL_STATUS = -1;
  40. //已提现
  41. const SUCCESS_STATUS = 1;
  42. protected static $extractType = ['alipay', 'bank', 'weixin'];
  43. protected static $extractTypeMsg = ['alipay' => '支付宝', 'bank' => '银行卡', 'weixin' => '微信'];
  44. protected static $status = array(
  45. -1 => '未通过',
  46. 0 => '审核中',
  47. 1 => '已提现'
  48. );
  49. /**
  50. * @param $mer_id
  51. * @return mixed
  52. */
  53. public static function merSet($mer_id)
  54. {
  55. return $mer_id ? self::where('mer_id', $mer_id) : new self;
  56. }
  57. /**
  58. * 用户自主提现记录提现记录,后台执行审核
  59. * @param array $userInfo 用户个人信息
  60. * @param array $data 提现详细信息
  61. * @return bool
  62. */
  63. public static function userExtract($userInfo, $data, $mer_id = '')
  64. {
  65. if (!in_array($data['extract_type'], self::$extractType))
  66. return self::setErrorInfo('提现方式不存在');
  67. $userInfo = User::get($userInfo['uid']);
  68. $extractPrice = $userInfo['brokerage_price'];
  69. if ($extractPrice < 0) return self::setErrorInfo('提现佣金不足' . $data['money']);
  70. if ($data['money'] > $extractPrice) return self::setErrorInfo('提现佣金不足' . $data['money']);
  71. if ($data['money'] <= 0) return self::setErrorInfo('提现佣金大于0');
  72. $balance = bcsub($userInfo['brokerage_price'], $data['money'], 2);
  73. if ($balance < 0) $balance = 0;
  74. $insertData = [
  75. 'uid' => $userInfo['uid'],
  76. 'extract_type' => $data['extract_type'],
  77. 'extract_price' => $data['money'],
  78. 'add_time' => time(),
  79. 'balance' => $balance,
  80. 'status' => self::AUDIT_STATUS,
  81. 'mer_id' => $mer_id
  82. ];
  83. if (isset($data['name']) && strlen(trim($data['name']))) $insertData['real_name'] = $data['name'];
  84. else $insertData['real_name'] = $userInfo['nickname'];
  85. if (isset($data['cardnum'])) $insertData['bank_code'] = $data['cardnum'];
  86. else $insertData['bank_code'] = '';
  87. if (isset($data['bankname'])) $insertData['bank_address'] = $data['bankname'];
  88. else $insertData['bank_address'] = '';
  89. if (isset($data['weixin'])) $insertData['wechat'] = $data['weixin'];
  90. else $insertData['wechat'] = $userInfo['nickname'];
  91. if ($data['extract_type'] == 'alipay') {
  92. if (!$data['alipay_code']) return self::setErrorInfo('请输入支付宝账号');
  93. $insertData['alipay_code'] = $data['alipay_code'];
  94. $mark = '使用支付宝提现' . $insertData['extract_price'] . '元';
  95. } else if ($data['extract_type'] == 'bank') {
  96. if (!$data['cardnum']) return self::setErrorInfo('请输入银行卡账号');
  97. if (!$data['bankname']) return self::setErrorInfo('请输入开户行信息');
  98. $mark = '使用银联卡' . $insertData['bank_code'] . '提现' . $insertData['extract_price'] . '元';
  99. } else if ($data['extract_type'] == 'weixin') {
  100. if (!$data['weixin']) return self::setErrorInfo('请输入微信账号');
  101. $mark = '使用微信提现' . $insertData['extract_price'] . '元';
  102. }
  103. self::beginTrans();
  104. try {
  105. $res1 = self::create($insertData);
  106. if (!$res1) return self::setErrorInfo('提现失败');
  107. $res2 = User::edit(['brokerage_price' => $balance], $userInfo['uid'], 'uid');
  108. $res3 = UserBill::expend('余额提现', $userInfo['uid'], 'now_money', 'extract', $data['money'], $res1['id'], $balance, $mark);
  109. $res = $res2 && $res3;
  110. if ($res) {
  111. self::commitTrans();
  112. try {
  113. ChannelService::instance()->send('WITHDRAW', ['id' => $res1->id]);
  114. } catch (\Exception $e) {
  115. }
  116. event('AdminNewPush');
  117. //发送模板消息
  118. return true;
  119. } else return self::setErrorInfo('提现失败!');
  120. } catch (\Exception $e) {
  121. self::rollbackTrans();
  122. return self::setErrorInfo('提现失败!');
  123. }
  124. }
  125. /**
  126. * 获得用户最后一次提现信息
  127. * @param $openid
  128. * @return mixed
  129. */
  130. public static function userLastInfo($uid)
  131. {
  132. return self::where(compact('uid'))->order('add_time DESC')->find();
  133. }
  134. /**
  135. * 获得用户提现总金额
  136. * @param $uid
  137. * @return mixed
  138. */
  139. public static function userExtractTotalPrice($uid, $status = self::SUCCESS_STATUS)
  140. {
  141. return self::where('uid', $uid)->where('status', $status)->value('SUM(extract_price)') ?: 0;
  142. }
  143. public static function userExtractAdminTotalPrice($uid, $status = 1, $where = [])
  144. {
  145. return self::getModelTime($where, self::where('uid', 'in', $uid)->where('status', $status))->sum('extract_price') ?: 0;
  146. }
  147. /*
  148. * 用户提现记录列表
  149. * @param int $uid 用户uid
  150. * @param int $first 截取行数
  151. * @param int $limit 截取数
  152. * @return array
  153. * */
  154. public static function extractList($uid, $first = 0, $limit = 8)
  155. {
  156. $list = UserExtract::where('uid', $uid)->order('add_time desc')->limit($first, $limit)->select();
  157. foreach ($list as &$v) {
  158. $v['add_time'] = date('Y/m/d', $v['add_time']);
  159. }
  160. return $list;
  161. }
  162. /**
  163. * 获取累计已提现佣金
  164. * @param $uid
  165. * @return float
  166. */
  167. public static function extractSum($uid)
  168. {
  169. return self::where('uid', $uid)->where('status', 1)->sum('extract_price');
  170. }
  171. /**
  172. * 获取用户累计提现金额
  173. * @param int $uid
  174. * @return int|mixed
  175. */
  176. public static function getUserCountPrice($uid = 0)
  177. {
  178. if (!$uid) return 0;
  179. $price = self::where('uid', $uid)->where('status', 1)->sum('extract_price');
  180. return $price ? $price : 0;
  181. }
  182. /**
  183. * 后台提现统计
  184. * @return array
  185. */
  186. public static function extractStatistics($where, $mer_id = '')
  187. {
  188. $model = new self;
  189. $model = self::getModelTime($where, $model, 'add_time');
  190. //待提现金额
  191. $data['price'] = floatval($model->where('mer_id', $mer_id)->where('status', 0)->sum('extract_price'));
  192. //佣金总金额
  193. $data['brokerage_count'] = floatval(UserBill::getBrokerageCount($where, $mer_id));
  194. //已提现金额
  195. $data['priced'] = floatval($model->where('mer_id', $mer_id)->where('status', 1)->sum('extract_price'));
  196. //未提现金额
  197. $data['brokerage_not'] = bcsub(bcsub($data['brokerage_count'], $data['priced'], 2), $data['price'], 2);
  198. return compact('data');
  199. }
  200. /**
  201. * 提现申请列表
  202. * @param $where
  203. * @return array
  204. */
  205. public static function systemPage($where, $mer_id = '')
  206. {
  207. $model = new self;
  208. $model = self::getModelTime($where, $model, 'a.add_time');
  209. if ($where['status'] != '') $model = $model->where('a.status', $where['status']);
  210. if ($where['extract_type'] != '') $model = $model->where('a.extract_type', $where['extract_type']);
  211. if ($where['nireid'] != '') $model = $model->where('a.real_name|a.id|b.nickname|a.bank_code|a.alipay_code', 'like', "%$where[nireid]%");
  212. $model = $model->alias('a');
  213. $model = $model->where('a.extract_type', '<>', 'balance');
  214. $model = $model->field('a.*,b.nickname');
  215. $model = $model->join('user b', 'b.uid=a.uid', 'LEFT');
  216. $model = $model->order('a.id desc');
  217. $model = $model->where('a.mer_id', $mer_id);
  218. $count = $model->count();
  219. $list = $model->page((int)$where['page'], (int)$where['limit'])->select();
  220. return compact('count', 'list');
  221. }
  222. /**
  223. * 拒绝提现申请
  224. * @param $id
  225. * @param $fail_msg
  226. * @return bool
  227. * @throws \think\db\exception\DataNotFoundException
  228. * @throws \think\db\exception\ModelNotFoundException
  229. * @throws \think\exception\DbException
  230. */
  231. public static function changeFail($id, $fail_msg)
  232. {
  233. $fail_time = time();
  234. $data = self::get($id);
  235. $extract_number = $data['extract_price'];
  236. $mark = '提现失败,退回佣金' . $extract_number . '元';
  237. $uid = $data['uid'];
  238. $status = -1;
  239. $User = User::where('uid', $uid)->find()->toArray();
  240. UserBill::income('提现失败', $uid, 'now_money', 'extract', $extract_number, $id, bcadd($User['now_money'], $extract_number, 2), $mark);
  241. User::bcInc($uid, 'brokerage_price', $extract_number, 'uid');
  242. $extract_type = '未知方式';
  243. switch ($data['extract_type']) {
  244. case 'alipay':
  245. $extract_type = '支付宝';
  246. break;
  247. case 'bank':
  248. $extract_type = '银行卡';
  249. break;
  250. case 'weixin':
  251. $extract_type = '微信';
  252. break;
  253. }
  254. if (strtolower($User['user_type']) == 'wechat') {
  255. // WechatTemplateService::sendTemplate(WechatUser::where('uid', $uid)->value('openid'), WechatTemplateService::USER_BALANCE_CHANGE, [
  256. // 'first' => $mark,
  257. // 'keyword1' => '佣金提现',
  258. // 'keyword2' => date('Y-m-d H:i:s', time()),
  259. // 'keyword3' => $extract_number,
  260. // 'remark' => '错误原因:' . $fail_msg
  261. // ], Url::buildUrl('/user/cashrecord')->suffix(false)->domain(true)->build());
  262. $wechatTemplate = new WechatTemplate();
  263. $wechatTemplate->sendUserBalanceChangeFial($uid, $extract_number, $fail_msg);
  264. } else if (strtolower($User['user_type']) == 'routine') {
  265. RoutineTemplate::sendExtractFail($uid, $fail_msg, $extract_number, $User['nickname']);
  266. }
  267. return self::edit(compact('fail_time', 'fail_msg', 'status'), $id);
  268. }
  269. /**
  270. * 通过提现申请
  271. * @param $id
  272. * @return bool
  273. * @throws \think\db\exception\DataNotFoundException
  274. * @throws \think\db\exception\ModelNotFoundException
  275. * @throws \think\exception\DbException
  276. */
  277. public static function changeSuccess($id)
  278. {
  279. $data = self::get($id);
  280. $extractNumber = $data['extract_price'];
  281. $mark = '成功提现佣金' . $extractNumber . '元';
  282. $wechatUserInfo = \app\models\wechat\WechatUser::where('uid', $data['uid'])->field('openid,user_type,routine_openid')->find();
  283. $extract_type = '未知方式';
  284. switch ($data['extract_type']) {
  285. case 'alipay':
  286. $extract_type = '支付宝';
  287. break;
  288. case 'bank':
  289. $extract_type = '银行卡';
  290. break;
  291. case 'weixin':
  292. $extract_type = '微信';
  293. break;
  294. }
  295. if ($wechatUserInfo) {
  296. if (strtolower($wechatUserInfo->user_type) == 'routine') {
  297. RoutineTemplate::sendExtractSuccess($data['uid'], $extractNumber, $wechatUserInfo->nickname);
  298. } else if (strtolower($wechatUserInfo->user_type) == 'wechat') {
  299. // WechatTemplateService::sendTemplate($wechatUserInfo->openid, WechatTemplateService::USER_BALANCE_CHANGE, [
  300. // 'first' => $mark,
  301. // 'keyword1' => '佣金提现',
  302. // 'keyword2' => date('Y-m-d H:i:s', time()),
  303. // 'keyword3' => $extractNumber,
  304. // 'remark' => '点击查看我的佣金明细'
  305. // ], Url::buildUrl('/user/cashrecord')->suffix('')->domain(true)->build());
  306. $wechatTemplate = new WechatTemplate();
  307. $wechatTemplate->sendUserBalanceChangeSuccess($data['uid'], $extractNumber);
  308. }
  309. }
  310. return self::edit(['status' => 1], $id);
  311. }
  312. /**
  313. * 获取用户累计提现次数
  314. * @param int $uid
  315. * @return int|string
  316. */
  317. public static function getUserCountNum($uid = 0)
  318. {
  319. if (!$uid) return 0;
  320. return self::where('uid', $uid)->count();
  321. }
  322. }