- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
<?php
namespace addons\shopro\controller;
use app\admin\model\shopro\Cart as CartModel;
use app\admin\model\shopro\goods\Goods;
use app\admin\model\shopro\goods\SkuPrice;
class Cart extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
// 被物理删除的商品直接删掉购物车,只删除自己的
CartModel::whereNotExists(function ($query) {
$goodsTableName = (new Goods())->getQuery()->getTable();
$query = $query->table($goodsTableName)->where($goodsTableName . '.id=goods_id'); // 软删除的商品购物车暂时不删,标记为失效
return $query;
})->where('user_id', $user->id)->delete();
$carts = CartModel::with([
'goods' => function ($query) {
$query->removeOption('soft_delete');
}, 'sku_price'
])->where('user_id', $user->id)->order('id', 'desc')->select();
$carts = collection($carts)->each(function ($cart) {
$cart->tags = $cart->tags; // 标签
$cart->status = $cart->status; // 状态
});
$this->success('获取成功', $carts);
}
public function update()
{
$user = auth_user();
$params = $this->request->only(['goods_id', 'goods_sku_price_id', 'goods_num', 'type']);
$goods_num = $params['goods_num'] ?? 1;
$type = $params['type'] ?? 'inc';
$cart = CartModel::where('user_id', $user->id)
->where('goods_id', $params['goods_id'])
->where('goods_sku_price_id', $params['goods_sku_price_id'])
->find();
$skuPrice = SkuPrice::where('goods_id', $params['goods_id'])->where('id', $params['goods_sku_price_id'])->find();
if (!$skuPrice) {
$this->error('商品规格未找到');
}
if ($cart) {
if ($type == 'dec') {
// 减
$cart->snapshot_price = $skuPrice->price;
$cart->save();
$cart->setDec('goods_num', $goods_num);
} else if ($type == 'cover') {
$cart->goods_num = $goods_num;
$cart->snapshot_price = $skuPrice->price;
$cart->save();
} else {
// 加
$cart->snapshot_price = $skuPrice->price;
$cart->save();
$cart->setInc('goods_num', $goods_num);
}
} else {
$cart = new CartModel();
$cart->user_id = $user->id;
$cart->goods_id = $params['goods_id'];
$cart->goods_sku_price_id = $params['goods_sku_price_id'];
$cart->goods_num = $goods_num;
$cart->snapshot_price = $skuPrice->price;
$cart->save();
}
$this->success('更新成功', $cart);
}
public function delete()
{
$user = auth_user();
$id = $this->request->param('id');
CartModel::where('user_id', $user->id)->whereIn('id', $id)->delete();
$this->success('删除成功');
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace addons\shopro\controller;
use app\admin\model\shopro\Category as CategoryModel;
class Category extends Common
{
protected $noNeedLogin = ['*'];
protected $noNeedRight = ['*'];
public function index()
{
$id = $this->request->param('id', 0);
$category = CategoryModel::where('parent_id', 0)->normal()->order('weigh', 'desc')->order('id', 'desc');
if ($id) {
// 指定 id 分类,否则获取 权重最高的一级分类
$category = $category->where('id', $id);
}
$category = $category->find();
if (!$category) {
$this->error(__('No Results were found'));
}
$childrenString = $category->getChildrenString($category);
$categories = CategoryModel::where('id', $category->id)->normal()->with([$childrenString])->find();
$this->success('商城分类', $categories);
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace addons\shopro\controller;
use think\Lang;
use app\common\controller\Api;
use addons\shopro\controller\traits\Util;
use addons\shopro\controller\traits\UnifiedToken;
/**
* shopro 基础控制器
*/
class Common extends Api
{
use Util, UnifiedToken;
protected $model = null;
public function _initialize()
{
Lang::load(APP_PATH . 'api/lang/zh-cn.php'); // 加载语言包
parent::_initialize();
if (check_env('yansongda', false)) {
set_addon_config('epay', ['version' => 'v3'], false);
}
}
// /**
// * 操作成功返回的数据
// * @param string $msg 提示信息
// * @param mixed $data 要返回的数据
// * @param int $code 错误码默认为1
// * @param string $type 输出类型
// * @param array $header 发送的 Header 信息
// */
// protected function success($msg = '', $data = null, $error = 0, $type = null, ?array $header = [])
// {
// $this->result($msg, $data, $error, $type, $header);
// }
// /**
// * 操作失败返回的数据
// * @param string $msg 提示信息
// * @param mixed $data 要返回的数据
// * @param int $code 错误码默认为0
// * @param string $type 输出类型
// * @param array $header 发送的 Header 信息
// */
// protected function error($msg = '', $error = 1, $data = null, $type = null, ?array $header = [])
// {
// $this->result($msg, $data, $error, $type, $header);
// }
// /**
// * 返回封装后的 API 数据到客户端
// * @access protected
// * @param mixed $msg 提示信息
// * @param mixed $data 要返回的数据
// * @param int $code 错误码默认为0
// * @param string $type 输出类型支持json/xml/jsonp
// * @param array $header 发送的 Header 信息
// * @return void
// * @throws HttpResponseException
// */
// protected function result($msg, $data = null, $error = 0, $type = null, ?array $header = [])
// {
// $result = [
// 'error' => $error,
// 'msg' => $msg,
// 'time' => Request::instance()->server('REQUEST_TIME'),
// 'data' => $data,
// ];
// // 如果未设置类型则自动判断
// $type = $type ? $type : ($this->request->param(config('var_jsonp_handler')) ? 'jsonp' : $this->responseType);
// $statuscode = 200;
// if (isset($header['statuscode'])) {
// $statuscode = $header['statuscode'];
// unset($header['statuscode']);
// }
// $response = Response::create($result, $type, $statuscode)->header($header);
// throw new HttpResponseException($response);
// }
}

View File

@@ -0,0 +1,103 @@
<?php
namespace addons\shopro\controller;
use app\admin\model\shopro\Coupon as CouponModel;
use addons\shopro\traits\CouponSend;
use app\admin\model\shopro\goods\Goods as GoodsModel;
class Coupon extends Common
{
use CouponSend;
protected $noNeedLogin = ['index', 'listByGoods', 'detail'];
protected $noNeedRight = ['*'];
public function index()
{
$ids = $this->request->param('ids', '');
$coupons = CouponModel::with(['user_coupons'])
->normal() // 正常的可以展示的优惠券
->canGet() // 在领取时间之内的
->order('id', 'desc');
if ($ids) {
$coupons = $coupons->whereIn('id', $ids);
}
$coupons = $coupons->paginate($this->request->param('list_rows', 10))->each(function ($coupon) {
$coupon->get_status = $coupon->get_status;
$coupon->get_status_text = $coupon->get_status_text;
});
$this->success('获取成功', $coupons);
}
/**
* 商品相关的优惠券列表,前端商品详情使用
*
* @param Request $request
* @param int $goods_id
* @return void
*/
public function listByGoods()
{
$user = auth_user();
$goods_id = $this->request->param('goods_id');
$goods = GoodsModel::field('id,category_ids')->where('id', $goods_id)->find();
if (!$goods) {
$this->error(__('No Results were found'));
}
$coupons = CouponModel::with(['user_coupons'])
->normal() // 正常的可以展示的优惠券
->canGet() // 在领取时间之内的
->goods($goods) // 符合指定商品,并且检测商品所属分类
->order('id', 'desc');
if ($user) {
// 关联用户优惠券
$coupons = $coupons->with(['userCoupons']);
}
$coupons = $coupons->select();
$coupons = collection($coupons)->each(function ($coupon) {
$coupon->get_status = $coupon->get_status;
$coupon->get_status_text = $coupon->get_status_text;
});
$this->success('获取成功', $coupons);
}
public function get()
{
$id = $this->request->param('id');
$this->repeatFilter(null, 2);
$userCoupon = $this->getCoupon($id);
$this->success('领取成功', $userCoupon);
}
public function detail()
{
$id = $this->request->param('id');
$coupon = CouponModel::where('id', $id)->find();
if (!$coupon) {
$this->error(__('No Results were found'));
}
$coupon->get_status = $coupon->get_status;
$coupon->get_status_text = $coupon->get_status_text;
$coupon->items_value = $coupon->items_value;
$this->success('优惠券详情', $coupon);
}
}

View File

@@ -0,0 +1,205 @@
<?php
namespace addons\shopro\controller;
use addons\shopro\controller\traits\Util;
use addons\shopro\library\easywechatPlus\WechatMiniProgramShop;
use app\admin\model\shopro\decorate\Decorate;
use app\admin\model\shopro\decorate\Page;
use app\common\library\Sms as Smslib;
use app\admin\model\shopro\user\User as UserModel;
use addons\shopro\facade\Wechat;
use think\Hook;
class Index extends Common
{
use Util;
protected $noNeedLogin = ['init', 'pageSync', 'page', 'feedback', 'send', 'test'];
protected $noNeedRight = ['*'];
public function init()
{
$platform = $this->request->header('platform');
$templateId = $this->request->param('templateId', 0);
$platformConfig = sheep_config("shop.platform.$platform");
if (empty($platformConfig['status']) || !$platformConfig['status']) {
$this->error('暂不支持该平台,请前往商城配置启用对应平台');
}
$template = Decorate::template()->whereRaw("find_in_set('$platform', platform)");
if ($templateId) {
$template->where('id', $templateId);
} else {
$template->where('status', 'enable');
}
$template = $template->find();
if ($template) {
$template = Page::where('decorate_id', $template->id)->select();
$template = collection($template)->column('page', 'type');
}
$shopConfig = sheep_config('shop.basic');
// 客服配置
$chatSystem = sheep_config('chat.system');
// 客服应用配置
$chatConfig = sheep_config('chat.application.shop');
// 初始化 socket ssl 类型, 默认 none
$ssl = $chatSystem['ssl'] ?? 'none';
$chat_domain = ($ssl == 'none' ? 'http://' : 'https://') . request()->host(true) . ($ssl == 'reverse_proxy' ? '' : (':' . $chatSystem['port'])) . '/chat';
$chatConfig['chat_domain'] = $chat_domain;
$data = [
'app' => [
'name' => $shopConfig['name'],
'logo' => $shopConfig['logo'],
'cdnurl' => cdnurl('', true),
'version' => $shopConfig['version'],
'user_protocol' => $shopConfig['user_protocol'],
'privacy_protocol' => $shopConfig['privacy_protocol'],
'about_us' => $shopConfig['about_us'],
'copyright' => $shopConfig['copyright'],
'copytime' => $shopConfig['copytime'],
],
'platform' => [
'auto_login' => $platformConfig['auto_login'] ?? 0,
'bind_mobile' => $platformConfig['bind_mobile'] ?? 0,
'payment' => $platformConfig['payment']['methods'],
'recharge_payment' => sheep_config('shop.recharge_withdraw.recharge.methods'), // 充值支持的支付方式
'share' => $platformConfig['share'],
],
'template' => $template,
'chat' => $chatConfig
];
if ($platform == 'WechatMiniProgram') {
$uploadshoppingInfo = new WechatMiniProgramShop(Wechat::miniProgram());
$data['has_wechat_trade_managed'] = intval($uploadshoppingInfo->isTradeManaged());
}
$this->success('初始化', $data);
}
public function pageSync()
{
$pages = $this->request->post('pages/a');
foreach ($pages as $page) {
if (!empty($page['meta']['sync']) && $page['meta']['sync']) {
$data = \app\admin\model\shopro\data\Page::getByPath($page['path']);
$name = $page['meta']['title'] ?? '未命名';
$group = $page['meta']['group'] ?? '其它';
if ($data) {
$data->name = $name;
$data->group = $group;
$data->save();
} else {
\app\admin\model\shopro\data\Page::create([
'name' => $name,
'group' => $group,
'path' => $page['path']
]);
}
}
}
$this->success();
}
public function page()
{
$id = $this->request->param('id');
$template = \app\admin\model\shopro\decorate\Decorate::typeDiypage()->with('diypage')->where('id', $id)->find();
if (!$template) {
$this->error(__('No Results were found'));
}
$this->success('', $template);
}
public function test()
{
}
public function feedback()
{
$user = auth_user();
$params = $this->request->only(['type', 'content', 'images', 'phone']);
if ($user) {
$params['user_id'] = $user->id;
}
$result = \app\admin\model\shopro\Feedback::create($params);
if ($result) {
$this->success('感谢您的反馈');
}
}
/**
* 发送验证码
*
* @param string $mobile 手机号
* @param string $event 事件名称
*/
public function send()
{
$mobile = $this->request->post("mobile");
$event = $this->request->post("event");
$event = $event ? strtolower($event) : 'register';
if (!$mobile || !\think\Validate::regex($mobile, "^1\d{10}$")) {
$this->error(__('手机号不正确'));
}
$last = Smslib::get($mobile, $event);
if ($last && time() - $last['createtime'] < 60) {
$this->error(__('发送频繁'));
}
$ipSendTotal = \app\common\model\Sms::where(['ip' => $this->request->ip()])->whereTime('createtime', '-1 hours')->count();
if ($ipSendTotal >= 5) {
$this->error(__('发送频繁'));
}
if ($event) {
$userinfo = UserModel::getByMobile($mobile);
if ($event == 'register' && $userinfo) {
//已被注册
$this->error(__('手机号已经被注册'));
} elseif (in_array($event, ['changemobile']) && $userinfo) {
//被占用
$this->error(__('手机号已经被占用'));
} elseif (in_array($event, ['changepwd', 'resetpwd', 'mobilelogin']) && !$userinfo) {
//未注册
$this->error(__('手机号未注册'));
}
}
if (!Hook::get('sms_send')) {
$this->error(__('请在后台插件管理安装短信验证插件'));
}
$ret = Smslib::send($mobile, null, $event);
if ($ret) {
$this->success(__('发送成功'));
} else {
$this->error(__('发送失败,请检查短信配置是否正确'));
}
}
/**
* 获取统一验证 token
*
* @return void
*/
public function unifiedToken()
{
$user = auth_user();
$token = $this->getUnifiedToken('user:' . $user->id);
$this->success('获取成功', [
'token' => $token
]);
}
}

View File

@@ -0,0 +1,348 @@
<?php
namespace addons\shopro\controller;
use Psr\Http\Message\ResponseInterface;
use think\exception\HttpResponseException;
use app\admin\model\shopro\Pay as PayModel;
use addons\shopro\service\pay\PayOper;
use addons\shopro\library\pay\PayService;
use app\admin\model\shopro\order\Order;
use app\admin\model\shopro\trade\Order as TradeOrderModel;
use think\Log;
use think\Db;
use addons\shopro\service\pay\PayRefund;
use Yansongda\Pay\Pay as YansongdaPay;
class Pay extends Common
{
protected $noNeedLogin = ['alipay', 'notify', 'notifyRefund'];
protected $noNeedRight = ['*'];
public function prepay()
{
$this->repeatFilter(); // 防止连点
check_env(['yansongda']);
$user = auth_user();
$order_sn = $this->request->post('order_sn');
$payment = $this->request->post('payment');
$openid = $this->request->post('openid', '');
$money = $this->request->post('money', 0);
$money = $money > 0 ? $money : 0;
$platform = $this->request->header('platform');
list($order, $order_type) = $this->getOrderInstance($order_sn);
$order = $order->where('user_id', $user->id)->where('order_sn', $order_sn)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
if (in_array($order->status, [$order::STATUS_CLOSED, $order::STATUS_CANCEL])) {
$this->error('订单已失效');
}
if (in_array($order->status, [$order::STATUS_PAID, $order::STATUS_COMPLETED])) {
$this->error('订单已支付');
}
if ($order_type == 'order' && $order->isOffline($order)) {
// 已经货到付款
$this->error('已下单成功');
}
if (!$payment || !in_array($payment, ['wechat', 'alipay', 'money', 'offline'])) {
$this->error('支付类型不能为空');
}
// pay 实例
$payOper = new PayOper();
if ($money && $order_type == 'order') {
// 余额混合支付
$order = Db::transaction(function () use ($payOper, $order, $order_type, $money) {
// 加锁读订单
$order = $order->lock(true)->find($order->id);
// 余额支付
$order = $payOper->money($order, $money, $order_type);
return $order;
});
if (in_array($order->status, [$order::STATUS_PAID, $order::STATUS_COMPLETED])) {
$this->success('订单支付成功', $order);
}
}
if ($payment == 'money' && $order_type == 'order') {
// 余额支付
$order = Db::transaction(function () use ($payOper, $order, $order_type) {
// 加锁读订单
$order = $order->lock(true)->find($order->id);
$order = $payOper->money($order, $order->remain_pay_fee, $order_type);
return $order;
});
if ($order->status != $order::STATUS_PAID) {
$this->error('订单支付失败');
}
$this->success('订单支付成功', $order);
}
if ($payment == 'offline' && $order_type == 'order') {
if (!isset($order->ext['offline_status']) || $order->ext['offline_status'] != 'enable') {
$this->error('订单不支持货到付款');
}
// 货到付款
$order = Db::transaction(function () use ($payOper, $order, $order_type) {
// 加锁读订单
$order = $order->lock(true)->find($order->id);
$order = $payOper->offline($order, 0, $order_type); // 增加 0 记录
return $order;
});
if ($order->status != $order::STATUS_PAID) {
$this->success('下单成功', $order); // 货到付款
}
$this->success('订单支付成功', $order);
}
// 微信支付宝(第三方)付款
$payModel = $payOper->{$payment}($order, $order->remain_pay_fee, $order_type);
$order_data = [
'order_id' => $order->id,
'out_trade_no' => $payModel->pay_sn,
'total_amount' => $payModel->pay_fee, // 剩余支付金额
];
// 微信公众号,小程序支付,必须有 openid
if ($payment == 'wechat') {
if (in_array($platform, ['WechatOfficialAccount', 'WechatMiniProgram'])) {
if (isset($openid) && $openid) {
// 如果传的有 openid
$order_data['payer']['openid'] = $openid;
} else {
// 没有 openid 默认拿下单人的 openid
$oauth = \app\admin\model\shopro\ThirdOauth::where([
'user_id' => $order->user_id,
'provider' => 'Wechat',
'platform' => lcfirst(str_replace('Wechat', '', $platform))
])->find();
$order_data['payer']['openid'] = $oauth ? $oauth->openid : '';
}
if (empty($order_data['payer']['openid'])) {
// 缺少 openid
$this->error('miss_openid', -1);
}
}
$order_data['description'] = '商城订单支付';
} else {
$order_data['subject'] = '商城订单支付';
}
$payService = new PayService($payment);
try {
$result = $payService->pay($order_data);
} catch (\Yansongda\Pay\Exception\Exception $e) {
$this->error('支付失败' . (config('app_debug') ? "" . $e->getMessage() : ',请重试'));
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
$this->error('支付失败' . (config('app_debug') ? "" . $message : ',请重试'));
}
if ($platform == 'App') {
if ($payment == 'wechat') {
// Yansongda\Supports\Collection可当数组可当字符串这里不用处理
} else {
// Guzzle
$result = $result->getBody()->getContents();
}
}
$this->success('', [
'pay_data' => $result,
]);
}
/**
* 支付宝网页支付
*/
public function alipay()
{
$pay_sn = $this->request->get('pay_sn');
$platform = $this->request->get('platform');
$payModel = PayModel::where('pay_sn', $pay_sn)->find();
if (!$payModel || $payModel->status != PayModel::PAY_STATUS_UNPAID) {
$this->error("支付单不存在或已支付");
}
try {
$order_data = [
'order_id' => $payModel->order_id,
'out_trade_no' => $payModel->pay_sn,
'total_amount' => $payModel->pay_fee,
'subject' => '商城订单支付',
];
$payService = new PayService('alipay', $platform);
$result = $payService->pay($order_data, [], 'url');
$result = $result->getBody()->getContents();
echo $result;
} catch (\Exception $e) {
echo $e->getMessage();
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
echo '支付失败' . (config('app_debug') ? "" . $message : ',请重试');
}
}
/**
* 支付成功回调
*/
public function notify()
{
Log::write('pay-notify-comein:');
$payment = $this->request->param('payment');
$platform = $this->request->param('platform');
$payService = new PayService($payment, $platform);
$result = $payService->notify(function ($data, $originData = []) use ($payment) {
Log::write('pay-notify-data:' . json_encode($data));
$out_trade_no = $data['out_trade_no'];
// 查询 pay 交易记录
$payModel = PayModel::where('pay_sn', $out_trade_no)->find();
if (!$payModel || $payModel->status != PayModel::PAY_STATUS_UNPAID) {
// 订单不存在,或者订单已支付
return YansongdaPay::$payment()->success();
}
Db::transaction(function () use ($payModel, $data, $originData, $payment) {
$notify = [
'pay_sn' => $data['out_trade_no'],
'transaction_id' => $data['transaction_id'],
'notify_time' => $data['notify_time'],
'buyer_info' => $data['buyer_info'],
'payment_json' => $originData ? json_encode($originData) : json_encode($data),
'pay_fee' => $data['pay_fee'], // 微信的已经*100处理过了
'pay_type' => $payment // 支付方式
];
// pay 实例
$payOper = new PayOper($payModel->user_id);
$payOper->notify($payModel, $notify);
});
return YansongdaPay::$payment()->success();
});
return $this->payResponse($result, $payment);
}
/**
* 微信退款回调 (仅微信用,支付宝走支付回调 notify 方法)
*
* @return void
*/
public function notifyRefund()
{
Log::write('pay-notify-refund-comein:');
$payment = $this->request->param('payment');
$platform = $this->request->param('platform');
$payService = new PayService($payment, $platform);
$result = $payService->notifyRefund(function ($data, $originData) use ($payment, $platform) {
Log::write('pay-notify-refund-result:' . json_encode($data));
Db::transaction(function () use ($data, $originData, $payment) {
$out_refund_no = $data['out_refund_no'];
$out_trade_no = $data['out_trade_no'];
// 交给退款实例处理
$refund = new PayRefund();
$refund->notify([
'out_trade_no' => $out_trade_no,
'out_refund_no' => $out_refund_no,
'payment_json' => json_encode($originData),
]);
});
return YansongdaPay::$payment()->success();
});
return $this->payResponse($result, $payment);
}
/**
* 处理返回结果 tp5 不能直接 return YansongdaPay::$payment()->success()
*
* @param object|string $result
* @param string|null $payment
* @return void
*/
private function payResponse($result = null, $payment = null)
{
if ($result instanceof ResponseInterface) {
$content = $result->getBody()->getContents();
$content = $payment == 'wechat' ? json_decode($content, true) : $content;
return response($content, 200, [], ($payment == 'wechat' ? 'json' : ''));
}
return $result;
}
/**
* 根据订单号获取订单实例
*
* @param [type] $order_sn
* @return void
*/
private function getOrderInstance($order_sn)
{
if (strpos($order_sn, 'TO') === 0) {
// 交易订单
$order_type = 'trade_order';
$order = new TradeOrderModel();
} else {
// 订单
$order_type = 'order';
$order = new Order();
}
return [$order, $order_type];
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace addons\shopro\controller;
use think\Db;
use app\admin\model\shopro\Share as ShareModel;
class Share extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function add()
{
$params = $this->request->only(['shareId', 'spm', 'page', 'query', 'from', 'platform']);
$user = auth_user();
$shareInfo = ShareModel::log($user, $params);
$this->success("");
}
/**
* 查看分享记录
*/
public function index()
{
$user = auth_user();
$logs = ShareModel::with(['user' => function ($query) {
return $query->field(['id', 'nickname', 'avatar']);
}])->where('share_id', $user->id)->paginate($this->request->param('list_rows', 8));
$this->success('获取成功', $logs);
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace addons\shopro\controller;
use app\admin\model\shopro\Withdraw as WithdrawModel;
use addons\shopro\service\Withdraw as WithdrawLibrary;
class Withdraw extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$withdraws = WithdrawModel::where(['user_id' => $user->id])->order('id desc')->paginate($this->request->param('list_rows', 10))->each(function ($withdraw) {
$withdraw->hidden(['withdraw_info']);
});
$this->success('获取成功', $withdraws);
}
// 提现规则
public function rules()
{
$user = auth_user();
$config = (new WithdrawLibrary($user))->config;
$this->success('提现规则', $config);
}
// 发起提现请求
public function apply()
{
$this->repeatFilter();
$user = auth_user();
$params = $this->request->param();
$this->svalidate($params, ".apply");
$withdrawLib = new WithdrawLibrary($user);
$withdraw = $withdrawLib->apply($params);
$this->success('申请成功', $withdraw);
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace addons\shopro\controller\activity;
use addons\shopro\controller\Common;
use addons\shopro\facade\Activity as ActivityFacade;
use app\admin\model\shopro\activity\Activity as ActivityModel;
class Activity extends Common
{
protected $noNeedLogin = ['detail'];
protected $noNeedRight = ['*'];
// 活动详情
public function detail()
{
$id = $this->request->get('id');
$activity = ActivityModel::where('id', $id)->find();
if (!$activity) {
$this->error(__('No Results were found'));
}
if ($activity->classify == 'promo') {
$rules = $activity['rules'];
$rules['simple'] = true;
$tags = ActivityFacade::formatRuleTags($rules, $activity['type']);
$activity['tag'] = $tags[0] ?? '';
$activity['tags'] = $tags;
$texts = ActivityFacade::formatRuleTexts($rules, $activity['type']);
$activity['texts'] = $texts;
}
$this->success('获取成功', $activity);
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace addons\shopro\controller\activity;
use addons\shopro\controller\Common;
use app\admin\model\shopro\activity\Groupon as GrouponModel;
use app\admin\model\shopro\activity\GrouponLog as GrouponLogModel;
use addons\shopro\service\goods\GoodsService;
use addons\shopro\facade\Activity as ActivityFacade;
class Groupon extends Common
{
protected $noNeedLogin = ['index', 'detail'];
protected $noNeedRight = ['*'];
// 商品详情,参团列表
public function index()
{
$params = $this->request->param();
$goods_id = $params['goods_id'] ?? 0;
$activity_id = $params['activity_id'] ?? 0;
$groupons = GrouponModel::with('leader')->ing()
->where('goods_id', $goods_id)
->where('activity_id', $activity_id)
->order('id', 'asc')
->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', $groupons);
}
// 团详情
public function detail()
{
$id = $this->request->param('id');
$groupon = GrouponModel::with(['my', 'groupon_logs', 'activity' => function ($query) {
$query->removeOption('soft_delete')->with(['activity_sku_prices']); // 关联团所属活动,并关联活动规格
}])->where('id', $id)->find();
if (!$groupon) {
$this->error(__('No Results were found'));
}
session('goods-activity_id:' . $groupon->goods_id, $groupon->activity_id);
$service = new GoodsService(function ($goods, $service) use ($groupon) {
$goods->skus = $goods->skus;
$goods->activity = $goods->activity;
return $goods;
});
// 查询所有状态的商品,并且包含被删除的商品
$goods = $service->activity($groupon->activity_id)->withTrashed()->where('id', $groupon->goods_id)->find();
if (!$goods) {
$this->error('活动商品不存在');
}
// 商品可能关联不出来活动因为活动可能已经被删除redis 也会被删除
if (!$currentActivity = $goods->activity) {
// 活动已经结束被删除
if ($currentActivity = $groupon->activity) { // 尝试获取包含回收站在内的活动信息
// 获取活动格式化之后的规格
$skuPrices = ActivityFacade::recoverSkuPrices($goods, $currentActivity);
$goods['new_sku_prices'] = $skuPrices;
}
}
$goods = $goods->toArray();
$goods['sku_prices'] = $goods['new_sku_prices'];
unset($goods['new_sku_prices']);
$groupon['goods'] = $goods;
$groupon['activity_status'] = $currentActivity['status'];
$this->success('获取成功', $groupon);
}
// 我的拼团
public function myGroupons()
{
$user = auth_user();
$params = $this->request->param();
$type = $params['type'] ?? 'all';
$grouponIds = GrouponLogModel::where('user_id', $user->id)->order('id', 'desc')->column('groupon_id');
$groupons = GrouponModel::with(['my' => function ($query) {
$query->with(['order', 'order_item']);
}, 'groupon_logs', 'activity' => function ($query) {
$query->removeOption('soft_delete')->with(['activity_sku_prices']); // 关联团所属活动,并关联活动规格
}, 'goods' => function ($query) {
$query->removeOption('soft_delete');
}])->whereIn('id', $grouponIds);
if ($type != 'all') {
$type = $type == 'finish' ? ['finish', 'finish-fictitious'] : [$type];
$groupons = $groupons->whereIn('status', $type);
}
if ($grouponIds) {
$groupons = $groupons->orderRaw('field(id, ' . join(',', $grouponIds) . ')');
}
$groupons = $groupons->paginate(request()->param('list_rows', 10))->toArray();
foreach ($groupons['data'] as &$groupon) {
if ($groupon['goods'] && isset($groupon['my']['order_item'])) {
$groupon['goods']['price'] = [$groupon['my']['order_item']['goods_price']];
}
if ($groupon['activity']) {
$activity = $groupon['activity'];
if ($activity['rules'] && isset($activity['rules']['sales_show_type']) && $activity['rules']['sales_show_type'] == 'real') {
$sales = [];
foreach ($activity['activity_sku_prices'] as $activitySkuPrice) {
if ($activitySkuPrice['goods_id'] == $groupon['goods_id']) {
$sales[] = $activitySkuPrice['sales'];
}
}
if ($groupon['goods']) {
$groupon['goods']['sales'] = array_sum($sales); // 这里计算的销量和 getSalesAttr 不一样,这里的没有排除下架的规格
}
}
}
}
$this->success('获取成功', $groupons);
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace addons\shopro\controller\activity;
use addons\shopro\controller\Common;
use addons\shopro\service\activity\Signin as SigninLibrary;
class Signin extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$params = $this->request->param();
$month = (isset($params['month']) && $params['month']) ? date('Y-m', strtotime($params['month'])) : date('Y-m'); // 前端可能传来 2023-1,这里再统一格式化一下 month
$signin = new SigninLibrary();
$days = $signin->getList($month);
$is_current = ($month == date('Y-m')) ? true : false;
// 当前月,获取连续签到天数
$continue_days = $signin->getContinueDays();
$rules = $signin->getRules();
$this->success('获取成功', compact('days', 'continue_days', 'rules'));
}
// 签到
public function signin()
{
$signin = new SigninLibrary();
$signin = $signin->signin();
$this->success('签到成功', $signin);
}
// 补签
public function replenish()
{
$params = $this->request->param();
$this->svalidate($params, ".replenish");
$signin = new SigninLibrary();
$signin = $signin->replenish($params);
$this->success('补签成功', $signin);
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace addons\shopro\controller\app;
use addons\shopro\controller\Common;
use app\admin\model\shopro\app\mplive\Room;
use addons\shopro\facade\Wechat;
use addons\shopro\library\mplive\ServiceProvider;
class Mplive extends Common
{
protected $noNeedLogin = ['getRoomList', 'getMpLink'];
protected $noNeedRight = ['*'];
public function getRoomList()
{
// 通过客户端访问触发每10分钟刷新一次房间状态
$lastUpdateTime = cache('wechatMplive.update');
if ($lastUpdateTime < (time() - 60 * 10)) {
cache('wechatMplive.update', time());
$app = Wechat::miniProgram();
(new ServiceProvider())->register($app);
$res = $app->broadcast->getRooms();
$data = [];
if (isset($res['errcode']) && ($res['errcode'] !== 0 && $res['errcode'] !== 1001)) {
$this->error($res['errmsg'] ?? '');
} else {
// 更新直播间列表
Room::where('roomid', '>', 0)->delete();
foreach ($res['room_info'] as $room) {
$room['status'] = $room['live_status'];
$room['type'] = $room['live_type'];
$data[] = $room;
}
Room::strict(false)->insertAll($data);
}
}
$params = $this->request->param();
$ids = $params['ids'] ?? '';
$list = Room::where('roomid', 'in', $ids)->select();
$this->success('获取成功', $list);
}
public function getMpLink()
{
$wechat = Wechat::miniProgram();
(new ServiceProvider())->register($wechat);
// TODO: 需防止被恶意消耗次数
$res = $wechat->broadcast->urlscheme();
$link = $res['openlink'];
$this->success('获取成功', $link);
}
}

View File

@@ -0,0 +1,94 @@
<?php
namespace addons\shopro\controller\app;
use addons\shopro\controller\Common;
use addons\shopro\service\goods\GoodsService;
use app\admin\model\shopro\user\GoodsLog;
class ScoreShop extends Common
{
protected $noNeedLogin = ['index', 'ids', 'detail'];
protected $noNeedRight = ['*'];
public function index()
{
$params = $this->request->param();
$keyword = $params['keyword'] ?? '';
$sort = $params['sort'] ?? 'weigh';
$order = $params['order'] ?? 'desc';
$service = new GoodsService(function ($goods) {
$goods->score = $goods->score;
return $goods;
});
$service->show()->score()->with(['all_score_sku_prices']); // 包含下架的积分规格
if ($keyword) {
$service->search($keyword);
}
if ($sort) {
$service->order($sort, $order);
}
$goods = $service->paginate();
$this->success('获取成功', $goods);
}
public function ids()
{
$params = $this->request->param();
$ids = $params['ids'] ?? '';
$service = new GoodsService(function ($goods) {
$goods->score = $goods->score;
return $goods;
});
$service->show()->score()->with(['all_score_sku_prices']);
if ($ids) {
$service->whereIds($ids);
}
$goods = $service->select();
$this->success('获取成功', $goods);
}
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$service = new GoodsService(function ($goods, $service) {
$goods->score = $goods->score;
$goods->service = $goods->service;
$goods->skus = $goods->skus;
return $goods;
});
$goods = $service->show()->score()->where('id', $id)->find();
if (!$goods) {
$this->error(__('No Results were found'));
}
// 添加浏览记录
GoodsLog::addView($user, $goods);
// 处理商品规格
$skuPrices = $goods['new_sku_prices'];
$content = $goods['content'];
$goods = $goods->toArray();
$goods['sku_prices'] = $skuPrices;
$goods['content'] = $content;
unset($goods['new_sku_prices']);
$this->success('获取成功', $goods);
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace addons\shopro\controller\chat;
use addons\shopro\controller\Common;
use app\admin\model\shopro\chat\Record as RecordModel;
use app\admin\model\shopro\chat\User as ChatUserModel;
class Record extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function noRead()
{
$user = auth_user();
$params = $this->request->param();
$room_id = $params['room_id'] ?? 'admin';
$session_id = $params['session_id'] ?? '';
if (!$user && !$session_id) {
$this->success('获取成功', null, 0);
}
// 查询客服用户
$chatUser = ChatUserModel::where(function($query) use ($user, $session_id) {
$query->where('auth', 'user')->where(function ($query) use ($user, $session_id) {
if ($user) {
$query->where('auth_id', $user->id);
}
if ($session_id) {
$query->whereOr('session_id', $session_id);
}
});
})->find();
$no_read_num = 0;
if($chatUser){
// 查询未读消息数量
$no_read_num = RecordModel::customer()->noRead()->where('room_id', $room_id)->where('sender_id', $chatUser->id)->count();
}
$this->success('获取成功', $no_read_num);
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace addons\shopro\controller\commission;
use think\Db;
use app\admin\model\shopro\user\User as UserModel;
use app\admin\model\shopro\commission\Agent as AgentModel;
use app\admin\model\shopro\goods\Goods as GoodsModel;
use addons\shopro\service\Wallet;
class Agent extends Commission
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
// 分销商详情
public function index()
{
$status = $this->service->getAgentStatus(true);
$condition = [
'type' => '',
'value' => ''
];
switch ($status) {
case AgentModel::AGENT_STATUS_NULL:
$condition = $this->service->config->getBecomeAgentEvent();
if ($condition['type'] === 'goods') {
$condition['value'] = GoodsModel::show()->whereIn('id', $condition['value'])->select();
}
$this->error('', $condition, 100);
break;
case AgentModel::AGENT_STATUS_NEEDINFO:
$this->error('待完善信息,请补充您的资料后提交审核', $condition, 103);
break;
case AgentModel::AGENT_STATUS_PENDING:
$this->error('正在审核中,请耐心等候结果', $condition, 104);
break;
case AgentModel::AGENT_STATUS_REJECT:
$agentFormStatus = $this->service->config->isAgentApplyForm();
if ($agentFormStatus) {
$this->error('抱歉!您的申请信息未通过,请尝试修改后重新提交', $condition, 105);
} else {
$this->error('抱歉!您的申请未通过,请尝试重新申请', $condition, 106);
}
break;
case AgentModel::AGENT_STATUS_FREEZE:
$this->error('抱歉!您的账户已被冻结,如有疑问请联系客服', $condition, 107);
break;
}
$data = $this->service->agent;
$this->success('分销商信息', $data);
}
// 分销商完善个人信息
public function form()
{
if (!$this->service->config->isAgentApplyForm()) {
$this->error('未开启分销商申请');
}
$agentForm = $this->service->config->getAgentForm();
$protocol = $this->service->config->getApplyProtocol();
$applyInfo = $this->service->agent->apply_info ?? [];
$config = [
'form' => $agentForm['content'],
'status' => $this->service->getAgentStatus(true),
'background' => $agentForm['background_image'],
'protocol' => $protocol,
'applyInfo' => $applyInfo
];
$this->success("", $config);
}
// 申请分销商/完善资料
public function apply()
{
if (!$this->service->config->isAgentApplyForm()) {
$this->error('未开启分销商申请');
}
$status = $this->service->getAgentStatus(true);
if (!in_array($status, [AgentModel::AGENT_STATUS_NEEDINFO, AgentModel::AGENT_STATUS_REJECT, AgentModel::AGENT_STATUS_NORMAL])) {
$this->error('您暂时不能申请');
}
Db::transaction(function () use ($status) {
$data = $this->request->param('data/a');
// 过滤无效表单字段数据
$config = $this->service->config->getAgentForm();
$form = (array)$config['content'];
$data = array_column($data, 'value', 'name');
foreach ($form as &$item) {
if (!empty($data[$item['name']])) {
$item['value'] = $data[$item['name']];
} else {
$this->error($item['name'] . '不能为空');
}
}
if ($status === AgentModel::AGENT_STATUS_NEEDINFO) {
$this->service->createNewAgent('', $form);
} else {
// 重置为审核中
if ($status === AgentModel::AGENT_STATUS_REJECT) {
$this->service->agent->status = AgentModel::AGENT_STATUS_PENDING;
}
// 更新分销商信息
$this->service->agent->apply_info = $form;
$this->service->agent->save();
}
});
$this->success('提交成功');
}
// 我的团队
public function team()
{
$agentId = $this->service->user->id;
$data = UserModel::where('parent_user_id', $agentId)
->where('status', 'normal')
->with(['agent' => function ($query) {
return $query->with('level_info');
}])
->paginate($this->request->param('list_rows', 8));
$this->success("", $data);
}
// 佣金转余额
public function transfer()
{
$amount = $this->request->param('amount');
if ($amount <= 0) {
$this->error('请输入正确的金额');
}
Db::transaction(function () use ($amount) {
$user = auth_user();
Wallet::change($user, 'commission', -$amount, 'transfer_to_money');
Wallet::change($user, 'money', $amount, 'transfer_by_commission');
});
$this->success('');
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace addons\shopro\controller\commission;
use addons\shopro\controller\Common;
use addons\shopro\service\commission\Agent as AgentService;
use app\admin\model\shopro\commission\Agent as AgentModel;
class Commission extends Common
{
protected AgentService $service;
public function _initialize()
{
parent::_initialize();
$on = sheep_config('shop.commission.level');
if (!$on) {
$this->error('分销中心已关闭,该功能暂不可用', null, 101);
}
$user = auth_user();
// 检查分销商状态
$this->service = new AgentService($user);
if ($this->service->agent && $this->service->agent->status === AgentModel::AGENT_STATUS_FORBIDDEN) {
$this->error('账户已被禁用,该功能暂不可用', null, 102);
}
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace addons\shopro\controller\commission;
use think\Request;
use app\admin\model\shopro\goods\Goods as GoodsModel;
use app\admin\model\shopro\commission\CommissionGoods;
use addons\shopro\service\commission\Goods as CommissionGoodsService;
class Goods extends Commission
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$goods_table_name = (new GoodsModel)->getQuery()->getTable();
$list = GoodsModel
::hasWhere('commissionGoods', ['status' => CommissionGoods::GOODS_COMMISSION_STATUS_ON])
->where($goods_table_name . '.status', 'up')
->order('weigh desc, id desc')
->paginate($this->request->param('list_rows', 8))
->each(function ($goods) {
$this->caculateMyCommission($goods);
});
$this->success("", $list);
}
private function caculateMyCommission($goods)
{
$commissionGoodsService = new CommissionGoodsService($goods->commission_goods, $goods->sku_prices[0]['id']);
$commissionRule = $commissionGoodsService->getCommissionLevelRule($this->service->agent->level ?? 1);
$goods->commission = $commissionGoodsService->caculateGoodsCommission($commissionRule, $goods->sku_prices[0]['price']);
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace addons\shopro\controller\commission;
use app\admin\model\shopro\commission\Log as LogModel;
use addons\shopro\library\Operator;
use app\admin\model\shopro\user\User as UserModel;
use app\admin\model\Admin as AdminModel;
class Log extends Commission
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
// 分销动态
public function index()
{
$agentId = $this->service->user->id;
$logs = LogModel::where([
'agent_id' => $agentId
])->order('id desc')->paginate(request()->param('list_rows', 10));
$morphs = [
'user' => UserModel::class,
'admin' => AdminModel::class,
'system' => AdminModel::class
];
$logs = morph_to($logs, $morphs, ['oper_type', 'oper_id']);
$logs = $logs->toArray();
// 解析操作人信息
foreach ($logs['data'] as &$log) {
$log['oper'] = Operator::info($log['oper_type'], $log['oper'] ?? null);
}
$this->success("", $logs);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace addons\shopro\controller\commission;
use think\Request;
use app\admin\model\shopro\commission\Order as OrderModel;
class Order extends Commission
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
// 分销动态
public function index()
{
$agentId = $this->service->user->id;
$type = $this->request->param('type', "all");
if (!in_array($type, ['all', 'back', 'cancel', 'yes'])) {
$this->error("");
}
$query = OrderModel
::where('agent_id', $agentId)
->with([
'buyer' => function ($query) {
return $query->field(['avatar', 'nickname']);
},
'order',
'rewards' => function ($query) use ($agentId) {
return $query->where('agent_id', $agentId);
},
'order_item'
])
->order('id desc');
if ($type !== 'all') {
$query->$type();
}
$data = $query->paginate($this->request->param('list_rows', 10));
$this->success("", $data);
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace addons\shopro\controller\commission;
use app\admin\model\shopro\commission\Reward as RewardModel;
class Reward extends Commission
{
}

View File

@@ -0,0 +1,24 @@
<?php
namespace addons\shopro\controller\data;
use addons\shopro\controller\Common;
use app\admin\model\shopro\data\Area as AreaModel;
class Area extends Common
{
protected $noNeedLogin = ['index'];
protected $noNeedRight = ['*'];
public function index()
{
$list = AreaModel::sheepFilter()->with(['children' => function ($query) {
return $query->field('id, pid, level, name')->with(['children' => function ($query) {
return $query->field('id, pid, level, name');
}]);
}])->where('pid', 0)->order('id', 'asc')->field('id, pid, level, name')->select();
$this->success('获取成功', $list);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace addons\shopro\controller\data;
use addons\shopro\controller\Common;
use app\admin\model\shopro\data\Faq as FaqModel;
class Faq extends Common
{
protected $noNeedLogin = ['index'];
protected $noNeedRight = ['*'];
public function index()
{
$list = FaqModel::where('status', 'normal')->order('id', 'asc')->select();
$this->success('获取成功', $list);
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace addons\shopro\controller\data;
use addons\shopro\controller\Common;
use app\admin\model\shopro\data\Richtext as RichtextModel;
class Richtext extends Common
{
protected $noNeedLogin = ['index'];
protected $noNeedRight = ['*'];
public function index()
{
$id = $this->request->param('id');
$data = RichtextModel::where('id', $id)->find();
if (!$data) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', $data);
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace addons\shopro\controller\goods;
use addons\shopro\controller\Common;
use app\admin\model\shopro\goods\Comment as CommentModel;
class Comment extends Common
{
protected $noNeedLogin = ['index', 'getType'];
protected $noNeedRight = ['*'];
public function index()
{
$params = $this->request->param();
$type = $params['type'] ?? 'all';
$goods_id = $params['goods_id'] ?? 0;
$comments = CommentModel::normal()->where('goods_id', $goods_id);
if ($type != 'all' && isset(CommentModel::$typeAll[$type])) {
$comments = $comments->{$type}();
}
$comments = $comments->order('id', 'desc')->paginate(request()->param('list_rows', 10));
// ->each(function ($comment) {
// if ($comment->user) {
// $comment->user->nickname_hide = $comment->user->nickname_hide;
// }
// })->toArray();
// $data = $comments['data'];
// foreach ($data as $key => &$comment) {
// if ($comment['user']) {
// $userData['id'] = $comment['user']['id'];
// $userData['nickname'] = $comment['user']['nickname_hide'];
// $userData['avatar'] = $comment['user']['avatar'];
// $userData['gender'] = $comment['user']['gender'];
// $userData['gender_text'] = $comment['user']['gender_text'];
// $comment['user'] = $userData;
// }
// }
// $comments['data'] = $data;
$this->success('获取成功', $comments);
}
public function getType()
{
$goods_id = $this->request->param('goods_id');
$type = array_values(CommentModel::$typeAll);
foreach ($type as $key => $val) {
$comment = CommentModel::normal()->where('goods_id', $goods_id);
if ($val['code'] != 'all') {
$comment = $comment->{$val['code']}();
}
$comment = $comment->count();
$type[$key]['num'] = $comment;
}
$this->success('筛选类型', $type);
}
}

View File

@@ -0,0 +1,196 @@
<?php
namespace addons\shopro\controller\goods;
use addons\shopro\controller\Common;
use addons\shopro\service\goods\GoodsService;
use app\admin\model\shopro\user\GoodsLog;
use app\admin\model\shopro\activity\Activity;
class Goods extends Common
{
protected $noNeedLogin = ['*'];
protected $noNeedRight = ['*'];
public function index()
{
$params = $this->request->param();
$keyword = $params['keyword'] ?? '';
$ids = $params['ids'] ?? '';
$category_id = $params['category_id'] ?? '';
$is_category_deep = $params['is_category_deep'] ?? true;
$sort = $params['sort'] ?? 'weigh';
$order = $params['order'] ?? 'desc';
$service = new GoodsService(function ($goods) {
$goods->activities = $goods->activities;
$goods->promos = $goods->promos;
return $goods;
});
$service->up()->with(['max_sku_price' => function ($query) { // 计算价格区间用(不知道为啥 with 必须再 show 后面)
$query->where('status', 'up');
}]);
if ($keyword) {
$service->search($keyword);
}
if ($ids) {
$service->whereIds($ids);
}
if ($category_id) {
$service->category($category_id, $is_category_deep);
}
if ($sort) {
$service->order($sort, $order);
}
$goods = $service->paginate();
$this->success('获取成功', $goods);
}
/**
* 通过 ids 获取商品(不分页)
*
* @return void
*/
public function ids()
{
$params = $this->request->param();
$ids = $params['ids'] ?? '';
$service = new GoodsService(function ($goods) {
$goods->activities = $goods->activities;
$goods->promos = $goods->promos;
return $goods;
});
$service->show()->with(['max_sku_price' => function ($query) {
$query->where('status', 'up');
}]);
if ($ids) {
$service->whereIds($ids);
}
$goods = $service->select();
$this->success('获取成功', $goods);
}
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$activity_id = $this->request->param('activity_id');
// 存一下,获取器获取指定活动的时候会用到
session('goods-activity_id:' . $id, $activity_id);
$service = new GoodsService(function ($goods, $service) use ($activity_id) {
$goods->service = $goods->service;
$goods->skus = $goods->skus;
if (!$activity_id) {
$goods->activities = $goods->activities;
$goods->promos = $goods->promos;
} else {
$goods->activity = $goods->activity;
$goods->original_goods_price = $goods->original_goods_price;
}
return $goods;
});
$goods = $service->show()->activity($activity_id)->with(['max_sku_price' => function ($query) { // 计算价格区间用(不知道为啥 with 必须再 show 后面)
$query->where('status', 'up');
}, 'favorite'])->where('id', $id)->find();
if (!$goods) {
$this->error(__('No Results were found'));
}
// 添加浏览记录
GoodsLog::addView($user, $goods);
// 处理商品规格
$skuPrices = $goods['new_sku_prices'];
$content = $goods['content'];
$goods = $goods->toArray();
$goods['sku_prices'] = $skuPrices;
$goods['content'] = $content;
unset($goods['new_sku_prices']);
$this->success('获取成功', $goods);
}
/**
* 获取指定活动相关商品
*
* @return void
*/
public function activity()
{
$activity_id = $this->request->param('activity_id');
$need_buyers = $this->request->param('need_buyers', 0); // 需要查询哪些人在参与活动
$activity = Activity::where('id', $activity_id)->find();
if (!$activity) {
$this->error(__('No Results were found'));
}
$goodsIds = $activity->goods_ids ? explode(',', $activity->goods_ids) : [];
// 存一下,获取器获取指定活动的时候会用到
foreach ($goodsIds as $id) {
session('goods-activity_id:' . $id, $activity_id);
}
$service = new GoodsService(function ($goods) use ($need_buyers) {
if ($need_buyers) {
$goods->buyers = $goods->buyers;
}
$goods->activity = $goods->activity;
return $goods;
});
$goods = $service->activity($activity_id)->whereIds($goodsIds)->show()->order('weigh', 'desc')->select();
$goods = collection($goods)->toArray();
foreach ($goods as &$gd) {
unset($gd['new_sku_prices'], $gd['activity']);
}
$this->success('获取成功', $goods);
}
/**
* 获取指定活动相关商品,带分页
*
* @param Request $request
* @return void
*/
public function activityList()
{
$activity_id = $this->request->param('activity_id');
$activity = Activity::where('id', $activity_id)->find();
if (!$activity) {
$this->error(__('No Results were found'));
}
$goodsIds = $activity->goods_ids ? explode(',', $activity->goods_ids) : [];
// 存一下,获取器获取指定活动的时候会用到
foreach ($goodsIds as $id) {
session('goods-activity_id:' . $id, $activity_id);
}
$service = new GoodsService(function ($goods) {
$goods->promos = $goods->promos;
return $goods;
});
$goods = $service->activity($activity_id)->whereIds($goodsIds)->show()->order('weigh', 'desc')->paginate();
$this->success('获取成功', $goods);
}
}

View File

@@ -0,0 +1,204 @@
<?php
namespace addons\shopro\controller\order;
use think\Db;
use addons\shopro\controller\Common;
use app\admin\model\shopro\order\Order as OrderModel;
use app\admin\model\shopro\order\OrderItem as OrderItemModel;
use app\admin\model\shopro\order\Aftersale as AftersaleModel;
use app\admin\model\shopro\order\AftersaleLog as AftersaleLogModel;
use app\admin\model\shopro\order\Action as OrderActionModel;
class Aftersale extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index() {
$user = auth_user();
$params = $this->request->param();
$type = $params['type'] ?? 'all';
$aftersales = AftersaleModel::where('user_id', $user->id);
if ($type != 'all') {
$aftersales = $aftersales->{$type}();
}
$aftersales = $aftersales->order('id', 'desc')->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', $aftersales);
}
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$aftersale = AftersaleModel::where('user_id', $user->id)->with('logs')->where('id', $id)->find();
if (!$aftersale) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', $aftersale);
}
public function add()
{
$user = auth_user();
$params = $this->request->param();
$this->svalidate($params, ".add");
$aftersale = Db::transaction(function () use ($user, $params) {
$type = $params['type'];
$order_id = $params['order_id'];
$order_item_id = $params['order_item_id'];
$mobile = $params['mobile'] ?? '';
$reason = $params['reason'] ?? '用户申请售后';
$content = $params['content'] ?? '';
$images = $params['images'] ?? [];
$order = OrderModel::canAftersale()->where('user_id', $user->id)->lock(true)->where('id', $order_id)->find();
if (!$order) {
error_stop('订单不存在或不可售后');
}
$item = OrderItemModel::where('user_id', $user->id)->where('id', $order_item_id)->find();
if (!$item) {
error_stop('参数错误');
}
if (!in_array($item->aftersale_status, [
OrderItemModel::AFTERSALE_STATUS_REFUSE,
OrderItemModel::AFTERSALE_STATUS_NOAFTER
])) {
error_stop('当前订单商品不可申请售后');
}
$aftersale = new AftersaleModel();
$aftersale->aftersale_sn = get_sn($user->id, 'A');
$aftersale->user_id = $user->id;
$aftersale->type = $type;
$aftersale->mobile = $mobile;
$aftersale->activity_id = $item['activity_id'];
$aftersale->activity_type = $item['activity_type'];
$aftersale->order_id = $order_id;
$aftersale->order_item_id = $order_item_id;
$aftersale->goods_id = $item['goods_id'];
$aftersale->goods_sku_price_id = $item['goods_sku_price_id'];
$aftersale->goods_sku_text = $item['goods_sku_text'];
$aftersale->goods_title = $item['goods_title'];
$aftersale->goods_image = $item['goods_image'];
$aftersale->goods_original_price = $item['goods_original_price'];
$aftersale->discount_fee = $item['discount_fee'];
$aftersale->goods_price = $item['goods_price'];
$aftersale->goods_num = $item['goods_num'];
$aftersale->dispatch_status = $item['dispatch_status'];
$aftersale->dispatch_fee = $item['dispatch_fee'];
$aftersale->aftersale_status = AftersaleModel::AFTERSALE_STATUS_NOOPER;
$aftersale->refund_status = AftersaleModel::REFUND_STATUS_NOREFUND; // 未退款
$aftersale->refund_fee = 0;
$aftersale->reason = $reason;
$aftersale->content = $content;
$aftersale->save();
// 增加售后单变动记录、
AftersaleLogModel::add($order, $aftersale, $user, 'user', [
'log_type' => 'apply_aftersale',
'content' => "申请原因:$reason <br>相关描述: $content",
'images' => $images
]);
$ext = $item->ext ?: [];
$ext['aftersale_id'] = $aftersale->id;
// 修改订单 item 状态,申请售后
$item->aftersale_status = OrderItemModel::AFTERSALE_STATUS_ING;
$item->ext = $ext;
$item->save();
OrderActionModel::add($order, $item, $user, 'user', '用户申请售后');
return $aftersale;
});
$this->success('申请成功', $aftersale);
}
public function cancel()
{
$user = auth_user();
$id = $this->request->param('id');
$aftersale = AftersaleModel::canCancel()->where('user_id', $user->id)->where('id', $id)->find();
if (!$aftersale) {
$this->error('售后单不存在或不可取消');
}
$order = OrderModel::where('user_id', $user->id)->find($aftersale['order_id']);
if (!$order) {
$this->error(__('No Results were found'));
}
$orderItem = OrderItemModel::find($aftersale['order_item_id']);
if (!$orderItem || in_array($orderItem['refund_status'], [OrderItemModel::REFUND_STATUS_AGREE, OrderItemModel::REFUND_STATUS_COMPLETED])) {
// 不存在, 或者已经退款
$this->error('退款商品不存在或已退款');
}
$aftersale = Db::transaction(function () use ($aftersale, $order, $orderItem, $user) {
$aftersale->aftersale_status = AftersaleModel::AFTERSALE_STATUS_CANCEL; // 取消售后单
$aftersale->save();
AftersaleLogModel::add($order, $aftersale, $user, 'user', [
'log_type' => 'cancel',
'content' => '用户取消申请售后',
'images' => []
]);
// 修改订单 item 为未申请售后
$orderItem->aftersale_status = OrderItemModel::AFTERSALE_STATUS_NOAFTER;
$orderItem->refund_status = OrderItemModel::REFUND_STATUS_NOREFUND;
$orderItem->save();
OrderActionModel::add($order, $orderItem, $user, 'user', '用户取消申请售后');
return $aftersale;
});
$this->success('取消成功', $aftersale);
}
public function delete()
{
$user = auth_user();
$id = $this->request->param('id');
$aftersale = AftersaleModel::canDelete()->where('user_id', $user->id)->where('id', $id)->find();
if (!$aftersale) {
$this->error('售后单不存在或不可删除');
}
$order = OrderModel::withTrashed()->where('id', $aftersale['order_id'])->find();
Db::transaction(function () use ($aftersale, $order, $user) {
AftersaleLogModel::add($order, $aftersale, $user, 'user', [
'log_type' => 'delete',
'content' => '用户删除售后单',
'images' => []
]);
$aftersale->delete(); // 删除售后单(后删除,否则添加记录时 $aftersale 没数据)
});
$this->success('删除成功');
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace addons\shopro\controller\order;
use addons\shopro\controller\Common;
use app\admin\model\shopro\order\Express as OrderExpressModel;
use addons\shopro\library\express\Express as ExpressLib;
class Express extends Common
{
protected $noNeedLogin = ['push'];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$order_id = $this->request->param('order_id');
// 更新包裹信息5分钟缓存
(new ExpressLib)->updateOrderExpress($order_id);
$expresses = OrderExpressModel::with(['logs', 'items' => function ($query) use ($order_id) {
return $query->where('order_id', $order_id);
}])->where('user_id', $user->id)->where('order_id', $order_id)->select();
$this->success('获取成功', $expresses);
}
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$order_id = $this->request->param('order_id');
// 更新包裹信息5分钟缓存
(new ExpressLib)->updateOrderExpress($order_id);
$express = OrderExpressModel::with(['logs', 'items' => function ($query) use ($order_id) {
return $query->where('order_id', $order_id);
}])->where('user_id', $user->id)->where('order_id', $order_id)->where('id', $id)->find();
$this->success('获取成功', $express);
}
/**
* 接受物流推送
*
* @param Request $request
* @return void
*/
public function push()
{
$data = $this->request->param();
$expressLib = new ExpressLib();
$result = $expressLib->push($data);
return response($result, 200, [], 'json');
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace addons\shopro\controller\order;
use addons\shopro\controller\Common;
use app\admin\model\shopro\order\Invoice as OrderInvoiceModel;
class Invoice extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$params = $this->request->param();
$type = $params['type'] ?? 'all';
$invoices = OrderInvoiceModel::where('user_id', $user->id);
switch ($type) {
case 'cancel':
$invoices = $invoices->cancel();
break;
case 'waiting':
$invoices = $invoices->waiting();
break;
case 'finish':
$invoices = $invoices->finish();
break;
default :
$invoices = $invoices->show(); // 除了未支付的
break;
}
$invoices = $invoices->order('id', 'desc')->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', $invoices);
}
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$invoice = OrderInvoiceModel::with(['order', 'order_items'])->where('user_id', $user->id)->where('id', $id)->find();
if (!$invoice) {
$this->error(__('No Results were found'));
}
$invoice->append(['order_items']); // 取消隐藏 order_items
$this->success('获取成功', $invoice);
}
// 取消订单
public function cancel()
{
$user = auth_user();
$id = $this->request->param('id');
$invoice = OrderInvoiceModel::where('user_id', $user->id)->waiting()->where('id', $id)->find();
if (!$invoice) {
$this->error(__('No Results were found'));
}
$invoice->status = 'cancel';
$invoice->save();
$this->success('取消成功', $invoice);
}
}

View File

@@ -0,0 +1,335 @@
<?php
namespace addons\shopro\controller\order;
use think\Db;
use addons\shopro\exception\ShoproException;
use addons\shopro\controller\Common;
use addons\shopro\service\order\OrderCreate;
use addons\shopro\service\order\OrderOper;
use app\admin\model\shopro\order\Order as OrderModel;
use app\admin\model\shopro\Pay as PayModel;
use app\admin\model\shopro\user\Invoice as UserInvoice;
use addons\shopro\library\express\Express as ExpressLib;
class Order extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$params = $this->request->param();
$type = $params['type'] ?? 'all';
$orders = OrderModel::where('user_id', $user->id)->with(['items', 'invoice']);
switch ($type) {
case 'unpaid':
$orders = $orders->unpaid();
break;
case 'nosend':
$orders = $orders->pretendPaid()->nosend();
break;
case 'noget':
$orders = $orders->pretendPaid()->noget();
break;
case 'nocomment':
$orders = $orders->paid()->nocomment();
break;
}
$orders = $orders->order('id', 'desc')->paginate(request()->param('list_rows', 10))->toArray();
$orderModel = new OrderModel();
foreach ($orders['data'] as &$order) {
$order = $orderModel->setOrderItemStatusByOrder($order);
}
$this->success('获取成功', $orders);
}
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$merchant_trade_no = $this->request->param('merchant_trade_no');
$transaction_id = $this->request->param('transaction_id');
$order = OrderModel::where('user_id', $user->id)->with(['items', 'address', 'invoice']);
if ($id) {
$order = $order->where(function ($query) use ($id) {
return $query->where('id', $id)->whereOr('order_sn', $id);
});
} else if ($merchant_trade_no) {
$pay = PayModel::where('pay_sn', $merchant_trade_no)->findOrFail();
$order = $order->where('id', $pay->order_id);
} else {
$this->error('参数错误');
}
$order = $order->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order->pay_types_text = $order->pay_types_text;
// 处理未支付订单 item status_code
$order = $order->setOrderItemStatusByOrder($order); // 这里订单转 数组了
// 更新包裹信息5分钟缓存
(new ExpressLib)->updateOrderExpress($order['id']);
$this->success('获取成功', $order);
}
public function itemDetail()
{
$user = auth_user();
$id = $this->request->param('id');
$item_id = $this->request->param('item_id');
if (!$id || !$item_id) {
$this->error('参数错误');
}
$order = OrderModel::with(['items' => function ($query) use ($item_id) {
$query->where('id', $item_id);
}])->where('user_id', $user->id)->where('id', $id)->find();
if (!$order || !$order->items) {
$this->error(__('No Results were found'));
}
$order = $order->setOrderItemStatusByOrder($order); // 这里订单转 数组了
$item = $order['items'][0];
$this->success('获取成功', $item);
}
public function calc()
{
$params = $this->request->param();
$this->svalidate($params, ".calc");
$orderCreate = new OrderCreate($params);
$result = $orderCreate->calc();
if (isset($result['msg']) && $result['msg']) {
$this->error($result['msg'], $result);
} else {
$this->success('计算成功', $result);
}
}
public function create()
{
$params = $this->request->param();
$this->svalidate($params, ".create");
$orderCreate = new OrderCreate($params);
$result = $orderCreate->calc('create');
$order = $orderCreate->create($result);
$this->success('订单添加成功', $order);
}
/**
* 获取用户可用和不可用优惠券
*
* @param Request $request
* @return void
*/
public function coupons()
{
$params = $this->request->param();
$this->svalidate($params, ".create");
$orderCreate = new OrderCreate($params);
$result = $orderCreate->getCoupons();
$this->success('获取成功', $result);
}
// 取消订单
public function cancel()
{
$user = auth_user();
$id = $this->request->param('id');
$order = Db::transaction(function () use ($id, $user) {
$order = OrderModel::canCancel()->where('user_id', $user->id)->with(['items', 'invoice'])->lock(true)->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$orderOper = new OrderOper();
$order = $orderOper->cancel($order, $user, 'user');
return $order;
});
// 订单未支付,处理 item 状态
$order = $order->setOrderItemStatusByOrder($order); // 这里订单转 数组了
$this->success('取消成功', $order);
}
// 订单申请全额退款
public function applyRefund()
{
$user = auth_user();
$id = $this->request->param('id');
$order = OrderModel::paid()->where('user_id', $user->id)->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order = Db::transaction(function () use ($order, $user) {
$orderOper = new OrderOper();
$order = $orderOper->applyRefund($order, $user, 'user');
return $order;
});
$order = OrderModel::with(['items', 'invoice'])->find($id);
$order = $order->setOrderItemStatusByOrder($order); // 这里订单转 数组了
$this->success('申请成功', $order);
}
// 确认收货(货到付款的确认收货在后台)
public function confirm()
{
$user = auth_user();
$id = $this->request->param('id');
$order = OrderModel::paid()->where('user_id', $user->id)->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order = Db::transaction(function () use ($order, $user) {
$orderOper = new OrderOper();
$order = $orderOper->confirm($order, [], $user, 'user');
return $order;
});
$order = OrderModel::with(['items', 'invoice'])->find($id);
$this->success('收货成功', $order);
}
// 评价
public function comment()
{
$user = auth_user();
$params = $this->request->param();
$id = $params['id'] ?? 0;
$this->svalidate($params, ".comment");
$comments = $params['comments'] ?? [];
foreach ($comments as $comment) {
$this->svalidate($comment, ".comment_item");
}
$order = OrderModel::paid()->where('user_id', $user->id)->where('id', $id)->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order = Db::transaction(function () use ($order, $params, $user) {
$orderOper = new OrderOper();
$order = $orderOper->comment($order, $params['comments'], $user, 'user');
return $order;
});
$this->success('评价成功', $order);
}
public function applyInvoice()
{
$user = auth_user();
$params = $this->request->param();
$id = $params['id'] ?? 0;
$invoice_id = $params['invoice_id'] ?? 0;
// 获取用户发票信息
$userInvoice = UserInvoice::where('user_id', $user->id)->find($invoice_id);
if (!$userInvoice) {
$this->error('请选择正确的发票信息');
}
$order = Db::transaction(function () use ($id, $userInvoice, $user) {
$order = OrderModel::paid()->lock(true)->where('user_id', $user->id)->find($id);
$orderOper = new OrderOper();
$order = $orderOper->applyInvoice($order, $userInvoice, $user, 'user');
return $order;
});
$this->success('申请成功');
}
/**
* 用户是否存在未支付的,当前团的订单
*
* @param Request $request
* @return void
*/
public function unpaidGrouponOrder()
{
$user = auth_user();
$params = $this->request->param();
$activity_id = $params['activity_id'] ?? 0;
if ($user && $activity_id) {
$order = OrderModel::unpaid()->where('user_id', $user->id)
->where('activity_id', $activity_id)
->whereIn('activity_type', ['groupon', 'groupon_ladder'])->find();
}
$this->success('获取成功', $order ?? null);
}
// 删除订单
public function delete()
{
$user = auth_user();
$id = $this->request->param('id');
$order = OrderModel::canDelete()->where('user_id', $user->id)->where('id', $id)->find();
if (!$order) {
$this->error('订单不存在或不可删除');
}
Db::transaction(function () use ($order, $user) {
$orderOper = new OrderOper();
$orderOper->delete($order, $user, 'user');
});
$this->success('删除成功');
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace addons\shopro\controller\third;
use addons\shopro\controller\Common;
use addons\shopro\service\third\apple\Apple as AppleService;
class Apple extends Common
{
protected $noNeedLogin = ['login'];
// 苹果登陆仅对接App登录
public function login()
{
$payload = $this->request->post('payload/a');
$apple = new AppleService();
$result = $apple->login($payload);
if ($result) {
$this->success('登陆成功');
}
$this->error('登陆失败');
}
}

View File

@@ -0,0 +1,195 @@
<?php
namespace addons\shopro\controller\third;
use think\Db;
use think\exception\HttpResponseException;
use addons\shopro\controller\Common;
use addons\shopro\service\third\wechat\Wechat as WechatService;
use app\admin\model\shopro\notification\Config as NotificationConfig;
class Wechat extends Common
{
protected $noNeedLogin = ['login', 'getSessionId', 'oauthLogin', 'jssdk', 'wxacode', 'subscribeTemplate'];
protected $noNeedRight = ['*'];
protected $payload = [];
protected $wechat;
protected $platform;
public function _initialize()
{
parent::_initialize();
$this->platform = $this->request->param('platform', '');
if ($this->platform === '') {
$this->error('参数错误');
}
$payloadString = htmlspecialchars_decode($this->request->param('payload', ''));
$this->payload = json_decode(urldecode($payloadString), true) ?? [];
$this->wechat = new WechatService($this->platform, $this->payload);
}
// 微信登陆(小程序+公众号+开放平台)
public function login()
{
$result = Db::transaction(function () {
return $this->wechat->login();
});
if ($result) {
$this->success('登陆成功');
}
$this->error('登陆失败');
}
// 获取小程序sessionId+自动登录
public function getSessionId()
{
$result = $this->wechat->getSessionId();
$this->success('', $result);
}
// 获取网页授权地址
public function oauthLogin()
{
$result = $this->wechat->oauthLogin();
if (isset($result['login_url'])) {
$this->success('', $result);
}
if (isset($result['redirect_url'])) {
return redirect($result['redirect_url']);
}
}
// 绑定用户手机号
public function bindUserPhoneNumber()
{
$result = Db::transaction(function () {
$user = auth_user();
$mobile = $this->wechat->getUserPhoneNumber();
$this->svalidate(['mobile' => $mobile], '.bindWechatMiniProgramMobile');
$user->mobile = $mobile;
$verification = $user->verification;
$verification->mobile = 1;
$user->verification = $verification;
return $user->save();
});
if ($result) {
$this->success('绑定成功');
}
$this->error('操作失败');
}
// 绑定微信账号
public function bind()
{
$result = Db::transaction(function () {
$user = auth_user();
return $this->wechat->bind($user);
});
if ($result) {
$this->success('绑定成功');
}
$this->error('绑定失败');
}
// 解绑微信账号
public function unbind()
{
$result = Db::transaction(function () {
return $this->wechat->unbind();
});
if ($result) {
$this->success('解绑成功');
}
$this->error('解绑失败');
}
// 微信网页jssdk
public function jssdk()
{
$apis = [
'checkJsApi',
'updateTimelineShareData',
'updateAppMessageShareData',
'getLocation', //获取位置
'openLocation', //打开位置
'scanQRCode', //扫一扫接口
'chooseWXPay', //微信支付
'chooseImage', //拍照或从手机相册中选图接口
'previewImage', //预览图片接口 'uploadImage', //上传图片
'openAddress', // 获取微信地址
];
// $openTagList = [
// 'wx-open-subscribe'
// ];
try {
$data = $this->wechat->jssdk($apis);
} catch (HttpResponseException $e) {
$data = $e->getResponse()->getData();
$message = $data ? ($data['msg'] ?? '') : $e->getMessage();
$this->error($message);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success('jssdkApi', $data);
}
/**
* 微信小程序码接口
*/
public function wxacode()
{
$mp = $this->wechat->getApp();
$path = $this->payload['path'];
list($page, $scene) = explode('?', $path);
$content = $mp->app_code->getUnlimit($scene, [
'page' => substr($page, 1),
'is_hyaline' => true,
// 'env_version' => 'develop'
'env_version' => 'release'
]);
if ($content instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
return response($content->getBody(), 200, ['Content-Length' => strlen($content->getBodyContents())])->contentType('image/png');
} else {
// 小程序码获取失败
$msg = $content['errcode'] ?? '-';
$msg .= $content['errmsg'] ?? '';
$this->error($msg);
}
}
/**
* 微信小程序订阅模板消息
*/
public function subscribeTemplate()
{
$templates = [];
// 获取订阅消息模板
$notificationConfig = NotificationConfig::where('channel', 'WechatMiniProgram')->enable()->select();
foreach ($notificationConfig as $k => $config) {
if ($config['content'] && isset($config['content']['template_id']) && $config['content']['template_id']) {
$templates[$config['event']] = $config['content']['template_id'];
}
}
$this->success('获取成功', $templates);
}
}

View File

@@ -0,0 +1,125 @@
<?php
namespace addons\shopro\controller\trade;
use addons\shopro\controller\Common;
use app\admin\model\shopro\trade\Order as TradeOrderModel;
use app\admin\model\shopro\Config;
class Order extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$params = $this->request->param();
$type = $params['type'] ?? 'recharge';
if (!in_array($type, ['recharge'])) {
$this->error('参数错误');
}
$orders = TradeOrderModel::{$type}()->where('user_id', $user->id)->paid()
->order('id', 'desc')->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', $orders);
}
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$order = TradeOrderModel::where('user_id', $user->id);
$order = $order->where(function ($query) use($id) {
return $query->where('id', $id)->whereOr('order_sn', $id);
});
$order = $order->find();
if (!$order) {
$this->error(__('No Results were found'));
}
$order->pay_type_text = $order->pay_type_text;
$this->success('获取成功', $order);
}
public function rechargeRules()
{
$config = sheep_config('shop.recharge_withdraw.recharge');
$config['status'] = $config['status'] ?? 0;
$config['quick_amounts'] = $config['quick_amounts'] ?? [];
$config['gift_type'] = $config['gift_type'] ?? 'money';
$this->success('获取成功', $config);
}
public function recharge()
{
$user = auth_user();
$params = $this->request->param();
// 表单验证
$this->svalidate($params, 'recharge');
$recharge_money = floatval($params['recharge_money']);
$config = Config::getConfigs('shop.recharge_withdraw.recharge');
$recharge_status = $config['status'] ?? 0;
$quick_amounts = $config['quick_amounts'] ?? [];
$gift_type = $config['gift_type'] ?? 'money';
if (!$recharge_status) {
$this->error('充值入口已关闭');
}
if ($recharge_money < 0.01) {
$this->error('请输入正确的充值金额');
}
$rule = ['money' => (string)$recharge_money];
foreach ($quick_amounts as $quick_amount) {
if (bccomp((string)$recharge_money, (string)$quick_amount['money'], 2) === 0) {
$rule = $quick_amount;
$rule['gift_type'] = $gift_type;
}
}
$close_time = Config::getConfigs('shop.order.auto_close');
$close_time = $close_time && $close_time > 0 ? $close_time : 0;
$orderData = [];
$orderData['type'] = 'recharge';
$orderData['order_sn'] = get_sn($user->id, 'TO');
$orderData['user_id'] = $user->id;
$orderData['status'] = TradeOrderModel::STATUS_UNPAID;
$orderData['order_amount'] = $recharge_money;
$orderData['pay_fee'] = $recharge_money;
$orderData['remain_pay_fee'] = $recharge_money;
$orderData['platform'] = request()->header('platform');
$orderData['remark'] = $params['remark'] ?? null;
$ext = [
'expired_time' => time() + ($close_time * 60),
'rule' => $rule
];
$orderData['ext'] = $ext;
$order = new TradeOrderModel();
$order->save($orderData);
if ($close_time) {
// 小于等于0 不自动关闭订单
\think\Queue::later(($close_time * 60), '\addons\shopro\job\trade\OrderAutoOper@autoClose', ['order' => $order], 'shopro');
}
$this->success('订单添加成功', $order);
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace addons\shopro\controller\traits;
/**
* 统一 md5 方式可解密签名校验,客服使用
*/
trait UnifiedToken
{
protected $expired = 86400000;
/**
* 获取加密 token
*
* @param string $content 要加密的数据
*/
public function getUnifiedToken($content)
{
$custom_sign = sheep_config('basic.site.sign') ?: 'sheep';
return base64_encode(md5(md5($content) . $custom_sign) . '.' . $content . '.' . time());
}
/**
* 获取被加密数据
*/
public function getUnifiedContent($token)
{
$custom_sign = sheep_config('basic.site.sign') ?: 'sheep';
$token_str = base64_decode($token);
$tokenArr = explode('.', $token_str);
$sign = $tokenArr[0] ?? '';
$content = $tokenArr[1] ?? 0;
$time = $tokenArr[2] ?? 0;
$time = intval($time);
if ($content && $sign) {
if (md5(md5($content) . $custom_sign) == $sign && ($time + $this->expired) > time()) {
return $content;
}
return false;
}
return false;
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace addons\shopro\controller\traits;
/**
* 控制器工具方法
*/
trait Util
{
/**
* 表单验证
*/
protected function svalidate(array $params, ?string $validator = "")
{
if (false !== strpos($validator, '.')) {
// 是否支持场景验证
[$validator, $scene] = explode('.', $validator);
}
$current_class = static::class;
$validate_class = false !== strpos($validator, '\\') ? $validator : str_replace('controller', 'validate', $current_class);
if (!class_exists($validate_class)) {
return;
}
$validate = validate($validate_class);
// 添加场景验证
if (!empty($scene)) {
if (!$validate->check($params, [], $scene)) {
$this->error($validate->getError());
}
} else {
// 添加自定义验证场景,字段为当前提交的所有字段
$validate->scene('custom', array_keys($params));
if (!$validate->check($params, [], 'custom')) {
$this->error($validate->getError());
}
}
return true;
}
/**
* 过滤前端发来的短时间内的重复的请求
*
* @return void
*/
public function repeatFilter($key = null, $expire = 5)
{
if (!$key) {
$url = request()->baseUrl();
$ip = request()->ip();
$key = 'shopro:' . $url . ':' . $ip;
}
if (redis_cache('?' . $key)) {
error_stop('请稍后再试');
}
// 缓存 5 秒
redis_cache($key, time(), $expire);
}
/**
* 监听数据库 sql
*
* @return void
*/
public function dbListen()
{
\think\Db::listen(function ($sql, $time) {
echo $sql . ' [' . $time . 's]' . "<br>";
});
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace addons\shopro\controller\user;
use addons\shopro\controller\Common;
use app\admin\model\shopro\user\Account as AccountModel;
class Account extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$params = $this->request->only([
'type'
]);
$user = auth_user();
$where = [
'user_id' => $user->id
];
if (!empty($params['type'])) {
$where['type'] = $params['type'];
}
$data = AccountModel::where($where)->order('updatetime desc')->find();
if (!$data) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', $data);
}
public function save()
{
$user = auth_user();
$params = $this->request->only([
'type', 'account_name', 'account_header', 'account_no'
]);
if (!in_array($params['type'], ['wechat', 'alipay', 'bank'])) {
$this->error('请选择正确的账户类型');
}
if ($params['type'] === 'alipay') {
$params['account_header'] = '支付宝账户';
}
if ($params['type'] === 'wechat') {
$params['account_header'] = '微信账户';
$params['account_no'] = '-';
}
$this->svalidate($params, ".{$params['type']}");
$data = AccountModel::where(['user_id' => $user->id, 'type' => $params['type']])->find();
if (!$data) {
$data = AccountModel::create([
'user_id' => $user->id,
'type' => $params['type'],
'account_name' => $params['account_name'],
'account_header' => $params['account_header'],
'account_no' => $params['account_no'],
]);
} else {
$data->save($params);
}
$this->success('保存成功', $data);
}
}

View File

@@ -0,0 +1,179 @@
<?php
namespace addons\shopro\controller\user;
use think\Db;
use addons\shopro\controller\Common;
use app\admin\model\shopro\data\Area as AreaModel;
use app\admin\model\shopro\user\Address as UserAddressModel;
class Address extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$userAddresses = UserAddressModel::where('user_id', $user->id)
->order('is_default', 'desc')
->order('id', 'desc')
->select();
$this->success('获取成功', $userAddresses);
}
/**
* 添加收货地址
*/
public function add()
{
$user = auth_user();
$params = $this->request->only([
'consignee', 'mobile', 'province_name', 'city_name', 'district_name', 'address', 'is_default'
]);
$params['user_id'] = $user->id;
$this->svalidate($params, ".add");
$params = $this->getAreaIdByName($params);
Db::transaction(function () use ($user, $params) {
$userAddress = new UserAddressModel();
$userAddress->save($params);
if ($userAddress->is_default) {
// 修改其他收货地址为非默认
UserAddressModel::where('id', '<>', $userAddress->id)
->where('user_id', $user->id)
->where('is_default', 1)
->update(['is_default' => 0]);
}
});
$this->success('保存成功');
}
/**
* 收货地址详情
*
* @param $id
* @return \think\Response
*/
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$userAddress = UserAddressModel::where('user_id', $user->id)->where('id', $id)->find();
if (!$userAddress) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', $userAddress);
}
/**
* 默认收货地址
*
* @return \think\Response
*/
public function default()
{
$user = auth_user();
$userAddress = UserAddressModel::default()->where('user_id', $user->id)->find();
$this->success('获取成功', $userAddress);
}
/**
* 编辑收货地址
*
* @return \think\Response
*/
public function edit()
{
$user = auth_user();
$id = $this->request->param('id');
$userAddress = UserAddressModel::where('user_id', $user->id)->where('id', $id)->find();
if (!$userAddress) {
$this->error(__('No Results were found'));
}
$params = $this->request->only([
'consignee', 'mobile', 'province_name', 'city_name', 'district_name', 'address', 'is_default'
]);
$this->svalidate($params, ".edit");
$params = $this->getAreaIdByName($params);
Db::transaction(function () use ($user, $params, $userAddress) {
$userAddress->save($params);
if ($userAddress->is_default) {
// 修改其他收货地址为非默认
UserAddressModel::where('id', '<>', $userAddress->id)
->where('user_id', $user->id)
->where('is_default', 1)
->update(['is_default' => 0]);
}
});
$this->success('保存成功');
}
/**
* 删除收货地址
*
* @param string $id 要删除的收货地址
* @return void
*/
public function delete()
{
$user = auth_user();
$id = $this->request->param('id');
$userAddress = UserAddressModel::where('user_id', $user->id)->where('id', $id)->find();
if (!$userAddress) {
$this->error(__('No Results were found'));
}
$userAddress->delete();
$this->success('删除成功');
}
private function getAreaIdByName($params)
{
$province = AreaModel::where([
'name' => $params['province_name'],
'level' => 'province'
])->find();
if (!$province) $this->error('请选择正确的行政区');
$params['province_id'] = $province->id;
$city = AreaModel::where([
'name' => $params['city_name'],
'level' => 'city',
'pid' => $province->id
])->find();
if (!$city) $this->error('请选择正确的行政区');
$params['city_id'] = $city->id;
$district = AreaModel::where([
'name' => $params['district_name'],
'level' => 'district',
'pid' => $city->id
])->find();
if (!$district) $this->error('请选择正确的行政区');
$params['district_id'] = $district->id;
return $params;
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace addons\shopro\controller\user;
use think\helper\Str;
use addons\shopro\controller\Common;
use app\admin\model\shopro\user\Coupon as UserCouponModel;
class Coupon extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$type = $this->request->param('type', 'can_use'); // 优惠券类型geted=已领取can_use=可用cannot_use=暂不可用used=已使用expired=已过期,invalid=已失效(包含已使用和已过期)
$userCoupons = UserCouponModel::with('coupon')->where('user_id', $user->id);
if (in_array($type, ['geted', 'can_use', 'cannot_use', 'used', 'expired', 'invalid'])) {
$userCoupons = $userCoupons->{Str::camel($type)}();
}
$userCoupons = $userCoupons->order('id', 'desc')->paginate($this->request->param('list_rows', 10));
$this->success('获取成功', $userCoupons);
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace addons\shopro\controller\user;
use addons\shopro\controller\Common;
use app\admin\model\shopro\user\GoodsLog as UserGoodsLogModel;
use app\admin\model\shopro\goods\Goods;
class GoodsLog extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$type = $this->request->param('type');
// 首先删除商品不存在的记录
UserGoodsLogModel::whereNotExists(function ($query) {
$goodsTableName = (new Goods())->getQuery()->getTable();
$tableName = (new UserGoodsLogModel())->getQuery()->getTable();
$query = $query->table($goodsTableName)->where($goodsTableName . '.id=' . $tableName . '.goods_id')->whereNull($goodsTableName . '.deletetime'); // 不查软删除的商品
return $query;
})->where('user_id', $user->id)->delete();
$logs = UserGoodsLogModel::with('goods')->{$type}()->where('user_id', $user->id);
$logs = $logs->order('updatetime', 'desc')->paginate($this->request->param('list_rows', 10)); // 按照更新时间排序
$this->success('获取成功', $logs);
}
/**
* 收藏/取消收藏
*
* @param Request $request
* @return void
*/
public function favorite()
{
$user = auth_user();
$goods_id = $this->request->param('goods_id');
$goods_ids = $this->request->param('goods_ids');
if (!$goods_id && !$goods_ids) {
$this->error('缺少参数');
}
if ($goods_ids) {
// 个人中心批量取消收藏
$log = UserGoodsLogModel::favorite()->whereIn('goods_id', $goods_ids)
->where('user_id', $user->id)->delete();
$this->success('取消收藏成功');
}
$log = UserGoodsLogModel::favorite()->where('goods_id', $goods_id)
->where('user_id', $user->id)->find();
$favorite = false; // 取消收藏
if ($log) {
// 取消收藏
$log->delete();
} else {
$favorite = true; // 收藏
$log = new UserGoodsLogModel();
$log->goods_id = $goods_id;
$log->user_id = $user->id;
$log->type = 'favorite';
$log->save();
}
$this->success($favorite ? '收藏成功' : '取消收藏');
}
public function viewDel()
{
$goods_id = $this->request->param('goods_id'); // 支持 逗号分开
$user = auth_user();
UserGoodsLogModel::views()->whereIn('goods_id', $goods_id)
->where('user_id', $user->id)->delete();
$this->success('删除成功');
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace addons\shopro\controller\user;
use addons\shopro\controller\Common;
use app\admin\model\shopro\user\Invoice as UserInvoiceModel;
use think\Db;
class Invoice extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$user = auth_user();
$userInvoices = UserInvoiceModel::where('user_id', $user->id)
->order('id', 'asc')
->select();
$this->success('获取成功', $userInvoices);
}
/**
* 添加发票抬头
*
* @return \think\Response
*/
public function add()
{
$user = auth_user();
$params = $this->request->only([
'type', 'name', 'tax_no', 'address', 'mobile', 'bank_name', 'bank_no'
]);
$params['user_id'] = $user->id;
$this->svalidate($params, ".add");
Db::transaction(function () use ($user, $params) {
$userInvoice = new UserInvoiceModel();
$userInvoice->save($params);
});
$this->success('保存成功');
}
/**
* 发票详情
*
* @param $id
* @return \think\Response
*/
public function detail()
{
$user = auth_user();
$id = $this->request->param('id');
$userInvoice = UserInvoiceModel::where('user_id', $user->id)->where('id', $id)->find();
if (!$userInvoice) {
$this->error(__('No Results were found'));
}
$this->success('获取成功', $userInvoice);
}
/**
* 编辑发票
*
* @return \think\Response
*/
public function edit()
{
$user = auth_user();
$id = $this->request->param('id');
$params = $this->request->only([
'type', 'name', 'tax_no', 'address', 'mobile', 'bank_name', 'bank_no'
]);
$this->svalidate($params, ".edit");
$userInvoice = UserInvoiceModel::where('user_id', $user->id)->where('id', $id)->find();
if (!$userInvoice) {
$this->error(__('No Results were found'));
}
Db::transaction(function () use ($params, $userInvoice) {
$userInvoice->save($params);
});
$this->success('保存成功');
}
/**
* 删除发票
*
* @param string $id 要删除的发票
* @return void
*/
public function delete()
{
$user = auth_user();
$id = $this->request->param('id');
$userInvoice = UserInvoiceModel::where('user_id', $user->id)->where('id', $id)->find();
if (!$userInvoice) {
$this->error(__('No Results were found'));
}
$userInvoice->delete();
$this->success('删除成功');
}
}

View File

@@ -0,0 +1,305 @@
<?php
namespace addons\shopro\controller\user;
use app\common\library\Sms;
use addons\shopro\controller\Common;
use addons\shopro\service\user\UserAuth;
use app\admin\model\shopro\user\User as UserModel;
use app\admin\model\shopro\user\Coupon as UserCouponModel;
use app\admin\model\shopro\order\Order as OrderModel;
use app\admin\model\shopro\order\Aftersale as AftersaleModel;
use app\admin\model\shopro\ThirdOauth;
class User extends Common
{
protected $noNeedLogin = ['smsRegister', 'accountLogin', 'smsLogin', 'resetPassword'];
protected $noNeedRight = ['*'];
public function _initialize()
{
parent::_initialize();
\think\Lang::load(APP_PATH . 'api/lang/zh-cn/user.php'); // 加载语言包
}
/**
* 用户数据
*/
public function data()
{
$user = auth_user();
// 查询用户优惠券数量
$data['coupons_num'] = UserCouponModel::geted()->where('user_id', $user->id)->count();
// 订单数量
$orderNum = [];
$orderNum['unpaid'] = OrderModel::where('user_id', $user->id)->unpaid()->count();
$orderNum['nosend'] = OrderModel::where('user_id', $user->id)->pretendPaid()->nosend()->count();
$orderNum['noget'] = OrderModel::where('user_id', $user->id)->pretendPaid()->noget()->count();
$orderNum['nocomment'] = OrderModel::where('user_id', $user->id)->paid()->nocomment()->count();
$orderNum['aftersale'] = AftersaleModel::where('user_id', $user->id)->needOper()->count();
$data['order_num'] = $orderNum;
$this->success('用户数据', $data);
}
/**
* 第三方授权信息
*/
public function thirdOauth()
{
$user = auth_user();
$provider = $this->request->param('provider', '');
$platform = $this->request->param('platform', '');
if (!in_array($platform, ['miniProgram', 'officialAccount', 'openPlatform'])) {
$this->error(__('Invalid parameters'));
}
$where = [
'platform' => $platform,
'user_id' => $user->id
];
if ($provider !== '') {
$where['provider'] = $provider;
}
$oauth = ThirdOauth::where($where)->field('nickname, avatar, platform, provider')->find();
$this->success('', $oauth);
}
/**
* 用户信息
*/
public function profile()
{
//TODO @ldh: 1.账号被禁用 2.连表查group
$user = auth_user(true);
$user = UserModel::with(['parent_user', 'third_oauth'])->where('id', $user->id)->find();
$user->hidden(['password', 'salt', 'createtime', 'updatetime', 'deletetime', 'remember_token', 'login_fail', 'login_ip', 'login_time']);
$this->success('个人详情', $user);
}
/**
* 更新用户资料
*/
public function update()
{
$user = auth_user();
$params = $this->request->only(['avatar', 'nickname', 'gender']);
$this->svalidate($params);
$user->save($params);
$user->hidden(['password', 'salt', 'createtime', 'updatetime', 'deletetime', 'remember_token', 'login_fail', 'login_ip', 'login_time']);
$this->success('更新成功', $user);
}
/**
* 账号密码登录
*/
public function accountLogin()
{
$user = auth_user();
if ($user) {
$this->error('您已登录,不需要重新登录');
}
$params = $this->request->only(['account', 'password']);
$this->svalidate($params, '.accountLogin');
$ret = $this->auth->login($params['account'], $params['password']);
if ($ret) {
set_token_in_header($this->auth->getToken());
$this->success(__('Logged in successful'));
} else {
$this->error($this->auth->getError() ?: '注册失败');
}
}
/**
* 短信验证码登陆
*/
public function smsLogin()
{
$user = auth_user();
if ($user) {
$this->error('您已登录,不需要重新登录');
}
$params = $this->request->only(['mobile', 'code']);
$this->svalidate($params, '.smsLogin');
if (!Sms::check($params['mobile'], $params['code'], 'mobilelogin')) {
$this->error(__('Captcha is incorrect'));
}
$user = UserModel::getByMobile($params['mobile']);
if ($user) {
if ($user->status != 'normal') {
$this->error(__('Account is locked'));
}
//如果已经有账号则直接登录
$ret = $this->auth->direct($user->id);
}else {
$this->error('该手机号暂未注册');
}
if (isset($ret) && $ret) {
Sms::flush($params['mobile'], 'mobilelogin');
set_token_in_header($this->auth->getToken());
$this->success(__('Logged in successful'));
} else {
$this->error($this->auth->getError() ?: '登录失败');
}
}
/**
* 短信验证码注册
*/
public function smsRegister()
{
$user = auth_user();
if ($user) {
$this->error('您已登录,请先退出登录');
}
$params = $this->request->only(['mobile', 'code', 'password']);
$this->svalidate($params, '.smsRegister');
$ret = Sms::check($params['mobile'], $params['code'], 'register');
if (!$ret) {
$this->error(__('Captcha is incorrect'));
}
// 注册
$userAuth = new UserAuth();
$auth = $userAuth->register($params);
set_token_in_header($auth->getToken());
$this->success(__('Sign up successful'));
}
/**
* 修改密码
*/
public function changePassword()
{
$user = auth_user();
$params = $this->request->only(['oldPassword', 'newPassword']);
$this->svalidate($params, '.changePassword');
$userAuth = new UserAuth();
$userAuth->changePassword($params['newPassword'], $params['oldPassword']);
$this->auth->direct($user->id);
set_token_in_header($this->auth->getToken());
$this->success(__('Change password successful'));
}
/**
* 重置/忘记密码
*/
public function resetPassword()
{
$params = $this->request->only(['mobile', 'code', 'password']);
$this->svalidate($params, '.resetPassword');
$ret = Sms::check($params['mobile'], $params['code'], 'resetpwd');
if (!$ret) {
$this->error(__('Captcha is incorrect'));
}
$userAuth = new UserAuth();
$userAuth->resetPassword($params);
$this->success(__('Reset password successful'));
}
/**
* 更换手机号
*/
public function changeMobile()
{
$params = $this->request->only(['mobile', 'code']);
$this->svalidate($params, '.changeMobile');
$ret = Sms::check($params['mobile'], $params['code'], 'changemobile');
if (!$ret) {
$this->error(__('Captcha is incorrect'));
}
$userAuth = new UserAuth();
$userAuth->changeMobile($params);
$this->success('绑定成功');
}
/**
* 修改用户名
*/
public function changeUsername()
{
$user = auth_user(true);
$params = $this->request->only(['username']);
$this->svalidate($params, '.changeUsername');
$userAuth = new UserAuth();
$userAuth->changeUsername($params);
$this->success('绑定成功');
}
/**
* 更新小程序头像和昵称
*/
public function updateMpUserInfo()
{
$user = auth_user(true);
$params = $this->request->only(['avatar', 'nickname']);
$this->svalidate($params, '.updateMpUserInfo');
$user->save($params);
$thirdOauth = \app\admin\model\shopro\ThirdOauth::where('user_id', $user->id)->where([
'provider' => 'wechat',
'platform' => 'miniProgram'
])->find();
$thirdOauth->save($params);
$this->success('绑定成功');
}
/**
* 登出
*/
public function logout()
{
$userAuth = new UserAuth();
$userAuth->logout();
$this->success(__('Logout successful'));
}
/**
* 用户注销
*/
public function logoff()
{
$userAuth = new UserAuth();
$userAuth->logoff();
$this->success('注销成功');
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace addons\shopro\controller\user;
use addons\shopro\controller\Common;
use app\admin\model\shopro\user\WalletLog as UserWalletLogModel;
class WalletLog extends Common
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
public function index()
{
$type = $this->request->param('type', 'money');
$tab = $this->request->param('tab', 'all');
$list_rows = $this->request->param('list_rows', 10);
$date = $this->request->param('date/a');
$user = auth_user();
$where['user_id'] = $user->id;
switch ($tab) {
case 'income':
$where['amount'] = ['>', 0];
break;
case 'expense':
$where['amount'] = ['<', 0];
break;
}
$income = UserWalletLogModel::where('user_id', $user->id)->{$type}()->where('amount', '>', 0)->whereTime('createtime', 'between', $date)->sum('amount');
$expense = UserWalletLogModel::where('user_id', $user->id)->{$type}()->where('amount', '<', 0)->whereTime('createtime', 'between', $date)->sum('amount');
$logs = UserWalletLogModel::where($where)->{$type}()->whereTime('createtime', 'between', $date)->order('createtime', 'desc')->paginate($list_rows);
$this->success('获取成功', ['list' => $logs, 'income' => $income, 'expense' => $expense]);
}
}

View File

@@ -0,0 +1,240 @@
<?php
namespace addons\shopro\controller\wechat;
use addons\shopro\facade\Wechat;
use app\admin\model\shopro\wechat\Reply;
use app\admin\model\shopro\wechat\Material;
use EasyWeChat\Kernel\Messages\Image;
use EasyWeChat\Kernel\Messages\Media;
use EasyWeChat\Kernel\Messages\Text;
use EasyWeChat\Kernel\Messages\News;
use EasyWeChat\Kernel\Messages\NewsItem;
use EasyWeChat\Kernel\Messages\Video;
use EasyWeChat\Kernel\Messages\Voice;
use app\admin\model\shopro\ThirdOauth;
class Serve
{
protected $noNeedLogin = ['*'];
protected $noNeedRight = ['*'];
protected $wechat = null;
protected $openid = "";
// 微信api
public function index()
{
$this->wechat = Wechat::officialAccountManage();
$this->wechat->server->push(function ($message) {
$this->openid = $message['FromUserName'];
return $this->reply($message);
});
$this->wechat->server->serve()->send();
}
// 回复消息
private function reply($message)
{
switch ($message['MsgType']) {
// 收到事件
case 'event':
switch ($message['Event']) {
// 订阅(关注)事件
case 'subscribe':
$data = ['openid' => $this->openid];
\think\Hook::listen('wechat_subscribe', $data);
$reply = Reply::where('group', 'subscribe')->enable()->find();
if ($reply) {
$this->getReplyData($reply);
}
if (!empty($message['EventKey'])) {
$event = str_replace('qrscene_', '', $message['EventKey']);
return $this->scanQrcode($event);
}
break;
// 取消订阅(关注)事件
case 'unsubscribe':
$data = ['openid' => $this->openid];
\think\Hook::listen('wechat_unsubscribe', $data);
break;
//自定义菜单事件
case 'CLICK':
$event = explode('|', $message['EventKey']);
return $this->getClickData($event);
break;
case 'SCAN':
if (!empty($event = $message['EventKey'])) {
return $this->scanQrcode($event);
}
break;
}
break;
// 收到文本消息
case 'text':
//检测关键字回复
$keywords = $message['Content'];
$reply = Reply::where('group', 'keywords')->enable()->where('find_in_set(:keywords, keywords)', ['keywords' => $keywords])->find();
if ($reply) {
return $this->getReplyData($reply);
}
break;
// 收到图片消息 暂不支持此消息类型
case 'image':
// 收到语音消息 暂不支持此消息类型
case 'voice':
// 收到视频消息 暂不支持此消息类型
case 'video':
// 收到坐标消息 暂不支持此消息类型
case 'location':
// 收到链接消息 暂不支持此消息类型
case 'link':
// 收到文件消息 暂不支持此消息类型
case 'file':
// 默认回复消息
default:
$reply = Reply::where('group', 'default')->enable()->find();
if ($reply) {
return $this->getReplyData($reply);
}
}
return true;
}
// 组装回复消息的数据结构
private function getReplyData($reply)
{
switch ($reply->type) {
// 回复文本消息
case 'text':
$material = Material::find($reply->content);
if ($material) {
$data = new Text($material->content);
}
break;
// 回复链接卡片
case 'link':
$material = Material::find($reply->content);
if ($material) {
$link = $material->content;
$items = new NewsItem([
'title' => $link['title'],
'description' => $link['description'],
'url' => $link['url'],
'image' => cdnurl($link['image'], true),
]);
$data = new News([$items]);
}
break;
case 'video':
$data = new Video($reply->content);
break;
case 'voice':
$data = new Voice($reply->content);
break;
case 'image':
$data = new Image($reply->content);
break;
case 'news':
$data = new Media($reply->content, 'mpnews');
break;
}
// 使用客服消息发送
$this->wechat->customer_service->message($data)->to($this->openid)->send();
}
// 组装事件消息的数据结构
private function getClickData($event)
{
switch ($event[0]) {
// 回复文本消息
case 'text':
$material = Material::find($event[1]);
if ($material) {
$data = new Text($material->content);
}
break;
// 回复链接卡片
case 'link':
$material = Material::find($event[1]);
if ($material) {
$link = $material->content;
$items = new NewsItem([
'title' => $link['title'],
'description' => $link['description'],
'url' => $link['url'],
'image' => cdnurl($link['image'], true),
]);
$data = new News([$items]);
}
break;
case 'video':
$data = new Video($event[1]);
break;
case 'voice':
$data = new Voice($event[1]);
break;
case 'image':
$data = new Image($event[1]);
break;
case 'news':
$data = new Media($event[1], 'mpnews');
break;
}
// 使用客服消息发送
$this->wechat->customer_service->message($data)->to($this->openid)->send();
}
// 扫一扫微信二维码
private function scanQrcode($eventStr)
{
list($flag, $event, $eventId) = explode('.', $eventStr);
$text = '';
if (empty($flag) || empty($event)) {
$text = '未找到对应扫码事件';
} else {
switch ($event) {
case 'login':
// $text = $this->login($eventId);
break;
case 'bind':
$text = $this->bind($eventId);
break;
}
}
if (!empty($text)) {
$this->wechat->customer_service->message(new Text($text))->to($this->openid)->send();
}
return;
}
// 扫一扫绑定管理员
private function bind($eventId)
{
$cacheKey = "wechatAdmin.bind.{$eventId}";
$cacheValue = cache($cacheKey);
if (empty($cacheValue)) {
return '二维码已过期,请重新扫码';
}
$thirdOauth = ThirdOauth::where([
'provider' => 'wechat',
'platform' => 'admin',
'openid' => $this->openid
])->find();
if ($thirdOauth && $thirdOauth->admin_id !== 0) {
return '该微信账号已绑定其他管理员';
}
cache($cacheKey, ['id' => $this->openid], 1 * 60);
return '正在绑定管理员快捷登录';
}
}