From 45e9f2810dfe1e268aec19f791fe9b5501faf8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E6=A1=83?= <1098598843@qq.com> Date: Sat, 8 Apr 2023 17:47:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/Api.php | 22 ++ app/admin/controller/StoreProduct.php | 79 ++++- app/admin/view/store_product/carlist.html | 389 +++++++++++++++++++++ app/admin/view/store_product/datalist.html | 17 +- app/admin/view/store_product/index.html | 65 +++- app/admin/view/store_product/order.html | 135 ++++++- app/admin/view/store_product/tixian.html | 3 +- 7 files changed, 672 insertions(+), 38 deletions(-) create mode 100644 app/admin/view/store_product/carlist.html diff --git a/app/admin/controller/Api.php b/app/admin/controller/Api.php index 15299a7..68e7b0b 100644 --- a/app/admin/controller/Api.php +++ b/app/admin/controller/Api.php @@ -23,9 +23,31 @@ use app\admin\model\InformationUserAddress; use app\admin\model\ShopUser; use app\admin\model\SupplyBrokerage as SupplyBrokerageModel; use app\admin\model\StoreOrder; +use app\admin\model\StoreCategory as StoreCategoryModel; +use app\common\controller\FormatList; +use app\common\model\merchant\user\UserMerchant; class Api extends BaseController { + protected $category; + public function __construct(StoreCategoryModel $category) + { + $this->category = $category; + } + /** + * 平台商品分类 + * + */ + public function getAllList() + { + $where['mer_id'] = 0; + $where['is_show'] = 0; + $data = $this->category->getStoreCategoryList(0,1); + $list = FormatList::FormatCategory($data,'store_category_id', 'pid', 'cate_name','child', 'id', 'title'); + + return to_assign(0, '', $list); + } + //上传文件 public function upload() { diff --git a/app/admin/controller/StoreProduct.php b/app/admin/controller/StoreProduct.php index 91bf9e5..ccfe1b0 100644 --- a/app/admin/controller/StoreProduct.php +++ b/app/admin/controller/StoreProduct.php @@ -384,7 +384,7 @@ class StoreProduct extends BaseController 'key' => '95d195Dcf6ec66156dfeeb4E7435faef',//支付秘钥 'secret' => 'c02aa7ad9e4a5c423862e068b6cb4ad4', 'notify_url' => Request::instance()->domain().'/api/PayNotify/notify',//异步回调通知地址 -// 'notify_url' => 'http://t7kqa2.natappfree.cc/api/PayNotify/notify',//异步回调通知地址 +// 'notify_url' => 'http://an8r22.natappfree.cc/api/PayNotify/notify',//异步回调通知地址 ]; // 这个就是 easywechat 封装的了, 一行代码搞定, 照着写就行了 @@ -423,6 +423,7 @@ class StoreProduct extends BaseController 'number' => $number, 'admin_id' =>$admin_id, 'create_time'=>time(), + 'total_fee' =>$post_price ]; Db::table('cms_store_product_paylog')->strict(false)->field(true)->insert($param); add_log('buy', $id, $param); @@ -495,7 +496,7 @@ class StoreProduct extends BaseController if($type == 2){ $where[] = ['a.admin_id','=',$this->uid]; if (isset($param['keywords']) && !empty($param['keywords'])){ - $where[]=['b.store_name','like','%'.$param['keywords'].'%']; + $where[]=['a.order_sn','=',$param['keywords']]; } if (isset($param['store_cate']) && !empty($param['store_cate'])){ $where[]=['b.cate_id','=',$param['store_cate']]; @@ -527,7 +528,7 @@ class StoreProduct extends BaseController }else{ $where[] = ['admin_id','=',$this->uid]; if (isset($param['keywords']) && !empty($param['keywords'])){ - $where[]=['store_name','like','%'.$param['keywords'].'%']; + $where[]=['out_trade_no','=',$param['keywords']]; } // if (isset($param['store_cate']) && !empty($param['store_cate'])){ // $where[]=['b.cate_id','=',$param['store_cate']]; @@ -547,9 +548,20 @@ class StoreProduct extends BaseController } }) ->withAttr('paid_at',function ($value,$data){ - return ''; + return '无'; + }) + ->withAttr('order_sn',function ($value,$data){ + return $data['out_trade_no']; + }) + ->withAttr('total_fee',function ($value,$data){ + return bcdiv($data['total_fee'],'100',2); + }) + ->withAttr('status',function ($value,$data){ + return 0; }) ->where($where) + ->whereNull('result_code') + ->whereNull('return_code') ->order('id desc') ->paginate($rows, false, ['query' => $param]); @@ -757,7 +769,8 @@ class StoreProduct extends BaseController 'number' => $number, 'admin_id' =>$admin_id, 'cart_id' =>$id, - 'create_time'=>time() + 'create_time'=>time(), + 'total_fee' => $post_price ]; Db::table('cms_store_product_paylog')->strict(false)->field(true)->insert($param); @@ -803,6 +816,7 @@ class StoreProduct extends BaseController } +// 删除购物车 public function delcar(){ $param = get_params(); $where['cart_id'] = $param['cart_id']; @@ -937,6 +951,61 @@ class StoreProduct extends BaseController } } + // 预支付订单支付 + public function payorder(){ + $param = get_params(); + $id = $param['id']; + if($id){ + $paylog = Db::table('cms_store_product_paylog')->where('id',$id)->find(); + if(empty($paylog)){ + return to_assign(0, '数据未找到'); + } + }else{ + return to_assign(0, '请选择需要支付的订单'); + } + + Db::startTrans();//开启事务 + $app = $this->payment(); + $order_sn = $paylog['out_trade_no']; + $total_fee = env('APP_DEBUG') ? 1 : $paylog['total_fee']; + +// $total_fee = $post_price; + // 用 easywechat 封装的方法请求微信的统一下单接口 + $result = $app->order->unify([ + 'trade_type' => 'NATIVE', // 原生支付即扫码支付,商户根据微信支付协议格式生成的二维码,用户通过微信“扫一扫”扫描二维码后即进入付款确认界面,输入密码即完成支付。 + 'body' => '购物车商品-订单支付', // 这个就是会展示在用户手机上巨款界面的一句话, 随便写的 + 'out_trade_no' => $order_sn, + 'total_fee' => $total_fee, + 'spbill_create_ip' => request()->ip(), // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址 + ]); + if ($result['result_code'] == 'SUCCESS') { + // 如果请求成功, 微信会返回一个 'code_url' 用于生成二维码 + $code_url = $result['code_url']; + // 生成二维码 + // 引用二维码生成方法 + require '../vendor/phpqrcode/phpqrcode.php'; + + $errorCorrectionLevel = 'L'; //容错级别 + $matrixPointSize = 5; //生成图片大小 + //生成二维码图片 + // 判断是否有这个文件夹 没有的话就创建一个 + if(!is_dir("static/qrcode")){ + // 创建文件加 + mkdir("static/qrcode"); + } + //设置二维码文件名 + $filename = 'static/qrcode/'.time().rand(10000,9999999).'.png'; + //生成二维码 + \QRcode::png($code_url,$filename , $errorCorrectionLevel, $matrixPointSize, 2); + // 订单编号, 用于在当前页面向微信服务器发起订单状态查询请求 + $data['order_sn'] = $order_sn; + $data['html'] = Request::instance()->domain().'/'.$filename; + + Db::commit(); + return to_assign(200,'操作成功',$data); + } + return to_assign(0,'操作失败'); + } diff --git a/app/admin/view/store_product/carlist.html b/app/admin/view/store_product/carlist.html new file mode 100644 index 0000000..365a021 --- /dev/null +++ b/app/admin/view/store_product/carlist.html @@ -0,0 +1,389 @@ +{extend name="common/base"/} + +{block name="body"} + +
+
+
+ + +
+
+ +
+ + +
+
+
+
+ +
+ +
+ +
+ +
+
+
+ + + + + + + + +{/block} + + +{block name="script"} + +{/block} + \ No newline at end of file diff --git a/app/admin/view/store_product/datalist.html b/app/admin/view/store_product/datalist.html index 23bc7a7..e255235 100644 --- a/app/admin/view/store_product/datalist.html +++ b/app/admin/view/store_product/datalist.html @@ -83,6 +83,11 @@ title: '编号', align: 'center', width: 80 + },{ + field: 'shangjia', + title: '商家', + align: 'center', + width: 100 },{ field: 'image', title: '商品图片', @@ -99,6 +104,11 @@ title: '商品简介', align: 'center', width: 100 + },{ + field: 'stock', + title: '总库存', + align: 'center', + width: 100 },{ field: 'keyword', title: '关键字', @@ -134,11 +144,6 @@ title: '原价', align: 'center', width: 100 - },{ - field: 'stock', - title: '总库存', - align: 'center', - width: 100 }, { fixed: 'right', field: 'right', @@ -189,7 +194,7 @@ //商户商品分类菜单 $.ajax({ - url: '/admin/product.StoreCategory/getAllList', + url: '/admin/api/getAllList', method: "get", data: {}, success: function(res) { diff --git a/app/admin/view/store_product/index.html b/app/admin/view/store_product/index.html index 8b3161a..cf5b7e5 100644 --- a/app/admin/view/store_product/index.html +++ b/app/admin/view/store_product/index.html @@ -51,7 +51,7 @@ {/block} @@ -78,6 +78,11 @@ title: '编号', align: 'center', width: 80 + },{ + field: 'shangjia', + title: '商家', + align: 'center', + width: 100 },{ field: 'image', title: '商品图片', @@ -94,6 +99,11 @@ title: '商品简介', align: 'center', width: 100 + },{ + field: 'stock', + title: '总库存', + align: 'center', + width: 100 },{ field: 'keyword', title: '关键字', @@ -134,11 +144,6 @@ title: '原价', align: 'center', width: 100 - },{ - field: 'stock', - title: '总库存', - align: 'center', - width: 100 }, { fixed: 'right', field: 'right', @@ -177,6 +182,52 @@ else if (obj.event === 'edit') { tool.side('/admin/store_product/edit?product_id='+obj.data.product_id); } + else if (obj.event === 'joincar') { + layer.open({ + type: 1, + area: ["400px", "200px"], + title: "加入购物车", + content: "", + btn: ['确定', '关闭'], + yes: function (index, layero) { + //ajax。必填参数,'options':请求参数,对象,'callback':成功回调函数 + // 单击之后提交按钮不可选,防止重复提交 + var DISABLED = 'layui-btn-disabled'; + // 增加样式 + $('.layui-layer-btn0').addClass(DISABLED); + // 增加属性 + $('.layui-layer-btn0').attr('disabled', 'disabled'); + let options = { + url: '/admin/store_product/joincar', + type: 'get', + data: { + product_id: obj.data.product_id, + cart_num:$('#carnum').val(), + is_new:1, + } + }; + + let callback = function(res) { + if (res.code == 200) { + layer.msg('加入成功',{time:2000,icon:6}); + // 关闭所有层 + setTimeout(function () { + layer.closeAll(); + }, 2000); + }else{ + layer.msg(res.msg,{time:2000,icon:2}); + $('.layui-layer-btn0').removeClass(DISABLED); + $('.layui-layer-btn0').removeAttr('disabled'); + } + } + tool.ajax(options, callback); + }, + cancel: function (layer_window) { + // 关闭弹出框页面 + layer.close(layer_window); + } + }); + } else if (obj.event === 'del') { layer.confirm('确定要删除该记录吗?', { icon: 3, @@ -221,7 +272,7 @@ //商户商品分类菜单 $.ajax({ - url: '/admin/product.StoreCategory/getAllList', + url: '/admin/api/getAllList', method: "get", data: {}, success: function(res) { diff --git a/app/admin/view/store_product/order.html b/app/admin/view/store_product/order.html index 10f53ed..86405e6 100644 --- a/app/admin/view/store_product/order.html +++ b/app/admin/view/store_product/order.html @@ -23,25 +23,34 @@ }
+ +
+ +
+
+
-
-
- -
- - -
-
-
-
+ + + + + + + + + +
- +
@@ -51,7 +60,9 @@ {/block} @@ -99,14 +110,22 @@ align: 'center', width: 300, templet: function (d) { - var html = '
'+d.store_name+'
'; - return html; + var html = '
'; + var img = ''; + var prod = d.product; + for (i = 0; i < prod.length; i++) { + img = ' '+prod[i].store_name + ' ' +img; + } + var html2 = '
'; + // var html = '
'+d[k].store_name+'
'; + var ret = html + img + html2; + return ret; } },{ field: 'paid_at', title: '支付完成时间', align: 'center', - width: 150 + width: 150, },{ field: 'status', title: '状态', @@ -119,6 +138,13 @@ } return html; } + }, { + fixed: 'right', + field: 'right', + title: '操作', + toolbar: '#barDemo', + width: 136, + align: 'center' } ] ] @@ -135,8 +161,80 @@ //监听表格行工具事件 table.on('tool(store_product)', function(obj) { var data = obj.data; - if (obj.event === 'read') { - tool.side('/admin/store_product/buy?product_id='+obj.data.product_id); + if (obj.event === 'topay') { + // 单击之后提交按钮不可选,防止重复提交 + var DISABLED = 'layui-btn-disabled'; + // 增加样式 + $('.preservation').addClass(DISABLED); + // 增加属性 + $('.preservation').attr('disabled', 'disabled'); + $.ajax({ + url : "/admin/store_product/payorder?id="+data.id, //请求的url地址 + dataType : "json", //返回格式为json + async : true,//请求是否异步,默认为异步,这也是ajax重要特性 + type : "POST", //请求方式 + success : function(data) { + var url = data.data.html; + /** 弹出二维码 **/ + layer.open({ + //type:1 表示页面层 + type: 1, + title: '扫码支付', + //是否点击遮罩关闭 + shadeClose: false, + //样式类名,可以自定义弹窗样式 + //弹层外区域 + shade: 0.3, + maxmin: false, //开启最大化最小化按钮 + //宽高 + area: ['250px','250px'], + //内容 + content: "", + }); + + /** 设置定时器, 即一弹出二维码就开始不断请求查看支付状态, 直到收到支付成功的返回, 再终止定时器 **/ + var timer = setInterval(function () { + /** 在这里请求微信支付状态的接口 **/ + //ajax。必填参数,'options':请求参数,对象,'callback':成功回调函数 + + let options = { + url: '/admin/store_product/paid', + type: 'get', + data: { + out_trade_no: data.data.order_sn, + } + }; + + let callback = function(res) { + if (res.code == 200) { + + layer.msg('支付成功',{time:2000,icon:6}); + + /** 如果支付成功, 就取消定时器, 并重新加载页面 */ + window.clearInterval(timer); + // 关闭所有层 + setTimeout(function () { + layer.closeAll(); + }, 2000); + // tool.sideClose(2000); + } + } + tool.ajax(options, callback); + + }, 3000); + }, + complete : function() { + //请求完成的处理 + }, + error : function() { + //请求出错处理 + layer.alert("系统异常"); + } + }); + // 恢复按钮 + var DISABLED = 'layui-btn-disabled'; + $('.preservation').removeClass(DISABLED); + $('.preservation').removeAttr('disabled'); } else if (obj.event === 'edit') { tool.side('/admin/store_product/edit?product_id='+obj.data.product_id); @@ -185,7 +283,7 @@ //商户商品分类菜单 $.ajax({ - url: '/admin/product.StoreCategory/getAllList', + url: '/admin/api/getAllList', method: "get", data: {}, success: function(res) { @@ -220,7 +318,6 @@ - //监听搜索提交 form.on('submit(searchform)', function(data) { layui.pageTable.reload({ diff --git a/app/admin/view/store_product/tixian.html b/app/admin/view/store_product/tixian.html index b6be53e..61a1968 100644 --- a/app/admin/view/store_product/tixian.html +++ b/app/admin/view/store_product/tixian.html @@ -155,6 +155,7 @@ field: 'right', title: '操作', toolbar: '#barDemo', + width: 136, align: 'center' } ] @@ -288,7 +289,7 @@ //商户商品分类菜单 $.ajax({ - url: '/admin/product.StoreCategory/getAllList', + url: '/admin/api/getAllList', method: "get", data: {}, success: function(res) {