作者 何书鹏

会员套餐

<?php
namespace app\admin\controller\package;
use app\common\controller\Backend;
/**
* 会员套餐订单管理
*
* @icon fa fa-circle-o
*/
class Order extends Backend
{
/**
* Order模型对象
* @var \app\admin\model\package\Order
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\package\Order;
$this->view->assign("statusList", $this->model->getStatusList());
$this->view->assign("payTypeList", $this->model->getPayTypeList());
}
public function import()
{
parent::import();
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
/**
* 查看
*/
public function index()
{
//当前是否为关联查询
$this->relationSearch = true;
//设置过滤方法
$this->request->filter(['strip_tags', 'trim']);
if ($this->request->isAjax()) {
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$list = $this->model
->with(['user'])
->where($where)
->order($sort, $order)
->paginate($limit);
foreach ($list as $row) {
$row->visible(['id','order_sn','user_id','package_id','package_name','package_price','month','pay_fee','status','paytime','remark','createtime']);
$row->visible(['user']);
$row->getRelation('user')->visible(['nickname']);
}
$result = array("total" => $list->total(), "rows" => $list->items());
return json($result);
}
return $this->view->fetch();
}
}
... ...
<?php
namespace app\admin\controller\package;
use app\common\controller\Backend;
/**
* 会员套餐管理
*
* @icon fa fa-circle-o
*/
class Package extends Backend
{
/**
* Package模型对象
* @var \app\admin\model\package\Package
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\package\Package;
}
public function import()
{
parent::import();
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
/**
* 查看
*/
public function index()
{
//当前是否为关联查询
$this->relationSearch = false;
//设置过滤方法
$this->request->filter(['strip_tags', 'trim']);
if ($this->request->isAjax()) {
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$list = $this->model
->where($where)
->order($sort, $order)
->paginate($limit);
foreach ($list as $row) {
$row->visible(['id','package_name','package_price','month','weigh']);
}
$result = array("total" => $list->total(), "rows" => $list->items());
return json($result);
}
return $this->view->fetch();
}
}
... ...
<?php
return [
'Id' => 'ID',
'Order_sn' => '订单号',
'User_id' => '用户',
'Package_id' => '套餐ID',
'Package_name' => '套餐名称',
'Package_price' => '套餐价格',
'Month' => '会员持续月数',
'Pay_fee' => '实际支付金额',
'Status' => '订单状态',
'Status -0' => '未支付',
'Status 1' => '已支付',
'Paytime' => '支付时间',
'Pay_type' => '支付方式',
'Pay_type wechat' => '微信支付',
'Pay_type alipay' => '支付宝',
'Pay_type wallet' => '钱包支付',
'Pay_type score' => '积分支付',
'Payment_json' => '交易原始数据',
'Transaction_id' => '交易单号',
'Remark' => '备注',
'Createtime' => '创建时间',
'User.nickname' => '下单用户'
];
... ...
<?php
return [
'Id' => 'ID',
'Package_name' => '套餐名称',
'Package_price' => '套餐价格',
'Month' => '会员持续月数',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'Weigh' => '权重'
];
... ...
<?php
namespace app\admin\model\package;
use think\Model;
class Order extends Model
{
// 表名
protected $name = 'package_order';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = false;
protected $deleteTime = false;
// 追加属性
protected $append = [
'status_text',
'paytime_text',
'pay_type_text'
];
public function getStatusList()
{
return ['-0' => __('Status -0'), '1' => __('Status 1')];
}
public function getPayTypeList()
{
return ['wechat' => __('Pay_type wechat'), 'alipay' => __('Pay_type alipay'), 'wallet' => __('Pay_type wallet'), 'score' => __('Pay_type score')];
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getPaytimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['paytime']) ? $data['paytime'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getPayTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['pay_type']) ? $data['pay_type'] : '');
$list = $this->getPayTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
protected function setPaytimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
public function user()
{
return $this->belongsTo('app\admin\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
}
... ...
<?php
namespace app\admin\model\package;
use think\Model;
class Package extends Model
{
// 表名
protected $name = 'package';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = false;
// 追加属性
protected $append = [
];
protected static function init()
{
self::afterInsert(function ($row) {
$pk = $row->getPk();
$row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]);
});
}
}
... ...
<?php
namespace app\admin\validate\package;
use think\Validate;
class Order extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\package;
use think\Validate;
class Package extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Order_sn')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-order_sn" data-rule="required" class="form-control" name="row[order_sn]" type="text">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-user_id" data-rule="required" data-source="user/user/index" data-field="nickname" class="form-control selectpage" name="row[user_id]" type="text" value="">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_id" data-rule="required" data-source="package/index" class="form-control selectpage" name="row[package_id]" type="text" value="">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_name" class="form-control" name="row[package_name]" type="text" value="">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_price')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_price" data-rule="required" class="form-control" step="0.01" name="row[package_price]" type="number" value="0.00">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Month')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-month" data-rule="required" class="form-control" name="row[month]" type="number" value="0">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Pay_fee')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-pay_fee" data-rule="required" class="form-control" step="0.01" name="row[pay_fee]" type="number" value="0.00">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="radio">
{foreach name="statusList" item="vo"}
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="-0"}checked{/in} /> {$vo}</label>
{/foreach}
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Paytime')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-paytime" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[paytime]" type="text" value="{:date('Y-m-d H:i:s')}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Pay_type')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-pay_type" class="form-control selectpicker" name="row[pay_type]">
{foreach name="payTypeList" item="vo"}
<option value="{$key}" {in name="key" value=""}selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Payment_json')}:</label>
<div class="col-xs-12 col-sm-8">
<dl class="fieldlist" data-name="row[payment_json]">
<dd>
<ins>{:__('Key')}</ins>
<ins>{:__('Value')}</ins>
</dd>
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[payment_json]" class="form-control hide" cols="30" rows="5"></textarea>
</dl>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Transaction_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-transaction_id" data-rule="required" data-source="transaction/index" class="form-control selectpage" name="row[transaction_id]" type="text" value="">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-remark" class="form-control" name="row[remark]" type="text">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
... ...
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Order_sn')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-order_sn" data-rule="required" class="form-control" name="row[order_sn]" type="text" value="{$row.order_sn|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-user_id" data-rule="required" data-source="user/user/index" data-field="nickname" class="form-control selectpage" name="row[user_id]" type="text" value="{$row.user_id|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_id" data-rule="required" data-source="package/index" class="form-control selectpage" name="row[package_id]" type="text" value="{$row.package_id|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_name" class="form-control" name="row[package_name]" type="text" value="{$row.package_name|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_price')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_price" data-rule="required" class="form-control" step="0.01" name="row[package_price]" type="number" value="{$row.package_price|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Month')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-month" data-rule="required" class="form-control" name="row[month]" type="number" value="{$row.month|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Pay_fee')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-pay_fee" data-rule="required" class="form-control" step="0.01" name="row[pay_fee]" type="number" value="{$row.pay_fee|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="radio">
{foreach name="statusList" item="vo"}
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="$row.status"}checked{/in} /> {$vo}</label>
{/foreach}
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Paytime')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-paytime" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[paytime]" type="text" value="{:$row.paytime?datetime($row.paytime):''}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Pay_type')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-pay_type" class="form-control selectpicker" name="row[pay_type]">
{foreach name="payTypeList" item="vo"}
<option value="{$key}" {in name="key" value="$row.pay_type"}selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Payment_json')}:</label>
<div class="col-xs-12 col-sm-8">
<dl class="fieldlist" data-name="row[payment_json]">
<dd>
<ins>{:__('Key')}</ins>
<ins>{:__('Value')}</ins>
</dd>
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[payment_json]" class="form-control hide" cols="30" rows="5">{$row.payment_json|htmlentities}</textarea>
</dl>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Transaction_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-transaction_id" data-rule="required" data-source="transaction/index" class="form-control selectpage" name="row[transaction_id]" type="text" value="{$row.transaction_id|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-remark" class="form-control" name="row[remark]" type="text" value="{$row.remark|htmlentities}">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
... ...
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null,FALSE)}
<ul class="nav nav-tabs" data-field="status">
<li class="{:$Think.get.status === null ? 'active' : ''}"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
{foreach name="statusList" item="vo"}
<li class="{:$Think.get.status === (string)$key ? 'active' : ''}"><a href="#t-{$key}" data-value="{$key}" data-toggle="tab">{$vo}</a></li>
{/foreach}
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('package/order/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('package/order/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('package/order/edit')}"
data-operate-del="{:$auth->check('package/order/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
... ...
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_name" class="form-control" name="row[package_name]" type="text" value="">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_price')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_price" data-rule="required" class="form-control" step="0.01" name="row[package_price]" type="number" value="0.00">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Month')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-month" data-rule="required" class="form-control" name="row[month]" type="number" value="0">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-weigh" data-rule="required" class="form-control" name="row[weigh]" type="number" value="0">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
... ...
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_name" class="form-control" name="row[package_name]" type="text" value="{$row.package_name|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Package_price')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-package_price" data-rule="required" class="form-control" step="0.01" name="row[package_price]" type="number" value="{$row.package_price|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Month')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-month" data-rule="required" class="form-control" name="row[month]" type="number" value="{$row.month|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-weigh" data-rule="required" class="form-control" name="row[weigh]" type="number" value="{$row.weigh|htmlentities}">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
... ...
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('package/package/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('package/package/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('package/package/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('package/package/edit')}"
data-operate-del="{:$auth->check('package/package/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
... ...
<?php
namespace app\api\controller;
use addons\shopro\exception\Exception;
use app\api\model\PackageOrder as PackageOrderModel;
use addons\shopro\model\User;
use think\Db;
use think\Log;
/**
* 会员套餐订单接口
*/
class PackageOrder extends Base
{
protected $noNeedLogin = ['prepay', 'notifyx'];
protected $noNeedRight = ['*'];
/**
* @ApiWeigh (99)
* @ApiTitle (创建订单)
* @ApiSummary (创建订单)
* @ApiMethod (POST)
*
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
* @ApiParams (name=package_id, type=inter, required=true, description="会员套餐ID")
*
* @ApiReturn({
"code": 1,
"msg": "订单添加成功",
"time": "1608639849",
"data": {
"id": 3, //订单ID
"order_sn": "202008241079705643001000", //订单号
"user_id": 1, //用户ID
"package_id": 1, //会员套餐ID
"package_name": "季度会员", //会员套餐名称
"package_price": "150.00", //会员套餐价格
"month": 3, //会员持续月数
"pay_fee": "150.00", //支付金额
"status": 0,
"paytime": null,
"pay_type": null,
"payment_json": null,
"transaction_id": null,
"remark": null,
"createtime": 1608639850
}
})
*/
public function createOrder()
{
$params = $this->request->post();
$order = PackageOrderModel::createOrder($params);
$this->success('订单添加成功', $order);
}
/**
* @ApiWeigh (97)
* @ApiTitle (拉起支付)
* @ApiSummary (拉起支付)
* @ApiMethod (POST)
*
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
* @ApiParams (name=order_sn, type=string, required=true, description="订单号")
*
* @ApiReturn()
*/
public function prepay()
{
$order_sn = $this->request->post('order_sn');
$payment = $this->request->post('payment','wechat');
$platform = request()->header('platform','wxMiniProgram');
$order = PackageOrderModel::where('status',0)->where('order_sn', $order_sn)->find();
if (!$order) {
throw new Exception("订单不存在");
}
if (!$payment || !in_array($payment, ['wechat', 'alipay', 'wallet'])) {
throw new Exception("支付类型不能为空");
}
$order_data = [
'out_trade_no' => $order->order_sn,
'total_fee' => $order->pay_fee,
'body' => '商城订单支付',
];
// openid
$oauth = \addons\shopro\model\UserOauth::where([
'user_id' => $order->user_id,
'provider' => 'Wechat',
'platform' => 'wxMiniProgram'
])->find();
$order_data['openid'] = $oauth ? $oauth->openid : '';
if (empty($order_data['openid'])) {
// 缺少 openid
return $this->success('缺少 openid', 'no_openid');
}
$notify_url = $this->request->root(true) . '/api/package_order/notifyx/payment/' . $payment . '/platform/' . $platform;
$pay = new \addons\shopro\library\PayService($payment, $platform, $notify_url);
$result = $pay->create($order_data);
$result = $result->getContent();
return $this->success('获取预付款成功', [
'pay_data' => $result,
'pay_action' => $pay->method,
]);
}
/**
* @ApiInternal
* 支付成功回调
*/
public function notifyx()
{
Log::write('notifyx-comein:');
$payment = $this->request->param('payment');
$platform = $this->request->param('platform');
$pay = new \addons\shopro\library\PayService($payment, $platform);
$result = $pay->notify(function ($data, $pay) use ($payment, $platform) {
Log::write('notifyx-result:'. json_encode($data));
// { // 微信回调参数
// "appid":"wx39cd0799d4567dd0",
// "bank_type":"OTHERS",
// "cash_fee":"1",
// "fee_type":"CNY",
// "is_subscribe":"N",
// "mch_id":"1481069012",
// "nonce_str":"dPpcZ6AzCDU8daNC",
// "openid":"oD9ko4x7QMDQPZEuN8V5jtZjie3g",
// "out_trade_no":"202010240834057843002700",
// "result_code":"SUCCESS",
// "return_code":"SUCCESS",
// "sign":"3103B6D06F13D2B3959C5B3F7F1FD61C",
// "time_end":"20200407102424",
// "total_fee":"1",
// "trade_type":"JSAPI",
// "transaction_id":"4200000479202004070804485027"
// }
// { // 支付宝支付成功回调参数
// "gmt_create":"2020-04-10 19:15:00",
// "charset":"utf-8",
// "seller_email":"xptech@qq.com",
// "subject":"\u5546\u57ce\u8ba2\u5355\u652f\u4ed8",
// "sign":"AOiYZ1a2mEMOuIbHFCi6V6A0LJ97UMiHsCWgNdSU9dlzKFl15Ts8b0mL\/tN+Hhskl+94S3OUiNTBD3dD0Kv923SqaTWxNdj533PCdo2GDKsZIZgKbavnOvaccSKUdmQRE9KtmePPq9V9lFzEQvdUkKq1M8KAWO5K9LTy2iT2y5CUynpiu\/04GVzsTL9PqY+LDwqj6K+w7MgceWm1BWaFWg27AXIRw7wvsFckr3k9GGajgE2fufhoCYGYtGFbhGOp6ExtqS5RXBuPODOyRhBLpD8mwpOX38Oy0X+R4YQIrOi02dhqwPpvw79YjnvgXY3qZEQ66EdUsrT7EBdcPHK0Gw==",
// "buyer_id":"2088902485164146",
// "invoice_amount":"0.01",
// "notify_id":"2020041000222191501064141414240102",
// "fund_bill_list":"[{\"amount\":\"0.01\",\"fundChannel\":\"PCREDIT\"}]",
// "notify_type":"trade_status_sync",
// "trade_status":"TRADE_SUCCESS",
// "receipt_amount":"0.01",
// "buyer_pay_amount":"0.01",
// "app_id":"2021001114666742",
// "sign_type":"RSA2",
// "seller_id":"2088721922277739",
// "gmt_payment":"2020-04-10 19:15:00",
// "notify_time":"2020-04-10 19:15:01",
// "version":"1.0",
// "out_trade_no":"202007144778322770017000",
// "total_amount":"0.01",
// "trade_no":"2020041022001464141443020240",
// "auth_app_id":"2021001114666742",
// "buyer_logon_id":"157***@163.com",
// "point_amount":"0.00"
// }
// { // 支付宝退款成功(交易关闭)回调参数
// "gmt_create": "2020-08-15 14:48:32",
// "charset": "utf-8",
// "seller_email": "xptech@qq.com",
// "gmt_payment": "2020-08-15 14:48:32",
// "notify_time": "2020-08-15 16:11:45",
// "subject": "商城订单支付",
// "gmt_refund": "2020-08-15 16:11:45.140",
// "sign": "b6ArkgzLIRteRL9FMGC6i\/jf6VwFYQbaGDGRx002W+pdmN5q9+O4edZ3ALF74fYaijSl9ksNr0dKdvanu3uYxBTcd\/GIS4N1CWzmCOv6pzgx5rO\/YvGoHLM3Yop0GKKuMxmnNsZ6jhYKEY7SYD3Y0L6PU9ZMdHV7yIiVj+zZmbKzUgK9MPDCEXs+nzpNAiSM8GTqYRSUvKobAK68hswG2k1QIcqr5z+ZmVYa\/nHHkoC9qXt5zwyGi4P+2eOsr6V2PjA3x8qqe7TN5aI1DeoZD5KqHPYYaYF17J2q6YPlgl3WUl1RhE7H86bivB1fIuYEv\/3+JR74WN\/o7krGw1RPHg==",
// "out_biz_no": "R202004114414846255015300",
// "buyer_id": "2088902485164146",
// "version": "1.0",
// "notify_id": "2020081500222161145064141453349793",
// "notify_type": "trade_status_sync",
// "out_trade_no": "202002460317545607015300",
// "total_amount": "0.01",
// "trade_status": "TRADE_CLOSED",
// "refund_fee": "0.01",
// "trade_no": "2020081522001464141438570535",
// "auth_app_id": "2021001114666742",
// "buyer_logon_id": "157***@163.com",
// "gmt_close": "2020-08-15 16:11:45",
// "app_id": "2021001114666742",
// "sign_type": "RSA2",
// "seller_id": "2088721922277739"
// }
try {
$out_trade_no = $data['out_trade_no'];
// 判断支付宝微信是否是支付成功状态,如果不是,直接返回响应
if ($payment == 'alipay' && $data['trade_status'] != 'TRADE_SUCCESS') {
// 不是交易成功的通知,直接返回成功
return $pay->success()->send();
}
if ($payment == 'wechat' && ($data['result_code'] != 'SUCCESS' || $data['return_code'] != 'SUCCESS')) {
// 微信交易未成功,返回 false,让微信再次通知
return false;
}
// 支付成功流程
$pay_fee = $payment == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
//你可以在此编写订单逻辑
$order = PackageOrderModel::where('order_sn', $out_trade_no)->find();
if (!$order || $order->status > 0) {
// 订单不存在,或者订单已支付
return $pay->success()->send();
}
// 本次购买会员的初始时间
$user = User::get($order['user_id']);
$starttime = $user['vip_time'] > time() ? $user['vip_time'] : time();
$endtime = strtotime('+'.$order['month'].'month',$starttime);
// 修改订单信息
$order->status = 2;
$order->paytime = time();
$order->transaction_id = $payment == 'alipay' ? $data['trade_no'] : $data['transaction_id'];
$order->payment_json = json_encode($data->all());
$order->pay_type = $payment;
$order->pay_fee = $pay_fee;
$order->starttime = $starttime;
$order->endtime = $endtime;
$order->save();
return $pay->success()->send();
} catch (\Exception $e) {
Log::write('notifyx-error:' . json_encode($e->getMessage()));
}
});
return $result;
}
}
... ...
... ... @@ -56,14 +56,16 @@ class User extends Base
"coupons_num": 0, //优惠券数量
"is_store": 1,
"store_id": 1,
"avatar_full": "http://www.ant.topshuoshenme" //头像全路径
"avatar_full": "http://www.ant.topshuoshenme", //头像全路径
"is_vip": 1, //是否会员:0=否,1=是
"vip_time": "2021/08/02", //会员到期时间
}
})
*/
public function index()
{
$auth = \app\common\library\Auth::instance();
$auth->setAllowFields(['id', 'nickname', 'avatar', 'score', 'money','group_id']);
$auth->setAllowFields(['id', 'nickname', 'avatar', 'score', 'money','group_id','vip_time']);
$data = $auth->getUserinfo();
if (!isset($data['group'])) {
$data['group'] = \addons\shopro\model\UserGroup::get($data['group_id']);
... ... @@ -83,11 +85,45 @@ class User extends Base
}
// 头像全路径
$data['avatar_full'] = cdnurl($data['avatar'],true);
// 是否会员:0=否,1=是
$data['is_vip'] = $data['vip_time'] > time() ? 1 : 0;
$data['vip_time'] = date('Y/m/d',$data['vip_time']);
$this->success('用户信息', $data);
}
/**
* @ApiWeigh (99)
* @ApiWeigh (98)
* @ApiTitle (会员套餐)
* @ApiSummary (会员套餐)
* @ApiMethod (GET)
*
* @ApiReturn({
"code": 1,
"msg": "会员套餐",
"time": "1608621344",
"data": {
"list": [{ //会员套餐列表
"id": 1, //套餐ID
"package_name": "季度会员", //套餐名称
"package_price": "150.00", //套餐价格
"month": 3 //会员持续月数
}],
"description": "富文本内容" //会员权益
}
})
*/
public function package()
{
$list = Db::name('package')
->field('id,package_name,package_price,month')
->order('weigh desc')
->select();
$description = \addons\shopro\model\Richtext::get(5)['content'];
$this->success('会员套餐',compact('list','description'));
}
/**
* @ApiWeigh (98)
* @ApiTitle (会员登录)
* @ApiSummary (会员登录)
* @ApiMethod (POST)
... ...
<?php
namespace app\api\model;
use think\Model;
class Package extends Model
{
}
... ...
<?php
namespace app\api\model;
use think\Model;
use addons\shopro\exception\Exception;
use addons\shopro\model\User;
use app\admin\model\package\Package;
use think\Db;
class PackageOrder extends Model
{
// 获取订单号
public static function getSn($user_id)
{
$rand = $user_id < 9999 ? mt_rand(100000, 99999999) : mt_rand(100, 99999);
$order_sn = date('Yhis') . $rand;
$id = str_pad($user_id, (24 - strlen($order_sn)), '0', STR_PAD_BOTH);
return $order_sn . $id;
}
// 创建订单
public static function createOrder($params)
{
$user = User::info();
// 入参
extract($params);
$package = Package::get($package_id);
if (!$package) {
throw new Exception('会员套餐不存在');
}
// 订单备注
$have_order = self::where('user_id',$user->id)->where('status',1)->field('id')->find();
$remark = $have_order ? '续费('.$package['month'].'个月)' : '开通会员';
$orderData = [];
$orderData['order_sn'] = self::getSn($user->id);
$orderData['user_id'] = $user->id;
$orderData['package_id'] = $package_id;
$orderData['package_name'] = $package['package_name'];
$orderData['package_price'] = $package['package_price'];
$orderData['month'] = $package['month'];
$orderData['pay_fee'] = $package['package_price'];
$orderData['remark'] = $remark;
$order = new PackageOrder();
$order->allowField(true)->save($orderData);
// 重新获取订单
$order = self::where('id', $order['id'])->find();
return $order;
}
}
... ...
此 diff 太大无法显示。
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'package/order/index' + location.search,
add_url: 'package/order/add',
edit_url: 'package/order/edit',
del_url: 'package/order/del',
multi_url: 'package/order/multi',
import_url: 'package/order/import',
table: 'package_order',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
columns: [
[
{checkbox: true},
{field: 'id', title: __('Id')},
{field: 'order_sn', title: __('Order_sn'), operate: 'LIKE'},
{field: 'package_name', title: __('Package_name'), operate: 'LIKE'},
{field: 'package_price', title: __('Package_price'), operate:'BETWEEN'},
{field: 'month', title: __('Month')},
{field: 'pay_fee', title: __('Pay_fee'), operate:'BETWEEN'},
{field: 'status', title: __('Status'), searchList: {"-0":__('Status -0'),"1":__('Status 1')}, formatter: Table.api.formatter.status},
{field: 'paytime', title: __('Paytime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
{field: 'remark', title: __('Remark'), operate: 'LIKE'},
{field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
{field: 'user.nickname', title: __('User.nickname'), operate: 'LIKE'},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
},
add: function () {
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
}
};
return Controller;
});
\ No newline at end of file
... ...
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'package/package/index' + location.search,
add_url: 'package/package/add',
edit_url: 'package/package/edit',
del_url: 'package/package/del',
multi_url: 'package/package/multi',
import_url: 'package/package/import',
table: 'package',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'weigh',
columns: [
[
{checkbox: true},
{field: 'id', title: __('Id')},
{field: 'package_name', title: __('Package_name'), operate: 'LIKE'},
{field: 'package_price', title: __('Package_price'), operate:'BETWEEN'},
{field: 'month', title: __('Month')},
{field: 'weigh', title: __('Weigh'), operate: false},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
},
add: function () {
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
}
};
return Controller;
});
\ No newline at end of file
... ...