ShopCashOutService.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. namespace app\service\admin\shop\site;
  3. use app\dict\shop\ShopCashOutDict;
  4. use app\dict\shop\ShopTransferDict;
  5. use app\model\shop\ShopCashOut;
  6. use app\service\core\sys\CoreSysConfigService;
  7. use core\exception\CommonException;
  8. use app\dict\member\MemberAccountTypeDict;
  9. use core\base\BaseAdminService;
  10. use think\facade\Cache;
  11. use think\facade\Db;
  12. class ShopCashOutService extends BaseAdminService
  13. {
  14. public function __construct()
  15. {
  16. parent::__construct();
  17. $this->model = new ShopCashOut();
  18. }
  19. public function getPage(array $where = [])
  20. {
  21. $field = 'apply_money, money, service_money, shop_cash_out.status, shop_cash_out.create_time, audit_time, transfer_time';
  22. $order = 'shop_cash_out.create_time desc';
  23. $search_model = $this->model
  24. ->withJoin(['siteInfo'])
  25. ->withSearch(['cash_out_no', 'create_time', 'audit_time', 'transfer_time', 'transfer_type', 'status'], $where)
  26. ->where([['shop_cash_out.site_id', '=', $this->site_id]])
  27. ->append([ 'status_name', 'transfer_type_name' ])
  28. ->field($field)->order($order);
  29. return $this->pageQuery($search_model);
  30. }
  31. /**
  32. * 店铺提现详情
  33. * @param int $id
  34. * @return array
  35. */
  36. public function getInfo(int $id)
  37. {
  38. $field = 'apply_money, money, service_money, shop_cash_out.status, shop_cash_out.create_time, audit_time, transfer_type, transfer_time';
  39. return $this->model
  40. ->withJoin(['siteInfo'])
  41. ->append([ 'status_name', 'transfer_type_name' ])
  42. ->field($field)->where([ [ 'id|cash_out_no', '=', $id ] ])->findOrEmpty()->toArray();
  43. }
  44. /**
  45. * 申请提现
  46. * @param array $data
  47. * @return true
  48. */
  49. public function apply(array $data)
  50. {
  51. $cash_out_config = ( new ShopConfigService() )->getCashOutConfig();
  52. if ($cash_out_config['is_open'] == 0) throw new CommonException('SHOP_CASH_OUT_NOT_START');//店铺提现未开启
  53. if ($cash_out_config['min'] > $data['apply_money']) throw new CommonException(get_lang('MIN_CASH_OUT_MONEY_CANNOT_UNDER').$cash_out_config['min']);//最低提现金额不能小于
  54. $shopAccount = ( new ShopService() )->find();
  55. if (!in_array($shopAccount['bank_type'], $cash_out_config['transfer_type'])) throw new CommonException('TRANSFER_TYPE_NOT_SUPPORT');//系统暂不支持该转账方式
  56. if (empty($shopAccount)) throw new CommonException('CASH_OUT_ACCOUNT_NOT_EXIST');
  57. if ($data['apply_money'] <= 0) throw new CommonException('CASH_OUT_MONEY_MUST_BE_GREATER_THAN_ZERO');
  58. if ($shopAccount['money'] < $data['apply_money']) throw new CommonException('EXCEEDING_MAXIMUM_WITHDRAWABLE_BALANCE');
  59. $service_money = format_round_money($data['apply_money'] * $cash_out_config['rate']/100);
  60. $money = $data['apply_money'] - $service_money;
  61. Db::startTrans();
  62. try {
  63. //生成提现交易号
  64. $cash_out_no = $this->createCashOutNo($this->site_id);
  65. //创建提现订单
  66. $data[ 'site_id' ] = $this->site_id;
  67. $data[ 'cash_out_no' ] = $cash_out_no;
  68. $data[ 'account_type' ] = MemberAccountTypeDict::MONEY;
  69. $data[ 'service_money' ] = $service_money;
  70. $data[ 'money' ] = $money;
  71. $data[ 'rate' ] = $cash_out_config['rate'];
  72. $data[ 'transfer_mobile' ] = '';
  73. $data[ 'transfer_bank' ] = $shopAccount['bank_type'] == ShopTransferDict::BANK ? $shopAccount['bank_name'] : '';
  74. $data[ 'transfer_type' ] = $shopAccount['bank_type'];
  75. if ($data[ 'transfer_type' ] == ShopTransferDict::BANK) {
  76. $data[ 'transfer_realname' ] = $shopAccount['bank_account_name'];
  77. $data[ 'transfer_account' ] = $shopAccount['bank_account_no'];
  78. } elseif ($data[ 'transfer_type' ] == ShopTransferDict::ALIPAY) {
  79. $data[ 'transfer_realname' ] = $shopAccount['alipay_name'];
  80. $data[ 'transfer_account' ] = $shopAccount['alipay_account_no'];
  81. $data[ 'transfer_payment_code' ] = $shopAccount['alipay_payment_code'];//支付宝收款码
  82. } elseif ($data[ 'transfer_type' ] == ShopTransferDict::WECHAT_CODE) {
  83. $data[ 'transfer_realname' ] = $shopAccount['wechat_name'];
  84. $data[ 'transfer_account' ] = $shopAccount['wechat_account_no'];
  85. $data[ 'transfer_payment_code' ] = $shopAccount['wechat_payment_code'];//微信收款码
  86. }
  87. $data[ 'status' ] = $cash_out_config['is_auto_verify'] == 1 ? 2 : 1;
  88. $data[ 'create_time' ] = time();
  89. $res = $this->model->create($data);
  90. //更新店铺信息
  91. $shopAccount->save([
  92. 'money_cash_outing' => $shopAccount['money_cash_outing'] + $data['apply_money'], //提现中金额计算
  93. 'money' => $shopAccount['money'] - $data['apply_money'], //当前余额计算
  94. ]);
  95. //添加账户收支记录
  96. $log_data['site_id'] = $this->site_id;
  97. $log_data['money'] = -1 * $data['apply_money'];
  98. $log_data['money_sum'] = $shopAccount['money'] - $data['apply_money'];
  99. $log_data['from_type'] = 'cash_out';
  100. $log_data['related_id'] = $cash_out_no;
  101. $log_data['memo'] = get_lang('SHOP_CASH_OUT');
  102. ( new ShopAccountLogService() )->add($log_data);
  103. Db::commit();
  104. } catch ( Exception $e) {
  105. Db::rollback();
  106. throw new CommonException($e->getMessage());
  107. }
  108. return true;
  109. }
  110. /**
  111. * 取消申请
  112. * @return true
  113. */
  114. public function cancel(int $id, array $data)
  115. {
  116. $info = $this->model->where([ [ 'id', '=', $id ] ])->findOrEmpty()->toArray();
  117. if(empty($info)) return true;
  118. $data[ 'update_time' ] = time();
  119. $data[ 'cancel_time'] = time();
  120. $data[ 'status' ] = -2;
  121. Db::startTrans();
  122. try {
  123. $this->model->where([['id', '=', $id]])->update($data);
  124. //审核取消,退回余额及减去提现中金额
  125. $shopAccount = ( new ShopService() )->find();
  126. $shopAccount->where([ [ 'site_id', '=', $info[ 'site_id' ] ] ])->update([
  127. 'money_cash_outing' => $shopAccount['money_cash_outing'] - $info['apply_money'],
  128. 'money' => $shopAccount['money'] + $info['apply_money']
  129. ]);
  130. $shopAccountLogService = new ShopAccountLogService();
  131. //添加账户收支记录
  132. $log_data['site_id'] = $info[ 'site_id' ];
  133. $log_data['money'] = $info['apply_money'];
  134. $log_data['money_sum'] = $shopAccount['money'] + $info['apply_money'];
  135. $log_data['from_type'] = 'cash_out';
  136. $log_data['related_id'] = $info['cash_out_no'];
  137. $log_data['memo'] = get_lang('USER_CANCEL_CASH_OUT_BACK_MONEY');
  138. $shopAccountLogService->add($log_data);
  139. Db::commit();
  140. } catch (\Exception $e) {
  141. Db::rollback();
  142. throw new CommonException($e->getMessage());
  143. }
  144. return true;
  145. }
  146. /**
  147. * 创建订单编号
  148. * @param int $site_id
  149. * @return string
  150. */
  151. public function createCashOutNo(int $site_id)
  152. {
  153. $time_str = date('YmdHi');
  154. $max_no = Cache::get('cash_out_no_' . $site_id . '_' . $time_str);
  155. if (!isset($max_no) || empty($max_no)) {
  156. $max_no = 1;
  157. } else {
  158. ++$max_no;
  159. }
  160. $cash_out_no = $time_str . $site_id . sprintf('%03d', $max_no);
  161. Cache::set('cash_out_no_' . $site_id . '_' . $time_str, $max_no);
  162. return $cash_out_no;
  163. }
  164. /**
  165. * 转账
  166. * @param int $id
  167. * @return array
  168. */
  169. public function transfer(int $id)
  170. {
  171. $info = $this->model->field('status,transfer_type')->where([ [ 'id', '=', $id ] ])->findOrEmpty()->toArray();
  172. if (empty($info)) throw new CommonException('CASHOUT_LOG_NOT_EXIST');
  173. if (!in_array($info['status'], [ ShopCashOutDict::WAIT_TRANSFER, ShopCashOutDict::TRANSFER_ING ])) throw new CommonException('CASH_OUT_APPLY_NOT_PASS_OR_TRANSFERED');//审核未通过或已转账
  174. if ($info['transfer_type'] != ShopTransferDict::WECHAT) throw new CommonException('THIS_TRANSFER_TYPE_IS_NOT_SUPPORTED');//不支持该提现方式
  175. $check_code = substr(md5(uniqid('', true)), 0, 5);
  176. Cache::tag('transfer_'.$info['transfer_type'].'_'.$id)->set($check_code, $id, 900);
  177. return [
  178. 'page' => 'app/pages/site/transfer?cod='. $check_code,
  179. 'qrcode' => $this->getQrcode($check_code)
  180. ];
  181. }
  182. /**
  183. * 生成转账小程序二维码
  184. * @param string $check_code
  185. * @return string
  186. */
  187. public function getQrcode(string $check_code)
  188. {
  189. $url = ( new CoreSysConfigService() )->getSceneDomain($this->site_id)[ 'wap_url' ];
  190. $page = 'app/pages/site/transfer';
  191. $data = [
  192. [
  193. 'key' => 'cod',
  194. 'value' => $check_code
  195. ]
  196. ];
  197. $dir = 'upload/qrcode/' . $this->site_id . '/transfer';
  198. $channel = 'weapp';
  199. return qrcode($url, $page, $data, $this->site_id, $dir, $channel);
  200. }
  201. }