feat(fsgx): 完成全部24项开发任务 Phase1-7
Phase1 后端核心:
- 新增 fsgx_v1.sql 迁移脚本(is_queue_goods/frozen_points/available_points/no_assess)
- SystemConfigServices 返佣设置扩展(周期人数/分档比例/范围/时机)
- StoreOrderCreateServices 周期循环佣金计算
- StoreOrderTakeServices 佣金发放后同步冻结积分
- StoreProductServices/StoreProduct 保存 is_queue_goods
Phase2 后端接口:
- GET /api/hjf/brokerage/progress 佣金周期进度
- GET /api/hjf/assets/overview 资产总览
- HjfPointsServices 每日 frozen_points 0.4‰ 释放定时任务
- PUT /adminapi/hjf/member/{uid}/no_assess 不考核接口
- GET /adminapi/hjf/points/release_log 积分日志接口
Phase3 前端清理:
- hjfCustom.js 路由精简(仅保留 points/log)
- hjfQueue.js/hjfMember.js API 清理/重定向至 CRMEB 原生接口
- pages.json 公排→推荐佣金/佣金记录/佣金规则
Phase4-5 前端改造:
- queue/status.vue 推荐佣金进度页整体重写
- 商品详情/订单确认/支付结果页文案与逻辑改造
- 个人中心/资产页/引导页/规则页文案改造
- HjfQueueProgress/HjfRefundNotice/HjfAssetCard 组件改造
- 推广中心嵌入佣金进度摘要
- hjfMockData.js 全量更新(公排字段→佣金字段)
Phase6 Admin 增强:
- 用户列表新增 frozen_points/available_points 列及不考核操作按钮
- hjfPoints.js USE_MOCK=false 对接真实积分日志接口
Phase7 配置文档:
- docs/fsgx-phase7-config-checklist.md 后台配置与全链路验收清单
Made-with: Cursor
This commit is contained in:
246
pro_v3.5.1_副本/vendor/overtrue/socialite/tests/Providers/FeiShuTest.php
vendored
Normal file
246
pro_v3.5.1_副本/vendor/overtrue/socialite/tests/Providers/FeiShuTest.php
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace Providers;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Handler\MockHandler;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Overtrue\Socialite\Exceptions\FeiShu\InvalidTicketException;
|
||||
use Overtrue\Socialite\Exceptions\InvalidTokenException;
|
||||
use Overtrue\Socialite\Providers\FeiShu;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FeiShuTest extends TestCase
|
||||
{
|
||||
public function testProviderCanCreateCorrect()
|
||||
{
|
||||
// one way
|
||||
$config = [
|
||||
'app_id' => 'xxxxx',
|
||||
'app_secret' => 'yyyyy',
|
||||
'app_mode' => 'internal',
|
||||
];
|
||||
$f = new FeiShu($config);
|
||||
$rf = new \ReflectionObject($f);
|
||||
|
||||
$this->assertEquals('xxxxx', $f->getClientId());
|
||||
$this->assertEquals('yyyyy', $f->getClientSecret());
|
||||
|
||||
$rfProperty = $rf->getProperty('isInternalApp');
|
||||
$rfProperty->setAccessible(true);
|
||||
$this->assertEquals(true, $rfProperty->getValue($f));
|
||||
|
||||
// diff filed way
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
'mode' => 'internal',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$rf = new \ReflectionObject($f);
|
||||
|
||||
$this->assertEquals('xxxxx', $f->getClientId());
|
||||
$this->assertEquals('yyyyy', $f->getClientSecret());
|
||||
$rfProperty = $rf->getProperty('isInternalApp');
|
||||
$rfProperty->setAccessible(true);
|
||||
$this->assertEquals(true, $rfProperty->getValue($f));
|
||||
|
||||
// no mode config way
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$rf = new \ReflectionObject($f);
|
||||
|
||||
$this->assertEquals('xxxxx', $f->getClientId());
|
||||
$this->assertEquals('yyyyy', $f->getClientSecret());
|
||||
$rfProperty = $rf->getProperty('isInternalApp');
|
||||
$rfProperty->setAccessible(true);
|
||||
$this->assertEquals(false, $rfProperty->getValue($f));
|
||||
}
|
||||
|
||||
public function testProviderWithInternalAppModeWork()
|
||||
{
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$rf = new \ReflectionObject($f);
|
||||
|
||||
$rfProperty = $rf->getProperty('isInternalApp');
|
||||
$rfProperty->setAccessible(true);
|
||||
|
||||
$f->withInternalAppMode();
|
||||
$this->assertEquals(true, $rfProperty->getValue($f));
|
||||
|
||||
$f->withDefaultMode();
|
||||
$this->assertEquals(false, $rfProperty->getValue($f));
|
||||
}
|
||||
|
||||
public function testProviderWithAppTicketWork()
|
||||
{
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$f->withAppTicket('app_ticket');
|
||||
$this->assertEquals('app_ticket', $f->getConfig()->get('app_ticket'));
|
||||
}
|
||||
|
||||
public function testConfigAppAccessTokenWithDefaultModeNoAppTicketWork()
|
||||
{
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$fr = new \ReflectionObject($f);
|
||||
$frClient = $fr->getProperty('httpClient');
|
||||
$frClient->setAccessible(true);
|
||||
$ff = new \ReflectionMethod(FeiShu::class, 'configAppAccessToken');
|
||||
|
||||
$mock = new MockHandler([
|
||||
new Response(403, []),
|
||||
new Response(200, [], \json_encode([
|
||||
'app_access_token' => 'app_access_token',
|
||||
])),
|
||||
]);
|
||||
|
||||
$handler = HandlerStack::create($mock);
|
||||
$client = new Client(['handler' => $handler]);
|
||||
$frClient->setValue($f, $client);
|
||||
$ff->setAccessible(true);
|
||||
|
||||
// 默认模式下没有 app_ticket
|
||||
$this->expectException(InvalidTicketException::class);
|
||||
$ff->invoke($f);
|
||||
|
||||
$ff->invoke($f);
|
||||
$f->withAppTicket('app_ticket');
|
||||
$this->assertEquals('app_access_token', $f->getConfig()->get('app_access_token'));
|
||||
|
||||
$this->expectException(InvalidTokenException::class);
|
||||
$ff->invoke($f);
|
||||
}
|
||||
|
||||
public function testConfigAppAccessTokenWithDefaultModeAndAppTicketWorkInBadResponse()
|
||||
{
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$fr = new \ReflectionObject($f);
|
||||
$frClient = $fr->getProperty('httpClient');
|
||||
$frClient->setAccessible(true);
|
||||
$ff = new \ReflectionMethod(FeiShu::class, 'configAppAccessToken');
|
||||
|
||||
$mock = new MockHandler([
|
||||
new Response(200, [], '{}'),
|
||||
]);
|
||||
|
||||
$handler = HandlerStack::create($mock);
|
||||
$client = new Client(['handler' => $handler]);
|
||||
$frClient->setValue($f, $client);
|
||||
$ff->setAccessible(true);
|
||||
|
||||
$this->expectException(InvalidTokenException::class);
|
||||
$ff->invoke($f->withAppTicket('app_ticket'));
|
||||
}
|
||||
|
||||
public function testConfigAppAccessTokenWithDefaultModeAndAppTicketWorkInGoodResponse()
|
||||
{
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$fr = new \ReflectionObject($f);
|
||||
$frClient = $fr->getProperty('httpClient');
|
||||
$frClient->setAccessible(true);
|
||||
$ff = new \ReflectionMethod(FeiShu::class, 'configAppAccessToken');
|
||||
|
||||
$mock = new MockHandler([
|
||||
new Response(200, [], \json_encode([
|
||||
'app_access_token' => 'app_access_token',
|
||||
])),
|
||||
]);
|
||||
|
||||
$handler = HandlerStack::create($mock);
|
||||
$client = new Client(['handler' => $handler]);
|
||||
$frClient->setValue($f, $client);
|
||||
$ff->setAccessible(true);
|
||||
|
||||
$this->assertEquals(null, $f->getConfig()->get('app_access_token'));
|
||||
$ff->invoke($f->withAppTicket('app_ticket'));
|
||||
$this->assertEquals('app_access_token', $f->getConfig()->get('app_access_token'));
|
||||
}
|
||||
|
||||
public function testConfigAppAccessTokenWithInternalInBadResponse()
|
||||
{
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
'mode' => 'internal',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$fr = new \ReflectionObject($f);
|
||||
$frClient = $fr->getProperty('httpClient');
|
||||
$frClient->setAccessible(true);
|
||||
$ff = new \ReflectionMethod(FeiShu::class, 'configAppAccessToken');
|
||||
|
||||
$mock = new MockHandler([
|
||||
new Response(200, [], '{}'),
|
||||
]);
|
||||
|
||||
$handler = HandlerStack::create($mock);
|
||||
$client = new Client(['handler' => $handler]);
|
||||
$frClient->setValue($f, $client);
|
||||
$ff->setAccessible(true);
|
||||
|
||||
$this->expectException(InvalidTokenException::class);
|
||||
$ff->invoke($f);
|
||||
}
|
||||
|
||||
public function testConfigAppAccessTokenWithInternalInGoodResponse()
|
||||
{
|
||||
$config = [
|
||||
'client_id' => 'xxxxx',
|
||||
'client_secret' => 'yyyyy',
|
||||
'mode' => 'internal',
|
||||
];
|
||||
|
||||
$f = new FeiShu($config);
|
||||
$fr = new \ReflectionObject($f);
|
||||
$frClient = $fr->getProperty('httpClient');
|
||||
$frClient->setAccessible(true);
|
||||
$ff = new \ReflectionMethod(FeiShu::class, 'configAppAccessToken');
|
||||
|
||||
$mock = new MockHandler([
|
||||
new Response(200, [], \json_encode([
|
||||
'app_access_token' => 'app_access_token',
|
||||
])),
|
||||
]);
|
||||
|
||||
$handler = HandlerStack::create($mock);
|
||||
$client = new Client(['handler' => $handler]);
|
||||
$frClient->setValue($f, $client);
|
||||
$ff->setAccessible(true);
|
||||
|
||||
$this->assertEquals(null, $f->getConfig()->get('app_access_token'));
|
||||
$ff->invoke($f);
|
||||
$this->assertEquals('app_access_token', $f->getConfig()->get('app_access_token'));
|
||||
}
|
||||
}
|
||||
20
pro_v3.5.1_副本/vendor/overtrue/socialite/tests/Providers/WeWorkTest.php
vendored
Normal file
20
pro_v3.5.1_副本/vendor/overtrue/socialite/tests/Providers/WeWorkTest.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
use Overtrue\Socialite\Providers\WeWork;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class WeWorkTest extends TestCase
|
||||
{
|
||||
public function testOAuthUrl()
|
||||
{
|
||||
$response = (new WeWork([
|
||||
'client_id' => 'CORPID',
|
||||
'client_secret' => 'client_secret',
|
||||
'redirect' => 'REDIRECT_URI',
|
||||
]))
|
||||
->scopes(['snsapi_base'])
|
||||
->redirect();
|
||||
|
||||
$this->assertSame('https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base#wechat_redirect', $response);
|
||||
}
|
||||
}
|
||||
120
pro_v3.5.1_副本/vendor/overtrue/socialite/tests/Providers/WechatTest.php
vendored
Normal file
120
pro_v3.5.1_副本/vendor/overtrue/socialite/tests/Providers/WechatTest.php
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
use Overtrue\Socialite\Providers\WeChat;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
// here we need loaded the symbols first.
|
||||
\class_exists(\Overtrue\Socialite\Contracts\FactoryInterface::class);
|
||||
|
||||
class WechatTest extends TestCase
|
||||
{
|
||||
public function testWeChatProviderHasCorrectlyRedirectResponse()
|
||||
{
|
||||
$response = (new WeChat([
|
||||
'client_id' => 'client_id',
|
||||
'client_secret' => 'client_secret',
|
||||
'redirect_url' => 'http://localhost/socialite/callback.php',
|
||||
]))->redirect();
|
||||
|
||||
$this->assertStringStartsWith('https://open.weixin.qq.com/connect/qrconnect', $response);
|
||||
$this->assertMatchesRegularExpression('/redirect_uri=http%3A%2F%2Flocalhost%2Fsocialite%2Fcallback.php/', $response);
|
||||
}
|
||||
|
||||
public function testWeChatProviderTokenUrlAndRequestFields()
|
||||
{
|
||||
$provider = new WeChat([
|
||||
'client_id' => 'client_id',
|
||||
'client_secret' => 'client_secret',
|
||||
'redirect_url' => 'http://localhost/socialite/callback.php',
|
||||
]);
|
||||
|
||||
$getTokenUrl = new ReflectionMethod(WeChat::class, 'getTokenUrl');
|
||||
$getTokenUrl->setAccessible(true);
|
||||
|
||||
$getTokenFields = new ReflectionMethod(WeChat::class, 'getTokenFields');
|
||||
$getTokenFields->setAccessible(true);
|
||||
|
||||
$getCodeFields = new ReflectionMethod(WeChat::class, 'getCodeFields');
|
||||
$getCodeFields->setAccessible(true);
|
||||
|
||||
$this->assertSame('https://api.weixin.qq.com/sns/oauth2/access_token', $getTokenUrl->invoke($provider));
|
||||
$this->assertSame([
|
||||
'appid' => 'client_id',
|
||||
'secret' => 'client_secret',
|
||||
'code' => 'iloveyou',
|
||||
'grant_type' => 'authorization_code',
|
||||
], $getTokenFields->invoke($provider, 'iloveyou'));
|
||||
|
||||
$this->assertSame([
|
||||
'appid' => 'client_id',
|
||||
'redirect_uri' => 'http://localhost/socialite/callback.php',
|
||||
'response_type' => 'code',
|
||||
'scope' => 'snsapi_login',
|
||||
'state' => 'wechat-state',
|
||||
'connect_redirect' => 1,
|
||||
], $getCodeFields->invoke($provider->withState('wechat-state')));
|
||||
}
|
||||
|
||||
public function testOpenPlatformComponent()
|
||||
{
|
||||
$provider = new WeChat([
|
||||
'client_id' => 'client_id',
|
||||
'client_secret' => null,
|
||||
'redirect' => 'redirect-url',
|
||||
'component' => [
|
||||
'id' => 'component-app-id',
|
||||
'token' => 'token',
|
||||
],
|
||||
]);
|
||||
$getTokenUrl = new ReflectionMethod(WeChat::class, 'getTokenUrl');
|
||||
$getTokenUrl->setAccessible(true);
|
||||
|
||||
$getTokenFields = new ReflectionMethod(WeChat::class, 'getTokenFields');
|
||||
$getTokenFields->setAccessible(true);
|
||||
|
||||
$getCodeFields = new ReflectionMethod(WeChat::class, 'getCodeFields');
|
||||
$getCodeFields->setAccessible(true);
|
||||
|
||||
$this->assertSame([
|
||||
'appid' => 'client_id',
|
||||
'redirect_uri' => 'redirect-url',
|
||||
'response_type' => 'code',
|
||||
'scope' => 'snsapi_base',
|
||||
'state' => 'state',
|
||||
'connect_redirect' => 1,
|
||||
'component_appid' => 'component-app-id',
|
||||
], $getCodeFields->invoke($provider->withState('state')));
|
||||
|
||||
$this->assertSame([
|
||||
'appid' => 'client_id',
|
||||
'component_appid' => 'component-app-id',
|
||||
'component_access_token' => 'token',
|
||||
'code' => 'simcode',
|
||||
'grant_type' => 'authorization_code',
|
||||
], $getTokenFields->invoke($provider, 'simcode'));
|
||||
|
||||
$this->assertSame('https://api.weixin.qq.com/sns/oauth2/component/access_token', $getTokenUrl->invoke($provider));
|
||||
}
|
||||
|
||||
public function testOpenPlatformComponentWithCustomParameters()
|
||||
{
|
||||
$provider = new WeChat([
|
||||
'client_id' => 'client_id',
|
||||
'client_secret' => null,
|
||||
'redirect' => 'redirect-url',
|
||||
'component' => [
|
||||
'id' => 'component-app-id',
|
||||
'token' => 'token',
|
||||
],
|
||||
]);
|
||||
|
||||
$getCodeFields = new ReflectionMethod(WeChat::class, 'getCodeFields');
|
||||
$getCodeFields->setAccessible(true);
|
||||
|
||||
$provider->with(['foo' => 'bar']);
|
||||
|
||||
$fields = $getCodeFields->invoke($provider->withState('wechat-state'));
|
||||
$this->assertArrayHasKey('foo', $fields);
|
||||
$this->assertSame('bar', $fields['foo']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user