| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- <?php
- namespace app\api\service;
- use addons\fastchat\library\Chat;
- use app\api\model\deposit\Record;
- use app\api\model\order\Order;
- use app\api\model\order\Progress;
- use app\api\model\ThirdPayLog;
- use app\api\model\User;
- use app\api\model\user\Bill;
- use app\api\model\user\Voucher;
- use app\api\model\user\Wallet;
- use redis\RedLock;
- use think\Db;
- use think\Exception;
- use think\Log;
- class WalletService extends BaseService
- {
- private $userModel;
- private $userVoucherModel;
- private $userWalletModel;
- private $userBillModel;
- private $orderModel;
- private $thirdPayService;
- private $thirdPayLogModel;
- public function __construct()
- {
- $this->userModel = new User();
- $this->userWalletModel = new Wallet();
- $this->userBillModel = new Bill();
- $this->orderModel = new Order();
- $this->thirdPayService = new ThirdPayService();
- $this->thirdPayLogModel = new ThirdPayLog();
- $this->userVoucherModel = new Voucher();
- }
- public function fetchRechargeOption()
- {
- $cfg = config("site.balance_recharge");
- return array_map(function ($data) use ($cfg) {
- return [
- "amount" => (float)$data,
- "give" => (float)$cfg[$data]
- ];
- }, array_keys($cfg));
- }
- public function fetchVoucher($user_id, $status, $page = 1, $size = 10)
- {
- $this->userVoucherModel->passVoucher($user_id);
- $paginate = $this->userVoucherModel->fetchVoucher($user_id, $status, $page, $size);
- return [
- $paginate->items(),
- $paginate->total()
- ];
- }
- // 余额充值
- public function rechargeBalance($user_id, $payment_type, $amount, $platform): \SResult
- {
- $user = $this->userModel->findById($user_id);
- if (!$user)
- return $this->fail("用户不存在!");
- $walletLock = new RedLock();
- $wLock = $walletLock->lock(Wallet::UWKey($user_id));
- if (!is_array($wLock))
- return $this->fail("请稍后再试!");
- try {
- $give = 0;
- foreach ($this->fetchRechargeOption() as $item) {
- if ($amount >= $item["amount"])
- $give = $item["give"];
- }
- $no = "RBU" . time() . rand(10000, 99999);
- $log = [
- "no" => $no,
- "user_id" => $user_id,
- "platform" => $payment_type,
- "type" => null,
- "value" => json_encode([
- "user_id" => $user_id,
- "amount" => $amount,
- "give" => $give
- ]),
- "reason" => null,
- "status" => \E_BASE_STATUS::Default,
- "relation_no" => $no,
- "createtime" => time(),
- "updatetime" => time()
- ];
- if (\E_ORDER_PAY_TYPE::Wechat === $payment_type) {
- $openid = null;
- if ($platform == "app")
- $openid = $user["app_openid"];
- if ($platform == "web")
- $openid = $user["web_openid"];
- if ($platform == "applet")
- $openid = $user["applet_openid"];
- if (is_null($openid) || mb_strlen($openid) === 0)
- throw new Exception("请先绑定微信再进行支付!");
- $user = $this->userModel->findById($user_id);
- if (!$user)
- throw new Exception("用户异常!");
- $res = $this->thirdPayService->payWechat($platform, $openid, $log["no"], $amount, "充值余额");
- $log["type"] = \E_USER_BILL_CHANGE_TYPE::BalanceWxRecharge[0];
- $log["reason"] = \E_USER_BILL_CHANGE_TYPE::BalanceWxRecharge[1];
- } else {
- $log["type"] = \E_USER_BILL_CHANGE_TYPE::BalanceAliRecharge[0];
- $log["reason"] = \E_USER_BILL_CHANGE_TYPE::BalanceAliRecharge[1];
- $res = $this->thirdPayService->payAli([]);
- }
- if ($res->code())
- $this->thirdPayLogModel->save($log);
- return $res;
- } catch (Exception $e) {
- return $this->fail($e->getMessage());
- } finally {
- $walletLock->unlock($wLock);
- }
- }
- // 余额支付
- public function payBalance($order)
- {
- $walletLock = new RedLock();
- $wLock = $walletLock->lock(Wallet::UWKey($order->user_id));
- if (!is_array($wLock))
- return $this->fail("请稍后再试");
- $massager = (new \app\api\model\massager\Massager())->findById($order["massager_id"] ?? -1);
- if ($order["massager_id"] > 0) {
- if (!$massager)
- return $this->fail("助教不存在!");
- }
- $wallet = $this->userWalletModel->getUserWallet($order->user_id);
- $change = $order->total_real_amount + $order->membership_amount;
- $w_money = $wallet->money;
- $w_g_money = $wallet->give_money;
- $w_total_money = $w_money + $w_g_money;
- $membership_no = "RBM" . time() . rand(10000, 99999);
- if ($order["membership_config_id"] > 0 && $order["membership_amount"] > 0) {
- $res = $this->thirdPayLogModel->save([
- "no" => $membership_no,
- "user_id" => $order["user_id"],
- "platform" => $order["pay_platform"],
- "type" => \E_USER_BILL_CHANGE_TYPE::MemberCharge[0],
- "reason" => \E_USER_BILL_CHANGE_TYPE::MemberCharge[1],
- "value" => null,
- "membership_config_id" => $order["membership_config_id"],
- "amount" => $order["membership_amount"],
- "status" => \E_BASE_STATUS::Default,
- "relation_no" => $order["no"],
- "createtime" => time(),
- "updatetime" => time()
- ]);
- if (!$res) {
- return $this->fail("会员订单保存异常");
- }
- }
- if ($w_total_money - $change < 0)
- return $this->fail("账户余额不足");
- Db::startTrans();
- try {
- if ($order["membership_config_id"] > 0 && $order["membership_amount"] > 0) {
- $r = (new CallbackService())->rechargeMembershipSuccess($membership_no);
- if (0 === $r->code()) {
- throw new Exception($r->msg());
- }
- }
- $bill = [
- "user_id" => $order->user_id,
- "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
- "change_type" => \E_USER_BILL_CHANGE_TYPE::BalanceOrderConsumption[0],
- "change" => -$change,
- "before" => $w_total_money,
- "after" => $w_total_money - $change,
- "reason" => \E_USER_BILL_CHANGE_TYPE::BalanceOrderConsumption[1],
- "money" => 0,
- "give_money" => 0,
- "relation_no" => $order->no,
- "createtime" => time()
- ];
- $update = [
- "score" => $wallet["score"] + $change,
- "updatetime" => time()
- ];
- // 优先减扣充值的钱
- if ($w_money - $change > 0) {
- $update["money"] = fixed2Float($w_money - $change);
- $bill["money"] = -$change;
- } else {
- $update["money"] = 0;
- $update["give_money"] = $w_g_money - ($change - $w_money);
- $bill["money"] = -$w_money;
- $bill["give_money"] = -($change - $w_money);
- }
- $this->userWalletModel->update($update, ["id" => $wallet->id]);
- $this->orderModel->update([
- "status" => \E_ORDER_STATUS::Purchase,
- "balance_deduction" => 0,
- "pay_time" => time(),
- "updatetime" => time()
- ], ["id" => $order->id]);
- $this->userBillModel->insertAll([$bill, [
- "user_id" => $order->user_id,
- "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Score,
- "change_type" => \E_USER_BILL_CHANGE_TYPE::ScoreOrderGive[0],
- "change" => $change,
- "before" => $wallet["score"],
- "after" => $wallet["score"] + $change,
- "reason" => \E_USER_BILL_CHANGE_TYPE::ScoreOrderGive[1],
- "money" => 0,
- "give_money" => 0,
- "relation_no" => $order->no,
- "createtime" => time()
- ]]);
- $progress = [];
- $types = $order["store_id"] > 0 ? [
- \E_ORDER_PROGRESS_TYPE::Start,
- \E_ORDER_PROGRESS_TYPE::Over,
- ] : ALL_ORDER_PROGRESS_TYPE;
- if ($order["reorder"] == 1) {
- $types = [
- \E_ORDER_PROGRESS_TYPE::Take,
- \E_ORDER_PROGRESS_TYPE::Over,
- ];
- }
- foreach ($types as $key => $value) {
- $progress[] = [
- "order_id" => $order->id,
- "order_no" => $order->no,
- "type" => $value,
- "clock_in" => 0,
- "index" => $key + 1,
- "clock_in_time" => null,
- "lng" => null,
- "lat" => null,
- "card_image" => null,
- "createtime" => time(),
- "updatetime" => time()
- ];
- }
- (new Progress())->insertAll($progress);
- if ($order["massager_id"] > 0 && $massager["mobile"]) {
- $r = TencentCloudService::tencent_cloud_vms_send($massager["mobile"], "1478969", [$order["no"]]);
- Log::custom_log("Vms", [$r->code(), $r->msg(), $r->data()], "Vms");
- }
- if ($order["voucher_id"] > 0) {
- $this->userVoucherModel->update([
- "status" => "use"
- ], ["id" => $order["voucher_id"]]);
- }
- if ($order["store_id"] > 0) {
- StoreService::inform($order["no"], $order["store_id"], $order["city_code"], $order["service_start_date"]);
- }
- if ($massager) {
- Chat::init(1)
- ->massager([$massager["id"]])
- ->send("您有新订单,请及时处理");
- }
- Db::commit();
- return $this->ok(true);
- } catch (Exception $e) {
- Db::rollback();
- return $this->fail($e->getMessage());
- } finally {
- UserService::updateGrouping($order["user_id"]);
- $walletLock->unlock($wLock);
- }
- }
- // 退款
- public function refundByBalance($order, $order_status = \E_ORDER_STATUS::Reject): \SResult
- {
- if (!in_array($order["status"], [\E_ORDER_STATUS::Purchase, \E_ORDER_STATUS::Proceed, \E_ORDER_STATUS::WaitFeedback])) {
- return $this->fail("订单的状态不支持退款!");
- }
- $wallet = $this->userWalletModel->getUserWallet($order->user_id);
- if (!$wallet)
- return $this->fail("钱包数据异常,无法取消订单!");
- $walletLock = new RedLock();
- $wLock = $walletLock->lock(Wallet::UWKey($order->user_id));
- if (!is_array($wLock))
- return $this->fail("请稍后再试");
- $bill = $this->userBillModel->getBill($order->user_id, \E_USER_BILL_CURRENCY_TYPE::Money, \E_USER_BILL_CHANGE_TYPE::BalanceOrderConsumption[0], $order->no);
- if (!$bill || (0 == $bill->money && 0 == $bill->give_money))
- return $this->fail("账单数据异常,无法取消订单!");
- $trip_amount = 0;
- if (\E_ORDER_STATUS::Purchase !== $order["status"]) {
- $trip_amount = $order["trip_amount"];
- }
- // 订单实际支付总额 - 出行费 出行费不退
- $change = abs($bill->change) - $trip_amount;
- $money = abs($bill->money);
- $give_money = abs($bill->give_money);
- if ($money - $trip_amount > 0) {
- $money -= $trip_amount;
- } else {
- $money = 0;
- $give_money -= ($money + $trip_amount);
- }
- Db::startTrans();
- try {
- $save_bill = [
- "user_id" => $order->user_id,
- "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
- "change_type" => \E_USER_BILL_CHANGE_TYPE::BalanceOrderRefund[0],
- "change" => $change,
- "before" => ($wallet->money + $wallet->give_money),
- "after" => ($wallet->money + $wallet->give_money) + $change,
- "reason" => \E_USER_BILL_CHANGE_TYPE::BalanceOrderRefund[1],
- "money" => $money,
- "give_money" => $give_money,
- "relation_no" => $order->no,
- "createtime" => time()
- ];
- $this->orderModel->update([
- "status" => $order_status,
- "cancel_time" => time(),
- "updatetime" => time()
- ], ["id" => $order->id]);
- $this->userWalletModel->update([
- "money" => $wallet->money + $money,
- "give_money" => $wallet->give_money + $give_money,
- "updatetime" => time()
- ], ["id" => $wallet->id]);
- if ($order["massager_id"] > 0 && $trip_amount > 0) {
- $mWalletModel = new \app\api\model\massager\Wallet();
- // 出行费到账助教账户
- $mWallet = $mWalletModel->getWallet($order["massager_id"]);
- $mWalletModel->where("id", $mWallet->id)->setInc("profit_amount", $trip_amount);
- (new \app\api\model\massager\Bill())->insert([
- "massager_id" => $order["massager_id"],
- "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
- "change_type" => \E_M_BILL_CHANGE_TYPE::Travel,
- "change" => $trip_amount,
- "before" => fixed2Float($mWallet->profit_amount),
- "after" => fixed2Float($mWallet->profit_amount + $trip_amount),
- "reason" => "出行费用",
- "relation_no" => $order->no,
- "createtime" => time()
- ]);
- }
- // 优惠券|积分 退还
- if ($order["voucher_id"] > 0) {
- $this->userVoucherModel->update(["status" => \E_BASE_STATUS::Normal], ["id" => $order["voucher_id"]]);
- }
- $this->userWalletModel->where("id", $wallet["id"])->setDec("score", $order["total_real_amount"]);
- $this->userBillModel->saveAll([
- $save_bill,
- [
- "user_id" => $order->user_id,
- "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Score,
- "change_type" => \E_USER_BILL_CHANGE_TYPE::ScoreOrderRefund[0],
- "change" => -$order["total_real_amount"],
- "before" => $wallet["score"],
- "after" => $wallet["score"] - $order["total_real_amount"],
- "reason" => \E_USER_BILL_CHANGE_TYPE::ScoreOrderRefund[1],
- "money" => 0,
- "give_money" => 0,
- "relation_no" => $order->no,
- "createtime" => time()
- ]]);
- Db::commit();
- return $this->ok(true);
- } catch (Exception $e) {
- Db::rollback();
- return $this->fail($e->getMessage());
- } finally {
- UserService::updateGrouping($order["user_id"]);
- $walletLock->unlock($wLock);
- }
- }
- // 退单
- public function chargeback($order, $identity_type, $chargeback_type)
- {
- if (!in_array($order["status"], [\E_ORDER_STATUS::Purchase, \E_ORDER_STATUS::Proceed, \E_ORDER_STATUS::WaitFeedback])) {
- return $this->fail("订单的状态不支持退款!");
- }
- }
- // 获取账单
- public function fetchBill($user_id, $currency_type, $change_types, $page = 1, $size = 10)
- {
- $paginate = $this->userBillModel->fetchBill($user_id, $currency_type, $change_types, $page, $size);
- return [
- $paginate->items(),
- $paginate->total()
- ];
- }
- public function delBills($user_id, array $bill_ids)
- {
- $this->userBillModel
- ->where("user_id", $user_id)
- ->where("id", "in", $bill_ids)
- ->update([
- "is_del" => 1,
- ]);
- return $this->ok(true);
- }
- /**
- * 兑换优惠券
- * @param $user_id
- * @param $voucher_id
- */
- public function exchangeVoucher($user_id, $voucher_id)
- {
- $systemVoucher = (new \app\api\model\Voucher)->findById($voucher_id);
- if (!$systemVoucher || $systemVoucher->exchange_score <= 0)
- return $this->fail("该优惠券不可兑换");
- $walletLock = new RedLock();
- $wLock = $walletLock->lock(Wallet::UWKey($user_id));
- if (!is_array($wLock))
- return $this->fail("请稍后再试");
- $wallet = $this->userWalletModel->getUserWallet($user_id);
- if ($wallet->score - $systemVoucher->exchange_score < 0)
- return $this->fail("账户积分余额不足");
- Db::startTrans();
- try {
- $this->userWalletModel->where("id", $wallet->id)->setDec("score", $systemVoucher->exchange_score);
- $this->userBillModel->save([
- "user_id" => $user_id,
- "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Score,
- "change_type" => \E_USER_BILL_CHANGE_TYPE::ScoreExchangeVoucher[0],
- "change" => -$systemVoucher->exchange_score,
- "before" => $wallet->score,
- "after" => $wallet->score - $systemVoucher->exchange_score,
- "reason" => \E_USER_BILL_CHANGE_TYPE::ScoreExchangeVoucher[1],
- "createtime" => time()
- ]);
- $this->userVoucherModel->save([
- "user_id" => $user_id,
- "voucher_id" => $voucher_id,
- "takeAmount" => $systemVoucher->takeAmount,
- "fullAmount" => $systemVoucher->fullAmount,
- "status" => \E_BASE_STATUS::Normal,
- "expiretime" => time() + (24 * 60 * 60) * $systemVoucher->indate_day,
- "createtime" => time(),
- "updatetime" => time()
- ]);
- Db::commit();
- return $this->ok(true);
- } catch (Exception $e) {
- Db::rollback();
- return $this->fail($e->getMessage());
- } finally {
- $walletLock->unlock($wLock);
- }
- }
- public function deposit($user_id, $platform, $amount)
- {
- $user = $this->userModel->get($user_id);
- if (!$user)
- return $this->fail("用户不存在");
- if ($platform == \E_ORDER_PAY_TYPE::Wechat)
- return $this->fail("微信提现功能暂未审核通过!");
- if ($platform == \E_ORDER_PAY_TYPE::Wechat) {
- if (null == $user["applet_openid"])
- return $this->fail("未绑定微信,无法发起提现!", 10001);
- } else if ($platform == \E_ORDER_PAY_TYPE::Bank) {
- if (mb_strlen($user["opening_bank_name"] ?? '') == 0
- || mb_strlen($user["bank_real_name"] ?? '') == 0
- || mb_strlen($user["bank_no"] ?? '') == 0
- )
- return $this->fail("未绑定银行卡信息,无法发起提现", 10002);
- }
- $wallet = $this->userWalletModel->getUserWallet($user_id);
- $deposit_min_amount = config("site.user_deposit_min_amount");
- if ($wallet["money"] < $amount)
- return $this->fail("数额不足,无法发起提现");
- if ($amount < $deposit_min_amount)
- return $this->fail("提现最小金额为:{$deposit_min_amount}");
- $record = (new Record())->where([
- "apply_status" => \E_BASE_STATUS::Default,
- "deposit_status" => \E_BASE_STATUS::Default,
- "identity_type" => \E_IDENTITY_TYPE::User,
- "user_id" => $user_id
- ])->find();
- if ($record) {
- return $this->fail("您上一笔提现未通过审核,等待上一笔提现后再次发起");
- }
- (new Record())->save([
- "no" => "TXU" . $user_id . time(),
- "platform" => $platform,
- "identity_type" => \E_IDENTITY_TYPE::User,
- "user_id" => $user_id,
- "deposit_amount" => $amount,
- "service_charge_rate" => config("site.service_charge_rate"),
- "apply_status" => \E_BASE_STATUS::Default,
- "deposit_status" => \E_BASE_STATUS::Default,
- "operation_id" => $user_id,
- "createtime" => time(),
- "updatetime" => time(),
- "opening_bank_name" => $user["opening_bank_name"],
- "bank_real_name" => $user["bank_real_name"],
- "bank_no" => $user["bank_no"],
- ]);
- return $this->ok(true, "申请提现成功,请耐心等待管理员审核!");
- }
- }
|