Browse Source

小程序分发

develop
李可松 4 years ago
parent
commit
1e79dec3dd
  1. 17
      MySQL_change.sql
  2. 53
      app/Admin/Controllers/AgentController.php
  3. 4
      app/Admin/Controllers/MiniProgramDraftController.php
  4. 1
      app/Admin/Controllers/MiniProgramListController.php
  5. 20
      app/Admin/Controllers/MiniProgramTemplateController.php
  6. 83
      app/Admin/Extensions/Grid/MiniProgramDelTemp.php
  7. 89
      app/Admin/Extensions/Grid/MiniProgramPull.php
  8. 160
      app/Admin/Extensions/Grid/MiniProgramReg.php
  9. 136
      app/Admin/Extensions/Grid/MiniProgramUpload.php
  10. 56
      app/Admin/Extensions/Grid/PullTemplateList.php
  11. 89
      app/Admin/Extensions/Grid/UploadMiniProgram.php
  12. 2
      app/Admin/Forms/Setting.php
  13. 53
      app/Admin/Repositories/MiniProgramDraft.php
  14. 2
      app/Admin/Repositories/MiniProgramTemplateList.php
  15. 6
      app/AdminAgent/Forms/AgentInfo.php
  16. 10
      app/AdminSettled/Controllers/AgentController.php
  17. 60
      app/Http/Controllers/Api/MiniProgramController.php
  18. 1
      app/Http/Controllers/Api/TestController.php
  19. 17
      app/Models/MiniProgramDraft.php
  20. 17
      app/Models/MiniProgramTemplate.php
  21. 11
      app/Models/MiniProgramTemplateList.php
  22. 1217
      composer.lock
  23. 3
      resources/lang/zh_CN/agent.php

17
MySQL_change.sql

@ -289,7 +289,7 @@ ALTER TABLE `agents`
CHANGE COLUMN `mchid` `mchid` VARCHAR(32) NULL COMMENT '微信支付mch_id' COLLATE 'utf8_general_ci' AFTER `appsecret`,
CHANGE COLUMN `mchkey` `mchkey` CHAR(32) NULL COMMENT '微信支付key' COLLATE 'utf8_general_ci' AFTER `mchid`;
CREATE TABLE `mini_program_template_lists` (
CREATE TABLE `mini_program_templates` (
`template_id` INT(10) NOT NULL,
`user_version` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '版本号' COLLATE 'utf8_general_ci',
`user_desc` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '描述' COLLATE 'utf8_general_ci',
@ -309,6 +309,7 @@ CREATE TABLE `mini_program_upload_logs` (
`agent_id` INT(10) NOT NULL COMMENT '代理商ID',
`appid` VARCHAR(50) NOT NULL COMMENT '代理商APPID' COLLATE 'utf8_general_ci',
`template_id` INT(10) NOT NULL COMMENT '小程序template_id',
`qrcode` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '小程序上传后获取到的二维码' COLLATE 'utf8_general_ci',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
INDEX `agent_id` (`agent_id`) USING BTREE
@ -316,3 +317,17 @@ CREATE TABLE `mini_program_upload_logs` (
COMMENT='注册小程序日志'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
# 9:29 2021/9/13
ALTER TABLE `agents`
ADD COLUMN `credit_codes` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '统一社会信用代码' AFTER `company_name`,
ADD COLUMN `legal_persona_name` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '法人姓名' AFTER `contact_phone`,
ADD COLUMN `legal_persona_wechat` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '法人微信号' AFTER `legal_persona_name`;
# 15:34 2021/9/13
ALTER TABLE `auth_event`
ADD COLUMN `appid` VARCHAR(50) NULL DEFAULT NULL AFTER `id`;
# 17:02 2021/9/13
ALTER TABLE `user_money_logs`
CHANGE COLUMN `money` `money` DECIMAL(20,2) NOT NULL COMMENT '变动金额,正数=平台收入,负数=平台支出' AFTER `agent_id`;

53
app/Admin/Controllers/AgentController.php

@ -3,7 +3,8 @@
namespace App\Admin\Controllers;
use App\Admin\Extensions\Grid\AuditAgent;
use App\Admin\Extensions\Grid\UploadMiniProgram;
use App\Admin\Extensions\Grid\MiniProgramReg;
use App\Admin\Extensions\Grid\MiniProgramUpload;
use App\Admin\Repositories\Agent;
use App\Common\AgentType;
use App\Common\UserStatus;
@ -46,6 +47,14 @@ class AgentController extends AdminController
$grid->column('created_at');
$grid->column('status', '状态')
->help('新用户入驻时,请先注册小程序。待企业法人认证通过之后,再上传小程序即可')
->using(UserStatus::array())
->dot([
UserStatus::NORMAL => 'success',
UserStatus::UNAUDITED => '',
UserStatus::REFUSE => 'danger',
UserStatus::DISABLED => 'warning',
], 'primary')
->if(fn() => $this->status == UserStatus::UNAUDITED)
->display('')
->then(function ($column) {
@ -55,16 +64,13 @@ class AgentController extends AdminController
->if(fn() => $this->status == UserStatus::NORMAL)
->display('')
->then(function ($column) {
$column->append((new UploadMiniProgram())->setKey($this->id));
})
->else()
->using(UserStatus::array())
->dot([
UserStatus::NORMAL => 'success',
UserStatus::UNAUDITED => '',
UserStatus::REFUSE => 'danger',
UserStatus::DISABLED => 'warning',
], 'primary');
if (empty($this->appid)) { //注册小程序
$column->append((new MiniProgramReg(null, 1))->setKey($this->id))->append(' ');
$column->append((new MiniProgramReg(null, 2))->setKey($this->id));
} else {
$column->append((new MiniProgramUpload(null, 1))->setKey($this->id));
}
});
$grid->filter(function ($filter) {
$filter->panel();
@ -92,17 +98,20 @@ class AgentController extends AdminController
$show->field('username');
$show->field('name');
$show->field('appid');
$show->field('appsecret');
$show->field('mchid');
$show->field('mchkey');
// $show->field('appsecret');
// $show->field('mchid');
// $show->field('mchkey');
$show->field('status')->using(UserStatus::array());
$show->field('type')->using(AgentType::array());
$show->field('company_name');
$show->field('credit_codes');
$show->field('logo')->image('', 80, 80);
$show->field('address');
$show->field('license_pic')->image('', 80, 80);
$show->field('director');
$show->field('contact_phone');
$show->field('legal_persona_name');
$show->field('legal_persona_wechat');
$show->field('rate');
$show->field('agentInfo.about', '关于我们')
->unescape()
@ -145,10 +154,10 @@ class AgentController extends AdminController
$form->text('password')->customFormat(fn() => '');
}
$form->text('name')->required();
$form->text('appid')->required();
$form->text('appsecret')->required();
$form->text('mchid')->required();
$form->text('mchkey')->required();
$form->text('appid')->help('无需填写,注册小程序后会自动生成');
// $form->text('appsecret')->help('无需填写,注册小程序后会自动生成');
// $form->text('mchid')->required();
// $form->text('mchkey')->required();
$form->select('status')
->default(UserStatus::NORMAL)
->options(UserStatus::array())
@ -157,13 +166,16 @@ class AgentController extends AdminController
->options(AgentType::array())
->default(AgentType::OPERATOR)
->required();
$form->text('company_name');
$form->text('company_name')->required()->help('请正确填写,保持跟营业执照上的完全一致,如:海南易游天下供应链有限公司');
$form->text('credit_codes')->required()->help('请正确填写,保持跟营业执照上的完全一致,如:91440300577652919M');
$form->distpicker(['province_id', 'city_id', 'area_id'], '请选择区域')->required();
$form->image('logo')->removable(false)->uniqueName();
$form->text('address');
$form->image('license_pic')->removable(false)->uniqueName();
$form->text('director');
$form->text('contact_phone');
$form->text('legal_persona_name')->required()->maxLength(20)->help('很重要,注册小程序时需要用到,用于实名认证');
$form->text('legal_persona_wechat')->required()->maxLength(100)->help('很重要,用于接收实名认证信息,不能是手机号或QQ号,微信号请前往微信“我的”页面查看');
$form->number('rate')->min(0)->max(100)->help('分成百分比,如10%,则输入10');
$form->editor('agentInfo.about', '关于我们');// 隐藏菜单用:->options(['menubar' => false]);
$form->editor('agentInfo.reg_protocol', '注册协议');
@ -187,8 +199,9 @@ class AgentController extends AdminController
}
//过滤null字段
$allow_null = ['avatar', 'remember_token', 'appid', 'appsecret', 'mchid', 'mchkey'];
foreach($form->input() as $k => $v) {
if (is_null($v)) {
if (is_null($v) && !in_array($k, $allow_null)) {
$form->$k = '';
} else if (is_array($v)) {
foreach ($v as $k2 => &$v2) {

4
app/Admin/Controllers/MiniProgramDraftController.php

@ -6,7 +6,7 @@ use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController;
/**
* 小程序草稿箱
* 小程序草稿箱(此类已弃用,更新模板列表时自动获取草稿,并自动创建模板)
* Class MiniProgramController
* @package App\Admin\Controllers
*/
@ -28,8 +28,6 @@ class MiniProgramDraftController extends AdminController
$grid->column('source_miniprogram_appid');
$grid->column('developer');
$grid->column('create_time')->display(fn($v) => date('Y-m-d H:i:s', $v));
$grid->column('op');
});
}
}

1
app/Admin/Controllers/MiniProgramListController.php

@ -19,6 +19,7 @@ class MiniProgramListController extends AdminController
return Grid::make(new MiniProgramList, function (Grid $grid) {
$grid->disableCreateButton();
$grid->disableRowSelector();
$grid->disableActions();
$grid->column('authorizer_appid');
});

20
app/Admin/Controllers/MiniProgramTemplateController.php

@ -1,7 +1,9 @@
<?php
namespace App\Admin\Controllers;
use App\Admin\Extensions\Grid\PullTemplateList;
use App\Admin\Extensions\Grid\MiniProgramDelTemp;
use App\Admin\Extensions\Grid\MiniProgramPull;
use App\Admin\Extensions\Grid\MiniProgramUpload;
use App\Admin\Repositories\MiniProgramTemplateList;
use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController;
@ -20,21 +22,27 @@ class MiniProgramTemplateController extends AdminController
return Grid::make(new MiniProgramTemplateList, function (Grid $grid) {
$grid->disableCreateButton();
$grid->disableRowSelector();
$grid->disableViewButton();
$grid->disableEditButton();
$grid->disableActions();
$grid->disableDeleteButton();
$grid->model()->orderBy('template_id', 'desc');
$grid->tools(new PullTemplateList);
$grid->tools(new MiniProgramPull);
$grid->column('template_id');
$grid->column('template_type')->using([0 => '普通模板', 1 => '标准模板']);
// $grid->column('template_type')->using([0 => '普通模板', 1 => '标准模板']);
$grid->column('user_version');
$grid->column('user_desc');
$grid->column('source_miniprogram');
$grid->column('source_miniprogram_appid');
$grid->column('developer');
$grid->column('create_time')->display(fn($v) => date('Y-m-d H:i:s', $v));
$grid->column('op')
->if(fn() => true)
->then(function ($column) {
// $column->append((new MiniProgramUpload(null, 2))->setKey($this->id))->append('&nbsp;');
$column->append(new MiniProgramDelTemp)->append('&nbsp;');
});
});
}
}

83
app/Admin/Extensions/Grid/MiniProgramDelTemp.php

@ -0,0 +1,83 @@
<?php
namespace App\Admin\Extensions\Grid;
use App\Models\AdminSetting;
use App\Models\MiniProgramTemplate;
use Dcat\Admin\Actions\Response;
use Dcat\Admin\Grid\RowAction;
use EasyWeChat\Factory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class MiniProgramDelTemp extends RowAction
{
/**
* @return string
*/
protected $title = '删除';
protected function html()
{
$this->appendHtmlAttribute('class', 'btn btn-sm btn-danger');
$this->defaultHtmlAttribute('href', 'javascript:;');
return "<a {$this->formatHtmlAttributes()}>{$this->title}</a>";
}
/**
* Handle the action request.
*
* @param Request $request
*
* @return Response
*/
public function handle(Request $request)
{
$id = $this->getKey(); //待删除的ID
//最大ID不允许删除,因为草稿箱已经记录创建模板,即使是更新列表也不再创建模板,删除之后就没有可用模板了
if ($id == MiniProgramTemplate::query()->max('template_id')) {
return $this->response()->error('第一个模板用于注册及创建小程序,不允许删除');
}
DB::beginTransaction();
try {
//删除腾讯服务器上的
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$openPlatform = Factory::openPlatform($config);
if (empty($openPlatform['code_template'])) {
throw new \Exception('获取code_template失败');
}
$codeTemplate = $openPlatform['code_template'];
$res = $codeTemplate->delete($id);
if (!isset($res['errcode'], $res['errmsg']) || $res['errcode'] != 0 || $res['errmsg'] != 'ok') {
throw new \Exception(isset($res['errmsg']) ? join(',', $res) : '删除失败,原因未知');
}
//删除数据库记录
MiniProgramTemplate::where('template_id', $id)->delete();
DB::commit();
return $this->response()->success('删除成功')->refresh();
} catch (\Exception $e) {
DB::rollBack();
return $this->response()->error($e->getMessage());
}
}
/**
* @return string|array|void
*/
public function confirm()
{
return ['确定要删除此模板吗?', ''];
}
}

89
app/Admin/Extensions/Grid/MiniProgramPull.php

@ -0,0 +1,89 @@
<?php
namespace App\Admin\Extensions\Grid;
use App\Models\AdminSetting;
use App\Models\MiniProgramDraft;
use App\Models\MiniProgramTemplate;
use Dcat\Admin\Grid\RowAction;
use EasyWeChat\Factory;
use Illuminate\Http\Request;
/**
* 获取小程序草稿,并创建模板,并保存草稿和模板列表
* Class UploadMiniProgram
* @package App\Admin\Extensions\Grid
*/
class MiniProgramPull extends RowAction
{
protected $title = '更新列表';
protected function html()
{
$this->appendHtmlAttribute('class', 'btn btn-primary');
$this->defaultHtmlAttribute('href', 'javascript:;');
return "<a {$this->formatHtmlAttributes()}>{$this->title}</a>";
}
/**
* 更新逻辑:
* 1、先获取草稿箱,并保存到数据库;
* 2、如果草稿未创建过模板,通过草稿创建模板;
* 3、将模板列表保存至数据库;
*/
public function handle(Request $request)
{
try {
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$openPlatform = Factory::openPlatform($config);
if (empty($openPlatform['code_template'])) {
return $this->response()->error('获取code_template失败');
}
$codeTemplate = $openPlatform['code_template'];
//草稿列表
$list = $codeTemplate->getDrafts();
if (empty($list['draft_list'])) {
return $this->response()->error('获取草稿箱失败或草稿箱为空');
}
MiniProgramDraft::insertOrIgnore($list['draft_list']);
MiniProgramDraft::whereNotIn('draft_id', array_column($list['draft_list'], 'draft_id'))->delete(); //删除不存在的数据
//从草稿创建模板
$ids = MiniProgramDraft::query()->where('is_create_template', 0)->pluck('draft_id');
foreach ($ids as $draft_id) {
$res = $codeTemplate->createFromDraft($draft_id, 1); //第二个参数,0:普通模板;1:标准模板
if (!isset($res['errcode'], $res['errmsg']) || $res['errcode'] != 0 || $res['errmsg'] != 'ok') {
return $this->response()->error("草稿ID $draft_id 创建模板失败");
} else {
MiniProgramDraft::where('draft_id', $draft_id)->update(['is_create_template' => 1]);
}
}
//模板列表
$list = $codeTemplate->list();
if (empty($list['template_list'])) {
return $this->response()->error('获取模板失败或模板为空');
}
MiniProgramTemplate::insertOrIgnore($list['template_list']);
MiniProgramTemplate::whereNotIn('template_id', array_column($list['template_list'], 'template_id'))->delete(); //删除不存在的数据
return $this->response()->success("更新列表成功")->refresh();
} catch (\Exception $e) {
return $this->response()->error($e->getMessage());
}
}
public function confirm()
{
return ['此操作将数据与腾讯服务器数据同步,是否继续?', ''];
}
}

160
app/Admin/Extensions/Grid/MiniProgramReg.php

@ -0,0 +1,160 @@
<?php
namespace App\Admin\Extensions\Grid;
use App\Models\AdminSetting;
use App\Models\Agent;
use App\Models\MiniProgramTemplate;
use App\Models\MiniProgramUploadLog;
use Dcat\Admin\Grid\RowAction;
use EasyWeChat\Factory;
use EasyWeChat\OpenPlatform\Component\Client;
use Illuminate\Http\Request;
/**
* 上传(注册)小程序
* Class UploadMiniProgram
* @package App\Admin\Extensions\Grid
*/
class MiniProgramReg extends RowAction
{
private $action;
public function __construct($title = null, $action = 1)
{
parent::__construct($title);
$this->action = $action; //$action:1=注册小程序;2=上传小程序
$this->title = $action == 1 ? '注册小程序' : '查询状态';
}
protected function html()
{
$class = $this->action == 1 ? 'btn btn-sm btn-success' : 'btn btn-sm';
$this->appendHtmlAttribute('class', $class);
$this->defaultHtmlAttribute('href', 'javascript:;');
return "<a {$this->formatHtmlAttributes()}>{$this->title}</a>";
}
public function handle(Request $request)
{
return $request->action == 1 ? $this->register() : $this->search();
}
private function register()
{
$agent = Agent::find($this->getKey());
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey', 'service_component_phone']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$openPlatform = Factory::openPlatform($config);
if (empty($openPlatform['component'])) {
return $this->response()->error('获取component失败,请检查配置信息是否正确');
}
$component = $openPlatform['component'];
$res = $component->registerMiniProgram([
'name' => $agent->company_name, // 企业名
'code' => $agent->credit_codes, // 企业代码
'code_type' => 1, // 企业代码类型(1:统一社会信用代码, 2:组织机构代码,3:营业执照注册号)
'legal_persona_wechat' => $agent->legal_persona_wechat, // 法人微信
'legal_persona_name' => $agent->legal_persona_name, // 法人姓名
'component_phone' => $setting['service_component_phone'], //第三方联系电话
]);
$errorArr = $this->regErrorCode();
if (!isset($res['errcode'], $res['errmsg'])) {
return $this->response()->error('注册错误,原因未知');
} else if ($res['errcode'] != 0 && isset($errorArr[$res['errcode']])) {
return $this->response()->error($errorArr[$res['errcode']]);
} else if ($res['errcode'] != 0 || $res['errmsg'] != 'ok') {
return $this->response()->error(join(',', $res));
}
return $this->response()->success('注册小程序成功')->refresh();
}
private function search()
{
$agent = Agent::find($this->getKey());
if (!empty($agent->appid)) {
return $this->response()->error("该代理商已经注册过小程序并分配了APPID:" . $agent->appid);
}
try {
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$openPlatform = Factory::openPlatform($config);
if (empty($openPlatform['component'])) {
return $this->response()->error('获取component失败,请检查配置信息是否正确');
}
/** @var Client $component */
$component = $openPlatform['component'];
$res = $component->getRegistrationStatus($agent->company_name, $agent->legal_persona_wechat, $agent->legal_persona_name);
$errorArr = $this->searchErrorCode();
if (isset($res['errcode'], $res['errmsg']) && $res['errcode'] == 0 && $res['errmsg'] == 'ok') {
return $this->response()->success("成功")->refresh();
} else if (isset($res['errcode'], $errorArr[$res['errcode']])) {
throw new \Exception($errorArr[$res['errcode']]);
} else {
throw new \Exception(join(',', $res));
}
} catch (\Exception $e) {
return $this->response()->error($e->getMessage());
}
}
public function confirm()
{
return ["确定要{$this->title}吗?", ''];
}
public function parameters()
{
return ['action' => $this->action];
}
private function regErrorCode(): array
{
return [
-1 => '非法 action 参数',
89249 => '该主体已有任务执行中,距上次任务 24小时 后再试',
89247 => '腾讯服务器内部错误',
86004 => '无效微信号',
61070 => '法人姓名与微信号不一致',
89248 => '企业代码类型无效,请选择正确类型填写',
89250 => '未找到该任务',
89251 => '待法人人脸核身校验',
89252 => '法人&企业信息一致性校验中',
89253 => '缺少参数',
89254 => '第三方权限集不全,请补充权限集后重试',
89255 => 'code参数无效,请检查code长度以及内容是否正确 ;注意code_type的值不同需要传的code长度不一样',
];
}
private function searchErrorCode(): array
{
return [
-1 => '非法请求',
89247 => '内部错误',
89250 => '未找到该企业的注册任务',
89251 => '模板消息已下发,待法人人脸核身校验',
89252 => '法人&企业信息一致性校验中',
89253 => '缺少参数',
];
}
}

136
app/Admin/Extensions/Grid/MiniProgramUpload.php

@ -0,0 +1,136 @@
<?php
namespace App\Admin\Extensions\Grid;
use App\Models\AdminSetting;
use App\Models\Agent;
use App\Models\MiniProgramTemplate;
use App\Models\MiniProgramUploadLog;
use Dcat\Admin\Grid\RowAction;
use EasyWeChat\Factory;
use EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Code\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
/**
* 上传(注册)小程序
* Class UploadMiniProgram
* @package App\Admin\Extensions\Grid
*/
class MiniProgramUpload extends RowAction
{
private $action;
public function __construct($title = null, $action = 1)
{
parent::__construct($title);
$this->action = $action; //$action:1=为指定代理商上传小程序;2=批量上传小程序(一键分发小程序给所有代理商)
$this->title = $action == 1 ? '上传小程序' : '为所有代理商上传';
}
protected function html()
{
$class = 'btn btn-sm btn-primary';
$this->appendHtmlAttribute('class', $class);
$this->defaultHtmlAttribute('href', 'javascript:;');
return "<a {$this->formatHtmlAttributes()}>{$this->title}</a>";
}
public function handle(Request $request)
{
return $this->action == 1 ? $this->uploadOne() : $this->uploadAll();
}
//注:uploadOne在代理商列表页使用
private function uploadOne()
{
$template = MiniProgramTemplate::orderBy('template_id', 'desc')->first();
/*if (MiniProgramUploadLog::query()->where(['agent_id' => $this->getKey(), 'template_id' => $template->template_id])->exists()) {
return $this->response()->error("该代理商已经上传过模板ID为 {$template->template_id} 的小程序,无需重复上传");
}*/
$agent = Agent::find($this->getKey());
if (empty($agent->appid)) {
return $this->response()->error('该代理商未注册过小程序,请先注册');
}
try {
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$openPlatform = Factory::openPlatform($config);
$refreshToken = $openPlatform->getAuthorizer($agent->appid)['authorization_info']['authorizer_refresh_token'] ?? null;
if (!$refreshToken) {
return $this->response()->error('获取refresh_token失败');
}
/** @var Client $code */
$code = $openPlatform->miniProgram($agent->appid, $refreshToken)['code'] ?? null;
if (!$code) {
return $this->response()->error('获取code失败');
}
$templateId = $template->template_id;
$extJson = json_encode(['extAppid' => $agent->appid]);
$version = $template->user_version;
$description = $agent->company_name;
//提交上传
$commit = $code->commit($templateId, $extJson, $version, $description);
//获取体验二维码并保存
$qrcode = $code->getQrCode(storage_path("app/public/{$agent->id}-{$agent->appid}.jpg"));
Storage::put("public/mini_program_qrcode/{$agent->id}-{$agent->appid}.jpg", $qrcode);
if (!isset($commit['errcode'], $commit['errmsg']) || $commit['errcode'] != 0 || $commit['errmsg'] != 'ok') {
throw new \Exception(isset($commit['errmsg']) ? $commit['errmsg'] : join(',', $commit));
}
//提交审核,文档:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/code/submit_audit.html
$res = $code->submitAudit([]);
if (isset($res['errcode'], $res['errmsg']) && $res['errcode'] == 0 && $res['errmsg'] == 'ok') {
//保存上传记录
MiniProgramUploadLog::insert([
'agent_id' => $agent->id,
'appid' => $agent->appid,
'template_id' => $templateId,
'qrcode' => "mini_program_qrcode/{$agent->id}-{$agent->appid}.jpg",
'audit_id' => $res['auditid'],
'created_at' => now(),
]);
return $this->response()->success("上传成功,并已提交审核")->refresh();
} else {
throw new \Exception($res['errmsg'] ?? join(',', $res));
}
} catch (\Exception $e) {
return $this->response()->error($e->getMessage());
}
}
//注:uploadAll在小程序模板列表页使用
private function uploadAll()
{
}
public function confirm()
{
if ($this->action == 1) {
return ["确定要为此代理商上传小程序吗?", ''];
} else {
return ['上传确认', '确定要将此小程序模板上传给所有已审核的代理商吗?'];
}
}
public function parameters()
{
return ['action' => $this->action];
}
}

56
app/Admin/Extensions/Grid/PullTemplateList.php

@ -1,56 +0,0 @@
<?php
namespace App\Admin\Extensions\Grid;
use App\Models\AdminSetting;
use App\Models\MiniProgramTemplateList;
use Dcat\Admin\Grid\RowAction;
use EasyWeChat\Factory;
use Illuminate\Http\Request;
/**
* 上传(注册)小程序
* Class UploadMiniProgram
* @package App\Admin\Extensions\Grid
*/
class PullTemplateList extends RowAction
{
protected $title = '更新列表';
protected function html()
{
$this->appendHtmlAttribute('class', 'btn btn-primary');
$this->defaultHtmlAttribute('href', 'javascript:;');
return "<a {$this->formatHtmlAttributes()}>{$this->title}</a>";
}
public function handle(Request $request)
{
try {
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$openPlatform = Factory::openPlatform($config);
$codeTemplate = $openPlatform['code_template'];
$list = $codeTemplate->list();
MiniProgramTemplateList::insertOrIgnore($list['template_list']);
//删除不存在的数据
MiniProgramTemplateList::whereNotIn('template_id', array_column($list['template_list'], 'template_id'))->delete();
return $this->response()->success("操作成功")->refresh();
} catch (\Exception $e) {
return $this->response()->error($e->getMessage());
}
}
public function confirm()
{
return ['此操作将数据与腾讯服务器数据同步,是否继续?', ''];
}
}

89
app/Admin/Extensions/Grid/UploadMiniProgram.php

@ -1,89 +0,0 @@
<?php
namespace App\Admin\Extensions\Grid;
use App\Common\UserStatus;
use App\Models\AdminSetting;
use App\Models\Agent;
use App\Models\Category;
use App\Models\Channel;
use App\Models\Advertising;
use App\Models\MiniProgramTemplateList;
use App\Models\MiniProgramUploadLog;
use Dcat\Admin\Admin;
use Dcat\Admin\Grid\RowAction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
/**
* 上传(注册)小程序
* Class UploadMiniProgram
* @package App\Admin\Extensions\Grid
*/
class UploadMiniProgram extends RowAction
{
protected $title = '上传小程序';
protected function html()
{
$this->appendHtmlAttribute('class', 'btn btn-sm btn-primary');
$this->defaultHtmlAttribute('href', 'javascript:;');
return "<a {$this->formatHtmlAttributes()}>{$this->title}</a>";
}
public function handle(Request $request)
{
$template = MiniProgramTemplateList::orderBy('template_id', 'desc')->first();
if (MiniProgramUploadLog::query()->where(['agent_id' => $this->getKey(), 'template_id' => $template->template_id])->exists()) {
return $this->response()->error('该代理商已经上传过小程序,无需重复上传');
}
$agent = Agent::find($this->getKey());
if (empty($agent->appid)) {
return $this->response()->error('该代理商未注册过小程序,请先注册');
}
try {
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$openPlatform = \EasyWeChat\Factory::openPlatform($config);
$refreshToken = $openPlatform->getAuthorizer($agent->appid)['authorization_info']['authorizer_refresh_token'] ?? null;
if (!$refreshToken) {
return $this->response()->error('获取refresh_token失败');
}
$code = $openPlatform->miniProgram($agent->appid, $refreshToken)['code'];
$templateId = $template->template_id;
$extJson = json_encode(['extAppid' => $agent->appid]);
$version = $template->user_version;
$description = $agent->company_name;
$commit = $code->commit($templateId, $extJson, $version, $description);
// $qrcode = $code->getQrCode();
if (isset($commit['errcode'], $commit['errmsg']) && $commit['errcode'] == 0 && $commit['errmsg'] == 'ok') {
MiniProgramUploadLog::insert([
'agent_id' => $agent->id,
'appid' => $agent->appid,
'template_id' => $templateId,
]);
return $this->response()->success("上传成功")->refresh();
} else {
throw new \Exception(join(',', $commit));
}
} catch (\Exception $e) {
return $this->response()->error($e->getMessage());
}
}
public function confirm()
{
return ['确定要上传小程序吗?', ''];
}
}

2
app/Admin/Forms/Setting.php

@ -36,9 +36,9 @@ class Setting extends Form
})->tab('小程序服务商配置', function () {
$this->text('service_appid', '小程序第三方平台APPID');
$this->text('service_appsecret', '小程序第三方平台APP_SECRET');
$this->text('service_binding_appid', '绑定小程序APPID');
$this->text('service_token', '消息校验Token')->help('跟小程序管理后台的一致,请勿随意更改');
$this->text('service_aeskey', '消息加解密Key')->help('跟小程序管理后台的一致,请勿随意更改');
$this->text('service_component_phone', '联系电话')->help('主要用于当注册小程序失败时,腾讯可能会通过此电话反馈问题');
});
}

53
app/Admin/Repositories/MiniProgramDraft.php

@ -1,60 +1,21 @@
<?php
namespace App\Admin\Repositories;
use App\Models\AdminSetting;
use Dcat\Admin\Grid;
use Dcat\Admin\Repositories\Repository;
use EasyWeChat\Factory;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Cache;
use App\Models\MiniProgramDraft as Model;
use Dcat\Admin\Repositories\EloquentRepository;
/**
* 小程序草稿箱
* Class MiniProgramDraft
* @package App\Admin\Repositories
*/
class MiniProgramDraft extends Repository
class MiniProgramDraft extends EloquentRepository
{
protected $keyName = 'draft_id';
protected $eloquentClass = Model::class;
/**
* 查询表格数据
*
* @param Grid\Model $model
* @return LengthAwarePaginator
* @throws GuzzleException
*/
public function get(Grid\Model $model): LengthAwarePaginator
public function __construct()
{
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$cache_key = 'mini_program:draft_list';
if ($data['subjects'] = Cache::get($cache_key)) {
$data['total'] = count($data['subjects']);
} else {
$openPlatform = Factory::openPlatform($config);
$codeTemplate = $openPlatform['code_template'];
if (empty($codeTemplate) || (!$list = $codeTemplate->getDrafts())) {
$data['total'] = 0;
$data['subjects'] = [];
} else {
$data['total'] = count($list['draft_list']);
$data['subjects'] = $list['draft_list'] ?? [];
Cache::put($cache_key, $list['draft_list'], 180);
}
}
return $model->makePaginator(
$data['total'] ?? 0, // 传入总记录数
$data['subjects'] ?? [] // 传入数据二维数组
);
parent::__construct();
$this->setKeyName('draft_id');
}
}

2
app/Admin/Repositories/MiniProgramTemplateList.php

@ -1,7 +1,7 @@
<?php
namespace App\Admin\Repositories;
use App\Models\MiniProgramTemplateList as Model;
use App\Models\MiniProgramTemplate as Model;
use Dcat\Admin\Repositories\EloquentRepository;
/**

6
app/AdminAgent/Forms/AgentInfo.php

@ -23,12 +23,15 @@ class AgentInfo extends Form
$model->name = $input['name'];
$model->company_name = $input['company_name'];
$model->credit_codes = $input['credit_codes'];
$model->address = $input['address'];
$model->director = $input['director'];
$model->contact_phone = $input['contact_phone'];
$model->logo = $input['logo'];
$model->avatar = $input['avatar'];
$model->license_pic = $input['license_pic'];
$model->legal_persona_name = $input['legal_persona_name'];
$model->legal_persona_wechat = $input['legal_persona_wechat'];
$model->status = UserStatus::UNAUDITED;
$model->agentInfo->about = $input['agentInfo']['about'];
@ -49,12 +52,15 @@ class AgentInfo extends Form
$this->text('name')->required();
$this->text('company_name')->required();
$this->text('credit_codes')->required();
$this->text('address')->required();
$this->text('director')->required();
$this->text('contact_phone')->required();
$this->image('logo')->required();
$this->image('avatar');
$this->image('license_pic')->required();
$this->text('legal_persona_name')->required();
$this->text('legal_persona_wechat')->required();
$this->editor('agentInfo.about')->required();
$this->editor('agentInfo.reg_protocol')->required();

10
app/AdminSettled/Controllers/AgentController.php

@ -69,13 +69,16 @@ class AgentController extends AdminController
->options(AgentType::array())
->default(AgentType::OPERATOR)
->required();
$form->text('company_name')->required();
$form->text('company_name')->required()->help('请正确填写,保持跟营业执照上的完全一致,如:海南易游天下供应链有限公司');
$form->text('credit_codes')->required()->help('请正确填写,保持跟营业执照上的完全一致,如:91440300577652919M');
$form->distpicker(['province_id', 'city_id', 'area_id'], '请选择区域')->required();
$form->image('logo')->required()->removable(false)->uniqueName();
$form->text('address')->required();
$form->image('license_pic')->required()->removable(false)->uniqueName();
$form->text('director')->required();
$form->text('contact_phone')->required()->maxLength(13);
$form->text('legal_persona_name')->required()->maxLength(20)->help('很重要,注册小程序时需要用到,用于实名认证');
$form->text('legal_persona_wechat')->required()->maxLength(100)->help('很重要,用于接收实名认证信息,不能是手机号或QQ号,微信号请前往微信“我的”页面查看');
})->saving(function (Form $form) {
if ($form->isEditing()) {
return $form->response()->error('服务器出错了~~');
@ -86,6 +89,11 @@ class AgentController extends AdminController
return $form->response()->error($form->username . ' 的账号已经存在');
}
//判断公司名称是否唯一
if ($form->repository()->model()->where(['company_name' => $form->company_name, 'credit_codes' => $form->credit_codes])->exists()) {
return $form->response()->error("公司名称 {$form->company_name} 已经存在");
}
//如果是供应商版旅行社,也不能存在相同的供应商账号,因为后台审核之后需要再次插入相同的供应商账号
if ($form->type == AgentType::SUPPLIER && Supplier::where('username', $form->username)->exists()) {
return $form->response()->error($form->username . ' 的账号已经存在');

60
app/Http/Controllers/Api/MiniProgramController.php

@ -3,8 +3,8 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\AdminSetting;
use App\Models\Agent;
use EasyWeChat\Factory;
use EasyWeChat\OpenPlatform\Server\Guard;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@ -18,6 +18,8 @@ class MiniProgramController extends Controller
// 第三方平台授权事件通知
public function authEvent(Request $request)
{
DB::table('mini_program_events')->insert(['response' => json_encode($request->all()), 'created_at' => now()]);
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [ // 第三方平台信息
'app_id' => $setting['service_appid'],
@ -29,30 +31,50 @@ class MiniProgramController extends Controller
$openPlatform = Factory::openPlatform($config);
$server = $openPlatform->server;
// 处理授权成功事件
// 处理授权成功事件:Guard::EVENT_AUTHORIZED
// 处理授权更新事件:Guard::EVENT_UPDATE_AUTHORIZED
// 处理授权取消事件:Guard::EVENT_UNAUTHORIZED
$server->push(function ($message) {
DB::table('auth_event')->insert([
['response' => json_encode($message)]
DB::table('mini_program_events')->insert([
'response' => json_encode($message),
'event' => $message['InfoType'] ?? '',
'created_at' => now()
]);
}, Guard::EVENT_AUTHORIZED);
// 处理授权更新事件
$server->push(function ($message) {
DB::table('auth_event')->insert([
['response' => json_encode($message)]
]);
}, Guard::EVENT_UPDATE_AUTHORIZED);
if (isset($message['InfoType'], $message['status'], $message['msg'], $message['info']) && $message['status'] == 0 && $message['msg'] == 'OK') {
//注册成功授权通知
if ($message['InfoType'] == 'notify_third_fasteregister') {
Agent::where(['company_name' => $message['info']['name'], 'credit_codes' => $message['info']['code']])
->update(['appid' => $message['appid']]);
}
}
});
return $server->serve();
}
public function msgEvent(Request $request)
{
$appid = $request->route('appid');
DB::table('mini_program_events')->insert(['appid' => $appid, 'response' => json_encode($request->all()), 'created_at' => now()]);
// 处理授权取消事件
$setting = AdminSetting::val(['service_appid', 'service_appsecret', 'service_token', 'service_aeskey']);
$config = [
'app_id' => $setting['service_appid'],
'secret' => $setting['service_appsecret'],
'token' => $setting['service_token'],
'aes_key' => $setting['service_aeskey'],
];
$openPlatform = Factory::openPlatform($config);
$server = $openPlatform->server;
//接收事件
$server->push(function ($message) {
DB::table('auth_event')->insert([
['response' => json_encode($message)]
]);
}, Guard::EVENT_UNAUTHORIZED);
if (isset($message['Event'])) {
DB::table('auth_event')->insert([
['response' => json_encode($request->all())]
]);
}
});
return $server->serve();
}

1
app/Http/Controllers/Api/TestController.php

@ -2,6 +2,7 @@
namespace App\Http\Controllers\Api;
use App\Models\Agent;
use App\Models\Order;
use App\Models\OrderProductItem;
use App\Models\Product;

17
app/Models/MiniProgramDraft.php

@ -0,0 +1,17 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MiniProgramDraft extends Model
{
use HasFactory;
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->timestamps = false;
}
}

17
app/Models/MiniProgramTemplate.php

@ -0,0 +1,17 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MiniProgramTemplate extends Model
{
use HasFactory;
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->timestamps = false;
}
}

11
app/Models/MiniProgramTemplateList.php

@ -1,11 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MiniProgramTemplateList extends Model
{
use HasFactory;
}

1217
composer.lock
File diff suppressed because it is too large
View File

3
resources/lang/zh_CN/agent.php

@ -16,10 +16,13 @@ return [
'status' => '状态',
'type' => '代理商类型',
'company_name' => '公司名称',
'credit_codes' => '统一社会信用代码',
'logo' => 'LOGO',
'address' => '公司地址',
'license_pic' => '营业执照',
'director' => '负责人',
'legal_persona_name' => '法人姓名',
'legal_persona_wechat' => '法人微信号',
'contact_phone' => '联系电话',
'rate' => '抽成比例',
'agentInfo' => trans('agent-info.fields'),

Loading…
Cancel
Save