From 09c53981b5f97dada33f26f482e61f9bfbe70698 Mon Sep 17 00:00:00 2001 From: panliang <1163816051@qq.com> Date: Thu, 12 May 2022 17:49:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=81=E4=B8=9A=E4=BB=98=E6=AC=BE=20todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/OrderProfitController.php | 2 + app/Admin/Controllers/StoreController.php | 18 ++++--- app/Admin/Controllers/VipController.php | 30 +++++------ app/Admin/Forms/ProfitSuccessForm.php | 11 +++- app/Admin/Repositories/Vip.php | 16 ------ .../Controllers/Order/OrderPreController.php | 18 +++++-- app/Models/OrderProfit.php | 2 +- app/Models/ShippingRule.php | 2 + app/Models/Vip.php | 13 ++++- app/Services/DistributeService.php | 24 +++++++++ app/Services/Payment/WxpayService.php | 50 +++++++++++++++++++ config/wechat.php | 9 ++++ ...5_06_150951_create_order_profits_table.php | 4 +- database/seeders/AdminMenuSeeder.php | 44 ++++++++-------- database/seeders/AdminPermissionSeeder.php | 11 ++++ database/seeders/AdminUserSeeder.php | 2 +- database/seeders/ShippingSeeder.php | 6 ++- database/seeders/UserSeeder.php | 4 ++ resources/lang/zh_CN/order-profit.php | 2 +- resources/lang/zh_CN/vip.php | 7 +-- 20 files changed, 199 insertions(+), 76 deletions(-) delete mode 100644 app/Admin/Repositories/Vip.php diff --git a/app/Admin/Controllers/OrderProfitController.php b/app/Admin/Controllers/OrderProfitController.php index bb721ef4..c86967fe 100644 --- a/app/Admin/Controllers/OrderProfitController.php +++ b/app/Admin/Controllers/OrderProfitController.php @@ -69,6 +69,8 @@ class OrderProfitController extends AdminController $show->field('money'); $show->field('status')->using(OrderProfit::$statusMap)->dot(OrderProfit::$statusColor); $show->field('paid_at'); + $show->field('pay_way'); + $show->field('pay_no'); $show->field('remarks'); $show->field('created_at'); $show->field('updated_at'); diff --git a/app/Admin/Controllers/StoreController.php b/app/Admin/Controllers/StoreController.php index 9e6c8dec..a27bd389 100644 --- a/app/Admin/Controllers/StoreController.php +++ b/app/Admin/Controllers/StoreController.php @@ -175,17 +175,19 @@ class StoreController extends AdminController $form->text('remarks'); $form->disableDeleteButton(); - - // 管理员删除店铺 - if ($form->isDeleting() && $canAdmin) { - $info = Store::find($form->getKey()); - // 删除店铺关联的数据 - $info->adminUsers()->detach(); - $info->productSkus()->detach(); - } }); } + public function destroy($id) + { + $info = Store::find($id); + // 删除店铺关联的数据 + $info->adminUsers()->detach(); + $info->productSkus()->detach(); + + return parent::destroy($id); + } + protected function canAdmin() { return Admin::user()->isRole('administrator'); diff --git a/app/Admin/Controllers/VipController.php b/app/Admin/Controllers/VipController.php index 3123088c..d4a2d634 100644 --- a/app/Admin/Controllers/VipController.php +++ b/app/Admin/Controllers/VipController.php @@ -2,9 +2,8 @@ namespace App\Admin\Controllers; -use App\Admin\Repositories\Vip; use App\Exceptions\BizException; -use App\Models\Vip as VipModel; +use App\Models\Vip; use Dcat\Admin\Admin; use Dcat\Admin\Form; use Dcat\Admin\Grid; @@ -32,20 +31,20 @@ class VipController extends AdminController /** 操作 **/ //新增 - // if (Admin::user()->can('dcat.admin.vips.create')) { - // $grid->disableCreateButton(false); - // $grid->enableDialogCreate(); - // } + if (Admin::user()->can('dcat.admin.vips.create')) { + $grid->disableCreateButton(false); + $grid->enableDialogCreate(); + } //修改 $grid->showQuickEditButton(Admin::user()->can('dcat.admin.vips.edit')); //删除以及自定义操作 - // $grid->actions(function (Grid\Displayers\Actions $actions) { - // $actions->disableDelete(Admin::user()->cannot('dcat.admin.vips.destroy')); - // }); + $grid->actions(function (Grid\Displayers\Actions $actions) { + $actions->disableDelete(Admin::user()->cannot('dcat.admin.vips.destroy')); + }); $grid->filter(function (Grid\Filter $filter) { $filter->panel(false); - $filter->like('name'); + $filter->like('name')->width(3); }); }); } @@ -62,6 +61,8 @@ class VipController extends AdminController return Show::make($id, new Vip(), function (Show $show) { $show->field('id'); $show->field('name'); + $show->field('sort'); + $show->filed('slug'); $show->column('ratio')->as(function ($value) { return $value . '%'; }); @@ -80,18 +81,17 @@ class VipController extends AdminController { return Form::make(new Vip(), function (Form $form) { $form->display('id'); + $form->number('sort')->min(1)->required()->help('不可重复'); $form->text('name')->required(); + $form->radio('slug')->options(Vip::$typeMap)->default(Vip::TYPE_FAVOITE); $form->number('ratio')->min(0)->max(100)->help('例如: 60%, 填写 60 即可'); - $form->number('growth_value')->min(0)->default(0); - - $form->display('created_at'); - $form->display('updated_at'); + $form->number('growth_value')->min(0)->default(0)->help('升级到此等级所需的成长值'); }); } public function destroy($id) { - $vip = VipModel::findOrFail($id); + $vip = Vip::findOrFail($id); if ($vip->hasUser()) { throw new BizException(__('vip.options.deny_message')); } diff --git a/app/Admin/Forms/ProfitSuccessForm.php b/app/Admin/Forms/ProfitSuccessForm.php index bd17ca66..64226512 100644 --- a/app/Admin/Forms/ProfitSuccessForm.php +++ b/app/Admin/Forms/ProfitSuccessForm.php @@ -38,9 +38,18 @@ class ProfitSuccessForm extends Form implements LazyRenderable { $order = OrderProfit::findOrFail($this->payload['id']); $service = new DistributeService(); + if ($input['pay_way'] === 'wechat-transfer' && !$order->pay_no) { + $order->update([ + 'pay_no' => serial_number() + ]); + } try { DB::beginTransaction(); - $service->success($order, $input); + if ($input['pay_way'] === 'wechat-transfer') { + $service->wechatTransfer($order); + } else { + $service->success($order, $input); + } DB::commit(); } catch (Throwable $th) { DB::rollBack(); diff --git a/app/Admin/Repositories/Vip.php b/app/Admin/Repositories/Vip.php deleted file mode 100644 index d4a3fc9a..00000000 --- a/app/Admin/Repositories/Vip.php +++ /dev/null @@ -1,16 +0,0 @@ - '未选择商品' ]); + // 验证商品是否属于该店铺 + $store = Store::findOrFail($request->input('store_id')); + $products = $request->input('products'); - // 验证商品的购买数量 大于 发货数量 foreach($products as $item) { $quantity = $item['quantity']; $send = $item['send']; + $sku_id = $item['sku_id']; + + // 验证商品是否属于该店铺 + if (!$store->productSkus()->wherePivot('product_sku_id', $sku_id)->exists()) { + throw new BizException('商品未在该店铺出售, ' . $sku_id); + } + + // 验证商品的购买数量 大于 发货数量 if ($send > $quantity) { - throw new BizException('商品购买数量大于发货数量, ' . $item['sku_id']); + throw new BizException('商品购买数量大于发货数量, ' . $sku_id); } } $order_pre = OrderPre::create([ 'user_id' => $user->id, - 'store_id' => $request->input('store_id'), + 'store_id' => $store->id, 'products' => $request->input('products'), 'remarks' => $request->input('remarks'), 'others' => [ diff --git a/app/Models/OrderProfit.php b/app/Models/OrderProfit.php index 727a1be6..82c5cda4 100644 --- a/app/Models/OrderProfit.php +++ b/app/Models/OrderProfit.php @@ -24,7 +24,7 @@ class OrderProfit extends Model 3 => 'danger' ]; - protected $fillable = ['id', 'order_id', 'from_user_id', 'user_id', 'role', 'role_name', 'growth_value', 'ratio', 'money', 'status', 'paid_at', 'pay_data', 'remarks']; + protected $fillable = ['id', 'order_id', 'from_user_id', 'user_id', 'role', 'role_name', 'growth_value', 'ratio', 'money', 'status', 'paid_at', 'pay_no', 'pay_way', 'pay_data', 'remarks']; public function user() { diff --git a/app/Models/ShippingRule.php b/app/Models/ShippingRule.php index a7d84652..a662d8af 100644 --- a/app/Models/ShippingRule.php +++ b/app/Models/ShippingRule.php @@ -15,6 +15,8 @@ class ShippingRule extends Model public const TYPE_FREE = 1;//包邮 public const TYPE_WEIGHT = 2;//计算重量 + protected $fillable = ['info', 'remarks', 'template_id', 'type', 'zones']; + protected $casts = [ // 'info' => JsonArray::class, 'zones' => JsonArray::class, diff --git a/app/Models/Vip.php b/app/Models/Vip.php index 4201e30a..7c740ab6 100644 --- a/app/Models/Vip.php +++ b/app/Models/Vip.php @@ -8,8 +8,17 @@ use Illuminate\Database\Eloquent\Model; class Vip extends Model { - use HasFactory; - use HasDateTimeFormatter; + use HasFactory, HasDateTimeFormatter; + + const TYPE_FAVOITE = 'favoite'; + const TYPE_AGENT = 'agent'; + + protected $fillable = ['growth_value', 'name', 'ratio', 'slug', 'sort']; + + public static $typeMap = [ + self::TYPE_FAVOITE => '爱好者', + self::TYPE_AGENT => '代理' + ]; public function users() { diff --git a/app/Services/DistributeService.php b/app/Services/DistributeService.php index da55d3af..1577a791 100644 --- a/app/Services/DistributeService.php +++ b/app/Services/DistributeService.php @@ -3,6 +3,9 @@ namespace App\Services; use App\Models\{User, Order, SalesValueLog, Vip, OrderProfit}; +use App\Services\Payment\WxpayService; +use App\Enums\SocialiteType; +use App\Exceptions\BizException; /** * 分销模块 @@ -94,6 +97,27 @@ class DistributeService $order->profits()->createMany($profit_list); } + /** + * 使用微信企业付款 + * 调用之前, 需要提前生成商户订单号 + */ + public function wechatTransfer(OrderProfit $profit) + { + $user = $profit->user; + $openid = $user->socialites()->where('socialite_type', SocialiteType::WechatMiniProgram->value)->value('socialite_id'); + $result = (new WxpayService())->transfer([ + 'partner_trade_no' => $profit->pay_no, + 'openid' => $openid, + 'check_name' => 'NO_CHECK', + 'amount' => $profit->money * 100, + 'desc' => '推荐返利', + ]); + + $this->success($profit, [ + 'paid_at' => data_get($result, 'payment_time') + ]); + } + /** * 返现记录支付成功 * diff --git a/app/Services/Payment/WxpayService.php b/app/Services/Payment/WxpayService.php index 6dc7d22f..a9f60d13 100644 --- a/app/Services/Payment/WxpayService.php +++ b/app/Services/Payment/WxpayService.php @@ -55,6 +55,56 @@ class WxpayService }; } + /** + * 微信企业付款到零钱 + * + * @param array $params + * @return array + */ + public function transfer(array $params) + { + $config = config('wechat.payment.default'); + if (!isset($params['openid']) && config('app.debug')) { + $params['openid'] = 'oU7xS5UspzVvpPEBqKZuW6N9WXDg'; + } + $app = Factory::payment($config); + + // 服务商模式 (子商户) + $appId = config('wechat.payment.sub.app_id'); + $mchId = config('wechat.payment.sub.mch_id'); + + if ($appId && $mchId) { + $app->setSubMerchant($mchId, $appId); + } + + /* + 'partner_trade_no' => '1233455', // 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号) + 'openid' => 'oxTWIuGaIt6gTKsQRLau2M0yL16E', + 'check_name' => 'FORCE_CHECK', // NO_CHECK:不校验真实姓名, FORCE_CHECK:强校验真实姓名 + 're_user_name' => '王小帅', // 如果 check_name 设置为FORCE_CHECK,则必填用户真实姓名 + 'amount' => 10000, // 企业付款金额,单位为分 + 'desc' => '理赔', // 企业付款操作说明信息。必填 + */ + $result = $app->transfer->toBalance($params); + $this->validateResult($result); + return $result; + } + + /** + * 查询 微信企业付款到零钱 的订单 + * + * @param string $no 商户订单号 + * @return array + */ + public function queryTransfer($no) + { + $config = config('wechat.payment.transfer'); + $app = Factory::payment($config); + $result = $app->transfer->queryBalanceOrder($no); + $this->validateResult($result); + return $result; + } + /** * 根据商户订单号退款 * diff --git a/config/wechat.php b/config/wechat.php index 4c9b093a..73096c4a 100644 --- a/config/wechat.php +++ b/config/wechat.php @@ -77,6 +77,15 @@ return [ 'app_id' => env('WECHAT_PAYMENT_SUB_APPID'), 'mch_id' => env('WECHAT_PAYMENT_SUB_MCH_ID'), ], + // 企业付款 + 'transfer' => [ + 'sandbox' => env('WECHAT_PAYMENT_SANDBOX', false), + 'app_id' => env('WECHAT_PAYMENT_SUB_APPID'), + 'mch_id' => env('WECHAT_PAYMENT_SUB_MCH_ID'), + 'key' => env('WECHAT_PAYMENT_SUB_KEY'), + 'cert_path' => env('WECHAT_PAYMENT_SUB_CERT_PATH'), + 'key_path' => env('WECHAT_PAYMENT_SUB_KEY_PATH'), + ], // 商城 - 微信小程序支付 'mini_program' => [ 'sandbox' => env('WECHAT_PAYMENT_SANDBOX', false), diff --git a/database/migrations/2022_05_06_150951_create_order_profits_table.php b/database/migrations/2022_05_06_150951_create_order_profits_table.php index d78c2eea..abeb88f5 100644 --- a/database/migrations/2022_05_06_150951_create_order_profits_table.php +++ b/database/migrations/2022_05_06_150951_create_order_profits_table.php @@ -26,7 +26,9 @@ class CreateOrderProfitsTable extends Migration $table->tinyInteger('status')->default(0)->comment('状态(0: 待付款, 1: 付款中, 2: 已付款)'); $table->string('remarks')->nullable()->comment('备注'); $table->timestamp('paid_at')->nullable()->comment('付款时间'); - $table->text('pay_data')->nullable()->comment('支付信息{pay_way, pay_sn}'); + $table->string('pay_way')->nullable()->comment('付款方式'); + $table->string('pay_no')->nullable()->comment('付款流水号'); + $table->text('pay_data')->nullable()->comment('支付信息'); $table->timestamps(); }); } diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php index 8d6ba5b3..2f9e095b 100644 --- a/database/seeders/AdminMenuSeeder.php +++ b/database/seeders/AdminMenuSeeder.php @@ -33,6 +33,7 @@ class AdminMenuSeeder extends Seeder 'icon' => '', 'uri' => 'users', ], + ['title' => '代理等级', 'icon' => '', 'uri' => 'vips'] ], ], [ @@ -248,31 +249,32 @@ class AdminMenuSeeder extends Seeder 'icon' => 'fa fa-jpy', 'uri'=> '', 'children'=>[ - [ - 'title' => '可提账户', - 'icon'=>'', - 'uri' => 'wallet-logs', - ], - [ - 'title' => '余额账户', - 'icon' => '', - 'uri' => 'balance-logs', - ], - [ - 'title' => '积分账户', - 'icon' => '', - 'uri' => 'points-logs', - ], - [ - 'title' =>'提现审核', - 'icon' => '', - 'uri' =>'wallet-to-bank-logs', - ], + // [ + // 'title' => '可提账户', + // 'icon'=>'', + // 'uri' => 'wallet-logs', + // ], + // [ + // 'title' => '余额账户', + // 'icon' => '', + // 'uri' => 'balance-logs', + // ], + // [ + // 'title' => '积分账户', + // 'icon' => '', + // 'uri' => 'points-logs', + // ], + // [ + // 'title' =>'提现审核', + // 'icon' => '', + // 'uri' =>'wallet-to-bank-logs', + // ], [ 'title' => '售后打款', 'icon' => '', 'uri' =>'finance-after-sales?state=5', ], + ['title' => '提成管理', 'icon' => '', 'uri' => 'profit'] ], ], [ @@ -300,7 +302,6 @@ class AdminMenuSeeder extends Seeder 'icon' => '', 'uri' =>'auth/menus', ], - ['title' => '代理等级', 'icon' => '', 'uri' => 'vips'], [ 'title' =>'配置管理', 'icon' => '', @@ -317,6 +318,7 @@ class AdminMenuSeeder extends Seeder } catch (Throwable $th) { DB::rollBack(); report($th); + dump($th->getMessage()); } } diff --git a/database/seeders/AdminPermissionSeeder.php b/database/seeders/AdminPermissionSeeder.php index 7c8ec78a..d673da93 100644 --- a/database/seeders/AdminPermissionSeeder.php +++ b/database/seeders/AdminPermissionSeeder.php @@ -309,6 +309,17 @@ class AdminPermissionSeeder extends Seeder 'store' => [ 'name' => '店铺管理', 'curd' => ['index', 'create', 'store', 'edit', 'update', 'destroy'], + ], + 'vip' => [ + 'name' => '代理等级管理', + 'curd' => ['index', 'create', 'store', 'edit', 'update', 'destroy'], + ], + 'profit' => [ + 'name' => '提成管理', + 'curd' => ['index', 'create', 'store', 'edit', 'update', 'destroy'], + 'children' => [ + 'pay' => ['name' => '修改支付状态'] + ] ] ]; // try { diff --git a/database/seeders/AdminUserSeeder.php b/database/seeders/AdminUserSeeder.php index 7c418972..0169c324 100644 --- a/database/seeders/AdminUserSeeder.php +++ b/database/seeders/AdminUserSeeder.php @@ -23,7 +23,7 @@ class AdminUserSeeder extends Seeder $user = $userModel::create([ 'username' => 'admin', - 'password' => 'admin', + 'password' => bcrypt('admin'), 'name' => '管理员', ]); diff --git a/database/seeders/ShippingSeeder.php b/database/seeders/ShippingSeeder.php index 0408d8d7..980795dd 100644 --- a/database/seeders/ShippingSeeder.php +++ b/database/seeders/ShippingSeeder.php @@ -18,11 +18,13 @@ class ShippingSeeder extends Seeder 'name' => '自提' ]); - ShippingRule::create([ + \DB::table('shipping_rules')->insert([ 'template_id' => $template->id, 'type' => 1, - 'info' => json_encode(["threshold" => "100"]), + 'info' => json_encode(["threshold" => "0"]), 'zones' => json_encode(Zone::where('type', Zone::TYPE_AREA)->pluck('id')), + 'created_at' => now(), + 'updated_at' => now() ]); } } diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index bd5b0dc5..96ea80c1 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -23,7 +23,11 @@ class UserSeeder extends Seeder DB::table('user_vips')->truncate(); DB::table('socialite_users')->truncate(); DB::table('personal_access_tokens')->truncate(); + DB::table('wallets')->truncate(); + DB::table('wallet_logs')->truncate(); + DB::table('wallet_to_bank_logs')->truncate(); + DB::table('balances')->truncate(); DB::table('users')->truncate(); $this->faker = $this->withFaker(); diff --git a/resources/lang/zh_CN/order-profit.php b/resources/lang/zh_CN/order-profit.php index fca28077..b11708b4 100644 --- a/resources/lang/zh_CN/order-profit.php +++ b/resources/lang/zh_CN/order-profit.php @@ -23,7 +23,7 @@ return [ 'remarks' => '备注', 'paid_at' => '付款时间', 'pay_way' => '支付方式', - 'pay_no' => '订单号', + 'pay_no' => '流水号', ], 'options' => [ ], diff --git a/resources/lang/zh_CN/vip.php b/resources/lang/zh_CN/vip.php index e92e4df2..28b4bcce 100644 --- a/resources/lang/zh_CN/vip.php +++ b/resources/lang/zh_CN/vip.php @@ -8,11 +8,12 @@ return [ 'fields' => [ 'name' => '等级名称', 'growth_value' => '升级', - 'sort' => '排序', - 'ratio' => '比例' + 'sort' => '等级', + 'ratio' => '比例', + 'slug' => '类别' ], 'options' => [ 'deny' => '删除失败', - 'deny_message'=>'当前会员等级下会员人数大于0', + 'deny_message'=> '该等级下还有用户, 无法删除', ], ];