代码初始化

This commit is contained in:
zoomtk@126.com 2023-02-10 12:51:18 +08:00
commit 680f1fbd6b
14922 changed files with 1928426 additions and 0 deletions

6
.env Normal file
View File

@ -0,0 +1,6 @@
APP_DEBUG = false
APP_TRACE = false
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[LANG]
default_lang = zh-cn

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
/.project
/.vscode
/.settings
/.idea
/.htaccess
/.buildpath
/cert.key
*.log
*.txt
/h5
/web
/mshop
/config/database.php
/cashregister
/upload
/runtime

42
.travis.yml Normal file
View File

@ -0,0 +1,42 @@
sudo: false
language: php
branches:
only:
- stable
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
install:
- composer install --no-dev --no-interaction --ignore-platform-reqs
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
script:
- php think unit
deploy:
provider: releases
api_key:
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
file:
- ThinkPHP_Core.zip
- ThinkPHP_Full.zip
skip_cleanup: true
on:
tags: true

26
404.html Normal file
View File

@ -0,0 +1,26 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>404</title>
<style>
body{
background-color:#444;
font-size:14px;
}
h3{
font-size:60px;
color:#eee;
text-align:center;
padding-top:30px;
font-weight:normal;
}
</style>
</head>
<body>
<h3>404您请求的文件不存在!</h3>
</body>
</html>

View File

@ -0,0 +1,26 @@
<?php
namespace addon\aliapp\api\controller;
use app\api\controller\BaseApi;
use addon\aliapp\model\MinCode;
class Aliapp extends BaseApi
{
/**
* 获取openid
*/
public function getOpenid()
{
// $weapp_model = new WeappModel();
// $res = $weapp_model->authCodeToOpenid($this->params);
return $this->response(['openid'=>'sdfsdfsdf']);
}
public function getUserInfo(){
$model= new MinCode();
$acut_code=input('code');
$userInof=$model->getUserInfo($acut_code);
return $this->response($userInof);
}
}

View File

@ -0,0 +1,14 @@
<?php
return [
'diy' => [
'view' => [
],
'util' => [
],
'link' => [
],
],
];

View File

@ -0,0 +1,49 @@
<?php
// 事件定义文件
return [
'bind' => [],
'listen' => [
// 生成获取二维码
'Qrcode' => [
'addon\aliapp\event\Qrcode'
],
'ShowPromotion' => [
'addon\aliapp\event\ShowPromotion',
],
'DecryptData' => [
'addon\aliapp\event\DecryptData',
],
'PayNotify' => [
'addon\aliapp\event\PayNotify'
],
// 支付宝网关通知
'AliAuthNotify' => [
'addon\aliapp\event\AliAuthNotify', // 服务订购通知
'addon\aliapp\event\AlipayMerchant', // 支付通进件通知
'addon\aliapp\event\AliAuditResult', // 小程序事件
],
'AliPayMerchantPassed' => [ //支付宝二级商户进件成功
'addon\aliapp\event\AliPayMerchantPassed'
],
'AliappRegAuth' => [ //小程序注册授权通知
'addon\aliapp\event\AliappMiniReg'
],
// 权益即将过期通知
'NoticeImpendingExpiration' => [
'addon\aliapp\event\NoticeImpendingExpiration'
],
// 权益即将过期列表获取
'ImpendingExpirationListGet' => [
'addon\aliapp\event\ImpendingExpirationListGet'
],
//会员群体定时刷新
'SettleConfirmSubLedger' => [
'addon\aliapp\event\SubLedger'
],
// 支付成功
'OrderPay' => [
'addon\aliapp\event\OrderPay',
],
],
'subscribe' => [],
];

View File

@ -0,0 +1,10 @@
<?php
return [
'name' => 'aliapp',
'title' => '支付宝小程序',
'description' => '支付宝小程序,支付,电商社交',
'status' => 1,
'author' => '',
'version' => '1.0',
'content' => '',
];

View File

@ -0,0 +1,5 @@
<?php
// +----------------------------------------------------------------------
// | 平台端菜单设置
// +----------------------------------------------------------------------
return [];

View File

@ -0,0 +1,82 @@
<?php
// +----------------------------------------------------------------------
// | 平台端菜单设置
// +----------------------------------------------------------------------
return [
[
'name' => 'SHOP_ALIAPP_ROOT',
'title' => '支付宝小程序',
'url' => 'aliapp://shop/aliapp/setting',
'parent' => 'CHANNEL_ROOT',
'picture' => 'addon/aliapp/shop/view/public/img/alipay_app_new.png',
'picture_selected' => 'addon/aliapp/shop/view/public/img/alipay_app_select.png',
'is_show' => 1,
'sort' => 1,
'child_list' => [
// [
// 'name' => 'ALIPAY_ROOT_CONFIG',
// 'title' => '概况',
// 'url' => 'aliapp://shop/alipay/setting',
// 'is_show' => 1,
// 'sort' => 1,
// ],
[
'name' => 'ALIPAY_CONFIG',
'title' => '基础配置',
'url' => 'aliapp://shop/alipay/config',
'is_show' => 0,
'sort' => 2,
],
[
'name' => 'ALIPAY_PACKAGE',
'title' => '小程序发布',
'url' => 'aliapp://shop/alipay/package',
'is_show' => 0,
'sort' => 3,
],
[
'name' => 'ALIPAY_SHARE',
'title' => '小程序分享',
'url' => 'aliapp://shop/alipay/share',
'is_show' => 0,
'sort' => 6
],
[
'name' => 'ALIPAY_BASEINFO',
'title' => '基础信息设置',
'url' => 'aliapp://aliapp/shop/aliapp/editapp',
'is_show' => 0,
'sort' => 6
],
// [
// 'name' => 'ALIPAY_CREATE_APPLET',
// 'title' => '创建小程序',
// 'url' => 'aliapp://shop/createApplet/index',
// 'is_show' => 1,
// 'sort' => 2
// ],
[
'name' => 'ALIPAY_RELEASE_APPLET',
'title' => '发布小程序',
'url' => 'aliapp://shop/AppletRelease/index',
'is_show' => 1,
'sort' => 2
],
[
'name' => 'ALIPAY_MEMBER_APPLET',
'title' => '应用成员',
'url' => 'aliapp://shop/member/index',
'is_show' => 1,
'sort' => 4
],
[
'name' => 'ALIAPP_PACKAGE_EDIT',
'parent' => 'MESSAGE_LISTS',
'title' => '编辑订阅消息',
'url' => 'aliapp://shop/message/edit',
'is_show' => 0,
'sort' => 1,
],
]
]
];

View File

@ -0,0 +1,95 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
use addon\aliapp\model\MinCode;
use think\facade\Db;
use think\facade\Log;
class AliAuditResult
{
// 支付宝小程序审核结果通知处理
public function handle($param = [])
{
$msgMethod = $param['msg_method'] ?? '';
if ($msgMethod && $this->rsaCheck($param)) {
Log::write('支付宝小程序通知:' . $msgMethod . json_encode($param));
$biz_content = json_decode($param['biz_content'], true);
switch ($msgMethod) {
case 'alipay.open.mini.version.audit.rejected'; //审核被拒绝
$this->auditResultHandle($biz_content);
break;
case 'alipay.open.mini.version.audit.passed'; //审核通过
echo 'success';
break;
case 'alipay.open.mini.merchant.confirmed'; //小程序创建
$this->confirmed($biz_content);
break;
case 'alipay.open.search.keyword.changed'; //小程序关键词审核进度消息通知
echo 'success';
break;
case 'alipay.open.mini.version.baseaudit.passed'; //小程序审核不可营销通知
echo 'success';
break;
}
}
}
/**
* Common: 支付宝小程序审核结果处理 —— 驳回处理
* Author: wu-hui
* Time: 2023/01/06 14:52
* @param $param
* @throws \think\db\exception\DbException
*/
public function auditResultHandle($bizContent)
{
$siteIds = Db::name('uni_account')->where('appid', $bizContent['mini_app_id'])->column('site_id');
Db::name('applet_release')
->whereIn('site_id', $siteIds)
->where('version', $bizContent['mini_app_version'])
->update(['version_status' => 'AUDIT_REJECT', 'audit_reason' => $bizContent['audit_reason']]);
echo 'success';
}
/***
* 小程序创建
* @param $param
*/
public function confirmed($bizContent)
{
$business_code=$bizContent['out_order_no'];
$info = Db::name('applet_list')->where('business_code', $business_code)->value('id');
if($info){
$data=[
'original_id'=>$bizContent['pid'],
'appid'=>$bizContent['min_app_id'],
'status'=>$bizContent['status'],
];
Db::name('applet_list')->where('business_code', $business_code)->update($data);
}
echo 'success';
}
/***
* 验证签名
* @param $param
* @return bool
*/
public function rsaCheck($param)
{
$payModel = new MinCode();
$res = $payModel->verifySgin($param);
return $res;
}
}

View File

@ -0,0 +1,25 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
use addon\aliapp\model\AuthNotify;
class AliAuthNotify
{
/**
* 执行安装
*/
public function handle($param = [])
{
$aliapp = new AuthNotify();
return $aliapp->Notify($param);
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
class AliPayMerchantPassed
{
/**
* 执行安装
*/
public function handle($param = [])
{
return success();
}
}

View File

@ -0,0 +1,23 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
class AliappMiniReg
{
// 支付宝小程序审核结果通知处理
public function handle($param = [])
{
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
use addon\aliapp\model\OpenPay;
use think\facade\Db;
class AlipayMerchant
{
// 支付宝小程序审核结果通知处理
public function handle($param = [])
{
$msgMethod = $param['msg_method'] ?? '';
$rsaCheck = $this->rsaCheck($param);
if ($rsaCheck && $msgMethod) {
switch ($msgMethod) {
case 'ant.merchant.expand.indirect.zft.passed':
$this->passed(json_decode($param['biz_content'], true));
break;
case 'ant.merchant.expand.indirect.zft.rejected':
$this->rejected(json_decode($param['biz_content'], true));
break;
}
}
}
/***
* 审核成功
* @param $param
*/
public function passed($param)
{
$business_code = $param['external_id'] ?? '';
$info = Db::name('pay_shop')->where('business_code', '=', $business_code)->find();
if ($info) {
$upData = [
'merchant_smid' => $param['smid'],
'apply_desc' => $param['memo'],
];
Db::name('pay_shop')->where('business_code', '=', $business_code)->update($upData);
event('AliPayMerchantPassed', array_merge($info, $param));
}
echo 'success';
}
/***
* 审核被拒绝
* @param $param
*/
public function rejected($param)
{
$business_code = $param['external_id'] ?? '';
$info = Db::name('pay_shop')->where('business_code', '=', $business_code)->find();
if ($info) {
$upData = [
'apply_desc' => $param['reason'],
'states' => 2,
];
Db::name('pay_shop')->where('business_code', '=', $business_code)->update($upData);
}
echo 'success';
}
public function rsaCheck($param)
{
$payModel = new OpenPay();
$res = $payModel->verifySgin($param);
return $res;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\aliapp\event;
use addon\aliapp\model\MinCode;
/**
* 开放数据解密
*/
class DecryptData
{
/**
* 执行安装
*/
public function handle($param = [])
{
if ($param['app_type'] == 'aliapp') {
$weapp = new MinCode($param['site_id']);
return $weapp->decryptData($param);
}
}
}

View File

@ -0,0 +1,128 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
use think\facade\Db;
class ImpendingExpirationListGet{
private $limit = 500;
public function handle($param = []){
$this->noticeHandle();
return $param;
}
/**
* Common: 权益即将过期列表获取
* Author: wu-hui
* Time: 2023/01/11 10:25
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function noticeHandle(){
// 获取所有开启通知的商家设置信息
$configList = $this->getConfigList();
// 获取即将过期信息
$list = $this->getExpiringSoonList($configList);
$insertData = [];
foreach($list as $item){
$insertData[] = [
'site_id' => $item['site_id'],
'uid' => $item['member_id'],
'member_goods_card' => $item['card_id'],
'time_day' => $configList[$item['site_id']],
'time_notice' => 0,
'is_notice' => 0,
];
}
Db::name('member_goods_card_notice')->insertAll($insertData);
}
/**
* Common: 获取所有平台的 服务卡即将过期提前多少天提醒设置
* Author: wu-hui
* Time: 2023/01/11 9:29
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getConfigList(){
$list = Db::name('config')
->field("convert(json_extract(value,'$.days_in_advance'), signed) as days_in_advance,site_id")
->where('config_key','ORDER_EVENT_TIME_CONFIG')
->where("convert(json_extract(value,'$.days_in_advance'), signed) > 0")
->select();
if($list) {
$list = $list->toArray();
return array_column($list,'days_in_advance','site_id');
}
return [];
}
/**
* Common: 获取指定数量的即将过期信息列表
* Author: wu-hui
* Time: 2023/01/11 10:20
* @param $configList
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getExpiringSoonList($configList){
$list = [];
foreach($configList as $siteId => $days_in_advance){
// 获取过期时间
$endTime = strtotime("+{$days_in_advance} day");
$list = array_merge($list,$this->getExpiringList($siteId,$endTime,(int)($this->limit - count($list))));
if(count($list) >= $this->limit) break;
}
return $list;
}
/**
* Common: 根据条件获取对应的信息列表
* Author: wu-hui
* Time: 2023/01/11 10:20
* @param $siteId
* @param $endTime
* @param $maxNum
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getExpiringList($siteId,$endTime,$maxNum){
$list = Db::name('member_goods_card')->alias('mgc')
->join('member_goods_card_notice mgcn','mgcn.member_goods_card = mgc.card_id','left')
->field('mgc.site_id,mgc.member_id,mgc.card_id')
->where('mgc.site_id',$siteId)
->where('mgc.end_time','<=',$endTime)
->where('mgcn.id IS NULL')
->order('mgc.end_time','ASC')
->limit($maxNum)
->select();
return $list ? $list->toArray() : [];
}
}

View File

@ -0,0 +1,16 @@
<?php
declare (strict_types = 1);
namespace addon\aliapp\event;
/**
* 应用安装
*/
class Install
{
/**
* 执行安装
*/
public function handle()
{
return success();
}
}

View File

@ -0,0 +1,83 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
use addon\aliapp\model\AliPayMessage;
use app\model\NewBaseModel;
use think\facade\Db;
class NoticeImpendingExpiration{
private $limit = 10;
public function handle($param = []){
$this->noticeMessageHandle();
return $param;
}
/**
* Common: 权益即将过期通知
* Author: wu-hui
* Time: 2023/01/11 10:43
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function noticeMessageHandle(){
// 获取通知列表
$list = $this->getList();
$updateData = [];
foreach($list as $item){
// 发送通知
$res = (new AliPayMessage($item['site_id']))->sendMessage($item['member_id'],'INTEREST_EXPIRATION_NOTICE',[
'store_name' => $item['store_name'],// 商家名称
'surplus' => (int)$item['surplus'],// 剩余次数
'content' => $item['goods_name'],// 优惠内容
]);
// 发送成功
if($res['code'] == 0){
$updateData[] = [
'id' => $item['id'],
'time_notice' => time(),
'is_notice' => 1,
];
}
}
(new NewBaseModel(['table_name'=>'member_goods_card_notice']))->saveAll($updateData);
}
/**
* Common: 获取通知列表
* Author: wu-hui
* Time: 2023/01/11 10:38
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getList(){
$list = Db::name('member_goods_card_notice')->alias('mgcn')
->join('member_goods_card mgc','mgcn.member_goods_card = mgc.card_id','left')
->join('store','mgc.store_id = store.store_id','left')
->field('mgcn.id,mgc.site_id,mgc.member_id,mgc.goods_name,(mgc.total_num - mgc.total_use_num) as surplus,store.store_name')
->where('mgcn.id','>',0)
->where('mgcn.is_notice',0)
->order('mgcn.id','ASC')
->limit($this->limit)
->select();
return $list ? $list->toArray() : [];
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
use addon\aliapp\model\AliPaySubLedger;
use think\facade\Log;
class OrderPay{
public function handle($param = []){
Log::write('支付回调 - 分账 —— 确认结算:'.json_encode($param, JSON_UNESCAPED_UNICODE));
if($param['order_id']) (new AliPaySubLedger($param['site_id']))->settleConfirm($param['order_id']);
return $param;
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
use addon\aliapp\model\CloudPay;
class PayNotify
{
/**
* 支付方式及配置
*/
public function handle()
{
$order=new CloudPay();
if (isset($_POST[ 'service' ])) {
unset($_POST['sign_type']);
$order->payNotify($_POST);
}
}
}

View File

@ -0,0 +1,33 @@
<?php
declare (strict_types = 1);
namespace addon\aliapp\event;
use addon\weapp\model\Weapp;
/**
* 二维码
*/
class Qrcode
{
/**
* 二维码生成获取
*/
public function handle($param)
{
if ($param["app_type"] == 'aliapp' || $param["app_type"] == 'all') {
// if ($param["app_type"] == 'all') $param["app_type"] = 'toutiao';
// $weapp = new Weapp();
// if ($param["type"] == 'create') {
// $res = $weapp->createQrcode($param);
// } else {
// $filename = $param['qrcode_path'] . '/' . $param['qrcode_name'] . '_' . $param['app_type'] . '.png';
// if (file_exists($filename)) {
// $res = success(0, '', ['path' => $filename]);
// } else {
// $res = $weapp->createQrcode($param);
// }
// }
// return $res;
}
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
/**
* 微信小程序
*/
class ShowPromotion
{
/**
* 活动展示
*
* @return multitype:number unknown
*/
public function handle()
{
$data = [
'shop' => [
[
//插件名称
'name' => 'aliapp',
//店铺端展示分类 shop:营销活动 member:互动营销
'show_type' => 'tool',
//展示主题
'title' => '支付宝小程序',
//展示介绍
'description' => '支付宝小程序',
//展示图标
'icon' => 'addon/aliapp/icon.png',
//跳转链接
'url' => 'aliapp://shop/aliapp/setting',
//是否开发中仅展示
'is_developing' => 0
]
]
];
return $data;
}
}

View File

@ -0,0 +1,34 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\event;
use addon\aliapp\model\AliPaySubLedger;
use think\facade\Db;
use think\facade\Log;
class SubLedger{
public function handle($param = []){
$orderId = $param['relate_id'] ?? 0;
if($orderId > 0){
$siteId = Db::name('order')->where('order_id',$orderId)->value('site_id');
(new AliPaySubLedger($siteId))->orderSettle($orderId);
}
return $param;
}
}

View File

@ -0,0 +1,19 @@
<?php
declare (strict_types = 1);
namespace addon\aliapp\event;
/**
* 应用卸载
*/
class UnInstall
{
/**
* 执行卸载
*/
public function handle()
{
return success();
}
}

BIN
addon/aliapp/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,534 @@
<?php
namespace addon\aliapp\model;
use app\model\BaseModel;
use think\Exception;
use think\facade\Db;
use app\model\NewBaseModel;
/**
* Common: 支付宝小程序相关操作
* Author: wu-hui
* Time: 2022/12/29 15:10
* Class AliPayApplet
* @package addon\aliapp\model
*/
class AliPayApplet extends BaseModel{
protected $site_id;
// 小程序模板信息
private $templateInfo = [];
// 小程序投放的端com.alipay.alipaywallet=支付宝端。com.alipay.iot.xpaas=支付宝IoT端。
private $bundle_id = 'com.alipay.alipaywallet';
public function __construct($siteId){
$this->site_id = $siteId;
$this->templateInfo=config('alipay.templateInfo');
}
/**
* Common: 小程序发布记录 查询集合
* Author: wu-hui
* Time: 2022/12/29 18:38
* @return Db
*/
private function appletReleaseSelectCollection($type){
return Db::name('applet_release')
->where('site_id',$this->site_id)
->where('type',$type);
}
/**
* Common: 获取已发布的最新版本
* Author: wu-hui
* Time: 2023/01/03 16:41
* @return string
*/
public function newestVersion():string{
$version = (string)$this->appletReleaseSelectCollection(1)
->order(['create_time'=>'desc','id'=>'desc'])
->value('version');
return !empty($version) ? $version : '0.0.0';
}
/**
* Common: 判断:当前版本是否为最新版本
* Author: wu-hui
* Time: 2023/01/03 17:07
* @return bool
*/
public function isNewestVersion():bool{
$version = (string) config('alipay.templateInfo.template_version');// 当前系统版本
$newestVersion = (string)$this->newestVersion();// 最新版本
return (boolean)version_compare($version, $newestVersion, '>');
}
/**
* Common: 发布流程处理 —— 开始处理
* Author: wu-hui
* Time: 2023/01/04 10:49
* @param $type
* @param $id
* @return array
*/
public function publishingInit($type,$id){
try{
// 根据操作类型获取对应信息
$config = $this->publishingConfig($type);
[$params,$textParams] = $this->publishingParams($type,$id);
// 发起请求
$result = (new MinCode($this->site_id))->requestApi($config['api'], $params,$textParams);
$result = $result[$config['result_key']] ?? ['code' => 0];
if($result['code'] == 10000) {
$res = $this->resultProcessing($type,$id,$result);
if($res) return success(0,$res);
else return $this->success();
}else{
return $this->error('',$result['sub_msg']);
}
}catch(\Exception $e){
return $this->error('',$e->getMessage());
}
}
/**
* Common: 发布流程处理 —— 根据操作类型获取配置信息
* Author: wu-hui
* Time: 2023/01/04 10:09
* @param $type
* @return string[]
* @throws Exception
*/
private function publishingConfig($type):array{
$list = [
'delete' => [
'api' => 'alipay.open.mini.version.delete', // 请求接口
'result_key' => 'alipay_open_mini_version_delete_response',// 返回结果字段名称
],
'release_experience_version' => [
'api' => 'alipay.open.mini.experience.create',
'result_key' => 'alipay_open_mini_experience_create_response',
],
'cancel_experience_version' => [
'api' => 'alipay.open.mini.experience.cancel',
'result_key' => 'alipay_open_mini_experience_cancel_response',
],
'see_experience_version' => [
'api' => 'alipay.open.mini.experience.query',
'result_key' => 'alipay_open_mini_experience_query_response',
],
'audit_submit' => [
'api' => 'alipay.open.mini.version.audit.apply',
'result_key' => 'alipay_open_mini_version_audit_apply_response',
],
'audit_cancel' => [
'api' => 'alipay.open.mini.version.audit.cancel',
'result_key' => 'alipay_open_mini_version_audit_cancel_response',
],
'audited_cancel' => [
'api' => 'alipay.open.mini.version.audited.cancel',
'result_key' => 'alipay_open_mini_version_audited_cancel_response',
],
'version_online' => [
'api' => 'alipay.open.mini.version.online',
'result_key' => 'alipay_open_mini_version_online_response',
],
'version_gray_online' => [
'api' => 'alipay.open.mini.version.gray.online',
'result_key' => 'alipay_open_mini_version_gray_online_response',
],
'version_gray_cancel' => [
'api' => 'alipay.open.mini.version.gray.cancel',
'result_key' => 'alipay_open_mini_version_gray_cancel_response',
],
'version_offline' => [
'api' => 'alipay.open.mini.version.offline',
'result_key' => 'alipay_open_mini_version_offline_response',
],
'version_rollback' => [
'api' => 'alipay.open.mini.version.rollback',
'result_key' => 'alipay_open_mini_version_rollback_response',
],
'version_upload' => [
'api' => 'alipay.open.mini.version.upload',
'result_key' => 'alipay_open_mini_version_upload_response',
],
];
if($list[$type]) return $list[$type];
else throw new Exception('无效的操作!');
}
/**
* Common: 发布流程处理 —— 根据操作类型生成接口请求参数
* Author: wu-hui
* Time: 2023/01/04 10:32
* @param $type
* @param $id
* @return array[]
* @throws Exception
*/
private function publishingParams($type,$id){
$params = $textParams = [];
// 根据类型进行对应的操作
switch($type){
case 'delete':
case 'release_experience_version':
case 'cancel_experience_version':
case 'see_experience_version':
case 'audit_cancel':
case 'audited_cancel':
case 'version_online':
case 'version_gray_cancel':
case 'version_offline':
case 'version_rollback':
$params = [
'app_version' => $this->getVersion($id),
'bundle_id' => $this->bundle_id,
];
break;
case 'audit_submit':
$version = $this->getVersion($id);
$textParams = [
'region_type' => 'CHINA',
'version_desc' => "发布{$version}版本",
'app_version' => $version, //开发版本 模板ID
'bundle_id' => $this->bundle_id,
'speed_up' => 'false',
'auto_online' => 'auto_online'
];
break;
case 'version_gray_online':
$params = [
'app_version' => $this->getVersion($id),
'gray_strategy' => 'p10',// 枚举支持p10、p30、p50
'bundle_id' => $this->bundle_id,
];
break;
case 'version_upload':
// 获取最新版本
$isNewestVersion = (new AliPayApplet($this->site_id))->isNewestVersion();
if(!$isNewestVersion) throw new Exception('当前版本为最新版本,请勿重复发布!');
// 获取默认门店id
$storeInfo =Db::name('store')
->where('site_id',$this->site_id)
->where('is_default',1)
->field('store_id,store_id,store_name')
->find();
if(empty($storeInfo)) throw new Exception('默认门店不存在,请添加后进行操作!');
// 判断:是否存在小程序配置信息
$hasAccount = Db::name('uni_account')->where('site_id',$this->site_id)->value('id');
if($hasAccount <= 0) throw new Exception('请先配置小程序!');
$ext = [
'extEnable' => true,
'ext' => [
'site_id' => $this->site_id,
'store_id' => $storeInfo['store_id'],
],
'window'=>[
'defaultTitle'=>$storeInfo['store_name']
],
];
$params = [
'template_version' => $this->templateInfo['template_version'],// 小程序模板版本号
'ext' => json_encode($ext),//自定义参数
'template_id' => $this->templateInfo['template_id'],// 小程序模板 APPID
'app_version' => $this->templateInfo['template_version'],//商家小程序版本号
'bundle_id' => $this->bundle_id,
];
break;
default:
throw new Exception('无效的操作!');
}
return [$params,$textParams];
}
/**
* Common: 发布流程处理 —— 根据id获取版本信息
* Author: wu-hui
* Time: 2023/01/04 10:18
* @param $id
* @return mixed
* @throws Exception
*/
private function getVersion($id){
$version = Db::name('applet_release')->where('id',$id)->value('version');
if(!$version) throw new Exception('版本不存在!');
return $version;
}
/**
* Common: 发布流程处理 —— 请求结果处理
* Author: wu-hui
* Time: 2023/01/04 10:46
* @param $type
* @param $id
* @param $result
* @return string
* @throws \think\db\exception\DbException
*/
private function resultProcessing($type,$id,$result){
$returnData = '';
switch($type){
case 'delete':
Db::name('applet_release')->where('id',$id)->delete();
break; // 删除版本
case 'release_experience_version':
$this->appletReleaseSelectCollection(1)->update(['is_experience_version'=>0]);
Db::name('applet_release')->where('id',$id)->update(['is_experience_version'=>1]);
break;// 发布体验版本
case 'cancel_experience_version':
Db::name('applet_release')->where('id',$id)->update(['is_experience_version'=>0]);
break;// 取消体验版发布
case 'see_experience_version':
$statusText = [
'expVersionPackged' => '体验版打包成功',
'expVersionPackaging' => '体验版打包中',
'notExpVersion' => '非体验版',
];
$returnData = $statusText[$result['status']];
break;// 体验版状态查看
case 'audit_submit':
Db::name('applet_release')->where('id',$id)->update(['version_status'=> 'AUDITING']);
break;// 提交审核
case 'audit_cancel':
case 'audited_cancel':
Db::name('applet_release')->where('id',$id)->update(['version_status'=> 'INIT']);
break;// 撤销审核 & 退回开发
case 'version_online':
Db::name('applet_release')->where('id',$id)->update(['version_status'=> 'RELEASE']);
break;//上架
case 'version_gray_online':
Db::name('applet_release')->where('id',$id)->update(['version_status'=> 'GRAY']);
break;//灰度上架
case 'version_gray_cancel':
Db::name('applet_release')->where('id',$id)->update(['version_status'=> 'WAIT_RELEASE']);
break;//结束灰度
case 'version_offline':
Db::name('applet_release')->where('id',$id)->update(['version_status'=> 'OFFLINE']);
break;// 下架
case 'version_rollback':
$this->versionSee($id);
break;// 回滚
case 'version_upload':
$version = config('alipay.templateInfo.template_version');
$data = [
'site_id' => $this->site_id,
'version' => $version,
'type' => 1,
'ali_create_status' => $result['create_status'],
'version_status' => 'INIT',
'create_time' => time(),
];
Db::name('applet_release')->insert($data);
break;// 发布新版本
}
return $returnData;
}
/**
* Common: 版本管理 —— 所有版本同步
* Author: wu-hui
* Time: 2022/12/30 9:58
* @return array
* @throws \Exception
*/
public function versionSynchronization(){
$params = [
'bundle_id' => $this->bundle_id,
// 版本状态INIT=开发中,AUDITING=审核中,AUDIT_REJECT=审核驳回,WAIT_RELEASE=待上架,BASE_AUDIT_PASS=准入不可营销,GRAY=灰度中,RELEASE=已上架,OFFLINE=已下架,AUDIT_OFFLINE: 已下架
'version_status' => 'INIT,AUDITING,AUDIT_REJECT,WAIT_RELEASE,BASE_AUDIT_PASS,GRAY,RELEASE,OFFLINE,AUDIT_OFFLINE',
];
$result = (new MinCode($this->site_id))->requestApi('alipay.open.mini.version.list.query', $params);
$result = $result['alipay_open_mini_version_list_query_response'];
if($result['code'] == 10000) {
// 同步版本信息
$appVersionInfos = $result['app_version_infos'] ?? [];
$hasList = $this->appletReleaseSelectCollection(1)->column('version','id');
$hasListIds = array_flip($hasList);
$insertData = [];
$updateData = [];
foreach($appVersionInfos as $val){
if(!in_array($val['app_version'],$hasList)){
$insertData[] = [
'site_id' => $this->site_id,
'version' => $val['app_version'],
'type' => 1,
'ali_create_status' => 0,
'version_status' => $val['version_status'],
'create_time' => strtotime($val['create_time']),
];
}else{
$updateData[] = [
'id' => $hasListIds[$val['app_version']],
'version_status' => $val['version_status'],
];
}
}
Db::name('applet_release')->insertAll($insertData);
(new NewBaseModel(['table_name'=>'applet_release']))->saveAll($updateData);
return $this->success();
}else{
return $this->error('',$result['sub_msg']);
}
}
/**
* Common: 版本管理 —— 查询小程序版本构建状态
* Author: wu-hui
* Time: 2022/12/29 17:45
* @param $version
* @param $id
* @return array|mixed
* @throws \think\db\exception\DbException
*/
public function versionBuildQuery($version,$id){
$params = [
'app_version' => $version,
'bundle_id' => $this->bundle_id,
];
$result = (new MinCode($this->site_id))->requestApi('alipay.open.mini.version.build.query', $params);
$result = $result['alipay_open_mini_version_build_query_response'];
if($result['code'] == 10000) {
Db::name('applet_release')->where('id',$id)->update(['ali_create_status'=>$result['create_status']]);
return $result['create_status'];
}else{
return $this->error('',$result['sub_msg']);
}
}
/**
* Common: 版本管理 —— 版本详情查询
* Author: wu-hui
* Time: 2022/12/30 16:54
* @param $id
* @return array
* @throws \think\db\exception\DbException
*/
public function versionSee($id){
$version = Db::name('applet_release')->where('id',$id)->value('version');
if(!$version) $this->error('','版本不存在!');
$params = [
'app_version' => $version,
'bundle_id' => $this->bundle_id,
];
$result = (new MinCode($this->site_id))->requestApi('alipay.open.mini.version.detail.query', $params);
$result = $result['alipay_open_mini_version_detail_query_response'];
if($result['code'] == 10000) {
Db::name('applet_release')->where('id',$id)->update(['version_status'=>$result['status']]);
return success(0,'版本详情',$result);
}else{
return $this->error('',$result['sub_msg']);
}
}
/**
* Common: 生成小程序推广二维码
* Author: wu-hui
* Time: 2023/01/03 14:12
* @return array
*/
public function qrcodeCreate(){
$cacheName = 'alipay_open_app_qrcode_create_response_'.$this->site_id;
// 缓存操作
$result = cache($cacheName);
if($result){
return $this->success($result);
}else{
// 获取默认门店id
$storeId = (int)Db::name('store')
->where('site_id',$this->site_id)
->where('is_default',1)
->value('store_id');
if($storeId <= 0) $this->error('','默认门店不存在,请添加后进行操作!');
$params = [
'url_param' => 'pages/index/index',// 访问页面路径
'query_param' => 'site_id='.$this->site_id.'&store_id='.$storeId,// 小程序的启动参数
'describe' => '小程序预览',//对应的二维码描述
'color' => '',
'size' => 'l',// 合成后图片的大小(s -- 8cm, m -- 12cm, l -- 30cm)
];
$result = (new MinCode($this->site_id))->requestApi('alipay.open.app.qrcode.create', $params);
$result = $result['alipay_open_app_qrcode_create_response'];
// 返回结果
if($result['code'] == 10000) {
cache($cacheName,$result);
return $this->success($result);
}else{
return $this->error('',$result['sub_msg']);
}
}
}
public function queryTestQrcode($version){
$params['app_version']=$version;
// (new MinCode($this->site_id))->requestApi('alipay.open.mini.experience.create', $params);
$result = (new MinCode($this->site_id))->requestApi('alipay.open.mini.experience.query', $params);
$result = $result['alipay_open_mini_experience_query_response'];
// 返回结果
if($result['code'] == 10000) {
return $this->success($result);
}else{
return $this->error('',$result['sub_msg']);
}
}
/**
* Common: 登录 —— 获取用户基本信息
* Author: wu-hui
* Time: 2023/01/05 13:33
* @param string $code
* @param string $grantType
* @param string $refreshToken
* @return array
*/
public function loginBaseInfo($code = '',$grantType = 'authorization_code',$refreshToken = ''){
// authorization_code=换取授权令牌access_tokenrefresh_token=刷新获取新授权令牌。
$textParams = [
'grant_type' => $grantType
];
if($grantType == 'refresh_token') $textParams['refresh_token'] = $refreshToken;
else if($grantType == 'authorization_code') $textParams['code'] = $code;
// 发起请求
$result = (new MinCode($this->site_id))->requestApi('alipay.system.oauth.token',[], $textParams);
$result = $result['alipay_system_oauth_token_response'] ?? $result['error_response'];
// 返回结果
if(array_key_exists('user_id',$result)) {
return $this->success($result);
}else{
return $this->error('',$result['sub_msg']);
}
}
/**
* Common: 登录 —— 获取用户详细信息
* Author: wu-hui
* Time: 2023/01/05 14:04
* @param $authToken
* @return array
*/
public function loginDetailsInfo($authToken){
// 发起请求
$result = (new MinCode($this->site_id))->requestMemberApi($authToken,'alipay.user.info.share');
$result = $result['alipay_user_info_share_response'] ?? $result['error_response'];
// 返回结果
if($result['code'] == 10000) {
return $this->success($result);
}else{
return $this->error('',$result['sub_msg']);
}
}
}

View File

@ -0,0 +1,188 @@
<?php
namespace addon\aliapp\model;
use app\model\BaseModel;
use think\facade\Db;
use app\model\NewBaseModel;
/**
* Common: 支付宝小程序应用成员管理
* Author: wu-hui
* Time: 2022/12/30 12:02
* Class AliPayMember
* @package addon\aliapp\model
*/
class AliPayMember extends BaseModel{
protected $site_id;
public function __construct($siteId){
$this->site_id = $siteId;
}
/**
* Common: 小程序成员管理 查询集合
* Author: wu-hui
* Time: 2022/12/29 18:38
* @return Db
*/
private function appletMemberCollection($type){
return Db::name('applet_member')
->where('site_id',$this->site_id)
->where('type',$type);
}
/**
* Common: 获取成员列表
* Author: wu-hui
* Time: 2022/12/30 13:51
* @return array
* @throws \think\db\exception\DbException
*/
public function getList(){
// 参数获取
$page = input('page',1);
$pageSize = input('page_size',PAGE_LIST_ROWS);
// 列表获取
$field = [
'id',
'user_id',
'nick_name',
'status',
'gmt_join',
'logon_id',
'gmt_invite',
'role'
];
$result = $this->appletMemberCollection(1)
->field($field)
->order(['gmt_join'=>'DESC','gmt_invite'=>'DESC'])
->paginate(['list_rows' => $pageSize,'page' => $page]);
if($result) {
$result = $result->toArray();
$list = [
'count' => $result['total'],
'list' => $result['data'],
'page_count' => $result['last_page'],
];
return $this->success($list);
}
return $this->success();
}
/**
* Common: 同步成员
* Author: wu-hui
* Time: 2022/12/30 13:46
* @param $role
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function synchronizationMember($role){
$params = ['role' => $role];
$result = (new MinCode($this->site_id))->requestApi('alipay.open.app.members.query',$params);
$result = $result['alipay_open_app_members_query_response'];
if($result['code'] == 10000) {
$list = $result['app_member_info_list'] ?? [];
$hasList = $this->appletMemberCollection(1)->field('id,logon_id')->select();
$logonIds = $ids = [];
if($hasList){
$hasList = $hasList->toArray();
$logonIds = array_column($hasList,'logon_id');
$ids = array_column($hasList,'id','logon_id');
}
$insertData = [];
$updateData = [];
foreach($list as $item){
// 判断:当前用户是 新增加成员 还是 旧的成员
if(!in_array($item['logon_id'],$logonIds)){
// 不存在 新增成员
$insertData[] = [
'site_id' => $this->site_id,
'type' => 1,
'user_id' => $item['user_id'] ?? '',
'nick_name' => $item['nick_name'] ?? '',
'status' => $item['status'] ?? '',
'gmt_join' => $item['gmt_join'] ?? '',
'logon_id' => $item['logon_id'] ?? '',
'gmt_invite' => $item['gmt_invite'] ?? '',
'role' => $item['role'] ?? '',
];
}
else if(in_array($item['logon_id'],$logonIds)){
// 存在 修改成员
$updateData[] = [
'id' => $ids[$item['logon_id']],
'nick_name' => $item['nick_name'] ?? '',
'status' => $item['status'] ?? '',
'role' => $item['role'] ?? ''
];
}
}
Db::name('applet_member')->insertAll($insertData);
(new NewBaseModel(['table_name'=>'applet_member']))->saveAll($updateData);
return success(0,'同步完成');
}else{
return $this->error('',$result['sub_msg']);
}
}
/**
* Common: 添加成员
* Author: wu-hui
* Time: 2022/12/30 14:27
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function addMember(){
$info = input('info');
$params = [
'logon_id' => $info['logon_id'],
'role' => $info['role'],
];
$result = (new MinCode($this->site_id))->requestApi('alipay.open.app.members.create',$params);
$result = $result['alipay_open_app_members_create_response'];
if($result['code'] == 10000) {
$this->synchronizationMember($info['role']);
return success(0,'添加成功');
}else{
return $this->error('',$result['sub_msg']);
}
}
/**
* Common: 删除成员
* Author: wu-hui
* Time: 2022/12/30 14:41
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function delMember(){
$id = input('id');
$info = Db::name('applet_member')->field('user_id,role')->where('id',$id)->find();
if(!$info) return $this->error('','不存在的成员!');
$params = [
'user_id' => $info['user_id'],
'role' => $info['role'],
];
$result = (new MinCode($this->site_id))->requestApi('alipay.open.app.members.delete',$params);
$result = $result['alipay_open_app_members_delete_response'];
if($result['code'] == 10000) {
Db::name('applet_member')->where('id',$id)->delete();
return success(0,'删除成功');
}else{
return $this->error('',$result['sub_msg']);
}
}
}

View File

@ -0,0 +1,357 @@
<?php
namespace addon\aliapp\model;
use app\model\BaseModel;
use think\Exception;
use think\facade\Db;
/**
* Common: 支付宝消息相关
* Author: wu-hui
* Time: 2023/01/04 14:52
* Class AliPayMessage
* @package addon\aliapp\model
*/
class AliPayMessage extends BaseModel{
protected $site_id;
public function __construct($siteId){
$this->site_id = $siteId;
}
/**
* Common: 订单中心 —— 订单同步
* Author: wu-hui
* Time: 2023/01/04 17:40
* @param int $zmOrderId zm_order表id
* @param string $orderStatus 订单状态
* @param string $refundPath 退款路径 例:花呗
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function orderSynchronization(int $zmOrderId,string $orderStatus,string $refundPath = ''){
// $orderStatus 订单状态:下单成功=CREATE已退款=REFUNDED核销成功=FINISHED
$siteName = Db::name('site')->where('site_id',$this->site_id)->value('site_name');
if($siteName) return $this->error('','未设置店铺(站点)名称!');
// 参数获取
$appid = $this->getAppid();// 获取小程序id
$info = $this->getOrderInfo($zmOrderId);// 获取订单信息
$cardInfo = $this->getCardInfo($info['order_id']); // 获取用户会员卡id
$backUrl = $cardInfo['card_id'] > 0 ? 'pages/card/my_detail?card_id='.$cardInfo['card_id'] : 'pages/card/my_card';
$params = [
'out_biz_no' => $info['out_trade_no'],// 外部订单号
'buyer_id' => $info['userid'],// 买家userId
'amount' => $info['amount'],// 订单金额,单位为【元】
'pay_amount' => $info['amount'],// 支付金额,单位为【元】
'order_type' => 'SERVICE_ORDER',// 订单类型新接入商户统一传入SERVICE_ORDER(服务订单)
//'discount_amount' => '',// 优惠金额,单位为【元】
//'trade_no' => $info['trade_no'],// 订单所对应的支付宝交易号
'order_create_time' => date('Y-m-d H:i:s',$info['create_time']),// 订单创建时间 当order_type为SERVICE_ORDER时必传 日期
'order_pay_time' => $info['pay_time'] > 0 ? date('Y-m-d H:i:s',$info['pay_time']) : '',// 订单支付时间 当pay_channel为非ALIPAY时 且订单状态已流转到“支付”或支付后时,需要将支付时间传入
//'send_msg' => 'Y',// 是否需要小程序订单代理发送模版消息Y代表需要发送N代表不需要发送不传默认不发送
'ext_info' => [
['ext_key' => 'merchant_biz_type','ext_value' => 'MERCHANT_SECURITIES'],
['ext_key' => 'merchant_order_status','ext_value' => $orderStatus],
['ext_key' => 'tiny_app_id','ext_value' => $appid],
['ext_key' => 'merchant_order_link_page','ext_value' => $backUrl],
[
'ext_key' => 'business_info',
'ext_value' => json_encode([
//'note' => $note,
'refund_path' => $refundPath,
'expiration_time' => date('Y-m-d H:i:s',$cardInfo['end_time']),
'charge_off_time' => date('Y-m-d H:i:s',time()),
])
]
],
'order_modified_time' => date('Y-m-d H:i:s',time()),// 订单修改时间
'item_order_list' => $this->getGoodsInfo($info['order_id']), // 商品信息
'ticket_info' => [
'resv_type' => 'RESERVATION',
],
'shop_info' => [
'name' => $siteName,
],
];
// 发起请求
$result = (new MinCode($this->site_id))->requestApi('alipay.merchant.order.sync', $params,[]);
$result = $result['alipay_merchant_order_sync_response'];
if($result['code'] == 10000) {
return $this->success($result);
}else{
return $this->error('',$result['sub_msg']);
}
}
/**
* Common: 订单中心 —— 获取小程序id
* Author: wu-hui
* Time: 2023/01/04 16:15
* @return mixed
*/
public function getAppid(){
return Db::name('uni_account')
->where('site_id',$this->site_id)
->where('app_type','=','aliapp')
->value('appid');
}
/**
* Common: 订单中心 —— 订单信息
* Author: wu-hui
* Time: 2023/01/04 16:16
* @param $zmOrderId
* @return array|mixed|Db|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOrderInfo($zmOrderId){
$field = [
'zo.order_id',
'zo.userid',
'zo.amount',
'zo.trade_no',
'zo.create_time',
'zo.pay_time',
'zo.out_trade_no',
'order.order_no',
];
return Db::name('zm_order')
->alias('zo')
->field($field)
->join('order','zo.order_id = order.order_id','left')
->where('zo.id',$zmOrderId)
->find();
}
/**
* Common: 订单中心 —— 获取会员卡信息
* Author: wu-hui
* Time: 2023/01/04 16:44
* @param $orderId
* @return array|mixed|Db|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getCardInfo($orderId){
return Db::name('member_goods_card')
->field('card_id,end_time')
->where('order_id',$orderId)
->find();
}
/**
* Common: 获取商品信息
* Author: wu-hui
* Time: 2023/01/04 16:28
* @param $orderId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getGoodsInfo($orderId){
// 获取商品列表
$list = Db::name('order_goods')
->field('sku_name')
->where('order_id',$orderId)
->select();
if($list){
$list = $list->toArray();
$data = [];
// 循环处理
foreach($list as $item){
$data[] = [
'item_name' => $item['sku_name']
];
}
return $data;
}
return [
['item_name' => '商品名称']
];
}
/**
* Common: 订阅消息发送 —— 开始
* Author: wu-hui
* Time: 2023/01/10 16:12
* @param $uid
* @param $keywords
* @param array $params
* @param string $page
* @return array
*/
public function sendMessage($uid,$keywords,$params = [],$page = 'pages/index/index'){
try{
// 通过用户user_id
$userId = Db::name('member')->where('member_id',$uid)->value('ali_openid');
if(!$userId) return $this->error('','用户不存在支付宝小程序user_id');
// 判断:用户是否订阅当前消息
$subscribeInfo = $this->userIsSubscribeMessage($uid,$keywords);
// 消息发送
$sendData = $this->getSendData($keywords,$params);
$params = [
'to_user_id' => $userId,
'user_template_id' => $subscribeInfo['template_id'],
'page' => $page,
'data' => json_encode($sendData,JSON_UNESCAPED_UNICODE),
];
// 发起请求
$result = (new MinCode($this->site_id))->requestApi('alipay.open.app.mini.templatemessage.send', $params,[]);
$result = $result['alipay_open_app_mini_templatemessage_send_response'];
if($result['code'] == 10000) {
// 发送成功后的处理
Db::name('message_form_id')->where($subscribeInfo)->delete();// 删除记录
// 发送记录
$this->sendLog($keywords,$params,$result,1);
return $this->success($result);
}else{
// 发送记录
$this->sendLog($keywords,$params,$result,0);
return $this->error('',$result['sub_msg']);
}
}catch(Exception $e){
// 发送记录
$this->sendLog($keywords,$params,['error_msg'=>$e->getMessage()],0);
return $this->error('',$e->getMessage());
}
}
/**
* Common: 订阅消息发送 —— 判断:用户是否订阅当前消息
* Author: wu-hui
* Time: 2023/01/10 15:13
* @param $uid
* @param $keywords
* @return array|mixed|Db|\think\Model
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function userIsSubscribeMessage($uid,$keywords){
// 获取模板id
$templateId = Db::name('message')
->where('site_id',$this->site_id)
->where('keywords',$keywords)
->where('aliapp_is_open',1)
->value('aliapp_template_id');
if(!$templateId) throw new Exception('当前模板消息未开启或未设置!');
// 获取用户订阅消息
$subscribeInfo = Db::name('message_form_id')
->where('template_id',$templateId)
->where('uid',$uid)
->where('type','aliapp')
->order('create_time','ASC')
->find();
if(!$subscribeInfo) throw new Exception('当前用户未订阅该信息!');
return $subscribeInfo;
}
/**
* Common: 订阅消息发送 —— 获取发送信息
* Author: wu-hui
* Time: 2023/01/10 15:40
* @param $keywords
* @param $params
* @return mixed
* @throws Exception
*/
private function getSendData($keywords,$params){
// 键名转驼峰 方法名称
$nameArr = array_map(function($item){
return ucwords(strtolower($item));
},explode('_',$keywords));
$classList = get_class_methods(self::class);
$className = 'message'.implode($nameArr);
if(in_array($className,$classList)) return $this->$className($params);
else throw new Exception('未获取发送信息!');
}
/**
* Common: 订阅消息发送 —— 发送记录
* Author: wu-hui
* Time: 2023/01/10 16:10
* @param $keywords
* @param $params
* @param $sendResult
* @param $isSuccess
* @return int|string
*/
private function sendLog($keywords,$params,$sendResult,$isSuccess){
$sendLog = [
'site_id' => $this->site_id,
'keywords' => $keywords,
'message_type' => 'aliapp',
'addon' => '',
'title' => '',
'message_json' => json_encode($params,JSON_UNESCAPED_UNICODE),
'create_time' => time(),
'send_time' => time(),
'send_log' => json_encode($sendResult,JSON_UNESCAPED_UNICODE),
'is_success' => $isSuccess,
];
return Db::name('message_send_log')->insert($sendLog);
}
/**
* Common: 订阅消息发送信息 —— 权益即将过期通知
* Author: wu-hui
* Time: 2023/01/10 15:40
* @param $params
* @return array[]
*/
private function messageInterestExpirationNotice($params){
return [
'keyword1' => ['value' => $params['store_name']], // 商家名称
'keyword2' => ['value' => $params['surplus']],// 剩余次数
'keyword3' => ['value' => $params['content']],// 优惠内容
];
}
/**
* Common: 订阅消息发送信息 —— 服务开通成功提醒
* Author: wu-hui
* Time: 2023/01/10 15:40
* @param $params
* @return array[]
*/
private function messageServiceOpenedSuccess($params){
return [
'keyword1' => ['value' => $params['end_time']], // 到期时间 日期2022年1月18日
'keyword2' => ['value' => $params['nickname']],// 姓名
'keyword3' => ['value' => $params['start_time']],// 开通时间 日期2022年1月18日
'keyword4' => ['value' => $params['content']],// 服务项目
];
}
/**
* Common: 订阅消息发送信息 —— 核销提醒
* Author: wu-hui
* Time: 2023/01/10 15:40
* @param $params
* @return array[]
*/
private function messageVerify($params){
return [
'keyword1' => ['value' => $params['goods_name']], // 核销产品
'keyword2' => ['value' => $params['store_name']],// 核销商户
'keyword3' => ['value' => $params['start_time']],// 核销时间 日期2022年1月18日
];
}
}

View File

@ -0,0 +1,394 @@
<?php
namespace addon\aliapp\model;
use app\model\BaseModel;
use app\model\system\Cron;
use think\Exception;
use think\facade\Db;
use think\facade\Log;
use addon\saasagent\model\SiteWebsite;
/**
* Common: 支付宝分账相关操作
* Author: wu-hui
* Time: 2023/01/29 14:46
* Class AliPaySubLedger
* @package addon\aliapp\model
*/
class AliPaySubLedger extends BaseModel{
protected int $site_id;
public function __construct($siteId){
$this->site_id = (int)$siteId;
}
/**
* Common: 分账关系绑定
* Author: wu-hui
* Time: 2023/01/29 16:06
* @param $websiteId
* @return array
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function relationBind($websiteId){
// 请求参数获取
$params = $this->relationParams($websiteId);
$textParams = [];
// 发起请求
$result = (new OpenPay($this->site_id))->requestApi('alipay.trade.royalty.relation.bind', $params,$textParams);
$result = $result['alipay_trade_royalty_relation_bind_response'];
if($result['code'] == 10000) return $this->success();
else throw new Exception($result['sub_msg']);
}
/**
* Common: 分账关系解绑
* Author: wu-hui
* Time: 2023/01/29 16:18
* @param $websiteId
* @return array
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function relationUnbind($websiteId){
// 请求参数获取
$params = $this->relationParams($websiteId);
$textParams = [];
// 发起请求
$result = (new OpenPay($this->site_id))->requestApi('alipay.trade.royalty.relation.unbind', $params,$textParams);
$result = $result['alipay_trade_royalty_relation_unbind_response'];
if($result['code'] == 10000) return $this->success();
else throw new Exception($result['sub_msg']);
}
/**
* Common: 分账关系查询
* Author: wu-hui
* Time: 2023/02/01 11:22
* @return array
* @throws Exception
*/
public function relationBatchQuery(){
// 请求参数获取
$params = [
'page_num' => 1,
'page_size' => 100,
'out_request_no' => $this->outRequestNo(0,'BDGX')
];
$textParams = [];
// 发起请求
$result = (new OpenPay($this->site_id))->requestApi('alipay.trade.royalty.relation.batchquery', $params,$textParams);
$result = $result['alipay_trade_royalty_relation_batchquery_response'];
if($result['code'] == 10000) return $this->success($result);
else throw new Exception($result['sub_msg']);
}
/**
* Common: 分账关系绑定|解绑 参数获取
* Author: wu-hui
* Time: 2023/01/29 15:47
* @param $websiteId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function relationParams($websiteId){
// 合伙人信息获取
$info = Db::name('website')->field('alipay_account,web_contacts')->where('id',$websiteId)->find();
// 店铺名称获取
$siteInfo = Db::name('site')->field('site_name,username')->where('site_id',$this->site_id)->find();
$siteName = $siteInfo['site_name'] ? : $siteInfo['username'];
return [
'receiver_list' => [
'type' => 'loginName',// 分账接收方方类型loginName表示是支付宝登录号
'account' => $info['alipay_account'],// 分账接收方账号当分账方类型是loginName时本参数为用户的支付宝登录号
//'account_open_id' => '',// 分账接收方openId
'name' => $info['web_contacts'],// 当分账方类型是loginName时本参数必传。
'memo' => "[{$siteName}]分账给[{$info['web_contacts']}]",// 分账关系描述
'login_name' => $info['alipay_account'],// 作为查询返回结果
'bind_login_name' => $info['alipay_account'],// 作为查询返回结果
],
'out_request_no' => $this->outRequestNo($websiteId)
];
}
/**
* Common: 生成外部唯一请求号
* Author: wu-hui
* Time: 2023/01/29 15:30
* @param $websiteId
* @param string $prefix
* @return string
*/
private function outRequestNo($websiteId,$prefix = 'SL'){
// 基础内容
$timeStr = $prefix.date('ymdHis').'S'.$this->site_id.'W'.$websiteId;
// 保证不重复 偏移操作
$cacheName = $this->site_id.'_'.$websiteId.'_'.$timeStr;
$maxNo = (int)cache($cacheName);
$order_no = $timeStr.'N'.$maxNo;
cache($cacheName,++$maxNo,5);
return $order_no;
}
/**
* Common: 分账 —— 确认结算
* Author: wu-hui
* Time: 2023/02/01 15:29
* @param int $orderId
* @return false|void
*/
public function settleConfirm(int $orderId){
try{
// 获取当前订单状态
$tradeQuery = $this->tradeQuery($orderId)['data'];
if($tradeQuery['trade_status'] != 'TRADE_SUCCESS') throw new Exception('当前订单不允许分账!订单状态:'.$tradeQuery['trade_status']);
if($orderId <= 0) throw new Exception("订单id错误 {$orderId}");
// 获取订单信息
$orderInfo = $this->getOrderInfo($orderId);
// 获取所有需要分红的合伙人信息
$siteWebsite = (new SiteWebsite())->getWholeSiteWebsiteList($orderInfo['site_id'])['data'];
if(!$siteWebsite) throw new Exception("没有合伙人订单id {$orderId}");
// 生成每个合伙人的分账信息
$insertData = [];
$time = time();
foreach($siteWebsite as $siteWebsiteInfo){
$insertData[] = [
'site_id' => $orderInfo['site_id'],
'order_id' => $orderInfo['order_id'],// 订单id
'trade_no' => $orderInfo['trade_no'],// 支付宝订单号
'trans_in' => $siteWebsiteInfo['alipay_account'],// 收入方账户
'amount' => sprintf("%.2f",($orderInfo['pay_money'] * ($siteWebsiteInfo['rate'] / 100))),// 添加时间
'website_id' => $siteWebsiteInfo['website_id'],
'create_time' => $time
];
}
Db::name('sub_ledger')->insertAll($insertData);
// 添加计划任务
$cron_model = new Cron();
$cron_model->addCron(1, 0, '分账确认结算', 'SettleConfirmSubLedger', strtotime('+1 minute', time()), $orderInfo['order_id']);
/*
// 配置信息
$params = [
'out_request_no' => $this->outRequestNo(0,'JS'),//确认结算请求流水号,开发者自行生成并保证唯一性,作为业务幂等性控制
'trade_no' => $orderInfo['trade_no'] ?? 0,// 支付宝交易号
'settle_info' => [
'settle_detail_infos' => [
[
// cardAliasNo结算收款方的银行卡编号;userId表示是支付宝账号对应的支付宝唯一用户号;loginName表示是支付宝登录号defaultSettle表示结算到商户进件时设置的默认结算账号结算主体为门店时不支持传defaultSettle
'trans_in_type' => 'defaultSettle',
// 结算收款方。当结算收款方类型是cardAliasNo时本参数为用户在支付宝绑定的卡编号结算收款方类型是userId时本参数为用户的支付宝账号对应的支付宝唯一用户号以2088开头的纯16位数字当结算收款方类型是loginName时本参数为用户的支付宝登录号当结算收款方类型是defaultSettle时本参数不能传值保持为空。
'trans_in' => '',
// 结算汇总维度按照这个维度汇总成批次结算由商户指定。目前需要和结算收款方账户类型为cardAliasNo配合使用
//'summary_dimension' => '',
// 结算主体标识。当结算主体类型为SecondMerchant时为二级商户的SecondMerchantID当结算主体类型为Store时为门店的外标。
//'settle_entity_id' => $payShopInfo['zmalipay_value']['smid'],
// 结算主体类型。二级商户:SecondMerchant;商户或者直连商户门店:Store
//'settle_entity_type' => 'SecondMerchant',
// 结算的金额,单位为元。在创建订单和支付接口时必须和交易 金额相同。在结算确认接口时必须等于交易金额减去已退款金额。直付通账期模式下如使用部分结算能力、传递了actual_amount字段则忽略本字段的校验、可不传。
//'amount' => 0.1,//$orderInfo['pay_money'] ?? 0,
// 仅在直付通账期模式场景下单笔交易需要分多次发起部分确认结算时使用表示本次确认结算的实际结算金额。传递本字段后原amount字段不再生效结算金额以本字段为准。
'actual_amount' => $orderInfo['pay_money'] ?? 0,
]
],
],
'extend_params' => [
'royalty_freeze' => 'true',// 是否进行资金冻结用于后续分账true表示冻结false或不传表示不冻结
],
];
// 发起请求
$result = (new OpenPay())->requestApi('alipay.trade.settle.confirm', $params, []);
$result = $result['alipay_trade_settle_confirm_response'];
if($result['code'] == 10000) return $this->success();
else throw new Exception($result['sub_msg']);
*/
}
catch(Exception $e){
Log::write("分账 - 确认结算:".$e->getMessage());
return false;
}
}
/**
* Common: 分账 —— 分账请求
* Author: wu-hui
* Time: 2023/02/01 17:08
* @param $orderId
* @return array|false
* @throws \think\db\exception\DbException
*/
public function orderSettle($orderId){
$time = time();
try{
// 获取所有分账信息
$subLedgerList = Db::name('sub_ledger')
->field(['trade_no','trans_in','amount'])
->where('order_id',$orderId)
->select();
if($subLedgerList) $subLedgerList = $subLedgerList->toArray();
else throw new Exception('不存在分账信息!');
// 基本参数
$outRequestNo = $this->outRequestNo(0,'FZ');//结算请求流水号
$tradeNo = array_column($subLedgerList,'trade_no')[0];
// 循环生成分账信息
$royaltyParameters = [];
foreach($subLedgerList as $subLedgerInfo){
$royaltyParameters[] = [
//'royalty_type' => 'transfer',//分账类型普通分账为transfer;补差为replenish;为空默认为分账transfer;
//'trans_out' => 'zoomtk@126.com',// 支出方账户
//'trans_out_type' => 'loginName',// 支出方账户类型
'trans_in_type' => 'loginName',// 收入方账户类型
'trans_in' => $subLedgerInfo['trans_in'],// 收入方账户
'amount' => $subLedgerInfo['amount'],// 分账的金额,单位为元
'desc' => "订单[{$tradeNo}]的分账金额",// 分账描述
//'royalty_scene' => '达人佣金',// 可选值:达人佣金、平台服务费、技术服务费、其他
//'trans_in_name' => '张志伟',// 分账收款方姓名,上送则进行姓名与支付宝账号的一致性校验,校验不一致则分账失败。不上送则不进行姓名校验
];
}
// 参数配置
$params = [
'out_request_no' => $outRequestNo,//结算请求流水号
'trade_no' => $tradeNo,// 支付宝交易订单号
'royalty_parameters' => $royaltyParameters,
'extend_params' => [
// 冻结分账场景下生效其他场景传入无效。代表该交易分账是否完结可选值true/false
// 不传默认为false。true代表分账完结则本次分账处理完成后会把该笔交易的剩余冻结金额全额解冻。false代表分账未完结。
'royalty_finish' => 'true',
],
'royalty_mode' => 'sync',// 分账模式目前有两种分账同步执行sync分账异步执行async不传默认同步执行
];
// 发起请求
$result = (new OpenPay())->requestApi('alipay.trade.order.settle',$params,[]);
Log::write('支付回调 - 分账 —— 分账请求:'.json_encode($result, JSON_UNESCAPED_UNICODE));
//debug([$params,$result]);
$result = $result['alipay_trade_order_settle_response'];
if($result['code'] == 10000) {
Db::name('sub_ledger')
->where('order_id',$orderId)
->update(['request_time'=>$time,'request_date'=>date('Y-m-d H:i:s',$time),'request_result'=>'成功']);
return $this->success();
}
else throw new Exception($result['sub_msg']);
}
catch(Exception $e){
// 记录失败信息
Db::name('sub_ledger')
->where('order_id',$orderId)
->update(['request_time'=>$time,'request_date'=>date('Y-m-d H:i:s',$time),'request_result'=>$e->getMessage()]);
Log::write("分账 - 分账请求:".$e->getMessage());
return false;
}
}
/**
* Common: 支付宝交易查询
* Author: wu-hui
* Time: 2023/01/31 16:49
* @param $orderId
* @return array
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function tradeQuery($orderId){
$cacheName = 'trade_query_'.$orderId;
$cacheResult = cache($cacheName);
if($cacheResult){
return $this->success(json_decode($cacheResult,true));
}
else{
// 判断订单id是否有效
if($orderId <= 0) throw new Exception("订单id错误 {$orderId}");
// 获取订单信息
$orderInfo = $this->getOrderInfo($orderId);
// 配置信息
$params = [
'out_trade_no' => $orderInfo['order_no'],//订单支付时传入的商户订单号,和支付宝交易号不能同时为空。
'trade_no' => $orderInfo['trade_no'] ?? 0,// 支付宝交易号
// 查询选项,商户传入该参数可定制本接口同步响应额外返回的信息字段,数组格式。支持枚举如下:
// trade_settle_info返回的交易结算信息包含分账、补差等信息
// fund_bill_list交易支付使用的资金渠道
// voucher_detail_list交易支付时使用的所有优惠券信息
// discount_goods_detail交易支付所使用的单品券优惠的商品优惠信息
// mdiscount_amount商家优惠金额
//'query_options' => []
];
// 发起请求
$result = (new OpenPay())->requestApi('alipay.trade.query',$params,[]);
$result = $result['alipay_trade_query_response'];
if($result['code'] == 10000){
cache($cacheName,json_encode($result),3600);
return $this->success($result);
}
else throw new Exception($result['sub_msg']);
}
}
/**
* Common: 获取订单信息
* Author: wu-hui
* Time: 2023/01/30 9:59
* @param $orderId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOrderInfo($orderId){
$field = [
'o.order_id',
'o.order_no',
'p.pay_money',
'p.trade_no',
'p.pay_time',
'p.site_id',
];
$orderInfo = Db::name('order')
->alias('o')
->join('pay p','o.out_trade_no = p.out_trade_no','left')
->field($field)
->where('o.order_id',$orderId)
->find();
// 判断:订单状态
if(($orderInfo['pay_time'] ?? 0) <= 0) throw new Exception('订单未支付-'.$orderId);
// 修改site_id
if($orderInfo['site_id'] != $this->site_id) $this->site_id = (int)$orderInfo['site_id'];
return $orderInfo ?? [];
}
/**
* Common: 获取直通商户信息
* Author: wu-hui
* Time: 2023/01/30 11:45
* @return array|mixed|Db|\think\Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getPayShopInfo(){
$info = (array)Db::name('pay_shop')
->field('shop_id,merchant_name,contacts_name,merchant_smid,zmalipay_value')
->where('site_id',$this->site_id)
->find();
if(!$info) throw new Exception('直通商户信息不存在!');
if($info) $info['zmalipay_value'] = json_decode($info['zmalipay_value'],true);
if(!$info['zmalipay_value'] || !$info['zmalipay_value']['smid']) throw new Exception('直通商户信息不全!');
return $info ?? [];
}
}

View File

@ -0,0 +1,110 @@
<?php
namespace addon\aliapp\model;
use app\model\BaseModel;
use think\facade\Db;
/**
* Common: 小程序发布记录
* Author: wu-hui
* Time: 2022/12/29 16:50
* Class AppletRelease
* @package addon\aliapp\model
*/
class AppletRelease extends BaseModel{
protected $site_id;
// 支付宝小程序 创建版本的状态
protected $aliCreateStatus = [
0 => '构建排队中',
1 => '正在构建',
2 => '构建成功',
3 => '构建失败',
5 => '构建超时',
6 => '版本创建成功',
];
// 支付宝小程序 状态
protected $versionStatus = [
'INIT' => '开发中',
'AUDITING' => '审核中',
'AUDIT_REJECT' => '审核驳回',
'WAIT_RELEASE' => '待上架',
'BASE_AUDIT_PASS' => '准入不可营销',
'GRAY' => '灰度中',
'RELEASE' => '已上架',
'OFFLINE' => '已下架',
'AUDIT_OFFLINE' => '已下架',
];
public function __construct($siteId){
$this->site_id = $siteId;
}
/**
* Common: 获取小程序发布记录
* Author: wu-hui
* Time: 2022/12/29 17:04
* @return array
* @throws \think\db\exception\DbException
*/
public function getList(){
// 参数获取
$page = input('page',1);
$pageSize = input('page_size',PAGE_LIST_ROWS);
$aliPayAppletModel = new AliPayApplet($this->site_id);
// 列表获取
$field = [
'id',
'version',
'ali_create_status',
'is_experience_version',
'version_status',
'create_time',
'audit_reason'
];
$result = Db::name('applet_release')
->field($field)
->where('site_id',$this->site_id)
->where('type',1)
->order('version','DESC')
->paginate(['list_rows' => $pageSize,'page' => $page]);
if($result) {
$result = $result->toArray();
try{
$aliCreateStatus = $this->aliCreateStatus;
$versionStatus = $this->versionStatus;
$newestVersion = $aliPayAppletModel->newestVersion();
// 循环处理信息
$list = $result['data'] ?? [];
foreach($list as &$item){
// 获取构建状态
if(in_array($item['ali_create_status'],[0,1])) $item['ali_create_status'] = (int)$aliPayAppletModel->versionBuildQuery($item['version'],$item['id']);
$item['ali_create_status_text'] = $aliCreateStatus[$item['ali_create_status']];
// 获取状态
if($item['version_status']) $item['version_status_text'] = $versionStatus[$item['version_status']];
// 判断当前版本是否为最新版本
$item['is_newest_version'] = false;
if($item['version'] == $newestVersion) $item['is_newest_version'] = true;
}
// 获取版本信息
$list = [
'count' => $result['total'],
'list' => $list,
'page_count' => $result['last_page'],
];
return $this->success($list);
}catch(\Exception $e){
return $this->error('',$e->getMessage());
}
}
return $this->success();
}
}

View File

@ -0,0 +1,164 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\model;
use app\model\system\Site;
use think\facade\Db;
use think\facade\Log;
class AuthNotify
{
public function Notify($param = [])
{
$rsaCheck = $this->rsaCheck($param);
if ($rsaCheck && isset($param['notify_type'])) {
Log::write('支付宝回调通知:' . $param['notify_type'] . json_encode($param, JSON_UNESCAPED_UNICODE));
switch ($param['notify_type']) {
case 'alipay.service.check':
echo 'success';
break;
case 'servicemarket_order_notify': //服务订单通知
$this->servicemarketOrderNotify($param);
break;
case 'open_app_auth_notify': //服务订单授权通知
$this->openAppAuthnotify($param);
break;
}
}
}
/***
* 授权通知处理
* @param $param
*/
public function openAppAuthnotify($param)
{
$authInfo = json_decode($param['biz_content'], true);
$detail = $authInfo['detail'];
$user_id = $detail['user_id'];
$data = [
'ag_site_id' => 1,
'original_id' => $user_id,
'type' => 'aliapp',
'auth_value' => json_encode($detail),
'update_time' => time(),
];
if (isset($param['status']) && $param['status'] == 'execute_auth') {
if (isset($authInfo['notify_context']['trigger_context']['out_biz_no'])) { //小程序新注册授权
$out_biz_no = $authInfo['notify_context']['trigger_context']['out_biz_no'];
$auth_app_id = $detail['auth_app_id'];
$where = [
'business_code' => $out_biz_no,
'appid' => $auth_app_id
];
$res = Db::name('applet_list')->where($where)->update($data);
event('AliappRegAuth', array_merge($detail, $where));
} else {
$where = [
['original_id', '=', $user_id]
];
$res = Db::name('cloud_order')->where($where)->update($data);
}
if ($res) {
echo 'success';
} else {
echo 'fail';
}
}
}
/***
* 用户小程序订购
*/
public function servicemarketOrderNotify($param)
{
$user_id = $param['merchant_pid'];
$data = [
'ag_site_id' => 1,
'goods_name' => $param['title'],
'cloud_goods_id' => $param['item_code'],
'order_id' => $param['commodity_order_id'],
'third_order_id' => $param['commodity_order_id'],
'original_id' => $user_id,
'type' => 'aliapp',
'pay_status' => 1,
'money' => $param['total_price'],
'contact_name' => $param['contactor'],
'mobile' => $param['phone'],
'raw_data' => json_encode($param),
'update_time' => time(),
];
$where = [
'original_id' => $user_id,
'third_order_id' => $param['commodity_order_id'],
];
$shopInfo = $this->createShop($data); //创建店铺
if ($shopInfo['data']['code'] == 0) {
$data['site_id'] = $shopInfo['data']['data'];
} else {
$data['site_id'] = Db::name('site')->where(['username' => $data['mobile']])->value('site_id');
}
$info = Db::name('cloud_order')->where($where)->find();
if ($info) {
Db::name('cloud_order')->where('original_id', '=', $user_id)->update($data);
} else {
$data['create_time'] = time();
Db::name('cloud_order')->insert($data);
}
echo 'success';
}
public function createShop($data)
{
//店铺信息
$shop_data = [
'site_name' => $data['contact_name'], //店铺名称
'contacts_name' => $data['contact_name'], //联系人
'contacts_mobile' => $data['mobile'], //联系电话
'agent_id' => $data['ag_site_id'], //所属代理
'group_id' => 1,
'expire_time' => 0,
'is_try' => 0, //是否体验用户
];
$username = $data['mobile'] ?? $data['original_id'];
$user_info = [
'username' => $username,
'password' => data_md5('kdb123'),
];
$site_model = new Site();
$result = $site_model->addSite($shop_data, $user_info, false);
if ($result['code'] == 0) {
$log = array(
"uid" => 0,
"username" => $username,
"site_id" => $data['ag_site_id'],
"url" => '',
"ip" => request()->ip(),
"data" => json_encode($shop_data),
"action_name" => '云市场自动注册店铺',
"create_time" => time(),
);
model("user_log")->add($log);
}
return success('0', '注册成功', $result);
}
public function rsaCheck($param)
{
$payModel = new MinCode();
$res = $payModel->verifySgin($param);
return $res;
}
}

View File

@ -0,0 +1,360 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\model;
use addon\alipay\data\sdk\AopCertClient;
use addon\alipay\data\sdk\AopClient;
use addon\alipay\data\sdk\request\AlipayTradeRefundRequest;
use addon\alipay\model\Config;
use app\exception\ApiException;
use app\model\system\Pay as PayCommon;
use think\Exception;
use think\facade\Db;
class CloudPay
{
public $aop;
function __construct()
{
try {
$config_info = config('alipay.cloudAlipay');
// 获取支付宝支付参数(统一支付到平台账户)
$this->aop = new AopClient();
$this->aop->alipayrsaPublicKey = $config_info['public_key'] ?? "";
$this->aop->alipayPublicKey = $config_info['alipay_public_key'] ?? "";
$this->aop->isv_app_id = $config_info["isv_app_id"] ?? "";
$this->aop->rsaPrivateKey = $config_info['private_key'] ?? "";
$this->aop->gatewayUrl = 'https://apigw.alipay-eco.com';
$this->aop->alipaySdkVersion = "alipay-sdk-php-20200415";
$this->aop->apiVersion = '1.0';
$this->aop->signType = 'RSA2';
$this->aop->postCharset = 'UTF-8';
$this->aop->format = 'json';
} catch (\Exception $e) {
throw new ApiException(-1, '支付宝配置错误');
}
}
public function payNotify($data)
{
if ($this->rsaCheckV($data)) {
switch ($data['service']) {
case 'spi.fitness.merchant.syncStatus'://商户状态
file_put_contents(__DIR__.'/pay/'.date('YmdHis').'syncStatus.txt',json_encode($_POST));
$biz_content = json_decode($_POST['biz_content'], true);
$res = $this->syncStatus($biz_content);
break;
case 'spi.fitness.subscription.syncSubscription':
file_put_contents(__DIR__.'/pay/'.date('YmdHis').'syncSubscription.txt',json_encode($_POST));
$biz_content = json_decode($_POST['biz_content'], true);
$res = $this->syncSubscription($biz_content);
break;
case 'spi.fitness.order.syncOrder':
file_put_contents(__DIR__.'/pay/'.date('YmdHis').'syncOrder.txt',json_encode($_POST));
$biz_content = json_decode($_POST['biz_content'], true);
$res = $this->syncOrder($biz_content);
break;
}
} else {
echo "fail";
}
}
/***
* 商户状态
* @param $data
*/
public function syncStatus($data)
{
echo "success";
}
/***
* 订单回调
* @param $data
* @throws \Exception
*/
public function syncSubscription($data)
{
$out_trade_no = $data['outSubscriptionNo'];
// 支付宝交易号
$trade_no = $data['subscriptionNo'];
// 交易状态
$trade_status = $data['subscriptionStatus'];
if ($trade_status == "NORMAL") {
switch ($trade_status){
case 'NORMAL': //正常
$pay_common = new PayCommon();
$retval = $pay_common->onlinePay($out_trade_no, "zmalipay", $trade_no, "aliapp");
// 发送 服务开通成功提醒
$orderInfo = Db::name('order')->where('out_trade_no',$out_trade_no)->find();
if(!is_array($orderInfo)) $orderInfo = $orderInfo->toArray();
$memberGoodsCard = Db::name('member_goods_card')->where('order_id',$orderInfo['order_id'])->find();
if(!is_array($memberGoodsCard)) $memberGoodsCard = $memberGoodsCard->toArray();
$nickname = Db::name('member')->where('member_id',$orderInfo['member_id'])->value('nickname');
$res = (new AliPayMessage($orderInfo['site_id']))->sendMessage($orderInfo['member_id'],'SERVICE_OPENED_SUCCESS',[
'end_time' => date('Y年m月d日',$memberGoodsCard['end_time']),// 到期时间 日期2022年1月18日
'nickname' => $nickname,// 姓名
'start_time' => date('Y年m月d日',$memberGoodsCard['create_time']),// 开通时间 日期2022年1月18日
'content' => $memberGoodsCard['goods_name'],// 服务项目
]);
break;
case 'PAUSE': //订单暂停
break;
case "SURRENDER": //解约
break;
case "END": //订单结束
break;
case "DEFAULT_CANCEL": //违约取消
break;
case "CANCEL": //超时取消
break;
}
}
echo "success";
}
/***
* 订单同步状态
* @param $data
*/
public function syncOrder($data)
{
$out_trade_no = $data['outSubscriptionNo']; //平台交易号
// 支付宝交易号
$trade_no = $data['subscriptionNo'];
$third_order_no = $data['orderNo'];
// 交易状态
$trade_status = $data['orderStatus'];
$where=[
'out_trade_no'=>$out_trade_no,
'third_order_no'=>$third_order_no
];
$orderInfo = model('order')->getInfo([[ 'out_trade_no', '=', $out_trade_no ]],'order_id,member_id');
$zmOrder=Db::name('zm_order')->where($where)->find();
if(empty($zmOrder)){
$insdata=[
'merchantPid'=>$data['merchantPid'],
'userid'=>$data['userId'],
'order_id'=>$orderInfo['order_id'],
'uid'=>$orderInfo['member_id'],
'trade_no'=>$trade_no,
'out_trade_no'=>$out_trade_no,
'third_order_no'=>$third_order_no,
'create_time'=>strtotime($data['orderDate']),
'plan_time'=>strtotime($data['planDeductionTime']??''),
'period'=>$data['period'],
'order_status'=>$trade_status,
'amount'=>$data['deductionAmount']
];
Db::name('zm_order')->insert($insdata);
}else{
$updata=[
'period'=>$data['period'],
'order_status'=>$trade_status,
];
if($trade_status=='PAID'){
$updata['pay_time']=strtotime($data['actualDeductionTime']);
}
if($trade_status=='PAYING'){
try{
event('AliVerify',$zmOrder);
}catch(Exception $exception){
trace($exception,'核销失败');
}
}
Db::name('zm_order')->where($where)->update($updata);
}
echo "success";
}
/***
* 退款
*/
public function refund($param){
$pay_info=$param['pay_info'];
$bizContent=[
'merchantPid'=>'2088420482043304',
'subscriptionNo'=>$pay_info['trade_no'],
'orderNo'=>$pay_info['order_no']
];
//其他参数
$params["charset"] = "UTF-8";
$params["isv_app_id"]= $this->aop->isv_app_id;
$params["utc_timestamp"]=$this->msectime();
//指定需要调用的service接口
$params["service"] = "api.fitness.orderRefund";
$params["request_id"] =$this->uuid();
$params["biz_content"] = json_encode($bizContent);
$params["version"] = "1.0";
$params["sign"] = $this->aop->generateSign($params, "RSA2");
$params["sign_type"] = 'RSA2';
// 调用ECOAPI
$result = $this->aop->call($params);
return $result;
}
/***
* 新增或者修改商户
* @param $param
* @return false|mixed
*/
public function upAlipayUser($param,$settleAccountList=''){
$bizContent=[
'merchantPid'=>$param['smid'],
'smid'=>$param['smid'],
'merchantAppId'=>$param['merchantAppId'],
'merchantLoginName'=>$param['merchantLoginName'],
'merchantName'=>$param['merchantName'],
'separateLedgerRate'=>$param['separateLedgerRate'],
'phone'=>$param['phone'],
];
if($settleAccountList){
$bizContent['settleAccountList']=array_values($settleAccountList);
}
//其他参数
$params["charset"] = "UTF-8";
$params["isv_app_id"]= $this->aop->isv_app_id;
$params["utc_timestamp"]=$this->msectime();
//指定需要调用的service接口
$params["service"] = "api.fitness.newSaveOrUpdate";
$params["request_id"] =$this->uuid();
$params["biz_content"] = json_encode($bizContent);
$params["version"] = "1.0";
$params["sign"] = $this->aop->generateSign($params, "RSA2");
$params["sign_type"] = 'RSA2';
// 调用ECOAPI
$result = $this->aop->call($params);
return $result['response'];
}
/***
* 商户解约
* @param $param
* @return false|mixed
*/
public function Surrender($param,$type='NORMAL'){
$pay_info=$param['pay_info'];
$bizContent=[
'subscriptionNo'=>$pay_info['trade_no'],
'subscriptionCancelType'=>$type //NORMAL 正常 DEFAULT违约
];
//其他参数
$params["charset"] = "UTF-8";
$params["isv_app_id"]= $this->aop->isv_app_id;
$params["utc_timestamp"]=$this->msectime();
//指定需要调用的service接口
$params["service"] = "api.fitness.subscriptionSurrender";
$params["request_id"] =$this->uuid();
$params["biz_content"] = json_encode($bizContent);
$params["version"] = "1.0";
$params["sign"] = $this->aop->generateSign($params, "RSA2");
$params["sign_type"] = 'RSA2';
// 调用ECOAPI
$result = $this->aop->call($params);
return $result;
}
/***
* 核销
* @param $orderNo
* @return false|mixed
*/
public function verify($orderNo,$verificationCode){
$bizContent=[
// 'orderNo'=>$orderNo,
'verificationCode'=>$verificationCode
];
//其他参数
$params["charset"] = "UTF-8";
$params["isv_app_id"]= $this->aop->isv_app_id;
$params["utc_timestamp"]=$this->msectime();
//指定需要调用的service接口
$params["service"] = "api.fitness.verification";
$params["request_id"] =$this->uuid();
$params["biz_content"] = json_encode($bizContent);
$params["version"] = "1.0";
$params["sign"] = $this->aop->generateSign($params, "RSA2");
$params["sign_type"] = 'RSA2';
// 调用ECOAPI
$result = $this->aop->call($params);
return $result;
}
/***
* 订单查询
* @param $subscriptionNo
* @param $orderNo
* @return false|mixed
*/
public function orderQuery($subscriptionNo = '',$orderNo = ''){
$bizContent=[
'subscriptionNo'=>$subscriptionNo,
'orderNo'=>$orderNo,
];
//其他参数
$params["charset"] = "UTF-8";
$params["isv_app_id"]= $this->aop->isv_app_id;
$params["utc_timestamp"]=$this->msectime();
//指定需要调用的service接口
$params["service"] = "api.fitness.orderQuery";
$params["request_id"] =$this->uuid();
$params["biz_content"] = json_encode($bizContent);
$params["version"] = "1.0";
$params["sign"] = $this->aop->generateSign($params, "RSA2");
$params["sign_type"] = 'RSA2';
// 调用ECOAPI
$result = $this->aop->call($params);
return $result;
}
/***
* 验证签名
* @param $data
* @return bool|void
*/
public function rsaCheckV($data)
{
$res = $this->aop->rsaCheckV2($data, $this->aop->alipayrsaPublicKey, 'RSA2');
return $res;
}
/**
* 返回当前的毫秒时间戳
*/
public function msectime()
{
list($s1, $s2) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
}
/**
* 生成UUID
*/
public function uuid()
{
$chars = md5(uniqid(mt_rand(), true));
$uuid = substr($chars, 0, 8) . '-'
. substr($chars, 8, 4) . '-'
. substr($chars, 12, 4) . '-'
. substr($chars, 16, 4) . '-'
. substr($chars, 20, 12);
return $uuid;
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace addon\aliapp\model;
use app\model\system\Config as ConfigModel;
use app\model\system\UniAccount;
use app\model\BaseModel;
/**
* 小程序配置
*/
class Config extends BaseModel
{
public function setAlipayConfig($appid,$data, $site_id = 1,$app_original='')
{
$config = new UniAccount();
$condition=[
'site_id'=>$site_id,
'appid'=>$appid
];
$res = $config->setUniConfig($condition,$data,'aliapp','ALIAPP_CONFIG',$app_original);
return $res;
}
/**
* 获取小程序配置信息
* @return multitype:string mixed
*/
public function getAppConfig($site_id,$app_type='aliapp', $config_key = 'ALIAPP_CONFIG')
{
$config = new UniAccount();
$condition=[
'site_id'=>$site_id,
'app_type'=>$app_type
];
$res = $config->getUniConfig($condition,$config_key);
return $res;
}
/**
* 根据appid获取配置信息
* @return multitype:string mixed
*/
public function getAppidConfig($appid,$config_key = 'ALIAPP_CONFIG')
{
$config = new UniAccount();
$res = $config->getUniConfig(['appid', '=', $appid],$config_key);
return $res;
}
public function getOpenConfig(){
$config = new ConfigModel();
$res = $config->getConfig([['site_id', '=', 0], ['app_module', '=', 'admin'], ['config_key', '=', 'ALIPAYOPEN_CONFIG']]);
return $res;
}
}

View File

@ -0,0 +1,163 @@
<?php
namespace addon\aliapp\model;
use addon\alipay\data\sdk\AopClient;
use addon\alipay\data\sdk\request\AlipayTradeCloseRequest;
use app\model\BaseModel;
use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Config as AliCon;
use app\model\order\OrderCreateTool;
use think\Exception;
use think\facade\Cache;
use think\facade\Db;
class CreateApplet extends BaseModel{
protected $site_id;
/**
* Common: 创建小程序 —— 开始创建
* Author: wu-hui
* Time: 2022/12/29 9:15
* @param $info
* @param $siteId
* @return array
* @throws Exception
*/
public function createAppletStart($info,$siteId){
$this->site_id = $siteId;
// 获取参数信息
$params = $this->createAppletParams($info);
$result = (new MinCode())->requestApi("alipay.open.mini.isv.create", ['create_mini_request' => $params])['alipay_open_mini_isv_create_response'];
if($result['code'] == 10000) {
$info['out_order_no'] = $params['out_order_no'];
$info['order_no'] = $result['order_no'];
return $this->success($info);
}else{
throw new Exception($result['sub_msg']);
}
}
/**
* Common: 创建小程序 —— 参数获取
* Author: wu-hui
* Time: 2022/12/29 9:10
* @param $info
* @return array
*/
private function createAppletParams($info){
// 获取图片base64
if($info['license_pic']) $info['license_pic'] = UrlimgBase64(img($info['license_pic']));
// 处理配置信息
$info['out_order_no'] = $this->createAppletOutOrderNo($this->site_id,$info['cert_no']);
return [
'out_order_no' => $info['out_order_no'], // 开发者外部订单号
'alipay_account' => $info['alipay_account'], // 商家登录支付宝的邮箱帐号或手机号
'legal_personal_name' => $info['legal_personal_name'],// 商家法人名称
'cert_name' => $info['cert_name'],// 营业执照企业名称,如果是“无主体名称个体工商户”则填“个体户+法人姓名”,例如“个体户张三”
'cert_no' => $info['cert_no'],// 营业执照编码
'app_name' => $info['app_name'], // 小程序名称
'contact_phone' => $info['contact_phone'], // 商家联系人手机电话
'contact_name' => $info['contact_name'], // 商家联系人名称
'is_individual' => TRUE, // 是否支持个体工商户的账号类型
'license_pic' => $info['license_pic'], // 营业执照图片的Base64编码字符串图片大小不能超过2M。
];
}
/**
* Common: 生成订单号
* Author: wu-hui
* Time: 2022/12/28 16:54
* @param $site_id
* @param $id
* @return string
*/
public function createAppletOutOrderNo($site_id, $cert_no){
$time_str = date('YmdHi');
$max_no = Cache::get($site_id . '_' . $cert_no . '_' . $time_str);
if (!isset($max_no) || empty($max_no)) $max_no = 1;
else $max_no = $max_no + 1;
$order_no = $time_str . $cert_no . sprintf('%03d', $max_no);
Cache::set($site_id . '_' . $cert_no . '_' . $time_str, $max_no);
return $order_no;
}
/**
* Common: 获取最新的小程序配置信息
* Author: wu-hui
* Time: 2022/12/28 17:41
* @param $siteId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getNewParams($siteId){
$info = Db::name('applet_list')
->where('site_id',$siteId)
->where('type',1)
->order('id','DESC')
->find();
if(!$info){
$content = [
'alipay_account' => '',// 商家登录支付宝的邮箱帐号或手机号
'legal_personal_name' => '',// 商家法人名称
'cert_name' => '',// 营业执照企业名称,如果是“无主体名称个体工商户”则填“个体户+法人姓名”,例如“个体户张三”
'cert_no' => '',// 营业执照编码
'app_name' => '',// 小程序名称
'contact_phone' => '',// 商家联系人手机电话
'contact_name' => '',// 商家联系人名称
'license_pic' => '',// 营业执照图片的Base64编码字符串图片大小不能超过2M。
];
}else{
$content = json_decode($info['content'],TRUE);
}
return [$info['id'] ?? 0,$content];
}
/**
* Common: 设置小程序信息
* Author: wu-hui
* Time: 2022/12/28 18:15
* @param $info
* @param $siteId
* @return array
*/
public function setNewParams($info,$siteId){
// 信息处理
$id = $info['id'];
unset($info['id']);
Db::name('applet_list')->startTrans();
try{
// 发起请求 创建小程序
$info = $this->createAppletStart($info,$siteId);
$data = [
'content' => json_encode($info,JSON_UNESCAPED_UNICODE)
];
// 记录信息
if($id > 0){
Db::name('applet_list')->where('id',$id)->update($data);
}else{
$data['site_id'] = $siteId;
$data['name'] = $info['app_name'];
$data['type'] = 1;
$data['status'] = 1;
$data['create_time'] = time();
Db::name('applet_list')->insert($data);
}
Db::name('applet_list')->commit();
return $this->success();
}catch(\Exception $e){
Db::name('applet_list')->rollback();
return $this->error('',$e->getMessage());
}
}
}

View File

@ -0,0 +1,272 @@
<?php
namespace addon\aliapp\model;
use app\model\BaseModel;
use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Config as AliCon;
class MinCode extends BaseModel
{
public $app;
protected $config;
public $appAuthToken = '';//'202301BB74ac1b3e3b5f4541b174febbaf07bX84';
public function __construct($site_id = '')
{
// 获取支付宝支付参数(统一支付到平台账户)
$config_model = new Config();
if ($site_id) {
$config_info = $config_model->getAppConfig($site_id)['data']['value'];
if (isset($config_info['line_type']) && $config_info['line_type'] == 'auth') {
$this->appAuthToken = $config_info['app_auth_token'];
}
}
$config_info = config('alipay.platform');
$this->config = $config_info;
$options = new AliCon();
$options->protocol = 'https';
$options->gatewayHost = 'openapi.alipay.com';
$options->signType = 'RSA2';
$options->appId = $config_info['appid'];
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
$options->merchantPrivateKey = $config_info['private_key'] ?? ""; //'<-- 请填写您的应用私钥例如MIIEvQIBADANB ... ... -->';
$options->alipayCertPath = ''; //'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
$options->alipayRootCertPath = ''; //'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
$options->merchantCertPath = ''; //'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
$options->alipayPublicKey = $config_info['alipay_public_key'] ?? ""; // '<-- 请填写您的支付宝公钥例如MIIBIjANBg... -->';
//可设置异步通知接收服务地址(可选)
$options->notifyUrl = ''; //"<-- 请填写您的支付类接口异步通知接收服务地址例如https://www.test.com/callback -->";
//可设置AES密钥调用AES加解密相关接口时需要可选
$options->encryptKey = $config_info['encryptKey']; // 'du/cSQ7P4YPw4d8+3jUc3w=='; //"<-- 请填写您的AES密钥例如aa4BtZ4tspm2wnXLb1ThQA== -->";
Factory::setOptions($options);
}
/**
* 消息解密
* @param array $param
*/
public function decryptData($encryptedData)
{
try {
// $cache = Cache::get('weapp_' . $param['weapp_openid']);
// $session_key = $cache['session_key'] ?? '';
// $result = $this->app->encryptor->decryptData($session_key, $param['iv'], $param['encryptedData']);
// if (isset($result['errcode']) && $result['errcode'] != 0) {
// return $this->handleError($result['errcode'], $result['errmsg']);
// }
//2. 发起API调用以支付能力下的统一收单交易创建接口为例
$result = Factory::util()
->AES()
->agent($this->appAuthToken)
->decrypt($encryptedData);
return json_decode($result, true);
} catch (\Exception $e) {
return $this->error([], $e->getMessage());
}
}
/***
* @param $authCode
* @return array|object|\Psr\Http\Message\ResponseInterface|\WannanBigPig\Supports\Collection|\WannanBigPig\Supports\Http\Response
* @throws \EasyAlipay\Kernel\Exceptions\InvalidSignException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \WannanBigPig\Supports\Exceptions\InvalidArgumentException
*/
public function handleAuthorize($authCode, $grant_type = 'authorization_code')
{
try {
$textParams = [];
$bizParams = [
'grant_type' => $grant_type,
'code' => $authCode,
];
//2. 发起API调用以支付能力下的统一收单交易创建接口为例
$result = Factory::util()
->generic()->execute("alipay.open.auth.token.app", $textParams, $bizParams);
return json_decode($result->httpBody, true)['alipay_open_auth_token_app_response'];
} catch (\Exception $e) {
return $e->getMessage();
}
}
/**
* 获取授权地址
* @param $urls //回调地址
* @param string $type
* @return string
*/
public function getPreAuthorizationUrl($urls, $type = 'WEBAPP,MOBILEAPP,PUBLICAPP,TINYAPP')
{
$urls = urlencode($urls);
$auth_url = "https://openauth.alipay.com/oauth2/appToAppAuth.htm?app_id={$this->config['appid']}&redirect_uri={$urls}";
return $auth_url;
}
public function getminiAuthorizationUrl($urls, $state)
{
$bizDataObj = [
'platformCode' => 'O',
'taskType' => 'INTERFACE_AUTH',
'agentOpParam' => [
'redirectUri' => $urls,
'appTypes' => ["TINYAPP"],
'isvAppId' => $this->config['appid'],
'state' => $state,
],
];
$bizData = json_encode($bizDataObj);
$auth_url = "alipays://platformapi/startapp?appId=2021003130652097&page=pages%2Fauthorize%2Findex%3FbizData%3D{$bizData}";
return $auth_url;
}
/**
* Common: 支付宝用户相关请求
* Author: wu-hui
* Time: 2023/01/05 13:44
* @param $authToken
* @param $api
* @param array $params
* @param array $textParams
* @return mixed|string
*/
public function requestMemberApi($authToken, $api, $params = [], $textParams = [])
{
try {
$result = Factory::util()
->generic()
->agent($this->appAuthToken)
->auth($authToken)
->execute($api, $textParams, $params);
return json_decode($result->httpBody, true);
} catch (\Exception $e) {
return $e->getMessage();
}
}
/**
* Common: 发起支付宝请求
* Author: wu-hui
* Time: 2022/12/28 17:31
* @param $api
* @param array $params
* @param array $textParams
* @return mixed|string
*/
public function requestApi($api, $params = [], $textParams = [])
{
try {
$result = Factory::util()
->generic()
->agent($this->appAuthToken)
->execute($api, $textParams, $params);
return json_decode($result->httpBody, true);
} catch (\Exception $e) {
return $e->getMessage();
}
}
/***
* 验签
* @param $param
* @return bool
*/
public function verifySgin($param)
{
$res = Factory::payment()->common()->verifyNotify($param);
return $res;
}
/***
* 查询小程序信息
* @param $order_no
* @param $appAuthToken
* @return mixed|string
*/
public function miniQuery($order_no, $appAuthToken)
{
try {
$biz_content['order_no'] = $order_no;
$result = Factory::util()->generic()
->agent($appAuthToken)
->execute('alipay.open.mini.isv.query', [], $biz_content);
return json_decode($result->httpBody, true)['alipay_open_mini_isv_query_response'];
} catch (\Exception $e) {
return $e->getMessage();
}
}
/***
* 查询订购订单
* @param $commodity_order_id
* @param int $start_page
* @return mixed|string
*/
public function queryServiceOrder($commodity_order_id, $start_page = 1)
{
try {
$biz_content['commodity_order_id'] = $commodity_order_id;
$biz_content['start_page'] = $start_page;
$result = Factory::util()->generic()
->execute('alipay.open.servicemarket.order.query', [], $biz_content);
return json_decode($result->httpBody, true)['alipay_open_servicemarket_order_query_response'];
} catch (\Exception $e) {
return $e->getMessage();
}
}
/***
* 查询订购订单
* @param $commodity_order_id
* @param int $start_page
* @return mixed|string
*/
public function MiniCreate($biz_content)
{
try {
$result = Factory::util()
->generic()
->execute('alipay.open.mini.isv.create', [], $biz_content);
return json_decode($result->httpBody, true)['alipay_open_mini_isv_create_response'];
} catch (\Exception $e) {
return $e->getMessage();
}
}
/***
* 设置小程序基础信息
* @param $textParams
* @return mixed|string
*/
public function miniSetBaseinfo($textParams,$app_logo)
{
$fileParams = [
'app_logo' => $app_logo,
];
try {
$result = Factory::util()
->generic()
->agent($this->appAuthToken)
->fileExecute("alipay.open.mini.baseinfo.modify", $textParams, [],$fileParams);
return json_decode($result->httpBody, true)['alipay_open_mini_baseinfo_modify_response'];
} catch (\Exception $e) {
return $e->getMessage();
}
}
public function miniCategoryQuery()
{
}
}

View File

@ -0,0 +1,142 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\model;
use Alipay\EasySDK\Kernel\Config as AliCon;
use Alipay\EasySDK\Kernel\Factory;
class OpenPay
{
public function __construct()
{
$config_info = config('alipay.zmAlipay');
$this->config = $config_info;
$options = new AliCon();
$options->protocol = 'https';
$options->gatewayHost = 'openapi.alipay.com';
$options->signType = 'RSA2';
$options->appId = $config_info['appid'];
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
$options->merchantPrivateKey = $config_info['private_key'] ?? ""; //'<-- 请填写您的应用私钥例如MIIEvQIBADANB ... ... -->';
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
$options->alipayPublicKey = $config_info['alipay_public_key'] ?? ""; // '<-- 请填写您的支付宝公钥例如MIIBIjANBg... -->';
//可设置异步通知接收服务地址(可选)
$options->notifyUrl = ''; //"<-- 请填写您的支付类接口异步通知接收服务地址例如https://www.test.com/callback -->";
//可设置AES密钥调用AES加解密相关接口时需要可选
$options->encryptKey = $config_info['encryptKey']; //"<-- 请填写您的AES密钥例如aa4BtZ4tspm2wnXLb1ThQA== -->";
$options->alipayCertPath = ''; //'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
$options->alipayRootCertPath = ''; //'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
$options->merchantCertPath = ''; //'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
Factory::setOptions($options);
}
/***
* 直通商户进件
* @param $bizParams
* @return mixed|string
*/
public function simpleCreate($bizParams)
{
try {
$textParams = [];
//2. 发起API调用以支付能力下的统一收单交易创建接口为例
$result = Factory::util()
->generic()
->execute("ant.merchant.expand.indirect.zft.simplecreate", $textParams, $bizParams);
return json_decode($result->httpBody, true)['ant_merchant_expand_indirect_zft_simplecreate_response'];
} catch (\Exception $e) {
return $e->getMessage();
}
}
public function query($external_id = '', $order_id = '')
{
try {
$textParams = [];
if ($external_id) {
$bizParams = [
'external_id' => $external_id
];
} else if ($order_id) {
$bizParams = [
'order_id' => $order_id
];
}
//2. 发起API调用以支付能力下的统一收单交易创建接口为例
$result = Factory::util()
->generic()
->execute("ant.merchant.expand.indirect.zftorder.query", $textParams, $bizParams);
return json_decode($result->httpBody, true)['ant_merchant_expand_indirect_zftorder_query_response'];
} catch (\Exception $e) {
return $e->getMessage();
}
}
public function upload($image_type = '', $image_content)
{
try {
$textParams = [
'image_type' => $image_type,
];
$fileParams = [
'image_content' => $image_content,
];
//2. 发起API调用以支付能力下的统一收单交易创建接口为例
$result = Factory::util()
->generic()
->fileExecute("ant.merchant.expand.indirect.image.upload", $textParams, [], $fileParams);
return json_decode($result->httpBody, true)['ant_merchant_expand_indirect_image_upload_response'];
} catch (\Exception $e) {
return $e->getMessage();
}
}
/***
* 验签
* @param $param
* @return bool
*/
public function verifySgin($param)
{
$res = Factory::payment()
->common()
->verifyNotify($param);
return $res;
}
/**
* Common: 发起支付宝请求
* Author: wu-hui
* Time: 2023/01/31 16:06
* @param $api
* @param array $params
* @param array $textParams
* @return mixed|string
*/
public function requestApi($api, $params = [], $textParams = []){
try {
$result = Factory::util()->generic()->execute($api,$textParams,$params);
return json_decode($result->httpBody, true);
} catch (\Exception $e) {
return $e->getMessage();
}
}
}

View File

@ -0,0 +1,231 @@
<?php
namespace addon\aliapp\shop\controller;
use addon\aliapp\model\Config;
use app\shop\controller\BaseShop;
use addon\aliapp\model\MinCode;
use app\model\upload\Upload as UploadModel;
class Aliapp extends BaseShop
{
protected $replace = [];
public function initialize()
{
parent::initialize();
$this->replace = [
'WEAPP_CSS' => __ROOT__ . '/addon/weapp/shop/view/public/css',
'WEAPP_JS' => __ROOT__ . '/addon/weapp/shop/view/public/js',
'WEAPP_IMG' => __ROOT__ . '/addon/weapp/shop/view/public/img',
'WEAPP_SVG' => __ROOT__ . '/addon/weapp/shop/view/public/svg',
];
}
/***
* 小程序设置
* @return mixed
*/
public function setting()
{
// $app = new MinCode($this->site_id);
// $url = addon_url('aliapp/shop/auth/authinfo', ['state' => 'minapp']);
// $auth_url = $app->getPreAuthorizationUrl($url);
// $this->assign('auth_url', $auth_url);
$config = new Config();
$config_info = $config->getAppConfig($this->site_id)['data']['value'];
$this->assign("config_info", $config_info);
return $this->fetch('aliapp/setting', [], $this->replace);
}
/***
* 小程序配置
* @return array|mixed
*/
public function config()
{
$config = new Config();
$config_info = $config->getAppConfig($this->site_id)['data']['value'];
if (request()->isAjax()) {
$appid = input('appid', '');
$qrcode = input('qrcode', '');
$app_name = input('app_name', '');
$app_original = input('app_original', '');
$alipay_public = input('alipay_public_key', '');
$private_key = input('private_key', '');
$public_key = input('public_key', '');
$data = array(
'line_type' => input('line_type', 'custom'),
"appid" => $appid,
'app_name' => $app_name,
'qrcode' => $qrcode,
'alipay_public_key' => $alipay_public,
'private_key' => $private_key,
'public_key' => $public_key,
'app_original' => $app_original,
);
$data = array_merge($config_info, $data);
$res = $config->setAlipayConfig($appid, $data, $this->site_id, $app_original);
return $res;
} else {
$app = new MinCode($this->site_id);
$url = addon_url('aliapp/shop/auth/authinfo', ['state' => 'minapp']);
$auth_url = $app->getPreAuthorizationUrl($url);
$this->assign('auth_url', $auth_url);
$this->assign("config_info", $config_info);
$this->assign("line_type", $config_info['line_type'] ?? 'custom');
return $this->fetch('aliapp/config', [], $this->replace);
}
}
/***
* 授权接入
* @return mixed
*/
public function auth()
{
$app = new MinCode();
$url = addon_url('aliapp/shop/auth/authinfo');
$ag_site_id = model('site')->getValue(['site_id' => $this->site_id], 'agent_id');
$text = $this->site_id . '|minapp|' . $ag_site_id;
$auth_url = $app->getminiAuthorizationUrl($url, url_safe_base64_encode($text));
$qrcode_name = 'alipay_auth';
$path = 'upload/qrcode';
qrcode($auth_url, $path, $qrcode_name);
$this->assign('auth_img', '/' . $path . '/' . $qrcode_name . '.png');
return $this->fetch('aliapp/auth', [], $this->replace);
}
/**
* 编辑小程序基础信息
* 已商上架小程序无法再次修改
* @return array|mixed
*/
public function editapp()
{
$app = new MinCode();
$config = new Config();
$config_info = $config->getAppConfig($this->site_id)['data']['value'];
$app->appAuthToken = $config_info['app_auth_token'];
if (request()->isAjax()) {
$data=request()->post();
$config_info['app_name']=$data['app_name'];
$config_info['head_img']=$data['app_logo'];
$app_original=$config_info['app_original'];
$config->setAlipayConfig($config_info['appid'],$config_info,$this->site_id,$app_original);
$data['app_logo']= ROOT_PATH.'/'.$data['app_logo'];
$app_logo=$data['app_logo'];
unset($data['category_ids'],$data['file'],$data['app_logo']);
$res=$app->miniSetBaseinfo($data,$app_logo); //设置小
if($res['code']=='10000'){
cache($app->appAuthToken . '_baseinfo',null);
$message='设置成功';
}else{
$message=$res['sub_msg'];
}
return success(0,$message,$res);
}
$baseinfo = cache($app->appAuthToken . '_baseinfo');
if (empty($baseinfo)) {
$baseinfo = $app->requestApi('alipay.open.mini.baseinfo.query')['alipay_open_mini_baseinfo_query_response'];
cache($app->appAuthToken . '_baseinfo', $baseinfo);
}
$one_category = cache($app->appAuthToken . '_category');
$category_all = cache($app->appAuthToken . '_alls_category');
if (empty($one_category)) {
$category = $app->requestApi('alipay.open.mini.category.query', ['is_filter' => true])['alipay_open_mini_category_query_response'];
if ($category['mini_category_list']) {
$category_all = array_column($category['mini_category_list'], null, 'category_id');
$one_category = [];
foreach ($category_all as $key => $item) {
if ($item['parent_category_id'] == '0') {
$one_category[] = $item;
}
}
cache($app->appAuthToken . '_category', $one_category);
cache($app->appAuthToken . '_alls_category', $category_all);
}
}
$original = [];
$mini_category_ids = [];
if(isset($baseinfo['category_names'])){
$category_names = $baseinfo['category_names'];
$category_ids = explode(';', $category_names);
$category_all_name = array_column($category_all, null, 'category_name');
foreach ($category_ids as $key => $val) {
if ($val) {
$text = explode('_', $val);
foreach ($text as $category_namet) {
$d=$category_all_name[$category_namet];
$d['checked']=true;
$category_all[$d['category_id']]['checked']=true;
$original[$key][] = $d;
}
}
}
}
if ($original) { //已设置分类
foreach ($original as $value) {
$category_ids = array_column($value, 'category_id');
$mini_category_ids[] = implode('_', $category_ids);
}
}
if (isset($baseinfo['app_logo'])&&strpos($baseinfo['app_logo'], 'http')===0){
$upload=new UploadModel($this->site_id);
$pic_img=$upload->setPath("common/images/" . date("Ymd") . '/')->remotePullToLocal($baseinfo['app_logo']);
$baseinfo['app_logo']=$pic_img['data']['path'];
}
$this->assign("original", $original);
$this->assign("allCategory", $this->getTreeCategory($category_all));
$this->assign("info", $baseinfo);
$this->assign("mini_category_ids", implode(';', $mini_category_ids));
return $this->fetch('aliapp/aliapp_edit', [], $this->replace);
}
/***
* 获取小程序分类
* @return mixed|void
*/
public function getMinicategory()
{
if (request()->isAjax()) {
$config = new Config();
$category_id = input('category_id');
$config_info = $config->getAppConfig($this->site_id)['data']['value'];
$appAuthToken = $config_info['app_auth_token'];
$category_all = cache($appAuthToken . '_alls_category');
$category = [];
if($category_id==''){
$one_category = cache($appAuthToken . '_category');
return $one_category;
}
foreach ($category_all as $key => $item) {
if ($item['parent_category_id'] == $category_id) {
$category[] = $item;
}
}
return $category;
}
}
public function getTreeCategory($category){
$category_all=$category;
$res = [];
//遍历寻父 O(n)
foreach ($category_all as &$item) {
if (isset($category_all[$item['parent_category_id']])){
//注意下面有一个引用符 & !
$category_all[$item['parent_category_id']]['child'] []= &$item;
}elseif(!$item['parent_category_id']){ // 此处判断是否加入到结果集 $item['pid'] === null 或者 $item['pid'] == -1 之类的
$res []= &$item;
}
}
unset($item);
return $res;
}
}

View File

@ -0,0 +1,139 @@
<?php
namespace addon\aliapp\shop\controller;
use addon\aliapp\event\AliAuditResult;
use addon\aliapp\event\ImpendingExpirationListGet;
use addon\aliapp\model\AliPayMessage;
use addon\aliapp\model\Config;
use addon\aliapp\model\MinCode;
use app\shop\controller\BaseShop;
use addon\aliapp\model\AliPayApplet;
use addon\aliapp\model\AppletRelease as appletReleaseModel;
class AppletRelease extends BaseShop{
public function __construct(){
parent::__construct();
// 输出菜单
if(request()->isGet()) $this->forthMenu();
}
/**
* Common: 进入发布小程序
* Author: wu-hui
* Time: 2023/01/03 17:05
* @return array|mixed
* @throws \think\db\exception\DbException
*/
public function index(){
if(request()->isAjax()) return (new appletReleaseModel($this->site_id))->getList();
$config = new Config();
$config_info = $config->getAppConfig($this->site_id)['data']['value'];
$baseinfo=[];
$is_baseinfo=1;
if(!empty($config_info['line_type'])&&$config_info['line_type']=='auth'){
$app = new MinCode();
$app->appAuthToken = $config_info['app_auth_token'];
$baseinfo = cache($app->appAuthToken . '_baseinfo');
if (empty($baseinfo)) {
$baseinfo = $app->requestApi('alipay.open.mini.baseinfo.query')['alipay_open_mini_baseinfo_query_response'];
cache($app->appAuthToken . '_baseinfo', $baseinfo);
}
if(!isset($baseinfo['category_names'])){
$is_baseinfo=0;
}
}
$this->assign('is_baseinfo',$is_baseinfo);
$this->assign('baseinfo',$baseinfo);
// 最新版本
$this->assign('isNewest',(new AliPayApplet($this->site_id))->isNewestVersion());
return $this->fetch('release/index');
}
/**
* Common: 小程序发布流程处理
* Author: wu-hui
* Time: 2023/01/04 11:05
* @return array
*/
public function publishingProcessProcessing(){
// 参数获取
$type = (string)input('type');
$id = (int)input('id');
return (new AliPayApplet($this->site_id))->publishingInit($type,$id);
}
/**
* Common: 版本管理 —— 版本同步
* Author: wu-hui
* Time: 2022/12/30 10:08
* @return array
* @throws \Exception
*/
public function versionSynchronization(){
return (new AliPayApplet($this->site_id))->versionSynchronization();
}
/**
* Common: 生成小程序推广二维码
* Author: wu-hui
* Time: 2023/01/03 14:13
* @return array
*/
public function qrcodeCreate(){
$version=config('alipay.templateInfo.template_version');
return (new AliPayApplet($this->site_id))->queryTestQrcode($version);
}
public function demo(){
// 订单中心消息 模拟发送信息
// $zmOrderId = 42;// zm_order 订单表id
// $orderStatus = 'REFUNDED';// 订单状态:
// $refundPath = '花呗';// 款到账的路径
// $res = (new AliPayMessage($this->site_id))->orderSynchronization($zmOrderId,$orderStatus,$refundPath);
event("NoticeImpendingExpiration");
debug("结束");
// INTEREST_EXPIRATION_NOTICE 权益即将过期通知
//--- SERVICE_OPENED_SUCCESS 服务开通成功提醒
//--- VERIFY 核销提醒
$data = [
'goods_name' => '商品名称',
'store_name' => '店铺名称',
'start_time' => '2023年1月8日',
'content' => '具体内容',
'end_time' => '2023年1月10日',
'nickname' => '用户昵称',
'surplus' => '剩余3次',
];
// 订阅消息发送
$res = (new AliPayMessage($this->site_id))->sendMessage(18,'INTEREST_EXPIRATION_NOTICE',[
'store_name' => '2023年1月10日',// 商家名称
'surplus' => '用户昵称',// 剩余次数
'content' => '2023年1月8日',// 优惠内容
]);
// 开启计划任务
// $cronWhere = [
// 'event' => 'HandleArticleMessage',
// ];
// $cronId = model('cron')->getValue($cronWhere,'id');
// if($cronId <= 0) (new Cron())->addCron(2, 5, "处理文章通知消息", "HandleArticleMessage", time(),0);
debug(['返回信息',$res]);
}
}

View File

@ -0,0 +1,107 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\shop\controller;
use addon\aliapp\model\Config;
use addon\aliapp\model\MinCode;
use app\Controller;
use think\facade\Session;
use think\facade\Db;
class Auth extends Controller
{
/**
* 授权接入
* @return string
* @throws \Exception
*/
public function authinfo()
{
$openPlatform = new MinCode();
$authCode = input('app_auth_code');
$state_base64 = input('state');
$state = url_safe_base64_decode($state_base64);
if ($authCode) {
if ($state) {
list($site_id, $type, $ag_site_id) = explode('|', $state);
} else {
$userInfo = Session::get("shop_user_info");
if ($userInfo) {
$type = 'minapp';
$site_id = $userInfo['site_id'];
$ag_site_id = Db::name('site')->where('site_id', '=', $site_id)->value('agent_id');
} else {
$this->error('会员信息无效', url("shop/login/login"));
}
}
$authinfo = $openPlatform->handleAuthorize($authCode);
if (isset($authinfo['code']) && $authinfo['code'] == 10000) {
$token = current($authinfo['tokens']);
switch ($type) {
case 'minapp':
$paydata = [
'line_type' => 'auth',
'app_type' => 'aliapp',
'site_id' => $site_id ?? 0,
'ag_site_id' => $ag_site_id ?? 0,
'appid' => $token['auth_app_id'],
'appsecret' => '',
'token' => '',
'app_name' => '',
'head_img' => '',
'qrcode' => '',
'account' => $token['user_id'],
'alipay_public' => '',
'private_key' => '',
'app_auth_token' => $token['app_auth_token'],
'app_refresh_token' => $token['app_refresh_token'],
'app_original' => $token['user_id'],
'original_values' => $token,
];
cache($state_base64, 'yes');
$paydata['state'] = $state;
event('MiniappAuthInfo', $paydata);
if ($site_id) {
$minapp = new Config();
$minapp->setAlipayConfig($token['auth_app_id'], $paydata, $site_id, $paydata['app_original']);
}
$this->assign('desc', '授权成功');
$this->assign('img', 'success');
return $this->fetch('aliapp/success');
case 'all':
break;
default;
$paydata = [
'appid' => $authinfo['auth_app_id'],
'appsecret' => '',
'user_id' => $token['user_id'],
'app_auth_token' => $authinfo['app_auth_token'],
'app_refresh_token' => $authinfo['app_refresh_token'],
'public_key' => '',
'private_key' => '',
'alipay_public_key' => '',
'is_isp' => 1,
'transfer_status' => 1,
'refund_status' => 1,
'pay_status' => 1,
];
$config = new Config();
$config->setAlipayConfig($authinfo['auth_app_id'], $paydata, $site_id);
return $this->success('授权成功', addon_url('aliapp/shop/aliapp/setting'));
}
} else {
return $this->error('授权失败', addon_url('aliapp/shop/aliapp/setting'));
}
} else {
return $this->error('授权失败', addon_url('aliapp/shop/aliapp/setting'));
}
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace addon\aliapp\shop\controller;
use app\shop\controller\BaseShop;
use addon\aliapp\model\CreateApplet as createAppletModel;
use addon\aliapp\model\AliPayApplet;
class CreateApplet extends BaseShop{
public function __construct(){
parent::__construct();
// 输出菜单
if(request()->isGet()) $this->forthMenu();
}
/**
* Common: 添加小程序
* Author: wu-hui
* Time: 2022/12/28 18:16
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function index(){
$createAppletModel = new createAppletModel();
if (request()->isAjax()) {
// 参数获取
$info = input('info',[]);
$res = $createAppletModel->setNewParams($info,$this->site_id);
return $res;
} else {
[$id,$content] = $createAppletModel->getNewParams($this->site_id);
$this->assign('id',$id);
$this->assign('info',$content);
return $this->fetch('aliapp/createApplet');
}
}
}

View File

@ -0,0 +1,81 @@
<?php
namespace addon\aliapp\shop\controller;
use addon\aliapp\model\AliPayMember;
use app\shop\controller\BaseShop;
class Member extends BaseShop{
// 成员角色类型。
private $memberRole = [
0 => 'DEVELOPER',
1 => 'EXPERIENCER',
'DEVELOPER' => '开发者',
'EXPERIENCER' => '体验者',
];
public function __construct(){
parent::__construct();
// 输出菜单
if(request()->isGet()) $this->forthMenu();
}
/**
* Common: 进入成员管理
* Author: wu-hui
* Time: 2022/12/30 13:53
* @return array|mixed
* @throws \think\db\exception\DbException
*/
public function index(){
if(request()->isAjax()) return (new AliPayMember($this->site_id))->getList();
return $this->fetch('member/index');
}
/**
* Common: 同步成员
* Author: wu-hui
* Time: 2022/12/30 13:47
* @return array
*/
public function synchronization(){
// 参数获取
$type = (int)input('type');
return (new AliPayMember($this->site_id))->synchronizationMember($this->memberRole[$type]);
}
/**
* Common: 添加成员
* Author: wu-hui
* Time: 2022/12/30 14:28
* @return array|mixed
*/
public function addMember(){
if (request()->isAjax()) {
return (new AliPayMember($this->site_id))->addMember();
} else {
return $this->fetch('member/add');
}
}
/**
* Common: 删除成员
* Author: wu-hui
* Time: 2022/12/30 14:41
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function delMember(){
return (new AliPayMember($this->site_id))->delMember();
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace addon\aliapp\shop\controller;
use addon\aliapp\model\AliPayMember;
use app\model\message\Message as MessageModel;
use app\model\message\MessageTemplate as MessageTemplateModel;
use app\shop\controller\BaseShop;
class Message extends BaseShop{
public function __construct(){
parent::__construct();
// 输出菜单
//if(request()->isGet()) $this->forthMenu();
}
/**
* Common: 订阅消息编辑
* Author: wu-hui
* Time: 2023/01/10 11:00
* @return array|mixed
*/
public function edit(){
// 基本信息修改
$message_model = new MessageModel();
$keywords = input("keywords","");
$infoResult = $message_model->getMessageInfo($this->site_id,$keywords);
$info = $infoResult["data"];
$aliAppJsonArray = $info["aliapp_json_array"];
$aliAppJsonArray['content'] = $aliAppJsonArray['content'] ?? $this->defaultMessageContent($keywords);
// 判断:进入页面 || 提交修改
if (request()->isAjax()) {
if(empty($info)) return error("","不存在的模板信息!");
// 参数获取
$wechatIsOpen = input('aliapp_is_open',0);
$aliAppJsonArray['template_id'] = trim(input('template_id',''));
$data = [
'aliapp_json' => json_encode($aliAppJsonArray),
];
$condition = [
["keywords","=",$keywords]
];
$templateModel = new MessageTemplateModel();
$res = $templateModel->editMessageTemplate($data,$condition);
if($res['code'] == 0){
$res = $message_model->editMessage([
'aliapp_is_open' => $wechatIsOpen,
'aliapp_template_id' => $aliAppJsonArray['template_id'],
'site_id' => $this->site_id,
'keywords' => $keywords
],[
["keywords","=",$keywords],
['site_id','=',$this->site_id],
]);
}
return $res;
}
else {
if (empty($info)) $this->error("不存在的模板信息!");
$this->assign("title", $info['title'] ?? '');
$this->assign("keywords", $keywords);
$this->assign("info", $aliAppJsonArray);
$this->assign('aliapp_is_open', $info['aliapp_is_open']);
return $this->fetch('message/edit');
}
}
/**
* Common: 默认模板内容
* Author: wu-hui
* Time: 2023/01/10 10:41
* @param $keywords
* @return array|string
*/
private function defaultMessageContent($keywords){
$list = [
'VERIFY' => "核销产品:{{keyword1}}\n核销商户:{{keyword2}}\n核销时间:{{keyword3}}\n",
'INTEREST_EXPIRATION_NOTICE' => "商家名称:{{keyword1}}\n剩余次数:{{keyword2}}\n优惠内容:{{keyword3}}\n",
'SERVICE_OPENED_SUCCESS' => "到期时间:{{keyword1}}\n姓名:{{keyword2}}\n开通时间:{{keyword3}}\n服务项目:{{keyword4}}\n",
];
return $list[$keywords] ?? [];
}
}

View File

@ -0,0 +1,21 @@
<?php
/**
* SAAS应用系统 --- 十年开发经验汇集巨献!
* ==========================================================
* Copy right 2020-2050 成都众联思索科技有限公司,保留所有权利。
* ----------------------------------------------------------
* 官方网址: https://www.zoomtk.com
* 这不是自由软件!未经允许不得用于商业目或程序代码摘取及修改。
* 任何企业和个人未经允许对程序代码以任何形式任何目的再发布传播。
* 唯一发布渠道www.zoomtk.com;非官方渠道统一视为侵权行为。
* ==========================================================
*/
namespace addon\aliapp\shop\controller;
class Pay
{
// public function
}

View File

@ -0,0 +1,306 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}{/block}
{block name="main"}
<div class="layui-form" >
<div class="layui-card card-common ns-card-brief">
<div class="layui-card-header">
<span class="card-title">小程序基础设置</span>
</div>
<div class="layui-card-body">
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>小程序名称:</label>
<div class="layui-input-block ">
<input type="text" name="app_name" lay-verify="required" autocomplete="off" class="layui-input len-long" value="{$info.app_name ?? ''}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>英文名称:</label>
<div class="layui-input-block ">
<input type="text" name="app_english_name" lay-verify="required" autocomplete="off" class="layui-input len-long" value="{$info.app_english_name ?? ''}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>小程序简介:</label>
<div class="layui-input-block">
<input type="text" name="app_slogan" lay-verify="required" autocomplete="off" class="layui-input len-long" value="{$info.app_slogan ?? ''}">
</div>
<div class="word-aux"> <p>10~32个字符一个中文两个字符。</p></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable"><span class="required">*</span>小程序Logo</label>
<div class="layui-input-block img-upload">
<input type="hidden" class="layui-input" name="app_logo" value="{$info.app_logo ?? ''}"/>
<div class="upload-img-block icon">
<div class="upload-img-box" id="img">
{if condition="isset($info.app_logo) && $info.app_logo"}
<img src="{:img($info.app_logo)}" />
{else/}
<div class="upload-default">
<img src="__STATIC__/img/upload_img.png" />
<p>点击上传</p>
</div>
{/if}
</div>
</div>
</div>
<div class="word-aux">
<p>建议上传像素为180*180 pxlogo图片最大 2M图片高度与宽度必须一致</p>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>小程序描述:</label>
<div class="layui-input-block">
<textarea name="app_desc" lay- autocomplete="off" lay-verify="required" class="layui-textarea len-long">{$info.app_desc ??''}</textarea>
</div>
<div class="word-aux"><p>20-400个字符一个中文两个字符。</p></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">服务电话:</label>
<div class="layui-input-block ">
<input type="text" name="service_phone" autocomplete="off" class="layui-input len-long" value="{$info.service_phone ?? ''}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱:</label>
<div class="layui-input-block">
<input type="text" name="service_email" autocomplete="off" class="layui-input len-long" value="{$info.service_email ?? ''}">
</div>
</div>
<!--服务分类-->
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>小程序服务分类:</label>
<div class="layui-input-block" id="app">
<div class="layui-form-item" v-if="category_list.length>0" v-for="(items,index) in category_list"
:key="index">
<div class="layui-input-inline len-mid" v-for="i in items.length">
<select name="category_ids[]" lay-filter="Category">
<option :value="item.category_id"
:data-child="JSON.stringify(item.child)"
:data-index="index"
:data-select="i-1"
:selected="item.checked"
v-for="(item,vi) in items[i-1]['categoryData']" >
{{item.category_name}}
</option>
</select>
</div>
<div class="layui-btn layui-btn-primary" @click="delCategory(items)">删除</div>
</div>
<button class="layui-btn" @click="addCategory()">增加分类</button>
</div>
<div class="word-aux"><p>请设置一个主营分类,最少设置一个分类</p></div>
</div>
</div>
</div>
<!--提交按钮-->
<div class="form-row">
<input name="mini_category_ids" type="hidden" value="{$mini_category_ids}">
<button class="layui-btn" lay-submit lay-filter="save">提交</button>
<button class="layui-btn layui-btn-primary" onclick="back()">返回</button>
</div>
</div>
{/block}
{block name="script"}
<script src="STATIC_JS/vue.js"></script>
<script>
var form,vue,upload;
vue = new Vue({
el: "#app",
data(){
return {
category_ids: [
['','',''],
['','',''],
['','',''],
['','','']
],
oneCategory:'',
twoCategory:'',
threeCategory:'',
allCategory:{:json_encode($allCategory)},
category_list: {:json_encode($original)}
}
},
created: function (){
let _this = this;
if (this.category_list.length > 0) {
this.category_list.forEach(res => {
let two = [];
res.forEach((v, i) => {
v.categoryData = [];
if (i == 0) {
v.categoryData = _this.allCategory;
} else if (i == 1) {
_this.allCategory.forEach(e => {
if (v.parent_category_id == e.category_id) {
v.categoryData = e.child;
two = v;
}
})
} else if (i == 2) {
if (two) {
let three = two.categoryData;
three.forEach(t => {
if (v.parent_category_id == t.category_id) {
if (t.hasOwnProperty('child')) {
v.categoryData = t.child;
}
}
});
}
}
})
})
}
layui.use(['form', 'upload', 'util'], function () {
upload = layui.upload, form = layui.form;
form.on('submit(save)', function (data) {
// if (repeat_flag) return;
// repeat_flag = true;
console.log(data.field);
console.log(_this.category_list);
let MiniCategoryIds=[];
if(_this.category_list.length>0){
_this.category_list.forEach(res=>{
let category_ids=[];
res.forEach(v=>{
if(v.category_id!=''){
category_ids.push(v.category_id);
}
})
MiniCategoryIds.push(category_ids.join('_'))
})
}else {
repeat_flag = false;
return layer.msg('请设置分类');
}
data.field.mini_category_ids=MiniCategoryIds.join(';');
$.ajax({
type: "post",
url: "{:addon_url('aliapp://shop/aliapp/editapp')}",
dataType: "JSON",
data: data.field,
success: function (data) {
repeat_flag = false;
layer.msg(data.message);
}
});
});
form.on('select(Category)', function(data){
var child=$(data.elem).find("option:selected").attr("data-child");
var index=$(data.elem).find("option:selected").attr("data-index");
var select_index=$(data.elem).find("option:selected").attr("data-select");
_this.category_ids[index][select_index]=data.value;
if (select_index == 0) {
_this.category_list[index][0].category_id=data.value;
child=JSON.parse(child);
let categorys = [
{..._this.category_list[index][0]},
{
category_id: child[0].category_id,
parent_category_id: _this.category_list[index][0].category_id,
categoryData: child
}
];
if (child[0].hasOwnProperty('child')) {
categorys.push(
{
category_id: child[0].category_id,
parent_category_id:categorys[1].category_id,
categoryData: [],
}
)
}
_this.category_list[index] = categorys;
}
if (select_index == 1) {
_this.category_list[index][1].category_id = data.value;
let categorys = [
{..._this.category_list[index][0]},
{..._this.category_list[index][1]}
];
if (child) {
child = JSON.parse(child);
categorys.push(
{
category_id: child[0].category_id,
parent_category_id: _this.category_list[index][1].category_id,
categoryData: child
}
)
}
_this.category_list[index] = categorys;
}
_this.$forceUpdate();
});
// 图片上传
var uploadInst = upload.render({
elem: '#img',
url: ns.url("shop/upload/upload"),
done: function (res) {
if (res.code >= 0) {
$("input[name='app_logo']").val(res.data.pic_path);
$("#img").html("<img src=" + ns.img(res.data.pic_path) + " >");
}
return layer.msg(res.message);
}
});
form.render();
});
},
mounted(){
},
updated(){
form.render();
},
methods: {
delCategory(item){
if (this.category_list.includes(item)) {
this.category_list.splice(this.category_list.findIndex(el => el == item), 1);
}
},
addCategory(){
let _this=this;
this.category_list.push([
{
category_id:_this.allCategory[0].category_id,
parent_category_id:0,
categoryData:_this.allCategory
},
{
category_id:_this.allCategory[0].child[0].category_id,
parent_category_id:_this.allCategory[0].category_id,
categoryData:_this.allCategory[0].child
},
{
category_id:_this.allCategory[0].child[0].child[0].category_id,
parent_category_id:_this.allCategory[0].child[0].child.category_id,
categoryData:_this.allCategory[0].child[0].child
}
])
_this.$forceUpdate();
},
getAllCategory(){
let _this=this;
$.ajax({
type: "post",
url: "{:addon_url('aliapp://shop/aliapp/getAllCategory')}",
dataType: "JSON",
success: function (data) {
this.allCategory=data;
_this.$forceUpdate();
// form.render();
}
});
}
}
})
function back() {
location.href = "{:addon_url('aliapp://shop/aliapp/setting')}";
}
</script>
{/block}

View File

@ -0,0 +1,45 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}
<style>
.upload-img-block {
padding: 13px;
width: 250px;
height: 250px;
border: 1px dashed #ddd;
box-sizing: border-box;
position: relative;
}
</style>
{/block}
{block name="main"}
<div class="layui-form form-wrap">
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable">扫码授权:</label>
<div class="layui-input-block img-upload">
<div class="upload-img-block icon">
<div class="upload-img-box">
<div class="upload-default" id="group_image">
<div class="upload">
<img src="{$auth_img}?v={:time()}"/>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-row">
<button class="layui-btn" onclick="back()">已完成授权</button>
<button type="reset" class="layui-btn layui-btn-primary" onclick="back()">返回</button>
<a id="imageQrcode"></a>
</div>
</div>
{/block}
{block name="script"}
<script>
var form, repeat_flag = false;
// 返回
function back() {
location.href = ns.url("aliapp://shop/aliapp/setting");
}
</script>
{/block}

View File

@ -0,0 +1,157 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}
{/block}
{block name="main"}
<div class="layui-form">
<div class="layui-card card-common ns-card-brief">
<div class="layui-card-header">
<span class="card-title">接入方式</span>
</div>
<div class="layui-form-item">
<div class="layui-input-block sm">
<input type="radio" lay-filter="line_type" name="line_type" value="auth" title="授权接入" {eq name="$line_type" value="auth"}checked {/eq}>
<input type="radio" lay-filter="line_type" name="line_type" value="custom" title="手动接入" {eq name="$line_type" value="custom"}checked{/eq}>
</div>
</div>
<div class="word-aux">设置接入方式</div>
</div>
<div class="layui-card card-common ns-card-brief">
<div class="layui-card-header">
<span class="card-title">开发者设置</span>
</div>
<div class="layui-card-body">
<div class="layui-form-item">
<label class="layui-form-label">小程序名称:</label>
<div class="layui-input-inline ">
<input type="text" name="app_name" autocomplete="off" class="layui-input len-long" value="{$config_info.app_name ?? ''}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">原始ID</label>
<div class="layui-input-inline ">
<input type="text" name="app_original" autocomplete="off" class="layui-input len-long" value="{$config_info.app_original ?? ''}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable">小程序二维码:</label>
<div class="layui-input-inline img-upload">
<input type="hidden" class="layui-input" name="qrcode" value="{$config_info.qrcode ?? ''}"/>
<div class="upload-img-block icon">
<div class="upload-img-box" id="img">
{if condition="$config_info && $config_info.qrcode"}
<img src="{:img($config_info.qrcode)}" />
{else/}
<div class="upload-default">
<img src="__STATIC__/img/upload_img.png" />
<p>点击上传</p>
</div>
{/if}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="layui-card card-common card-brief">
<div class="layui-card-header">
<span class="card-title">开发者ID设置</span>
</div>
<div class="layui-form-item">
<div class="layui-form-item">
<label class="layui-form-label">APPID</label>
<div class="layui-input-inline ">
<input type="text" name="appid" autocomplete="off" class="layui-input len-long" value="{$config_info.appid ?? ''}">
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">应用私钥:</label>
<div class="layui-input-block">
<textarea name="private_key" class="layui-textarea len-long" placeholder="请输入应用私钥">{$config_info.private_key ?? ''}</textarea>
</div>
</div>
<div class="countersign_type_zero" >
<div class="layui-form-item " >
<label class="layui-form-label">应用公钥:</label>
<div class="layui-input-block">
<textarea name="public_key" class="layui-textarea len-long" placeholder="请输入应用公钥">{$config_info.public_key ?? ''}</textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">支付宝公钥:</label>
<div class="layui-input-block">
<textarea name="alipay_public_key" class="layui-textarea len-long" placeholder="请输入支付宝公钥">{$config_info.alipay_public_key ?? ''}</textarea>
</div>
</div>
</div>
<div class="layui-card-body">
<div class="layui-form-item">
<label class="layui-form-label">原始ID</label>
<div class="layui-input-inline ">
<input type="text" name="app_original" autocomplete="off" class="layui-input len-long" value="{$config_info.app_original ?? ''}">
</div>
</div>
</div>
<div class="form-row">
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
<button type="reset" class="layui-btn layui-btn-primary" onclick="back()">返回</button>
<a id="imageQrcode"></a>
</div>
</div>
</div>
{/block}
{block name="script"}
<script type="text/javascript">
layui.use(['form', 'upload', 'util'], function () {
var form = layui.form,
upload = layui.upload,
repeat_flag = false; //防重复标识
form.render();
form.on('submit(save)', function (data) {
if (repeat_flag) return;
repeat_flag = true;
$.ajax({
type: "post",
url: "{:addon_url('aliapp://shop/aliapp/config')}",
dataType: "JSON",
data: data.field,
success: function (data) {
repeat_flag = false;
layer.msg(data.message);
}
});
});
form.on('radio(line_type)', function(data){
if(data.value=='auth'){
layer.confirm('您将是要授权方式接入', {
btn: ['取消', '去授权'] //可以无限个按钮
}, function (index, layero) {
layer.close(index);
//按钮【按钮一】的回调
}, function (index) {
window.open('{$auth_url}')
});
}
});
// 图片上传
var uploadInst = upload.render({
elem: '#img',
url: ns.url("shop/upload/upload"),
done: function (res) {
if (res.code >= 0) {
$("input[name='qrcode']").val(res.data.pic_path);
$("#img").html("<img src=" + ns.img(res.data.pic_path) + " >");
}
return layer.msg(res.message);
}
});
});
function back() {
location.href = "{:addon_url('aliapp://shop/aliapp/setting')}";
}
</script>
{/block}

View File

@ -0,0 +1,143 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}
<style>
.tips{
font-size: 13px;
color: #cccccc;
}
</style>
{/block}
{block name="main"}
<div class="layui-form form-wrap" lay-filter="formInfo">
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label"><span class="required">*</span>小程序名称:</label>
<div class="layui-input-inline">
<input type="text" name="info[app_name]" value="{$info['app_name']}" autocomplete="off" class="layui-input len-long">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label"><span class="required">*</span>登录帐号:</label>
<div class="layui-input-inline">
<input type="text" name="info[alipay_account]" value="{$info['alipay_account']}" autocomplete="off" class="layui-input len-long">
<div class="tips">登录支付宝的邮箱帐号或手机号</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label"><span class="required">*</span>商家法人名称:</label>
<div class="layui-input-inline">
<input type="text" name="info[legal_personal_name]" value="{$info['legal_personal_name']}" autocomplete="off" class="layui-input len-long">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label"><span class="required">*</span>营业执照企业名称:</label>
<div class="layui-input-inline">
<input type="text" name="info[cert_name]" value="{$info['cert_name']}" autocomplete="off" class="layui-input len-long">
<div class="tips">如果是“无主体名称个体工商户”则填[个体户+法人姓名],例如:个体户张三</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label"><span class="required">*</span>营业执照编码:</label>
<div class="layui-input-inline">
<input type="text" name="info[cert_no]" value="{$info['cert_no']}" autocomplete="off" class="layui-input len-long">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label"><span class="required">*</span>商家联系人名称:</label>
<div class="layui-input-inline">
<input type="text" name="info[contact_name]" value="{$info['contact_name']}" autocomplete="off" class="layui-input len-long">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label"><span class="required">*</span>商家联系人手机电话:</label>
<div class="layui-input-inline">
<input type="text" name="info[contact_phone]" value="{$info['contact_phone']}" autocomplete="off" class="layui-input len-long">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>营业执照图片:</label>
<div class="layui-input-block img-upload">
<div class="upload-img-block square simple-uploading">
<div class="upload-img-box" id="img">
<div class="upload-default">
<i class="iconfont iconshangchuan"></i>
<p>点击上传</p>
</div>
</div>
<input type="hidden" name="image" />
<i class="del">x</i>
</div>
</div>
</div>
<!--操作按钮-->
<div class="form-row">
<input type="hidden" name="info[id]" value="{$id}" />
<button class="layui-btn" lay-submit lay-filter="save">提交</button>
<button class="layui-btn layui-btn-primary" onclick="back()">返回</button>
</div>
</div>
{/block}
{block name="script"}
<script>
var form,repeat_flag = false,license_pic = '{$info.license_pic}';
initImg();//初始化图片
function initImg(){
if(license_pic.length > 0){
$("#img").html("<img src=" + ns.img(license_pic) + " >");
imageCollection = [license_pic];
}
}
$(function () {
// 表单内容
layui.use(['form'], function() {
form = layui.form;
form.render();
// 表单提交
form.on('submit(save)', function(data){
var field = data.field;
field['info[license_pic]'] = imageCollection.join();
// 数据提交
//if(repeat_flag) return;
repeat_flag = true;
$.ajax({
type: 'POST',
dataType: 'JSON',
url: ns.url("aliapp://shop/createApplet/index"),
data: field,
async: false,
success: function(res){
repeat_flag = false;
if (res.code == 0) {
layer.alert('编辑成功', function(index){
back();
});
}else{
layer.msg(res.message);
}
}
})
});
// 单图上传
$("body").on("click", "#img", function () {
var html = '';
openAlbum(function (data) {
imageCollection = [];
imageCollection.push(data[0].pic_path);
imageCollection.splice(1, imageCollection.length);
var val = '<img src="' + ns.img(imageCollection[0]) + '" alt="">';
$("#img").html(val);
}, 1);
});
});
});
// 返回
function back() {
location.href = ns.url("aliapp://shop/aliapp/setting");
}
</script>
{/block}

View File

@ -0,0 +1,261 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}
<style>
.ns-progress-wrap {
display: flex;
align-items: center;
text-align: center;
min-height: 120px;
}
.ns-progress-point {
flex-grow: 1;
}
.ns-progress-point-pic {
display: inline-block;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
margin-top: 10px;
margin-bottom: 20px;
}
.ns-progress-point-pic img {
max-width: 100%;
max-height: 100%;
}
/* 到期提示 */
.expire-hint{
display: flex;
align-items: center;
padding: 15px 30px;
height: 115px;
line-height: 75px;
background-color: #fff9f5;
box-sizing: border-box;
}
.expire-hint .expire-logo{
display: flex;
justify-content: center;
align-items: center;
margin-right: 15px;
width: 40px;
height: 40px;
}
.expire-hint .expire-logo img{
max-height: 100%;
max-width: 100%;
}
.expire-hint .expire-center{
line-height: 1;
}
.expire-hint .expire-center h3{
font-size: 15px;
font-weight: 700;
}
.expire-hint .expire-center p{
margin-top: 10px;
color:#5d5c5c;
}
.expire-hint .expire-center p span:nth-of-type(2){
margin-left: 15px;
}
.expire-hint .expire-center h3 a{
font-size: 12px;
font-weight: normal;
margin-left: 5px;
cursor: pointer;
}
</style>
{/block}
{block name="main"}
<div class="layui-card ns-card-common ns-card-brief">
<div class="layui-card-header">
<span class="ns-card-title">支付宝小程序源码上传</span>
</div>
<div class="layui-card-body">
<ul class="ns-progress-wrap">
<li class="ns-progress-point">
<div class="ns-progress-point-pic">
<img src="WEAPP_IMG/register.png" alt="">
</div>
<a href="{:addon_url('weapp://shop/weapp/reg')}">
<p class="ns-progress-point-text">注册小程序</p>
</a>
</li>
<li class="ns-progress-point-arrow">
<img src="WEAPP_IMG/arrow.png" alt="">
</li>
<li class="ns-progress-point">
<div class="ns-progress-point-pic">
<img src="WEAPP_IMG/set_up.png" alt="">
</div>
<a href="https://mp.weixin.qq.com">
<p class="ns-progress-point-text">填写信息</p>
</a>
</li>
<li class="ns-progress-point-arrow">
<img src="WEAPP_IMG/arrow.png" alt="">
</li>
<li class="ns-progress-point">
<div class="ns-progress-point-pic">
<img src="WEAPP_IMG/public_number.png" alt="">
</div>
<p class="ns-progress-point-text">上传代码</p>
</li>
<li class="ns-progress-point-arrow">
<img src="WEAPP_IMG/arrow.png" alt="">
</li>
<li class="ns-progress-point">
<div class="ns-progress-point-pic">
<img src="WEAPP_IMG/edition.png" alt="">
</div>
<p class="ns-progress-point-text">提交审核</p>
</li>
<li class="ns-progress-point-arrow">
<img src="WEAPP_IMG/arrow.png" alt="">
</li>
<li class="ns-progress-point">
<div class="ns-progress-point-pic">
<img src="WEAPP_IMG/complete.png" alt="">
</div>
<p class="ns-progress-point-text">发布</p>
</li>
</ul>
</div>
{if $errcode}
<div class="expire-hint">
<div class="expire-logo">
<img src="SHOP_IMG/warning.png" >
</div>
<div class="expire-center">
<h3>未能获取到服务分类列表 错误编码:{$errcode.errcode}-{$errcode.errmsg}</h3>
<p><span class="ns-red-color">1.如果未添加请到官方添加服务分类 <a href="https://mp.weixin.qq.com">立即添加</a></span></p>
<p><span class="ns-red-color">2.如已添加但依然无法显示 当前API权限不足请重新授权选择所有权限</span></p>
<p><span class="ns-red-color">3.如已其他第三方开发平台需要取消后重新授权</span></p>
</div>
</div>
{/if}
</div>
<div class="layui-card ns-card-common ns-card-brief">
<div class="layui-card-header">
<span class="ns-card-title">程序上传</span>
</div>
<div class="layui-form layui-card-body">
<div class="layui-form-item">
<label class="layui-form-label">版本号:</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="text" lay-verify="required|verify" name="user_version" id="user_version" class="layui-input ns-len-long" value="">
</div>
</div>
<div class="ns-word-aux">版本库用户自定义如1.0.1;1.0.2...等</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">版本描述:</label>
<div class="layui-input-block">
<div class="layui-input-inline ns-len-long">
<textarea class="layui-textarea ns-len-long" type="text" name="user_desc" id="user_desc" ></textarea>
<div style="display: block;margin-top: 5px;color: #B2B2B2; font-size: 12px;line-height: 1.6;">
版本描述,描述应用场景用途
</div>
</div>
</div>
</div>
<!-- <div class="layui-form-item">-->
<!-- <label class="layui-form-label">发布应用</label>-->
<!-- <div class="layui-input-block">-->
<!-- <input type="radio" name="auto_release" value="0" title="手动发布" checked>-->
<!-- <input type="radio" name="auto_release" value="1" title="自动发布">-->
<!-- </div>-->
<!-- <div class="ns-word-aux">当支付宝官方对小程序内容进行审核如果通过是否发布</div>-->
<!-- </div>-->
<!-- <div class="layui-form-item">-->
<!-- <label class="layui-form-label">服务分类:</label>-->
<!-- <div class="layui-input-block">-->
<!-- <input type="hidden" name="category" lay-verify="required" id="category">-->
<!-- <input type="hidden" name="category_name" lay-verify="required" id="category_name">-->
<!-- <table id="gctable" lay-filter="gctable"></table>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="layui-form-item">-->
<!-- <label class="layui-form-label">直播</label>-->
<!-- <div class="layui-input-block">-->
<!-- <input type="radio" name="islive" value="no" title="未开通" checked>-->
<!-- <input type="radio" name="islive" value="yes" title="已开通">-->
<!-- </div>-->
<!-- <div class="ns-word-aux">微信小程序官方直播插件,如你已开通选择已开通,如还未开通选择未开通(注:后期开通需要重新上传代码)</div>-->
<!-- </div>-->
<div class="ns-form-row">
<button class="layui-btn ns-bg-color" lay-submit lay-filter="save">上传代码</button>
</div>
</div>
{/block}
{block name="script"}
<script type="text/javascript">
layui.use(['table', 'form','util','layer'], function () {
var table = layui.table,
form = layui.form,
util = layui.util,
layer = layui.layer,
repeat_flag = false; //防重复标识
//监听表格复选框选择
table.on('radio(gctable)', function(obj){
let data={
'first_id':obj.data.first,
'second_id':obj.data.second,
'third_id':obj.data.third||'',
}
let name = obj.data.first_name + "|" +obj.data.second_name+"|" + obj.data.third_name||''
$('#category').val(JSON.stringify(data))
$('#category_name').val(name)
});
form.render();
//自定义验证规则
form.verify({
verify: function(value){
const reg = /^([1-9]\d|[1-9])(\.([1-9]\d|\d)){2}$/
if(!reg.test(value)){
return '非正确格式'
}
}
});
form.on('submit(save)', function (data) {
if (repeat_flag) return;
// repeat_flag = true;
console.log(data)
$.ajax({
type: "post",
url: "{:addon_url('qqapp://shop/qq/upload_code')}",
dataType: "JSON",
data: data.field,
success: function (data) {
repeat_flag = false;
layer.msg(data.message);
if(data.err==0){
layer.open({
type: 1,
title: '体验码--提交成功',
area: ['280px', '320px']
,content:"<div><img style='width: 240px;align-content: center'src='data:image/jpeg;base64," + data.test_qrcode + "'></div>"
})
}
}
});
});
table.render({
elem: '#gctable'
,height: 258
,data: JSON.parse('{:json_encode($category)}')
, cols: [[ //表头
{type: 'radio', fixed: 'left',title: '选择分类',width: '10%'}
, {field: 'first_name', title: '一级类别', width: '15%'}
, {field: 'second_name', title: '二级类目', width: '15%'}
, {field: 'second_name', title: '三级类目', width: '15%'}
, {field: 'audit_status', title: '审核状态', width: '10%'}
, {field: 'audit_reason', title: '原由', width: '35%'}
]]
});
});
</script>
{/block}

View File

@ -0,0 +1,201 @@
{extend name="app/shop/view/base.html" /}
{block name="resources"}
<style>
.progress-wrap {
display: flex;
align-items: center;
text-align: center;
min-height: 120px;
}
.progress-point {
flex-grow: 1;
}
.progress-point-pic {
display: inline-block;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
margin-top: 10px;
margin-bottom: 20px;
}
.progress-point-pic img {
max-width: 100%;
max-height: 100%;
}
.item-block-wrap .new-tips{
width: 8px;
height: 8px;
background: #f00;
border-radius: 50%;
position: absolute;
right: 15px;
}
.item-content-desc{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.insert-type .type-title {font-size: 23px;font-weight: 100;text-align: center;margin-bottom: 10px;}
.insert-type .item-type {width: 47%;border: 1px solid #e6e9f0;display: inline-block;margin: 10px 1% 0px;padding: 20px 10px 20px 10px;box-sizing: border-box;cursor: pointer;height: 90px;}
.insert-type .item-type:last-child{margin-right: 0;}
.insert-type .item-type div {display: inline-block;float: left;height: 50px;width: 50px;}
.insert-type .item-type div img{width: 100%;}
.insert-type .item-type div.item-content {margin-left: 10px;width: 180px;}
.insert-type .item-type div.item-content p.name {margin-top: 2px;}
.insert-type .item-type div.item-content p {margin-bottom: 0px;}
.insert-type .item-type div.item-content p.description {color: #999;font-size: 12px;margin-top: 7px;}
</style>
<div class="insert-type" style="display: none" id="insert">
<div class="item-type" lay-active="authinsert">
<div class="item-img"><img src="SHOP_IMG/goods_icon.png" alt=""></div>
<div class="item-content">
<p class="name">授权接入</p>
<p class="description">(授权接入无需复杂参数配置)</p>
</div>
</div>
<div class="item-type" lay-active="paraminsert">
<div class="item-img"><img src="SHOP_IMG/virtual_goods_icon.png" alt=""></div>
<div class="item-content">
<p class="name">参数设置</p>
<p class="description">(手动接入需要录入开发相关数据)</p>
</div>
</div>
</div>
{/block}
{block name="main"}
<div class="layui-card card-common card-brief">
<div class="layui-card-header">
<span class="card-title">支付宝小程序使用流程</span>
</div>
<div class="layui-card-body">
<ul class="progress-wrap">
<li class="progress-point">
<div class="progress-point-pic">
<img src="WEAPP_IMG/register.png" alt="">
</div>
<p class="progress-point-text">注册小程序应用</p>
</li>
<li class="progress-point-arrow">
<img src="WEAPP_IMG/arrow.png" alt="">
</li>
<li class="progress-point">
<div class="progress-point-pic">
<img src="WEAPP_IMG/set_up.png" alt="">
</div>
<p class="progress-point-text">信息完善</p>
</li>
<li class="progress-point-arrow">
<img src="WEAPP_IMG/arrow.png" alt="">
</li>
<li class="progress-point">
<div class="progress-point-pic">
<img src="WEAPP_IMG/public_number.png" alt="">
</div>
<p class="progress-point-text">开发</p>
</li>
<li class="progress-point-arrow">
<img src="WEAPP_IMG/arrow.png" alt="">
</li>
<li class="progress-point">
<div class="progress-point-pic">
<img src="WEAPP_IMG/edition.png" alt="">
</div>
<p class="progress-point-text">提交审核</p>
</li>
<li class="progress-point-arrow">
<img src="WEAPP_IMG/arrow.png" alt="">
</li>
<li class="progress-point">
<div class="progress-point-pic">
<img src="WEAPP_IMG/complete.png" alt="">
</div>
<p class="progress-point-text">发布</p>
</li>
</ul>
</div>
</div>
<div class="layui-card card-common card-brief">
<div class="layui-card-header">
<span class="card-title">小程序入口</span>
</div>
<div class="layui-card-body">
<div class="site_list item-block-parent item-five">
<a class="item-block item-block-hover-a" lay-active="active">
<div class="item-block-wrap">
<div class="item-pic">
<img src="WEAPP_IMG/administration.png">
</div>
<div class="item-con">
<div class="item-content-title">小程序管理</div>
<p class="item-content-desc">小程序管理</p>
</div>
</div>
</a>
{if !empty($config_info['line_type']) &&$config_info.line_type=='auth'}
<a class="item-block item-block-hover-a" href="{:addon_url('aliapp://shop/aliapp/editapp')}">
<div class="item-block-wrap">
<div class="item-pic">
<img src="WEAPP_IMG/message.png">
</div>
<div class="item-con">
<div class="item-content-title">基础设置</div>
<p class="item-content-desc">完善基础信基础设置</p>
</div>
</div>
</a>
<a class="item-block item-block-hover-a" href="{:addon_url('aliapp://shop/appletRelease/index')}">
<div class="item-block-wrap">
<div class="item-pic">
<img src="WEAPP_IMG/message.png">
</div>
<div class="item-con">
<div class="item-content-title">发布小程序</div>
<p class="item-content-desc">构建&提审小程序</p>
</div>
</div>
</a>
{/if}
<a class="item-block item-block-hover-a" href="{:addon_url('shop/message/lists')}">
<div class="item-block-wrap">
<div class="item-pic">
<img src="WEAPP_IMG/message.png">
</div>
<div class="item-con">
<div class="item-content-title">订阅消息</div>
<p class="item-content-desc">给用户提供更好的服务闭环体验</p>
</div>
</div>
</a>
</div>
</div>
</div>
{/block}
{block name="script"}
<script type="text/javascript">
layui.use(['layer','util'], function() {
var layer = layui.layer,util=layui.util,index;
//处理属性 为 lay-active 的所有元素事件
util.event('lay-active', {
active: function () {
index = layer.open({
type: 1,
title: '接入方式',
area: ['600px']
, content: $('#insert')
})
}
,paraminsert(){
location.href="{:addon_url('aliapp://shop/aliapp/config')}"
}
,authinsert(){
location.href="{:addon_url('aliapp://shop/aliapp/auth')}"
}
});
});
</script>
{/block}

View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>支付宝扫码授权</title>
<script src="__STATIC__/ext/layui/layui.js"></script>
<link rel="stylesheet" type="text/css" href="__STATIC__/ext/layui/css/layui.css" />
</head>
<body>
<div class="container">
<div><img style='width: 200px;align-content: center;' src='/addon/aliapp/shop/view/public/{$img}.png'></div>
<div style= "font-size:60px;margin-top: 25px">{$desc}</div>
<form class="layui-form" action="">
<div class="layui-form-item">
<!-- <button type="button" class="layui-btn layui-btn-normal" onclick="close()" style="margin-top: 100px;font-size: 50px;height:90px;">关闭页面</button>-->
</div>
</form>
</div>
</body>
<style>
.container {
/*margin-top: 50px;*/
text-align: center;
margin: 100px auto;
}
.item{
display: inline-block;
width: 100px;
background-color: #ff266e;
}
</style>
<script>
function close() {
window.opener=null;
// window.open('','_self');
window.open(location, '_self').close();
// window.close();
}
// layui.use('layer', function(){
// let msg='授权接入';
// var layer = layui.layer;
// var index = parent.layer.getFrameIndex(window.name); //当前iframe层的索引
// layer.msg(msg);
// setTimeout(function(){
// parent.layer.close(index); //再执行关闭
// },3000)
// });
</script>
</html>

View File

@ -0,0 +1,78 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}
<style>
</style>
{/block}
{block name="body"}
<div class="layui-form form-wrap" lay-filter="formInfo">
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label">
<span class="required">*</span>支付宝登录账号
</label>
<div class="layui-input-inline">
<input type="text" name="info[logon_id]" lay-verify="required" autocomplete="off" placeholder="请输入支付宝登录账号" class="layui-input len-long">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label img-upload-lable short-label">
<span class="required">*</span>角色类型:
</label>
<div class="layui-input-inline">
<select name="info[role]" lay-verify="required">
<option value="DEVELOPER">开发者</option>
<option value="EXPERIENCER">体验者</option>
</select>
</div>
</div>
<!--提交按钮-->
<div class="form-row">
<button class="layui-btn" lay-submit lay-filter="save">提交</button>
<button class="layui-btn layui-btn-primary" onclick="closeIframe()">关闭</button>
</div>
</div>
{/block}
{block name="script"}
<script>
var _thisIndex,form,repeat_flag = false;
$(function () {
// 基本参数
_thisIndex = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
// 表单内容
layui.use(['form'], function() {
form = layui.form;
form.render();
// 表单提交
form.on('submit(save)', function(data){
var field = data.field;
// 数据提交
if(repeat_flag) return;
repeat_flag = true;
$.ajax({
type: 'POST',
dataType: 'JSON',
url: ns.url("aliapp://shop/Member/addMember"),
data: field,
async: false,
success: function(res){
repeat_flag = false;
if (res.code == 0) {
layer.alert(res.message, function(index){
parent.layer.close(_thisIndex);
});
}else{
layer.msg(res.message);
}
}
})
});
});
});
// 点击关闭弹框
function closeIframe() {
parent.layer.close(_thisIndex);
}
</script>
{/block}

View File

@ -0,0 +1,156 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}
<style>
.prompt-block .prompt {
display: inline-block;
}
.prompt-block .prompt {
width: 18px;
height: 18px;
line-height: 18px;
position: relative;
}
.user-head-img{
width:40px;
height:40px;
margin-right:20px;
}
</style>
{/block}
{block name="main"}
<!-- 顶部操作内容 -->
<div class="single-filter-box top">
<div class="right">
<button class="layui-btn" onclick="addMember()">添加成员</button>
<button class="layui-btn" style="background-color: #009688;" onclick="synchronization(0)">同步开发者</button>
<button class="layui-btn" style="background-color: #FFB800;" onclick="synchronization(1)">同步体验者</button>
</div>
<div class="left"></div>
</div>
<!-- 列表 -->
<table id="listContent" lay-filter="listContent"></table>
<!-- 操作 -->
<script type="text/html" id="operation">
<div class="table-btn">
<a class="layui-btn" lay-event="delete">删除</a>
</div>
</script>
{/block}
{block name="script"}
<script>
var table,
form,
editIframe,
repeat_flag = false;//防重复标识;
layui.use(['form'], function() {
form = layui.form;
form.render();
// 内容获取
table = new Table({
elem: '#listContent',
url: ns.url("aliapp://shop/member/index"),
cols: [[
{align: 'center', field: 'id', title: 'ID', width: '5%', unresize: 'false'},
{align: 'center', field: 'user_id', title: '支付宝用户id', unresize: 'area'},
{align: 'center', field: 'nick_name', title: '昵称', unresize: 'area'},
{
align: 'center', templet: function (d) {
// 成员的状态VALID-有效UNCONFIRMED-未确认TIMEOUT-已经失效REFUSED-用户拒绝
let statusText = '';
switch (d.status) {
case 'VALID': statusText = '有效'; break;
case 'UNCONFIRMED': statusText = '未确认'; break;
case 'TIMEOUT': statusText = '已经失效'; break;
case 'REFUSED': statusText = '用户拒绝'; break;
}
return statusText;
}, title: '状态', unresize: 'false'
},
{align: 'center', field: 'gmt_join', title: '加入时间', unresize: 'area'},
{align: 'center', field: 'logon_id', title: '支付宝账号', unresize: 'area'},
{align: 'center', field: 'gmt_invite', title: '邀请时间', unresize: 'area'},
{
align: 'center', templet: function (d) {
// 角色类型DEVELOPER-开发者EXPERIENCER-体验者
return d.role === 'DEVELOPER' ? '开发者' : '体验者';
}, title: '角色类型', unresize: 'false'
},
{title: '操作', toolbar: '#operation', unresize: 'false', align: 'right'}
]],
});
// 监听工具栏操作
table.tool(function(obj) {
var data = obj.data;
switch (obj.event) {
case 'delete':
delMember(data.id);
break;//删除
}
});
});
// 成员同步
function synchronization(type){
let index = ns.loading('open','同步中,请等待......');
requestApi("aliapp://shop/Member/synchronization",{ type: type },function (res) {
table.reload({
page: {
curr: 1
},
});
layer.close(index);
})
}
// 添加成员
function addMember(){
editIframe = layer.open({
type: 2,
title: '添加名片',
skin: 'layer-tips-class',
area: ['70%','90%'],
content: ns.url("aliapp://shop/Member/addMember", {}),
end: function(){
table.reload({
page: {
curr: 1
},
});
}
});
}
// 删除成员
function delMember(id){
layer.confirm('确定删除成员吗!', {icon: 3, title:'提示'}, function(confirmIndex){
layer.close(confirmIndex);
let index = ns.loading('open','删除中,请等待......');
requestApi("aliapp://shop/Member/delMember",{ id: id },function (res) {
table.reload({
page: {
curr: 1
},
});
layer.close(index);
})
});
}
// 发起请求
function requestApi(api,data,fun){
if (repeat_flag) return false;
repeat_flag = true;
$.ajax({
url: ns.url(api),
data: data,
dataType: 'JSON',
type: 'POST',
success: function(res) {
layer.msg(res.message);
repeat_flag = false;
if(typeof fun === 'function') fun(res);
}
});
}
</script>
{/block}

View File

@ -0,0 +1,73 @@
{extend name="app/shop/view/base.html" /}
{block name="main"}
<div class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">模板名称:</label>
<div class="layui-input-block">
{$title ?? ''}
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">是否开启:</label>
<div class="layui-input-block">
<input type="checkbox" name="aliapp_is_open" value="1" {if $aliapp_is_open == 1}checked{/if} lay-skin="switch">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>模板消息ID</label>
<div class="layui-input-block">
<input type="text" name="template_id" value="{$info.template_id ?? ''}" placeholder="模板消息ID" autocomplete="off" class="layui-input len-long">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label"><span class="required"></span>模板内容:</label>
<div class="layui-input-inline">
<textarea placeholder="" class="layui-textarea len-long" readonly>{$info.content ?? ''}</textarea>
</div>
</div>
<div class="form-row">
<input type="hidden" name="keywords" value="{$keywords}" />
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
<button type="reset" class="layui-btn layui-btn-primary" onclick="back()">返回</button>
</div>
</div>
{/block}
{block name="script"}
<script>
layui.use(['form'], function() {
var form = layui.form, repeat_flag = false; //防重复标识
form.render();
form.on('submit(save)', function(data) {
//if (repeat_flag) return;
repeat_flag = true;
$.ajax({
url: ns.url("aliapp://shop/Message/edit"),
data: data.field,
dataType: 'JSON',
type: 'POST',
success: function(res) {
repeat_flag = false;
if (res.code == 0) {
layer.confirm('编辑成功', {
title:'操作提示',
btn: ['返回列表', '继续操作'],
yes: function(){
location.href = ns.url("shop/message/lists")
},
btn2: function() {
location.reload();
}
});
}else{
layer.msg(res.message);
}
}
});
});
});
// 返回消息列表
function back() {
location.href = ns.url("shop/message/lists");
}
</script>
{/block}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -0,0 +1,342 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}
<style>
.prompt-block .prompt {
display: inline-block;
}
.prompt-block .prompt {
width: 18px;
height: 18px;
line-height: 18px;
position: relative;
}
.user-head-img{
width:40px;
height:40px;
margin-right:20px;
}
.qrcode-content{
width: 100%;
height: 100%;
display: inline-flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: center;
align-items: center;
}
.qrcode-content .qrcode-content-img{
width: 120px;
}
</style>
{/block}
{block name="main"}
<div class="layui-collapse ns-tips">
<div class="layui-colla-item">
<h2 class="layui-colla-title">操作提示</h2>
<ul class="layui-colla-content layui-show">
<li>通过平台注册小程序需要完善基础信息</li>
{if $is_baseinfo==0}
<li style="color:#d55959;">未完善基础信息将无法通过审核<a style="color: #0d73f9;margin-left: 10px" href="{:addon_url('aliapp/shop/aliapp/editapp')}">去完善</a></li>
{/if}
</ul>
</div>
</div>
<!-- 顶部操作内容 -->
<div class="single-filter-box top">
<div class="right">
{if $isNewest}
<button class="layui-btn" onclick="operationRequest('version_upload')">发布新版本</button>
{/if}
<button class="layui-btn" style="background-color: #009688;" onclick="versionSynchronization()">同步线上版本</button>
<button class="layui-btn" style="background-color: #FFB800;" onclick="qrcodeCreate()">体验二维码</button>
</div>
<div class="left"></div>
</div>
<!-- 列表 -->
<table id="listContent" lay-filter="listContent"></table>
<!-- 操作 -->
<script type="text/html" id="operation">
<div class="table-btn">
{{# if(d.is_newest_version){ }}
<!-- 审核中相关按钮 INIT: 开发中, AUDITING: 审核中, AUDIT_REJECT: 审核驳回, WAIT_RELEASE: 待上架, BASE_AUDIT_PASS: 准入不可营销, GRAY: 灰度中, RELEASE: 已上架, OFFLINE: 已下架, AUDIT_OFFLINE: 已下架 -->
{{# if(d.version_status == 'AUDITING'){ }}
<a class="layui-btn" lay-event="audit_cancel">审核撤销</a>
{{# }else if(d.version_status == 'AUDIT_REJECT' || d.version_status == 'BASE_AUDIT_PASS' || d.version_status == 'OFFLINE' || d.version_status == 'AUDIT_OFFLINE'){ }}
<a class="layui-btn" lay-event="audited_cancel">退回开发</a>
<a class="layui-btn" lay-event="reason_rejection">驳回原因</a>
{{# }else if(d.version_status == 'WAIT_RELEASE' || d.version_status == 'OFFLINE' || d.version_status == 'AUDIT_OFFLINE'){ }}
<a class="layui-btn" lay-event="version_online">上架</a>
<a class="layui-btn" lay-event="version_gray_online">灰度上架</a>
{{# }else if(d.version_status == 'GRAY'){ }}
<a class="layui-btn" lay-event="version_gray_cancel">结束灰度</a>
{{# }else if(d.version_status == 'GRAY' || d.version_status == 'RELEASE'){ }}
<a class="layui-btn" lay-event="version_offline">下架</a>
<a class="layui-btn" lay-event="version_rollback">回滚</a>
{{# }else if(d.version_status == 'GRAY' || d.version_status == 'OFFLINE' || d.version_status == 'AUDIT_OFFLINE'){ }}
<a class="layui-btn" lay-event="version_rollback">回滚</a>
{{# }else{ }}
<a class="layui-btn" lay-event="delete">删除</a>
<a class="layui-btn" lay-event="audit_submit">提交审核</a>
<!-- 体验版相关按钮 -->
{{# if(d.is_experience_version == 0){ }}
<a class="layui-btn" lay-event="release_experience_version">发布体验版</a>
{{# }else if(d.is_experience_version == 1){ }}
<a class="layui-btn" lay-event="cancel_experience_version">取消体验版</a>
<a class="layui-btn" lay-event="see_experience_version">查看体验版状态</a>
{{# } }}
{{# } }}
{{# }else{ }}
{{# if(d.is_experience_version == 1){ }}
<a class="layui-btn" lay-event="cancel_experience_version">取消体验版</a>
{{# } }}
{{# if(d.version_status == 'AUDITING'){ }}
<a class="layui-btn" lay-event="audit_cancel">审核撤销</a>
{{# }else if(d.version_status == 'AUDIT_REJECT' || d.version_status == 'BASE_AUDIT_PASS' || d.RELEASE == 'OFFLINE' || d.RELEASE == 'AUDIT_OFFLINE'){ }}
<a class="layui-btn" lay-event="audited_cancel">退回开发</a>
<a class="layui-btn" lay-event="reason_rejection">驳回原因</a>
{{# }else{ }}
<a class="layui-btn" lay-event="delete">删除</a>
{{# } }}
{{# } }}
</div>
</script>
{/block}
{block name="script"}
<script>
var table,
form,
repeat_flag = false;//防重复标识;
layui.use(['form'], function() {
form = layui.form;
form.render();
// 内容获取
table = new Table({
elem: '#listContent',
url: ns.url("aliapp://shop/AppletRelease/index"),
cols: [[
{align: 'center', field: 'id', title: 'ID', width: '5%', unresize: 'false'},
{align: 'center', field: 'version', title: '版本', unresize: 'area'},
{
align: 'center', templet: function (d) {
return ns.time_to_date(d.create_time, "YYYY-MM-DD hh:mm:ss");
}, title: '发布时间', unresize: 'false'
},
{
align: 'center', field: 'ali_create_status_text', title: '版本构建状态', unresize: 'false'
},
{
align: 'center', field: 'version_status_text', title: '版本状态', unresize: 'false'
},
{
align: 'center', templet: function (d) {
return parseInt(d.is_experience_version) === 0 ? '不是' : '是';
}, title: '是否为体验版', unresize: 'false'
},
{title: '操作', toolbar: '#operation', unresize: 'false', align: 'right'}
]],
});
// 监听工具栏操作
table.tool(function(obj) {
let data = obj.data;
let key = obj.event;
if(key === 'reason_rejection'){
reasonRejection(data);
}else{
operationRequest(key,data);
}
});
});
// 发起操作请求
function operationRequest(key,data = {}){
let config = getApiConfig(key);
let params = getApiParams(key,data);
layer.confirm(config['tips'], {icon: 3, title:'提示'}, function(confirmIndex){
layer.close(confirmIndex);
let index = ns.loading('open', config['loading_tips']);
requestApi("aliapp://shop/AppletRelease/publishingProcessProcessing",params,function (res) {
layer.close(index);
// 返回处理
resultProcessing(key,res);
});
});
}
// 接口配置信息
function getApiConfig(key){
let config = {
delete:{
title: '删除版本',
tips:'确定删除当前版本吗?',// 询问语句
loading_tips: '删除中,请耐心等待......',// 加载栏提示语句
},
release_experience_version:{
title: '发布体验版本',
tips:'确认发布当前版本为体验版吗?',
loading_tips: '发布中,请耐心等待......',
},
cancel_experience_version:{
title: '取消体验版',
tips:'确认取消当前版本的体验版?',
loading_tips: '取消中,请耐心等待......',
},
see_experience_version:{
title: '查看体验版状态',
tips:'确认查看当前版本的状态?',
loading_tips: '查询中,请耐心等待......',
},
audit_submit:{
title: '提交审核',
tips:'确定提交审核吗?',
loading_tips: '正在提交中,请耐心等待......',
},
audit_cancel:{
title: '审核撤销',
tips:'确定撤销审核吗?',
loading_tips: '正在撤销中,请耐心等待......',
},
audited_cancel:{
title: '退回开发',
tips:'确定退回开发吗?退回后可以从新提交审核!',
loading_tips: '正在退回中,请耐心等待......',
},
version_online:{
title: '上架',
tips:'确定发布当前版本为正式版本吗?',
loading_tips: '正在发布中,请耐心等待......',
},
version_gray_online:{
title: '灰度上架',
tips:'确定灰度上架当前版本吗?',
loading_tips: '正在灰度上架中,请耐心等待......',
},
version_gray_cancel:{
title: '结束灰度',
tips:'确定结束当前版本的灰度测试吗?',
loading_tips: '正在结束灰度中,请耐心等待......',
},
version_offline:{
title: '下架',
tips:'确定下架当前版本吗?',
loading_tips: '正在下架中,请耐心等待......',
},
version_rollback:{
title: '回滚',
tips:'确定回滚当前版本吗?回滚后会自动上架上一个正式版本!',
loading_tips: '正在回滚中,请耐心等待......',
},
version_upload:{
title: '发布新版本',
tips:'确定发布新版本吗?发布后将只能对新版本进行操作,不可对当前版本进行任何操作!',
loading_tips: '正在发布中,请耐心等待......',
},
};
return config[key] ?? {};
}
// 获取提交参数
function getApiParams(key,data){
switch (key) {
case 'version_upload':
return {
type: key,
};
break;
default:
return {
id: data.id,
type: key,
};
}
}
// 返回信息处理
function resultProcessing(key,res){
switch (key) {
case 'see_experience_version': break;
case 'version_upload':
if(res.message.indexOf("门店不存在") > -1) {
layer.alert(res.message, function(index){
window.location.href = ns.url('store://shop/store/lists')
});
}
else if(res.message.indexOf("配置小程序") > -1) {
layer.alert(res.message, function(index){
window.location.href = ns.url('aliapp://shop/aliapp/setting')
});
}
break;
default:
location.reload();
// table.reload({
// page: {
// curr: 1
// },
// });
}
}
// 版本同步
function versionSynchronization(){
let index = ns.loading('open');
requestApi("aliapp://shop/AppletRelease/versionSynchronization",{ },function (res) {
table.reload({
page: {
curr: 1
},
});
layer.close(index);
})
}
// 查看推广二维码
function qrcodeCreate() {
let index = ns.loading('open', '正在生成二维码,请耐心等待......');
requestApi("aliapp://shop/AppletRelease/qrcodeCreate",{ },function (res) {
layer.close(index);
let data = res.data;
// 生成html
// qr_code_url=方形二维码图片链接地址
// qr_code_url_circle_blue=圆形二维码地址-白色slogan
// qr_code_url_circle_white=圆形二维码地址-蓝色slogan
let html =
`<div class="qrcode-content">
<img class="qrcode-content-img" src="${data['exp_qr_code_url']}" />
</div>`;
// 显示二维码
layer.open({
type: 1,
title: "体验二维码",
area: ['350px', '300px'],
btn: ["关闭"],
content: html,
});
},false);
}
// 查看驳回原因
function reasonRejection(data){
layer.alert(data.audit_reason);
}
// 发起请求
function requestApi(api,data,fun,show_message = true){
if (repeat_flag) return false;
repeat_flag = true;
$.ajax({
url: ns.url(api),
data: data,
dataType: 'JSON',
type: 'POST',
success: function(res) {
if(show_message) layer.msg(res.message);
repeat_flag = false;
if(typeof fun === 'function') fun(res);
}
});
}
</script>
{/block}

View File

@ -0,0 +1,38 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
return [
// 自定义模板页面类型,格式:[ 'title' => '页面类型名称', 'name' => '页面标识', 'path' => '页面路径', 'value' => '页面数据json格式' ]
'template' => [],
// 后台自定义组件——装修
'util' => [],
// 自定义页面路径
'link' => [],
// 自定义图标库
'icon_library' => [],
// uni-app 组件,格式:[ 'name' => '组件名称/文件夹名称', 'path' => '文件路径/目录路径' ]多个逗号隔开自定义组件名称前缀必须是diy-,也可以引用第三方组件
'component' => [],
// uni-app 页面,多个逗号隔开
'pages' => [],
// 模板信息,格式:'title' => '模板名称', 'name' => '模板标识', 'cover' => '模板封面图', 'preview' => '模板预览图', 'desc' => '模板描述'
'info' => [],
// 主题风格配色格式可以自由定义扩展【在uni-app中通过this.themeStyle... 获取定义的颜色字段例如this.themeStyle.main_color】
'theme' => [],
// 自定义页面数据,格式:[ 'title' => '页面名称', 'name' => "页面标识", 'value' => [页面数据json格式] ]
'data' => []
];

View File

@ -0,0 +1,26 @@
<?php
// 事件定义文件
return [
'bind' => [
],
'listen' => [
//短信方式
'OssType' => [
'addon\alioss\event\OssType'
],
'Put' => [
'addon\alioss\event\Put'
],
'CloseOss' => [
'addon\alioss\event\CloseOss'
],
'ClearAlbumPic' => [
'addon\alioss\event\ClearAlbumPic'
]
],
'subscribe' => [
],
];

View File

@ -0,0 +1,21 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
return [
'name' => 'alioss',
'title' => '阿里云OSS',
'description' => '阿里云OSS',
'type' => 'system', //插件类型 system :系统插件(自动安装), business:业务插件 promotion:营销插件 tool:工具插件
'status' => 1,
'author' => '',
'version' => '5.1.1',
'version_no' => '520221115001',
'content' => '',
];

View File

@ -0,0 +1,18 @@
<?php
// +----------------------------------------------------------------------
// | 平台端菜单设置
// +----------------------------------------------------------------------
return [
[
'name' => 'ALIOSS_CONFIG',
'title' => '阿里云OSS上传配置',
'url' => 'alioss://shop/config/config',
'parent' => 'UPLOAD_OSS',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_select' => '',
'sort' => 1,
],
];

View File

@ -0,0 +1,39 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\event;
use addon\alioss\model\Alioss;
use addon\alioss\model\Config;
/**
* 删除阿里云图片
*/
class ClearAlbumPic
{
public function handle($params)
{
$config_model = new Config();
$alioss_model = new Alioss();
$config = $config_model->getAliossConfig($params[ 'site_id' ]);
if (!empty($config[ 'data' ])) {
if (!empty($config[ 'data' ][ 'value' ][ 'endpoint' ]) && strpos($params[ 'pic_path' ], $config[ 'data' ][ 'value' ][ 'endpoint' ]) === 0) {
$result = $alioss_model->deleteAlbumPic($params[ 'pic_path' ], $config[ 'data' ][ 'value' ][ 'endpoint' ]);
return $result;
}
if (!empty($config[ 'data' ][ 'value' ][ 'domain' ]) && strpos($params[ 'pic_path' ], $config[ 'data' ][ 'value' ][ 'domain' ]) === 0) {
$result = $alioss_model->deleteAlbumPic($params[ 'pic_path' ], $config[ 'data' ][ 'value' ][ 'domain' ]);
return $result;
}
}
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\event;
use addon\alioss\model\Config;
/**
* 关闭云上传
*/
class CloseOss
{
public function handle()
{
$config_model = new Config();
$result = $config_model->modifyConfigIsUse(0);
return $result;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\event;
/**
* 应用安装
*/
class Install
{
/**
* 执行安装
*/
public function handle()
{
return success();
}
}

View File

@ -0,0 +1,34 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\event;
/**
* 云上传方式
*/
class OssType
{
/**
* 短信发送方式方式及配置
*/
public function handle()
{
$info = array(
"sms_type" => "alioss",
"sms_type_name" => "阿里云上传",
"edit_url" => "alioss://shop/config/config",
"shop_url" => "alioss://shop/config/config",
"desc" => "阿里云上传"
);
return $info;
}
}

View File

@ -0,0 +1,31 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\event;
use addon\alioss\model\Alioss;
/**
* 云上传方式
*/
class Put
{
/**
* 短信发送方式方式及配置
*/
public function handle($param)
{
$qiniu_model = new Alioss();
$result = $qiniu_model->putFile($param);
return $result;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\event;
/**
* 应用卸载
*/
class UnInstall
{
/**
* 执行卸载
*/
public function handle()
{
return success();
}
}

BIN
addon/alioss/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,147 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\model;
use app\model\BaseModel;
use OSS\Core\OssException;
use OSS\OssClient;
/**
* 阿里云OSS上传
*/
class Alioss extends BaseModel
{
/**
* 字节组上传
* @param $data
* @param $key
* @return array
*/
public function put($param)
{
$data = $param[ "data" ];
$key = $param[ "key" ];
$config_model = new Config();
$config_result = $config_model->getAliossConfig();
$config = $config_result[ "data" ];
if ($config[ "is_use" ] == 1) {
$config = $config[ "value" ];
$access_key_id = $config[ "access_key_id" ];
$access_key_secret = $config[ "access_key_secret" ];
$bucket = $config[ "bucket" ];
$endpoint = $config[ "endpoint" ];
try {
$ossClient = new OssClient($access_key_id, $access_key_secret, $endpoint);
$result = $ossClient->putObject($bucket, $key, $data);
$is_domain = $config[ 'is_domain' ] ?? 0;
$path = $is_domain > 0 ? $config[ 'domain' ] . "/" . $key : $result[ "info" ][ "url" ];
$data = array (
"path" => $path,
// "path" => $result["info"]["url"],
"domain" => $endpoint,
"bucket" => $bucket
);
return $this->success($data);
} catch (OssException $e) {
return $this->error('', $e->getErrorMessage());
}
}
}
/**
* 设置阿里云OSS参数配置
* @param unknown $filePath 上传图片路径
* @param unknown $key 上传到阿里云后保存的文件名
*/
public function putFile($param)
{
$file_path = $param[ "file_path" ];
$key = $param[ "key" ];
$config_model = new Config();
$config_result = $config_model->getAliossConfig();
$config = $config_result[ "data" ];
if ($config[ "is_use" ] == 1) {
$config = $config[ "value" ];
$access_key_id = $config[ "access_key_id" ];
$access_key_secret = $config[ "access_key_secret" ];
$bucket = $config[ "bucket" ];
//要上传的空间
$endpoint = $config[ "endpoint" ];
try {
$ossClient = new OssClient($access_key_id, $access_key_secret, $endpoint);
$result = $ossClient->uploadFile($bucket, $key, $file_path);
$is_domain = $config[ 'is_domain' ] ?? 0;
$path = $is_domain > 0 ? $config[ 'domain' ] . "/" . $key : $result[ "info" ][ "url" ];
$path = str_replace('http://', 'https://', $path);
//返回图片的完整URL
$data = array (
// "path" => $this->subEndpoint($endpoint, $bucket)."/". $key,
"path" => $path,
"domain" => $endpoint,
"bucket" => $bucket
);
return $this->success($data);
} catch (OssException $e) {
return $this->error('', $e->getErrorMessage());
}
}
}
public function subEndpoint($endpoint, $bucket)
{
if (strpos($endpoint, 'http://') === 0) {
$temp = "http://";
} else {
$temp = "https://";
}
$temp_array = explode($temp, $endpoint);
return $temp . $bucket . "." . $temp_array[ 1 ];
}
/**
* @param $file_path
* @return array
* 删除阿里云图片
*/
public function deleteAlbumPic($file_path, $prefix)
{
$config_model = new Config();
$config_result = $config_model->getAliossConfig();
$config = $config_result[ "data" ];
if (!empty($config)) {
$config = $config[ "value" ];
$access_key_id = $config[ "access_key_id" ];
$access_key_secret = $config[ "access_key_secret" ];
$bucket = $config[ "bucket" ];
//要上传的空间
$endpoint = $config[ "endpoint" ];
try {
$ossClient = new OssClient($access_key_id, $access_key_secret, $endpoint);
$ossClient->deleteObject($bucket, str_replace($prefix . "/", "", $file_path));
$ossClient->deleteObject($bucket, str_replace($prefix . "/", "", img($file_path, 'big')));
$ossClient->deleteObject($bucket, str_replace($prefix . "/", "", img($file_path, 'mid')));
$ossClient->deleteObject($bucket, str_replace($prefix . "/", "", img($file_path, 'small')));
return $this->success();
} catch (OssException $e) {
return $this->error('', $e->getErrorMessage());
}
}
}
}

View File

@ -0,0 +1,56 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\model;
use app\model\system\Config as ConfigModel;
use app\model\BaseModel;
/**
* 阿里云配置
*/
class Config extends BaseModel
{
/**
* 设置阿里云OSS上传配置
* array $data
*/
public function setAliossConfig($data, $status, $site_id = 1, $app_module = 'shop')
{
if ($status == 1) {
event("CloseOss", []);//同步关闭所有云上传
}
$config = new ConfigModel();
$res = $config->setConfig($data, '阿里云OSS上传配置', $status, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'ALIOSS_CONFIG' ] ]);
return $res;
}
/**
* 获取阿里云上传配置
*/
public function getAliossConfig($site_id = 1, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'ALIOSS_CONFIG' ] ]);
return $res;
}
/**
* 配置阿里云开关状态
* @param $status
*/
public function modifyConfigIsUse($status, $site_id = 1, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->modifyConfigIsUse($status, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'ALIOSS_CONFIG' ] ]);
return $res;
}
}

View File

@ -0,0 +1,57 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace addon\alioss\shop\controller;
use addon\alioss\model\Config as ConfigModel;
use app\shop\controller\BaseShop;
/**
* 七牛云上传管理
*/
class Config extends BaseShop
{
/**
* 云上传配置
* @return mixed
*/
public function config()
{
$config_model = new ConfigModel();
if (request()->isAjax()) {
$bucket = input("bucket", "");
$access_key_id = input("access_key_id", "");
$access_key_secret = input("access_key_secret", "");
$endpoint = input("endpoint", "");
$status = input("status", 0);
$domain = input("domain", "");
$is_domain = input("is_domain", 0);
$data = array(
"bucket" => $bucket,
"access_key_id" => $access_key_id,
"access_key_secret" => $access_key_secret,
"endpoint" => $endpoint,
"domain" => $domain,
"is_domain" => $is_domain
);
$result = $config_model->setAliossConfig($data, $status, $this->site_id, $this->app_module);
return $result;
} else {
$info_result = $config_model->getAliossConfig($this->site_id, $this->app_module);
$info = $info_result["data"];
$this->assign("info", $info);
return $this->fetch("config/config");
}
}
}

View File

@ -0,0 +1,130 @@
{extend name="app/shop/view/base.html"/}
{block name="resources"}
<style>
.form-wrap {margin-top: 0;}
</style>
{/block}
{block name="main"}
<div class="layui-form form-wrap">
<div class="layui-form-item">
<label class="layui-form-label">是否开启:</label>
<div class="layui-input-block" id="isOpen">
<input type="checkbox" name="status" lay-filter="isOpen" value="1" lay-skin="switch" {if condition="$info.is_use == 1"} checked {/if} />
</div>
<div class="word-aux">当前使用阿里云上传配置</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>AccessKeyID</label>
<div class="layui-input-block">
<input type="text" name="access_key_id" lay-verify="required" placeholder="请输入Access Key ID" value="{$info.value.access_key_id ?? ''}" autocomplete="off" class="layui-input len-long">
</div>
<div class="word-aux">填写阿里云Access Key管理的(ID)。</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>AccessKeySecret</label>
<div class="layui-input-block">
<input type="text" name="access_key_secret" lay-verify="required" placeholder="请输入Access Key Secret" value="{$info.value.access_key_secret ?? ''}" autocomplete="off" class="layui-input len-long">
</div>
<div class="word-aux">Access Key Secret是您访问阿里云API的密钥具有该账户完全的权限请您妥善保管。(填写完Access Key ID 和 Access Key Secret 后请选择bucket)</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>Bucket</label>
<div class="layui-input-block">
<input type="text" name="bucket" lay-verify="required" placeholder="请输入存储空间的名称" value="{$info.value.bucket ?? ''}" autocomplete="off" class="layui-input len-long">
</div>
<div class="word-aux">与阿里云OSS开通对象名称一致</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>endpoint</label>
<div class="layui-input-block">
<input type="text" name="endpoint" lay-verify="required" placeholder="请输入endpoint" value="{$info.value.endpoint ?? ''}" autocomplete="off" class="layui-input len-long">
</div>
<div class="word-aux">Bucket地域endpoint</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">是否开启自定义域名:</label>
<div class="layui-input-block" >
<input type="checkbox" name="is_domain" lay-filter="is_domain" value="1" lay-skin="switch" {if condition="!empty($info.value.is_domain) && $info.value.is_domain == 1"} checked {/if} />
</div>
<div class="word-aux">默认选关闭官方建议开启绑定域名域名格式http://xx.xxxx.com/(不可绑定当前网站域名,建议新开二级域名)</div>
</div>
<div class="layui-form-item domain-view" {if empty($info.value.is_domain) || $info.value.is_domain == 0}style="display:none;"{/if}>
<label class="layui-form-label"><span class="required">*</span>domain</label>
<div class="layui-input-block">
<input type="text" name="domain" lay-verify="domain" placeholder="请输入domain" value="{$info.value.domain ?? ''}" autocomplete="off" class="layui-input len-long">
</div>
<div class="word-aux">域名格式http://xx.xxxx.com/(不可绑定当前网站域名,建议新开二级域名)</div>
</div>
<!-- 表单操作 -->
<div class="form-row">
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
<button class="layui-btn layui-btn-primary" onclick="back()">返回</button>
</div>
</div>
{/block}
{block name="script"}
<script>
layui.use('form', function() {
var form = layui.form,
repeat_flag = false; //防重复标识
form.on('switch(is_domain)', function(data){
if(data.elem.checked){
$(".domain-view").show();
}else{
$(".domain-view").hide();
}
});
form.verify({
domain: function (value, item) { //value表单的值、item表单的DOM对象
var is_domain = $("input[name=is_domain]").prop("checked");
if(is_domain > 0 && value == ""){
return '自定义域名不可为空!';
}
},
});
form.on('submit(save)', function(data) {
if (repeat_flag) return;
repeat_flag = true;
$.ajax({
url: ns.url("alioss://shop/config/config"),
data: data.field,
dataType: 'JSON',
type: 'POST',
success: function(res) {
repeat_flag = false;
if (res.code >= 0) {
layer.confirm('编辑成功', {
title:'操作提示',
btn: ['返回列表', '继续操作'],
yes: function(){
location.href = ns.url("shop/upload/oss")
},
btn2: function() {
location.reload();
}
});
}else{
layer.msg(res.message);
}
}
});
});
form.render();
});
function back() {
location.href = ns.url("shop/upload/oss");
}
</script>
{/block}

View File

@ -0,0 +1,38 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
return [
// 自定义模板页面类型,格式:[ 'title' => '页面类型名称', 'name' => '页面标识', 'path' => '页面路径', 'value' => '页面数据json格式' ]
'template' => [],
// 后台自定义组件——装修
'util' => [],
// 自定义页面路径
'link' => [],
// 自定义图标库
'icon_library' => [],
// uni-app 组件,格式:[ 'name' => '组件名称/文件夹名称', 'path' => '文件路径/目录路径' ]多个逗号隔开自定义组件名称前缀必须是diy-,也可以引用第三方组件
'component' => [],
// uni-app 页面,多个逗号隔开
'pages' => [],
// 模板信息,格式:'title' => '模板名称', 'name' => '模板标识', 'cover' => '模板封面图', 'preview' => '模板预览图', 'desc' => '模板描述'
'info' => [],
// 主题风格配色格式可以自由定义扩展【在uni-app中通过this.themeStyle... 获取定义的颜色字段例如this.themeStyle.main_color】
'theme' => [],
// 自定义页面数据,格式:[ 'title' => '页面名称', 'name' => "页面标识", 'value' => [页面数据json格式] ]
'data' => []
];

View File

@ -0,0 +1,49 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
return [
'bind' => [
],
'listen' => [
//支付异步回调
'PayNotify' => [
'addon\alipay\event\PayNotify'
],
//支付方式,后台查询
'PayType' => [
'addon\alipay\event\PayType',
'addon\alipay\event\ZMPayType'
],
//支付,前台应用
'Pay' => [
'addon\alipay\event\Pay'
],
'PayClose' => [
'addon\alipay\event\PayClose'
],
'PayRefund' => [
'addon\alipay\event\PayRefund'
],
'PayTransfer' => [
'addon\alipay\event\PayTransfer'
],
'TransferType' => [
'addon\alipay\event\TransferType'
],
'AuthcodePay' => [
'addon\alipay\event\AuthcodePay'
]
],
'subscribe' => [
],
];

View File

@ -0,0 +1,21 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
return [
'name' => 'alipay',
'title' => '支付宝支付',
'description' => '支付宝支付功能',
'type' => 'system', //插件类型 system :系统插件(自动安装), promotion:营销插件 tool:工具插件
'status' => 1,
'author' => '',
'version' => '5.1.1',
'version_no' => '520221115001',
'content' => '',
];

View File

@ -0,0 +1,23 @@
<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
return [
[
'name' => 'ALI_PAY_CONFIG',
'title' => '支付宝支付编辑',
'url' => 'alipay://shop/pay/config',
'parent' => 'CONFIG_PAY',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_select' => '',
'sort' => 1,
],
];

View File

@ -0,0 +1,231 @@
<?php
/**
* 多媒体文件客户端
* @author yikai.hu
* @version $Id: AlipayMobilePublicMultiMediaClient.php, v 0.1 Aug 15, 2014 10:19:01 AM yikai.hu Exp $
*/
//namespace alipay\api ;
include("AlipayMobilePublicMultiMediaExecute.php");
class AlipayMobilePublicMultiMediaClient{
private $DEFAULT_CHARSET = 'UTF-8';
private $METHOD_POST = "POST";
private $METHOD_GET = "GET";
private $SIGN = 'sign'; //get name
private $timeout = 10 ;// 超时时间
private $serverUrl;
private $appId;
private $privateKey;
private $prodCode;
private $format = 'json'; //todo
private $sign_type = 'RSA'; //todo
private $charset;
private $apiVersion = "1.0";
private $apiMethodName = "alipay.mobile.public.multimedia.download";
private $media_id = "L21pZnMvVDFQV3hYWGJKWFhYYUNucHJYP3Q9YW13ZiZ4c2lnPTU0MzRhYjg1ZTZjNWJmZTMxZGJiNjIzNDdjMzFkNzkw575";
//此处写死的,实际开发中,请传入
private $connectTimeout = 3000;
private $readTimeout = 15000;
function __construct($serverUrl = '', $appId = '', $partner_private_key = '', $format = '', $charset = 'GBK'){
$this -> serverUrl = $serverUrl;
$this -> appId = $appId;
$this -> privateKey = $partner_private_key;
$this -> format = $format;
$this -> charset = $charset;
}
/**
* getContents 获取网址内容
* @param $request
* @return text | bin
*/
public function getContents(){
//自己的服务器如果没有 curl可用fsockopen() 等
//1:
//2 私钥格式
$datas = array(
"app_id" => $this -> appId,
"method" => $this -> METHOD_POST,
"sign_type" => $this -> sign_type,
"version" => $this -> apiVersion,
"timestamp" => date('Y-m-d H:i:s') ,//yyyy-MM-dd HH:mm:ss
"biz_content" => '{"mediaId":"'. $this -> media_id .'"}',
"charset" => $this -> charset
);
//要提交的数据
$data_sign = $this -> buildGetUrl( $datas );
$post_data = $data_sign;
//初始化 curl
$ch = curl_init();
//设置目标服务器
curl_setopt($ch, CURLOPT_URL, $this -> serverUrl );
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, $this-> timeout);
if( $this-> METHOD_POST == 'POST'){
// post数据
curl_setopt($ch, CURLOPT_POST, 1);
// post的变量
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $output;
//分离头部
//list($header, $body) = explode("\r\n\r\n", $output, 2);
$datas = explode("\r\n\r\n", $output, 2);
$header = $datas[0];
if( $httpCode == '200'){
$body = $datas[1];
}else{
$body = '';
}
return $this -> execute( $header, $body, $httpCode );
}
/**
*
* @param $request
* @return text | bin
*/
public function execute( $header = '', $body = '', $httpCode = '' ){
$exe = new AlipayMobilePublicMultiMediaExecute( $header, $body, $httpCode );
return $exe;
}
public function buildGetUrl( $query = array() ){
if( ! is_array( $query ) ){
//exit;
}
//排序参数,
$data = $this -> buildQuery( $query );
// 私钥密码
$passphrase = '';
$key_width = 64;
//私钥
$privateKey = $this -> privateKey;
$p_key = array();
//如果私钥是 1行
if( ! stripos( $privateKey, "\n" ) ){
$i = 0;
while( $key_str = substr( $privateKey , $i * $key_width , $key_width) ){
$p_key[] = $key_str;
$i ++ ;
}
}else{
//echo '一行?';
}
$privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" . implode("\n", $p_key) ;
$privateKey = $privateKey ."\n-----END RSA PRIVATE KEY-----";
// echo "\n\n私钥:\n";
// echo( $privateKey );
// echo "\n\n\n";
//私钥
$private_id = openssl_pkey_get_private( $privateKey , $passphrase);
// 签名
$signature = '';
if("RSA2"==$this->sign_type){
openssl_sign($data, $signature, $private_id, OPENSSL_ALGO_SHA256 );
}else{
openssl_sign($data, $signature, $private_id, OPENSSL_ALGO_SHA1 );
}
openssl_free_key( $private_id );
//加密后的内容通常含有特殊字符,需要编码转换下
$signature = base64_encode($signature);
$signature = urlencode( $signature );
//$signature = 'XjUN6YM1Mc9HXebKMv7GTLy7gmyhktyOgKk2/Jf+cz4DtP6udkzTdpkjW2j/Z4ZSD7xD6CNYI1Spz4yS93HPT0a5X9LgFWYY8SaADqe+ArXg+FBSiTwUz49SE//Xd9+LEiIRsSFkbpkuiGoO6mqJmB7vXjlD5lx6qCM3nb41wb8=';
$out = $data .'&'. $this -> SIGN .'='. $signature;
// echo "\n\n 加密后:\n";
// echo( $out );
// echo "\n\n\n";
return $out ;
}
/*
* 查询参数排序 a-z
* */
public function buildQuery( $query ){
if ( !$query ) {
return null;
}
//将要 参数 排序
ksort( $query );
//重新组装参数
$params = array();
foreach($query as $key => $value){
$params[] = $key .'='. $value ;
}
$data = implode('&', $params);
return $data;
}
}

View File

@ -0,0 +1,108 @@
<?php
/**
* 多媒体文件客户端
* @author yuanwai.wang
* @version $Id: AlipayMobilePublicMultiMediaExecute.php, v 0.1 Aug 15, 2014 10:19:01 AM yuanwai.wang Exp $
*/
//namespace alipay\api ;
class AlipayMobilePublicMultiMediaExecute{
private $code = 200 ;
private $msg = '';
private $body = '';
private $params = '';
private $fileSuffix = array(
"image/jpeg" => 'jpg', //+
"text/plain" => 'text'
);
/*
* @$header : 头部
* */
function __construct( $header, $body, $httpCode ){
$this -> code = $httpCode;
$this -> msg = '';
$this -> params = $header ;
$this -> body = $body;
}
/**
*
* @return text | bin
*/
public function getCode(){
return $this -> code ;
}
/**
*
* @return text | bin
*/
public function getMsg(){
return $this -> msg ;
}
/**
*
* @return text | bin
*/
public function getType(){
$subject = $this -> params ;
$pattern = '/Content\-Type:([^;]+)/';
preg_match($pattern, $subject, $matches);
if( $matches ){
$type = $matches[1];
}else{
$type = 'application/download';
}
return str_replace( ' ', '', $type );
}
/**
*
* @return text | bin
*/
public function getContentLength(){
$subject = $this -> params ;
$pattern = '/Content-Length:\s*([^\n]+)/';
preg_match($pattern, $subject, $matches);
return (int)( isset($matches[1] ) ? $matches[1] : '' );
}
public function getFileSuffix( $fileType ){
$type = isset( $this -> fileSuffix[ $fileType ] ) ? $this -> fileSuffix[ $fileType ] : 'text/plain' ;
if( !$type ){
$type = 'json';
}
return $type;
}
/**
*
* @return text | bin
*/
public function getBody(){
//header('Content-type: image/jpeg');
return $this -> body ;
}
/**
* 获取参数
* @return text | bin
*/
public function getParams(){
return $this -> params ;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,527 @@
<?php
/**
* 验证支付宝公钥证书是否可信
* @param $alipayCert 支付宝公钥证书
* @param $rootCert 支付宝根证书
*/
function isTrusted($alipayCert, $rootCert)
{
$alipayCerts = readPemCertChain($alipayCert);
$rootCerts = readPemCertChain($rootCert);
if (verifyCertChain($alipayCerts, $rootCerts)) {
return verifySignature($alipayCert, $rootCert);
} else {
return false;
}
}
function verifySignature($alipayCert, $rootCert)
{
$alipayCertArray = explode("-----END CERTIFICATE-----", $alipayCert);
$rootCertArray = explode("-----END CERTIFICATE-----", $rootCert);
$length = count($rootCertArray) - 1;
$checkSign = isCertSigner($alipayCertArray[0] . "-----END CERTIFICATE-----", $alipayCertArray[1] . "-----END CERTIFICATE-----");
if (!$checkSign) {
$checkSign = isCertSigner($alipayCertArray[1] . "-----END CERTIFICATE-----", $alipayCertArray[0] . "-----END CERTIFICATE-----");
if ($checkSign) {
$issuer = openssl_x509_parse($alipayCertArray[0] . "-----END CERTIFICATE-----")['issuer'];
for ($i = 0; $i < $length; $i++) {
$subject = openssl_x509_parse($rootCertArray[$i] . "-----END CERTIFICATE-----")['subject'];
if ($issuer == $subject) {
isCertSigner($alipayCertArray[0] . "-----END CERTIFICATE-----", $rootCertArray[$i] . $rootCertArray);
return $checkSign;
}
}
} else {
return $checkSign;
}
} else {
$issuer = openssl_x509_parse($alipayCertArray[1] . "-----END CERTIFICATE-----")['issuer'];
for ($i = 0; $i < $length; $i++) {
$subject = openssl_x509_parse($rootCertArray[$i] . "-----END CERTIFICATE-----")['subject'];
if ($issuer == $subject) {
$checkSign = isCertSigner($alipayCertArray[1] . "-----END CERTIFICATE-----", $rootCertArray[$i] . "-----END CERTIFICATE-----");
return $checkSign;
}
}
return $checkSign;
}
}
function readPemCertChain($cert)
{
$array = explode("-----END CERTIFICATE-----", $cert);
$certs[] = null;
for ($i = 0; $i < count($array) - 1; $i++) {
$certs[$i] = openssl_x509_parse($array[$i] . "-----END CERTIFICATE-----");
}
return $certs;
}
function verifyCert($prev, $rootCerts)
{
$nowTime = time();
if ($nowTime < $prev['validFrom_time_t']) {
echo "证书未激活";
return false;
}
if ($nowTime > $prev['validTo_time_t']) {
echo "证书已经过期";
return false;
}
$subjectMap = null;
for ($i = 0; $i < count($rootCerts); $i++) {
$subjectDN = array2string($rootCerts[$i]['subject']);
$subjectMap[$subjectDN] = $rootCerts[$i];
}
$issuerDN = array2string(($prev['issuer']));
if (!array_key_exists($issuerDN, $subjectMap)) {
echo "证书链验证失败";
return false;
}
return true;
}
/**
* 验证证书链是否是信任证书库中证书签发的
* @param $alipayCerts 目标验证证书列表
* @param $rootCerts 可信根证书列表
*/
function verifyCertChain($alipayCerts, $rootCerts)
{
$sorted = sortByDn($alipayCerts);
if (!$sorted) {
echo "证书链验证失败:不是完整的证书链";
return false;
}
//先验证第一个证书是不是信任库中证书签发的
$prev = $alipayCerts[0];
$firstOK = verifyCert($prev, $rootCerts);
$length = count($alipayCerts);
if (!$firstOK || $length == 1) {
return $firstOK;
}
$nowTime = time();
//验证证书链
for ($i = 1; $i < $length; $i++) {
$cert = $alipayCerts[$i];
if ($nowTime < $cert['validFrom_time_t']) {
echo "证书未激活";
return false;
}
if ($nowTime > $cert['validTo_time_t']) {
echo "证书已经过期";
return false;
}
}
return true;
}
/**
* 将证书链按照完整的签发顺序进行排序,排序后证书链为:[issuerA, subjectA]-[issuerA, subjectB]-[issuerB, subjectC]-[issuerC, subjectD]...
* @param $certs 证书链
*/
function sortByDn(&$certs)
{
//是否包含自签名证书
$hasSelfSignedCert = false;
$subjectMap = null;
$issuerMap = null;
for ($i = 0; $i < count($certs); $i++) {
if (isSelfSigned($certs[$i])) {
if ($hasSelfSignedCert) {
return false;
}
$hasSelfSignedCert = true;
}
$subjectDN = array2string($certs[$i]['subject']);
$issuerDN = array2string(($certs[$i]['issuer']));
$subjectMap[$subjectDN] = $certs[$i];
$issuerMap[$issuerDN] = $certs[$i];
}
$certChain = null;
addressingUp($subjectMap, $certChain, $certs[0]);
addressingDown($issuerMap, $certChain, $certs[0]);
//说明证书链不完整
if (count($certs) != count($certChain)) {
return false;
}
//将证书链复制到原先的数据
for ($i = 0; $i < count($certs); $i++) {
$certs[$i] = $certChain[count($certs) - $i - 1];
}
return true;
}
/**
* 验证证书是否是自签发的
* @param $cert 目标证书
*/
function isSelfSigned($cert)
{
$subjectDN = array2string($cert['subject']);
$issuerDN = array2string($cert['issuer']);
return ($subjectDN == $issuerDN);
}
function array2string($array)
{
$string = [];
if ($array && is_array($array)) {
foreach ($array as $key => $value) {
$string[] = $key . '=' . $value;
}
}
return implode(',', $string);
}
/**
* 向上构造证书链
* @param $subjectMap 主题和证书的映射
* @param $certChain 证书链
* @param $current 当前需要插入证书链的证书include
*/
function addressingUp($subjectMap, &$certChain, $current)
{
$certChain[] = $current;
if (isSelfSigned($current)) {
return;
}
$issuerDN = array2string($current['issuer']);
if (!array_key_exists($issuerDN, $subjectMap)) {
return;
}
addressingUp($subjectMap, $certChain, $subjectMap[$issuerDN]);
}
/**
* 向下构造证书链
* @param $issuerMap 签发者和证书的映射
* @param $certChain 证书链
* @param $current 当前需要插入证书链的证书exclude
*/
function addressingDown($issuerMap, &$certChain, $current)
{
$subjectDN = array2string($current['subject']);
if (!array_key_exists($subjectDN, $issuerMap)) {
return $certChain;
}
$certChain[] = $issuerMap[$subjectDN];
addressingDown($issuerMap, $certChain, $issuerMap[$subjectDN]);
}
/**
* Extract signature from der encoded cert.
* Expects x509 der encoded certificate consisting of a section container
* containing 2 sections and a bitstream. The bitstream contains the
* original encrypted signature, encrypted by the public key of the issuing
* signer.
* @param string $der
* @return string on success
* @return bool false on failures
*/
function extractSignature($der = false)
{
if (strlen($der) < 5) {
return false;
}
// skip container sequence
$der = substr($der, 4);
// now burn through two sequences and the return the final bitstream
while (strlen($der) > 1) {
$class = ord($der[0]);
$classHex = dechex($class);
switch ($class) {
// BITSTREAM
case 0x03:
$len = ord($der[1]);
$bytes = 0;
if ($len & 0x80) {
$bytes = $len & 0x0f;
$len = 0;
for ($i = 0; $i < $bytes; $i++) {
$len = ($len << 8) | ord($der[$i + 2]);
}
}
return substr($der, 3 + $bytes, $len);
break;
// SEQUENCE
case 0x30:
$len = ord($der[1]);
$bytes = 0;
if ($len & 0x80) {
$bytes = $len & 0x0f;
$len = 0;
for ($i = 0; $i < $bytes; $i++) {
$len = ($len << 8) | ord($der[$i + 2]);
}
}
$contents = substr($der, 2 + $bytes, $len);
$der = substr($der, 2 + $bytes + $len);
break;
default:
return false;
break;
}
}
return false;
}
/**
* Get signature algorithm oid from der encoded signature data.
* Expects decrypted signature data from a certificate in der format.
* This ASN1 data should contain the following structure:
* SEQUENCE
* SEQUENCE
* OID (signature algorithm)
* NULL
* OCTET STRING (signature hash)
* @return bool false on failures
* @return string oid
*/
function getSignatureAlgorithmOid($der = null)
{
// Validate this is the der we need...
if (!is_string($der) or strlen($der) < 5) {
return false;
}
$bit_seq1 = 0;
$bit_seq2 = 2;
$bit_oid = 4;
if (ord($der[$bit_seq1]) !== 0x30) {
die('Invalid DER passed to getSignatureAlgorithmOid()');
}
if (ord($der[$bit_seq2]) !== 0x30) {
die('Invalid DER passed to getSignatureAlgorithmOid()');
}
if (ord($der[$bit_oid]) !== 0x06) {
die('Invalid DER passed to getSignatureAlgorithmOid');
}
// strip out what we don't need and get the oid
$der = substr($der, $bit_oid);
// Get the oid
$len = ord($der[1]);
$bytes = 0;
if ($len & 0x80) {
$bytes = $len & 0x0f;
$len = 0;
for ($i = 0; $i < $bytes; $i++) {
$len = ($len << 8) | ord($der[$i + 2]);
}
}
$oid_data = substr($der, 2 + $bytes, $len);
// Unpack the OID
$oid = floor(ord($oid_data[0]) / 40);
$oid .= '.' . ord($oid_data[0]) % 40;
$value = 0;
$i = 1;
while ($i < strlen($oid_data)) {
$value = $value << 7;
$value = $value | (ord($oid_data[$i]) & 0x7f);
if (!(ord($oid_data[$i]) & 0x80)) {
$oid .= '.' . $value;
$value = 0;
}
$i++;
}
return $oid;
}
/**
* Get signature hash from der encoded signature data.
* Expects decrypted signature data from a certificate in der format.
* This ASN1 data should contain the following structure:
* SEQUENCE
* SEQUENCE
* OID (signature algorithm)
* NULL
* OCTET STRING (signature hash)
* @return bool false on failures
* @return string hash
*/
function getSignatureHash($der = null)
{
// Validate this is the der we need...
if (!is_string($der) or strlen($der) < 5) {
return false;
}
if (ord($der[0]) !== 0x30) {
die('Invalid DER passed to getSignatureHash()');
}
// strip out the container sequence
$der = substr($der, 2);
if (ord($der[0]) !== 0x30) {
die('Invalid DER passed to getSignatureHash()');
}
// Get the length of the first sequence so we can strip it out.
$len = ord($der[1]);
$bytes = 0;
if ($len & 0x80) {
$bytes = $len & 0x0f;
$len = 0;
for ($i = 0; $i < $bytes; $i++) {
$len = ($len << 8) | ord($der[$i + 2]);
}
}
$der = substr($der, 2 + $bytes + $len);
// Now we should have an octet string
if (ord($der[0]) !== 0x04) {
die('Invalid DER passed to getSignatureHash()');
}
$len = ord($der[1]);
$bytes = 0;
if ($len & 0x80) {
$bytes = $len & 0x0f;
$len = 0;
for ($i = 0; $i < $bytes; $i++) {
$len = ($len << 8) | ord($der[$i + 2]);
}
}
return bin2hex(substr($der, 2 + $bytes, $len));
}
/**
* Determine if one cert was used to sign another
* Note that more than one CA cert can give a positive result, some certs
* re-issue signing certs after having only changed the expiration dates.
* @param string $cert - PEM encoded cert
* @param string $caCert - PEM encoded cert that possibly signed $cert
* @return bool
*/
function isCertSigner($certPem = null, $caCertPem = null)
{
if (!function_exists('openssl_pkey_get_public')) {
die('Need the openssl_pkey_get_public() function.');
}
if (!function_exists('openssl_public_decrypt')) {
die('Need the openssl_public_decrypt() function.');
}
if (!function_exists('hash')) {
die('Need the php hash() function.');
}
if (empty($certPem) or empty($caCertPem)) {
return false;
}
// Convert the cert to der for feeding to extractSignature.
$certDer = pemToDer($certPem);
if (!is_string($certDer)) {
die('invalid certPem');
}
// Grab the encrypted signature from the der encoded cert.
$encryptedSig = extractSignature($certDer);
if (!is_string($encryptedSig)) {
die('Failed to extract encrypted signature from certPem.');
}
// Extract the public key from the ca cert, which is what has
// been used to encrypt the signature in the cert.
$pubKey = openssl_pkey_get_public($caCertPem);
if ($pubKey === false) {
die('Failed to extract the public key from the ca cert.');
}
// Attempt to decrypt the encrypted signature using the CA's public
// key, returning the decrypted signature in $decryptedSig. If
// it can't be decrypted, this ca was not used to sign it for sure...
$rc = openssl_public_decrypt($encryptedSig, $decryptedSig, $pubKey);
if ($rc === false) {
return false;
}
// We now have the decrypted signature, which is der encoded
// asn1 data containing the signature algorithm and signature hash.
// Now we need what was originally hashed by the issuer, which is
// the original DER encoded certificate without the issuer and
// signature information.
$origCert = stripSignerAsn($certDer);
if ($origCert === false) {
die('Failed to extract unsigned cert.');
}
// Get the oid of the signature hash algorithm, which is required
// to generate our own hash of the original cert. This hash is
// what will be compared to the issuers hash.
$oid = getSignatureAlgorithmOid($decryptedSig);
if ($oid === false) {
die('Failed to determine the signature algorithm.');
}
switch ($oid) {
case '1.2.840.113549.2.2':
$algo = 'md2';
break;
case '1.2.840.113549.2.4':
$algo = 'md4';
break;
case '1.2.840.113549.2.5':
$algo = 'md5';
break;
case '1.3.14.3.2.18':
$algo = 'sha';
break;
case '1.3.14.3.2.26':
$algo = 'sha1';
break;
case '2.16.840.1.101.3.4.2.1':
$algo = 'sha256';
break;
case '2.16.840.1.101.3.4.2.2':
$algo = 'sha384';
break;
case '2.16.840.1.101.3.4.2.3':
$algo = 'sha512';
break;
default:
die('Unknown signature hash algorithm oid: ' . $oid);
break;
}
// Get the issuer generated hash from the decrypted signature.
$decryptedHash = getSignatureHash($decryptedSig);
// Ok, hash the original unsigned cert with the same algorithm
// and if it matches $decryptedHash we have a winner.
$certHash = hash($algo, $origCert);
return ($decryptedHash === $certHash);
}
/**
* Convert pem encoded certificate to DER encoding
* @return string $derEncoded on success
* @return bool false on failures
*/
function pemToDer($pem = null)
{
if (!is_string($pem)) {
return false;
}
$cert_split = preg_split('/(-----((BEGIN)|(END)) CERTIFICATE-----)/', $pem);
if (!isset($cert_split[1])) {
return false;
}
return base64_decode($cert_split[1]);
}
/**
* Obtain der cert with issuer and signature sections stripped.
* @param string $der - der encoded certificate
* @return string $der on success
* @return bool false on failures.
*/
function stripSignerAsn($der = null)
{
if (!is_string($der) or strlen($der) < 8) {
return false;
}
$bit = 4;
$len = ord($der[($bit + 1)]);
$bytes = 0;
if ($len & 0x80) {
$bytes = $len & 0x0f;
$len = 0;
for ($i = 0; $i < $bytes; $i++) {
$len = ($len << 8) | ord($der[$bit + $i + 2]);
}
}
return substr($der, 4, $len + 4);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
<?php
/**
* 加密工具类
*
* User: jiehua
* Date: 16/3/30
* Time: 下午3:25
*/
/**
* 加密方法
* @param string $str
* @return string
*/
function new_encrypt($str,$screct_key){
//AES, 128 模式加密数据 CBC
$screct_key = base64_decode($screct_key);
$str = trim($str);
$str = addPKCS7Padding($str);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC),1);
$encrypt_str = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $screct_key, $str, MCRYPT_MODE_CBC);
return base64_encode($encrypt_str);
}
/**
* 解密方法
* @param string $str
* @return string
*/
function new_decrypt($str,$screct_key){
//AES, 128 模式加密数据 CBC
$str = base64_decode($str);
$screct_key = base64_decode($screct_key);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC),1);
$encrypt_str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $screct_key, $str, MCRYPT_MODE_CBC);
$encrypt_str = trim($encrypt_str);
$encrypt_str = stripPKSC7Padding($encrypt_str);
return $encrypt_str;
}
/**
* 填充算法
* @param string $source
* @return string
*/
function addPKCS7Padding($source){
$source = trim($source);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$pad = $block - (strlen($source) % $block);
if ($pad <= $block) {
$char = chr($pad);
$source .= str_repeat($char, $pad);
}
return $source;
}
/**
* 移去填充算法
* @param string $source
* @return string
*/
function stripPKSC7Padding($source){
$source = trim($source);
$char = substr($source, -1);
$num = ord($char);
if($num==62)return $source;
$source = substr($source,0,-$num);
return $source;
}

View File

@ -0,0 +1,19 @@
<?php
/**
* TODO 补充说明
*
* User: jiehua
* Date: 16/3/30
* Time: 下午8:55
*/
class EncryptParseItem {
public $startIndex;
public $endIndex;
public $encryptContent;
}

View File

@ -0,0 +1,18 @@
<?php
/**
* TODO 补充说明
*
* User: jiehua
* Date: 16/3/30
* Time: 下午8:51
*/
class EncryptResponseData {
public $realContent;
public $returnContent;
}

View File

@ -0,0 +1,17 @@
<?php
namespace addon\alipay\data\sdk;
/**
* Created by PhpStorm.
* User: jiehua
* Date: 15/5/2
* Time: 下午6:21
*/
class SignData {
public $signSourceData=null;
public $sign=null;
}

View File

@ -0,0 +1,120 @@
<?php
namespace addon\alipay\data\sdk\request;
/**
* ALIPAY API: alipay.fund.trans.toaccount.transfer request
*
* @author auto create
* @since 1.0, 2018-08-14 14:05:00
*/
class AlipayFundTransToaccountTransferRequest
{
/**
* 单笔转账到支付宝账户接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.fund.trans.toaccount.transfer";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace addon\alipay\data\sdk\request;
/**
* ALIPAY API: alipay.fund.trans.uni.transfer request
*
* @author auto create
* @since 1.0, 2020-04-02 22:40:08
*/
class AlipayFundTransUniTransferRequest
{
/**
* 支付宝转账支付接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.fund.trans.uni.transfer";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace addon\alipay\data\sdk\request;
/**
* ALIPAY API: alipay.trade.app.pay request
*
* @author auto create
* @since 1.0, 2018-07-16 16:20:00
*/
class AlipayTradeAppPayRequest
{
/**
* app支付接口2.0
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.app.pay";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* ALIPAY API: alipay.trade.cancel request
*
* @author auto create
* @since 1.0, 2018-07-13 17:18:06
*/
class AlipayTradeCancelRequest
{
/**
* 统一收单交易撤销接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.cancel";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,120 @@
<?php
namespace addon\alipay\data\sdk\request;
/**
* ALIPAY API: alipay.trade.close request
*
* @author auto create
* @since 1.0, 2018-07-13 17:18:06
*/
class AlipayTradeCloseRequest
{
/**
* 统一收单交易关闭接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.close";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace addon\alipay\data\sdk\request;
/**
* ALIPAY API: alipay.trade.create request
*
* @author auto create
* @since 1.0, 2018-09-01 17:05:01
*/
class AlipayTradeCreateRequest
{
/**
* 商户通过该接口进行交易的创建下单
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.create";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* ALIPAY API: alipay.trade.customs.declare request
*
* @author auto create
* @since 1.0, 2016-12-08 00:48:24
*/
class AlipayTradeCustomsDeclareRequest
{
/**
* 统一收单报关接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.customs.declare";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* ALIPAY API: alipay.trade.customs.query request
*
* @author auto create
* @since 1.0, 2018-03-02 14:37:16
*/
class AlipayTradeCustomsQueryRequest
{
/**
* 查询报关详细信息
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.customs.query";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* ALIPAY API: alipay.trade.fastpay.refund.query request
*
* @author auto create
* @since 1.0, 2018-07-25 17:25:00
*/
class AlipayTradeFastpayRefundQueryRequest
{
/**
* 商户可使用该接口查询自已通过alipay.trade.refund提交的退款请求是否执行成功。
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.fastpay.refund.query";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* ALIPAY API: alipay.trade.order.settle request
*
* @author auto create
* @since 1.0, 2018-07-13 17:18:06
*/
class AlipayTradeOrderSettleRequest
{
/**
* 统一收单交易结算接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.order.settle";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* ALIPAY API: alipay.trade.orderinfo.sync request
*
* @author auto create
* @since 1.0, 2018-07-23 11:40:00
*/
class AlipayTradeOrderinfoSyncRequest
{
/**
* 支付宝订单信息同步接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.orderinfo.sync";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,120 @@
<?php
namespace addon\alipay\data\sdk\request;
/**
* ALIPAY API: alipay.trade.page.pay request
*
* @author auto create
* @since 1.0, 2018-08-14 15:31:43
*/
class AlipayTradePagePayRequest
{
/**
* 统一收单下单并支付页面接口
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.page.pay";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

View File

@ -0,0 +1,119 @@
<?php
/**
* ALIPAY API: alipay.trade.pay request
*
* @author auto create
* @since 1.0, 2018-08-31 11:20:00
*/
class AlipayTradePayRequest
{
/**
* 用于在线下场景交易一次创建并支付掉
修改路由策略到R
**/
private $bizContent;
private $apiParas = array();
private $terminalType;
private $terminalInfo;
private $prodCode;
private $apiVersion="1.0";
private $notifyUrl;
private $returnUrl;
private $needEncrypt=false;
public function setBizContent($bizContent)
{
$this->bizContent = $bizContent;
$this->apiParas["biz_content"] = $bizContent;
}
public function getBizContent()
{
return $this->bizContent;
}
public function getApiMethodName()
{
return "alipay.trade.pay";
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl=$notifyUrl;
}
public function getNotifyUrl()
{
return $this->notifyUrl;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl=$returnUrl;
}
public function getReturnUrl()
{
return $this->returnUrl;
}
public function getApiParas()
{
return $this->apiParas;
}
public function getTerminalType()
{
return $this->terminalType;
}
public function setTerminalType($terminalType)
{
$this->terminalType = $terminalType;
}
public function getTerminalInfo()
{
return $this->terminalInfo;
}
public function setTerminalInfo($terminalInfo)
{
$this->terminalInfo = $terminalInfo;
}
public function getProdCode()
{
return $this->prodCode;
}
public function setProdCode($prodCode)
{
$this->prodCode = $prodCode;
}
public function setApiVersion($apiVersion)
{
$this->apiVersion=$apiVersion;
}
public function getApiVersion()
{
return $this->apiVersion;
}
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt=$needEncrypt;
}
public function getNeedEncrypt()
{
return $this->needEncrypt;
}
}

Some files were not shown because too many files have changed in this diff Show More