更新代码
This commit is contained in:
20
vendor/overtrue/easy-sms/.editorconfig
vendored
Normal file
20
vendor/overtrue/easy-sms/.editorconfig
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{vue,js,scss}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
512
vendor/overtrue/easy-sms/README.md
vendored
Normal file
512
vendor/overtrue/easy-sms/README.md
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
<h1 align="center">Easy SMS</h1>
|
||||
|
||||
<p align="center">:calling: 一款满足你的多种发送需求的短信发送组件</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/overtrue/easy-sms"><img src="https://travis-ci.org/overtrue/easy-sms.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/easy-sms"><img src="https://poser.pugx.org/overtrue/easy-sms/v/stable.svg" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/easy-sms"><img src="https://poser.pugx.org/overtrue/easy-sms/v/unstable.svg" alt="Latest Unstable Version"></a>
|
||||
<a href="https://scrutinizer-ci.com/g/overtrue/easy-sms/?branch=master"><img src="https://scrutinizer-ci.com/g/overtrue/easy-sms/badges/quality-score.png?b=master" alt="Scrutinizer Code Quality"></a>
|
||||
<a href="https://scrutinizer-ci.com/g/overtrue/easy-sms/?branch=master"><img src="https://scrutinizer-ci.com/g/overtrue/easy-sms/badges/coverage.png?b=master" alt="Code Coverage"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/easy-sms"><img src="https://poser.pugx.org/overtrue/easy-sms/downloads" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/easy-sms"><img src="https://poser.pugx.org/overtrue/easy-sms/license" alt="License"></a>
|
||||
</p>
|
||||
|
||||
|
||||
## 特点
|
||||
|
||||
1. 支持目前市面多家服务商
|
||||
1. 一套写法兼容所有平台
|
||||
1. 简单配置即可灵活增减服务商
|
||||
1. 内置多种服务商轮询策略、支持自定义轮询策略
|
||||
1. 统一的返回值格式,便于日志与监控
|
||||
1. 自动轮询选择可用的服务商
|
||||
1. 更多等你去发现与改进...
|
||||
|
||||
## 平台支持
|
||||
|
||||
- [阿里云](https://www.aliyun.com/)
|
||||
- [云片](https://www.yunpian.com)
|
||||
- [Submail](https://www.mysubmail.com)
|
||||
- [螺丝帽](https://luosimao.com/)
|
||||
- [容联云通讯](http://www.yuntongxun.com)
|
||||
- [互亿无线](http://www.ihuyi.com)
|
||||
- [聚合数据](https://www.juhe.cn)
|
||||
- [SendCloud](http://www.sendcloud.net/)
|
||||
- [百度云](https://cloud.baidu.com/)
|
||||
- [华信短信平台](http://www.ipyy.com/)
|
||||
- [253云通讯(创蓝)](https://www.253.com/)
|
||||
- [融云](http://www.rongcloud.cn)
|
||||
- [天毅无线](http://www.85hu.com/)
|
||||
- [腾讯云 SMS](https://cloud.tencent.com/product/sms)
|
||||
- [阿凡达数据](http://www.avatardata.cn/)
|
||||
|
||||
## 环境需求
|
||||
|
||||
- PHP >= 5.6
|
||||
|
||||
## 安装
|
||||
|
||||
```shell
|
||||
$ composer require "overtrue/easy-sms"
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
||||
```php
|
||||
use Overtrue\EasySms\EasySms;
|
||||
|
||||
$config = [
|
||||
// HTTP 请求的超时时间(秒)
|
||||
'timeout' => 5.0,
|
||||
|
||||
// 默认发送配置
|
||||
'default' => [
|
||||
// 网关调用策略,默认:顺序调用
|
||||
'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class,
|
||||
|
||||
// 默认可用的发送网关
|
||||
'gateways' => [
|
||||
'yunpian', 'aliyun',
|
||||
],
|
||||
],
|
||||
// 可用的网关配置
|
||||
'gateways' => [
|
||||
'errorlog' => [
|
||||
'file' => '/tmp/easy-sms.log',
|
||||
],
|
||||
'yunpian' => [
|
||||
'api_key' => '824f0ff2f71cab52936axxxxxxxxxx',
|
||||
],
|
||||
'aliyun' => [
|
||||
'access_key_id' => '',
|
||||
'access_key_secret' => '',
|
||||
'sign_name' => '',
|
||||
],
|
||||
//...
|
||||
],
|
||||
];
|
||||
|
||||
$easySms = new EasySms($config);
|
||||
|
||||
$easySms->send(13188888888, [
|
||||
'content' => '您的验证码为: 6379',
|
||||
'template' => 'SMS_001',
|
||||
'data' => [
|
||||
'code' => 6379
|
||||
],
|
||||
]);
|
||||
```
|
||||
|
||||
## 短信内容
|
||||
|
||||
由于使用多网关发送,所以一条短信要支持多平台发送,每家的发送方式不一样,但是我们抽象定义了以下公用属性:
|
||||
|
||||
- `content` 文字内容,使用在像云片类似的以文字内容发送的平台
|
||||
- `template` 模板 ID,使用在以模板ID来发送短信的平台
|
||||
- `data` 模板变量,使用在以模板ID来发送短信的平台
|
||||
|
||||
所以,在使用过程中你可以根据所要使用的平台定义发送的内容。
|
||||
|
||||
```php
|
||||
$easySms->send(13188888888, [
|
||||
'content' => '您的验证码为: 6379',
|
||||
'template' => 'SMS_001',
|
||||
'data' => [
|
||||
'code' => 6379
|
||||
],
|
||||
]);
|
||||
```
|
||||
|
||||
你也可以使用闭包来返回对应的值:
|
||||
|
||||
```php
|
||||
$easySms->send(13188888888, [
|
||||
'content' => function($gateway){
|
||||
return '您的验证码为: 6379';
|
||||
},
|
||||
'template' => function($gateway){
|
||||
return 'SMS_001';
|
||||
},
|
||||
'data' => function($gateway){
|
||||
return [
|
||||
'code' => 6379
|
||||
];
|
||||
},
|
||||
]);
|
||||
```
|
||||
|
||||
你可以根据 `$gateway` 参数类型来判断返回值,例如:
|
||||
|
||||
```php
|
||||
$easySms->send(13188888888, [
|
||||
'content' => function($gateway){
|
||||
if ($gateway->getName() == 'yunpian') {
|
||||
return '云片专用验证码:1235';
|
||||
}
|
||||
return '您的验证码为: 6379';
|
||||
},
|
||||
'template' => function($gateway){
|
||||
if ($gateway->getName() == 'aliyun') {
|
||||
return 'TP2818';
|
||||
}
|
||||
return 'SMS_001';
|
||||
},
|
||||
'data' => function($gateway){
|
||||
return [
|
||||
'code' => 6379
|
||||
];
|
||||
},
|
||||
]);
|
||||
```
|
||||
|
||||
## 发送网关
|
||||
|
||||
默认使用 `default` 中的设置来发送,如果某一条短信你想要覆盖默认的设置。在 `send` 方法中使用第三个参数即可:
|
||||
|
||||
```php
|
||||
$easySms->send(13188888888, [
|
||||
'content' => '您的验证码为: 6379',
|
||||
'template' => 'SMS_001',
|
||||
'data' => [
|
||||
'code' => 6379
|
||||
],
|
||||
], ['yunpian', 'juhe']); // 这里的网关配置将会覆盖全局默认值
|
||||
```
|
||||
|
||||
## 返回值
|
||||
|
||||
由于使用多网关发送,所以返回值为一个数组,结构如下:
|
||||
```php
|
||||
[
|
||||
'yunpian' => [
|
||||
'gateway' => 'yunpian',
|
||||
'status' => 'success',
|
||||
'result' => [...] // 平台返回值
|
||||
],
|
||||
'juhe' => [
|
||||
'gateway' => 'juhe',
|
||||
'status' => 'failure',
|
||||
'exception' => \Overtrue\EasySms\Exceptions\GatewayErrorException 对象
|
||||
],
|
||||
//...
|
||||
]
|
||||
```
|
||||
|
||||
如果所选网关列表均发送失败时,将会抛出 `Overtrue\EasySms\Exceptions\NoGatewayAvailableException` 异常,你可以使用 `$e->results` 获取发送结果。
|
||||
|
||||
你也可以使用 `$e` 提供的更多便捷方法:
|
||||
|
||||
```php
|
||||
$e->getResults(); // 返回所有 API 的结果,结构同上
|
||||
$e->getExceptions(); // 返回所有调用异常列表
|
||||
$e->getException($gateway); // 返回指定网关名称的异常对象
|
||||
$e->getLastException(); // 获取最后一个失败的异常对象
|
||||
```
|
||||
|
||||
## 自定义网关
|
||||
|
||||
本拓展已经支持用户自定义网关,你可以很方便的配置即可当成与其它拓展一样的使用:
|
||||
|
||||
```php
|
||||
$config = [
|
||||
...
|
||||
'default' => [
|
||||
'gateways' => [
|
||||
'mygateway', // 配置你的网站到可用的网关列表
|
||||
],
|
||||
],
|
||||
'gateways' => [
|
||||
'mygateway' => [...], // 你网关所需要的参数,如果没有可以不配置
|
||||
],
|
||||
];
|
||||
|
||||
$easySms = new EasySms($config);
|
||||
|
||||
// 注册
|
||||
$easySms->extend('mygateway', function($gatewayConfig){
|
||||
// $gatewayConfig 来自配置文件里的 `gateways.mygateway`
|
||||
return new MyGateway($gatewayConfig);
|
||||
});
|
||||
|
||||
$easySms->send(13188888888, [
|
||||
'content' => '您的验证码为: 6379',
|
||||
'template' => 'SMS_001',
|
||||
'data' => [
|
||||
'code' => 6379
|
||||
],
|
||||
]);
|
||||
```
|
||||
|
||||
## 国际短信
|
||||
|
||||
国际短信与国内短信的区别是号码前面需要加国际码,但是由于各平台对国际号码的写法不一致,所以在发送国际短信的时候有一点区别:
|
||||
|
||||
```php
|
||||
use Overtrue\EasySms\PhoneNumber;
|
||||
|
||||
// 发送到国际码为 31 的国际号码
|
||||
$number = new PhoneNumber(13188888888, 31);
|
||||
|
||||
$easySms->send($number, [
|
||||
'content' => '您的验证码为: 6379',
|
||||
'template' => 'SMS_001',
|
||||
'data' => [
|
||||
'code' => 6379
|
||||
],
|
||||
]);
|
||||
```
|
||||
|
||||
## 定义短信
|
||||
|
||||
你可以根据发送场景的不同,定义不同的短信类,从而实现一处定义多处调用,你可以继承 `Overtrue\EasySms\Message` 来定义短信模型:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Overtrue\EasySms\Message;
|
||||
use Overtrue\EasySms\Contracts\GatewayInterface;
|
||||
use Overtrue\EasySms\Strategies\OrderStrategy;
|
||||
|
||||
class OrderPaidMessage extends Message
|
||||
{
|
||||
protected $order;
|
||||
protected $strategy = OrderStrategy::class; // 定义本短信的网关使用策略,覆盖全局配置中的 `default.strategy`
|
||||
protected $gateways = ['alidayu', 'yunpian', 'juhe']; // 定义本短信的适用平台,覆盖全局配置中的 `default.gateways`
|
||||
|
||||
public function __construct($order)
|
||||
{
|
||||
$this->order = $order;
|
||||
}
|
||||
|
||||
// 定义直接使用内容发送平台的内容
|
||||
public function getContent(GatewayInterface $gateway = null)
|
||||
{
|
||||
return sprintf('您的订单:%s, 已经完成付款', $this->order->no);
|
||||
}
|
||||
|
||||
// 定义使用模板发送方式平台所需要的模板 ID
|
||||
public function getTemplate(GatewayInterface $gateway = null)
|
||||
{
|
||||
return 'SMS_003';
|
||||
}
|
||||
|
||||
// 模板参数
|
||||
public function getData(GatewayInterface $gateway = null)
|
||||
{
|
||||
return [
|
||||
'order_no' => $this->order->no
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 更多自定义方式请参考:[`Overtrue\EasySms\Message`](Overtrue\EasySms\Message;)
|
||||
|
||||
发送自定义短信:
|
||||
|
||||
```php
|
||||
$order = ...;
|
||||
$message = new OrderPaidMessage($order);
|
||||
|
||||
$easySms->send(13188888888, $message);
|
||||
```
|
||||
|
||||
## 各平台配置说明
|
||||
|
||||
### [阿里云](https://www.aliyun.com/)
|
||||
|
||||
短信内容使用 `template` + `data`
|
||||
|
||||
```php
|
||||
'aliyun' => [
|
||||
'access_key_id' => '',
|
||||
'access_key_secret' => '',
|
||||
'sign_name' => '',
|
||||
],
|
||||
```
|
||||
|
||||
### [云片](https://www.yunpian.com)
|
||||
|
||||
短信内容使用 `content`
|
||||
|
||||
```php
|
||||
'yunpian' => [
|
||||
'api_key' => '',
|
||||
],
|
||||
```
|
||||
|
||||
### [Submail](https://www.mysubmail.com)
|
||||
|
||||
短信内容使用 `data`
|
||||
|
||||
```php
|
||||
'submail' => [
|
||||
'app_id' => '',
|
||||
'app_key' => '',
|
||||
'project' => '', // 默认 project,可在发送时 data 中指定
|
||||
],
|
||||
```
|
||||
|
||||
### [螺丝帽](https://luosimao.com/)
|
||||
|
||||
短信内容使用 `content`
|
||||
|
||||
```php
|
||||
'luosimao' => [
|
||||
'api_key' => '',
|
||||
],
|
||||
```
|
||||
|
||||
### [容联云通讯](http://www.yuntongxun.com)
|
||||
|
||||
短信内容使用 `template` + `data`
|
||||
|
||||
```php
|
||||
'yuntongxun' => [
|
||||
'app_id' => '',
|
||||
'account_sid' => '',
|
||||
'account_token' => '',
|
||||
'is_sub_account' => false,
|
||||
],
|
||||
```
|
||||
|
||||
### [互亿无线](http://www.ihuyi.com)
|
||||
|
||||
短信内容使用 `content`
|
||||
|
||||
```php
|
||||
'huyi' => [
|
||||
'api_id' => '',
|
||||
'api_key' => '',
|
||||
],
|
||||
```
|
||||
|
||||
### [聚合数据](https://www.juhe.cn)
|
||||
|
||||
短信内容使用 `template` + `data`
|
||||
|
||||
```php
|
||||
'juhe' => [
|
||||
'app_key' => '',
|
||||
],
|
||||
```
|
||||
|
||||
### [SendCloud](http://www.sendcloud.net/)
|
||||
|
||||
短信内容使用 `template` + `data`
|
||||
|
||||
```php
|
||||
'sendcloud' => [
|
||||
'sms_user' => '',
|
||||
'sms_key' => '',
|
||||
'timestamp' => false, // 是否启用时间戳
|
||||
],
|
||||
```
|
||||
### [百度云](https://cloud.baidu.com/)
|
||||
|
||||
短信内容使用 `template` + `data`
|
||||
|
||||
```php
|
||||
'baidu' => [
|
||||
'ak' => '',
|
||||
'sk' => '',
|
||||
'invoke_id' => '',
|
||||
'domain' => '',
|
||||
],
|
||||
```
|
||||
|
||||
### [华信短信平台](http://www.ipyy.com/)
|
||||
|
||||
短信内容使用 `content`
|
||||
|
||||
```php
|
||||
'huaxin' => [
|
||||
'user_id' => '',
|
||||
'password' => '',
|
||||
'account' => '',
|
||||
'ip' => '',
|
||||
'ext_no' => '',
|
||||
],
|
||||
```
|
||||
|
||||
### [253云通讯(创蓝)](https://www.253.com/)
|
||||
|
||||
短信内容使用 `content`
|
||||
|
||||
```php
|
||||
'chuanglan' => [
|
||||
'account' => '',
|
||||
'password' => '',
|
||||
|
||||
// \Overtrue\EasySms\Gateways\ChuanglanGateway::CHANNEL_VALIDATE_CODE => 验证码通道(默认)
|
||||
// \Overtrue\EasySms\Gateways\ChuanglanGateway::CHANNEL_PROMOTION_CODE => 会员营销通道
|
||||
'channel' => \Overtrue\EasySms\Gateways\ChuanglanGateway::CHANNEL_VALIDATE_CODE,
|
||||
|
||||
// 会员营销通道 特定参数。创蓝规定:api提交营销短信的时候,需要自己加短信的签名及退订信息
|
||||
'sign' => '【通讯云】',
|
||||
'unsubscribe' => '回TD退订',
|
||||
],
|
||||
```
|
||||
|
||||
### [融云](http://www.rongcloud.cn)
|
||||
|
||||
短信分为两大类,验证类和通知类短信。 发送验证类短信使用 `template` + `data`
|
||||
|
||||
```php
|
||||
'rongcloud' => [
|
||||
'app_key' => '',
|
||||
'app_secret' => '',
|
||||
]
|
||||
```
|
||||
|
||||
### [天毅无线](http://www.85hu.com/)
|
||||
|
||||
短信内容使用 `content`
|
||||
|
||||
```php
|
||||
'tianyiwuxian' => [
|
||||
'username' => '', //用户名
|
||||
'password' => '', //密码
|
||||
'gwid' => '', //网关ID
|
||||
]
|
||||
```
|
||||
|
||||
### [twilio](https://www.twilio.com)
|
||||
|
||||
短信使用 `content`
|
||||
发送对象需要 使用`+`添加区号
|
||||
|
||||
```php
|
||||
'twilio' => [
|
||||
'account_sid' => '', // sid
|
||||
'from' => '', // 发送的号码 可以在控制台购买
|
||||
'token' => '', // apitoken
|
||||
],
|
||||
```
|
||||
|
||||
### [腾讯云 SMS](https://cloud.tencent.com/product/sms)
|
||||
|
||||
短信内容使用 `content`。
|
||||
|
||||
```php
|
||||
'qcloud' => [
|
||||
'sdk_app_id' => '', // SDK APP ID
|
||||
'app_key' => '', // APP KEY
|
||||
'sign_name' => '', // 短信签名,如果使用默认签名,该字段可缺省(对应官方文档中的sign)
|
||||
],
|
||||
```
|
||||
|
||||
### [阿凡达数据](http://www.avatardata.cn/)
|
||||
|
||||
短信内容使用 `template` + `data`
|
||||
|
||||
```php
|
||||
'avatardata' => [
|
||||
'app_key' => '', // APP KEY
|
||||
],
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
30
vendor/overtrue/easy-sms/composer.json
vendored
Normal file
30
vendor/overtrue/easy-sms/composer.json
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "overtrue/easy-sms",
|
||||
"description": "The easiest way to send short message.",
|
||||
"type": "library",
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.2",
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.6",
|
||||
"mockery/mockery": "1.0.x-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Overtrue\\EasySms\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Overtrue\\EasySms\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"email": "i@overtrue.me"
|
||||
}
|
||||
]
|
||||
}
|
||||
38
vendor/overtrue/easy-sms/src/Contracts/GatewayInterface.php
vendored
Normal file
38
vendor/overtrue/easy-sms/src/Contracts/GatewayInterface.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Contracts;
|
||||
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
|
||||
/**
|
||||
* Class GatewayInterface.
|
||||
*/
|
||||
interface GatewayInterface
|
||||
{
|
||||
/**
|
||||
* Get gateway name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Send a short message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config);
|
||||
}
|
||||
63
vendor/overtrue/easy-sms/src/Contracts/MessageInterface.php
vendored
Normal file
63
vendor/overtrue/easy-sms/src/Contracts/MessageInterface.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Contracts;
|
||||
|
||||
/**
|
||||
* Interface MessageInterface.
|
||||
*/
|
||||
interface MessageInterface
|
||||
{
|
||||
const TEXT_MESSAGE = 'text';
|
||||
|
||||
const VOICE_MESSAGE = 'voice';
|
||||
|
||||
/**
|
||||
* Return the message type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMessageType();
|
||||
|
||||
/**
|
||||
* Return message content.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(GatewayInterface $gateway = null);
|
||||
|
||||
/**
|
||||
* Return the template id of message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate(GatewayInterface $gateway = null);
|
||||
|
||||
/**
|
||||
* Return the template data of message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getData(GatewayInterface $gateway = null);
|
||||
|
||||
/**
|
||||
* Return message supported gateways.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGateways();
|
||||
}
|
||||
53
vendor/overtrue/easy-sms/src/Contracts/PhoneNumberInterface.php
vendored
Normal file
53
vendor/overtrue/easy-sms/src/Contracts/PhoneNumberInterface.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Contracts;
|
||||
|
||||
/**
|
||||
* Interface PhoneNumberInterface.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
interface PhoneNumberInterface extends \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* 86.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getIDDCode();
|
||||
|
||||
/**
|
||||
* 18888888888.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNumber();
|
||||
|
||||
/**
|
||||
* +8618888888888.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUniversalNumber();
|
||||
|
||||
/**
|
||||
* 008618888888888.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getZeroPrefixedNumber();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
||||
27
vendor/overtrue/easy-sms/src/Contracts/StrategyInterface.php
vendored
Normal file
27
vendor/overtrue/easy-sms/src/Contracts/StrategyInterface.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Contracts;
|
||||
|
||||
/**
|
||||
* Interface StrategyInterface.
|
||||
*/
|
||||
interface StrategyInterface
|
||||
{
|
||||
/**
|
||||
* Apply the strategy and return result.
|
||||
*
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply(array $gateways);
|
||||
}
|
||||
353
vendor/overtrue/easy-sms/src/EasySms.php
vendored
Normal file
353
vendor/overtrue/easy-sms/src/EasySms.php
vendored
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms;
|
||||
|
||||
use Closure;
|
||||
use Overtrue\EasySms\Contracts\GatewayInterface;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Contracts\StrategyInterface;
|
||||
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
|
||||
use Overtrue\EasySms\Strategies\OrderStrategy;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class EasySms.
|
||||
*/
|
||||
class EasySms
|
||||
{
|
||||
/**
|
||||
* @var \Overtrue\EasySms\Support\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultGateway;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $customCreators = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $gateways = [];
|
||||
|
||||
/**
|
||||
* @var \Overtrue\EasySms\Messenger
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $strategies = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->config = new Config($config);
|
||||
|
||||
if (!empty($config['default'])) {
|
||||
$this->setDefaultGateway($config['default']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message.
|
||||
*
|
||||
* @param string|array $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface|array $message
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
* @throws \Overtrue\EasySms\Exceptions\NoGatewayAvailableException
|
||||
*/
|
||||
public function send($to, $message, array $gateways = [])
|
||||
{
|
||||
$to = $this->formatPhoneNumber($to);
|
||||
$message = $this->formatMessage($message);
|
||||
$gateways = empty($gateways) ? $message->getGateways() : $gateways;
|
||||
|
||||
if (empty($gateways)) {
|
||||
$gateways = $this->config->get('default.gateways', []);
|
||||
}
|
||||
|
||||
return $this->getMessenger()->send($to, $message, $this->formatGateways($gateways));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a gateway.
|
||||
*
|
||||
* @param string|null $name
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\GatewayInterface
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public function gateway($name = null)
|
||||
{
|
||||
$name = $name ?: $this->getDefaultGateway();
|
||||
|
||||
if (!isset($this->gateways[$name])) {
|
||||
$this->gateways[$name] = $this->createGateway($name);
|
||||
}
|
||||
|
||||
return $this->gateways[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a strategy instance.
|
||||
*
|
||||
* @param string|null $strategy
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\StrategyInterface
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public function strategy($strategy = null)
|
||||
{
|
||||
if (is_null($strategy)) {
|
||||
$strategy = $this->config->get('default.strategy', OrderStrategy::class);
|
||||
}
|
||||
|
||||
if (!class_exists($strategy)) {
|
||||
$strategy = __NAMESPACE__.'\Strategies\\'.ucfirst($strategy);
|
||||
}
|
||||
|
||||
if (!class_exists($strategy)) {
|
||||
throw new InvalidArgumentException("Unsupported strategy \"{$strategy}\"");
|
||||
}
|
||||
|
||||
if (empty($this->strategies[$strategy]) || !($this->strategies[$strategy] instanceof StrategyInterface)) {
|
||||
$this->strategies[$strategy] = new $strategy($this);
|
||||
}
|
||||
|
||||
return $this->strategies[$strategy];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom driver creator Closure.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Closure $callback
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function extend($name, Closure $callback)
|
||||
{
|
||||
$this->customCreators[$name] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Overtrue\EasySms\Support\Config
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default gateway name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException if no default gateway configured
|
||||
*/
|
||||
public function getDefaultGateway()
|
||||
{
|
||||
if (empty($this->defaultGateway)) {
|
||||
throw new RuntimeException('No default gateway configured.');
|
||||
}
|
||||
|
||||
return $this->defaultGateway;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default gateway name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefaultGateway($name)
|
||||
{
|
||||
$this->defaultGateway = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Overtrue\EasySms\Messenger
|
||||
*/
|
||||
public function getMessenger()
|
||||
{
|
||||
return $this->messenger ?: $this->messenger = new Messenger($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new driver instance.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return GatewayInterface
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
protected function createGateway($name)
|
||||
{
|
||||
if (isset($this->customCreators[$name])) {
|
||||
$gateway = $this->callCustomCreator($name);
|
||||
} else {
|
||||
$className = $this->formatGatewayClassName($name);
|
||||
$gateway = $this->makeGateway($className, $this->config->get("gateways.{$name}", []));
|
||||
}
|
||||
|
||||
if (!($gateway instanceof GatewayInterface)) {
|
||||
throw new InvalidArgumentException(sprintf('Gateway "%s" not inherited from %s.', $name, GatewayInterface::class));
|
||||
}
|
||||
|
||||
return $gateway;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make gateway instance.
|
||||
*
|
||||
* @param string $gateway
|
||||
* @param array $config
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\GatewayInterface
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
protected function makeGateway($gateway, $config)
|
||||
{
|
||||
if (!class_exists($gateway)) {
|
||||
throw new InvalidArgumentException(sprintf('Gateway "%s" not exists.', $gateway));
|
||||
}
|
||||
|
||||
return new $gateway($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format gateway name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatGatewayClassName($name)
|
||||
{
|
||||
if (class_exists($name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
$name = ucfirst(str_replace(['-', '_', ''], '', $name));
|
||||
|
||||
return __NAMESPACE__."\\Gateways\\{$name}Gateway";
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a custom gateway creator.
|
||||
*
|
||||
* @param string $gateway
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function callCustomCreator($gateway)
|
||||
{
|
||||
return call_user_func($this->customCreators[$gateway], $this->config->get("gateways.{$gateway}", []));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|\Overtrue\EasySms\Contracts\PhoneNumberInterface $number
|
||||
*
|
||||
* @return \Overtrue\EasySms\PhoneNumber
|
||||
*/
|
||||
protected function formatPhoneNumber($number)
|
||||
{
|
||||
if ($number instanceof PhoneNumberInterface) {
|
||||
return $number;
|
||||
}
|
||||
|
||||
return new PhoneNumber(trim($number));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string|\Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\MessageInterface
|
||||
*/
|
||||
protected function formatMessage($message)
|
||||
{
|
||||
if (!($message instanceof MessageInterface)) {
|
||||
if (!is_array($message)) {
|
||||
$message = [
|
||||
'content' => $message,
|
||||
'template' => $message,
|
||||
];
|
||||
}
|
||||
|
||||
$message = new Message($message);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
protected function formatGateways(array $gateways)
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
foreach ($gateways as $gateway => $setting) {
|
||||
if (is_int($gateway) && is_string($setting)) {
|
||||
$gateway = $setting;
|
||||
$setting = [];
|
||||
}
|
||||
|
||||
$formatted[$gateway] = $setting;
|
||||
$globalSettings = $this->config->get("gateways.{$gateway}", []);
|
||||
|
||||
if (is_string($gateway) && !empty($globalSettings) && is_array($setting)) {
|
||||
$formatted[$gateway] = new Config(array_merge($globalSettings, $setting));
|
||||
}
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($this->strategy()->apply($formatted) as $name) {
|
||||
$result[$name] = $formatted[$name];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
21
vendor/overtrue/easy-sms/src/Exceptions/Exception.php
vendored
Normal file
21
vendor/overtrue/easy-sms/src/Exceptions/Exception.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Exceptions;
|
||||
|
||||
/**
|
||||
* Class Exception.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
||||
35
vendor/overtrue/easy-sms/src/Exceptions/GatewayErrorException.php
vendored
Normal file
35
vendor/overtrue/easy-sms/src/Exceptions/GatewayErrorException.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Exceptions;
|
||||
|
||||
/**
|
||||
* Class GatewayErrorException.
|
||||
*/
|
||||
class GatewayErrorException extends Exception
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $raw = [];
|
||||
|
||||
/**
|
||||
* GatewayErrorException constructor.
|
||||
*
|
||||
* @param array $raw
|
||||
*/
|
||||
public function __construct($message, $code, array $raw = [])
|
||||
{
|
||||
parent::__construct($message, intval($code));
|
||||
|
||||
$this->raw = $raw;
|
||||
}
|
||||
}
|
||||
19
vendor/overtrue/easy-sms/src/Exceptions/InvalidArgumentException.php
vendored
Normal file
19
vendor/overtrue/easy-sms/src/Exceptions/InvalidArgumentException.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Exceptions;
|
||||
|
||||
/**
|
||||
* Class InvalidArgumentException.
|
||||
*/
|
||||
class InvalidArgumentException extends Exception
|
||||
{
|
||||
}
|
||||
81
vendor/overtrue/easy-sms/src/Exceptions/NoGatewayAvailableException.php
vendored
Normal file
81
vendor/overtrue/easy-sms/src/Exceptions/NoGatewayAvailableException.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class NoGatewayAvailableException.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class NoGatewayAvailableException extends Exception
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $results = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $exceptions = [];
|
||||
|
||||
/**
|
||||
* NoGatewayAvailableException constructor.
|
||||
*
|
||||
* @param array $results
|
||||
* @param int $code
|
||||
* @param \Throwable|null $previous
|
||||
*/
|
||||
public function __construct(array $results = [], $code = 0, Throwable $previous = null)
|
||||
{
|
||||
$this->results = $results;
|
||||
$this->exceptions = \array_column($results, 'exception', 'gateway');
|
||||
|
||||
parent::__construct('All the gateways have failed. You can get error details by `$exception->getExceptions()`', $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $gateway
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getException($gateway)
|
||||
{
|
||||
return isset($this->exceptions[$gateway]) ? $this->exceptions[$gateway] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getExceptions()
|
||||
{
|
||||
return $this->exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastException()
|
||||
{
|
||||
return end($this->exceptions);
|
||||
}
|
||||
}
|
||||
111
vendor/overtrue/easy-sms/src/Gateways/AliyunGateway.php
vendored
Normal file
111
vendor/overtrue/easy-sms/src/Gateways/AliyunGateway.php
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class AliyunGateway.
|
||||
*
|
||||
* @author carson <docxcn@gmail.com>
|
||||
*
|
||||
* @see https://help.aliyun.com/document_detail/55451.html
|
||||
*/
|
||||
class AliyunGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://dysmsapi.aliyuncs.com';
|
||||
|
||||
const ENDPOINT_METHOD = 'SendSms';
|
||||
|
||||
const ENDPOINT_VERSION = '2017-05-25';
|
||||
|
||||
const ENDPOINT_FORMAT = 'JSON';
|
||||
|
||||
const ENDPOINT_REGION_ID = 'cn-hangzhou';
|
||||
|
||||
const ENDPOINT_SIGNATURE_METHOD = 'HMAC-SHA1';
|
||||
|
||||
const ENDPOINT_SIGNATURE_VERSION = '1.0';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'RegionId' => self::ENDPOINT_REGION_ID,
|
||||
'AccessKeyId' => $config->get('access_key_id'),
|
||||
'Format' => self::ENDPOINT_FORMAT,
|
||||
'SignatureMethod' => self::ENDPOINT_SIGNATURE_METHOD,
|
||||
'SignatureVersion' => self::ENDPOINT_SIGNATURE_VERSION,
|
||||
'SignatureNonce' => uniqid(),
|
||||
'Timestamp' => $this->getTimestamp(),
|
||||
'Action' => self::ENDPOINT_METHOD,
|
||||
'Version' => self::ENDPOINT_VERSION,
|
||||
'PhoneNumbers' => !\is_null($to->getIDDCode()) ? strval($to->getZeroPrefixedNumber()) : $to->getNumber(),
|
||||
'SignName' => $config->get('sign_name'),
|
||||
'TemplateCode' => $message->getTemplate($this),
|
||||
'TemplateParam' => json_encode($message->getData($this), JSON_FORCE_OBJECT),
|
||||
];
|
||||
|
||||
$params['Signature'] = $this->generateSign($params);
|
||||
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
|
||||
if ('OK' != $result['Code']) {
|
||||
throw new GatewayErrorException($result['Message'], $result['Code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params)
|
||||
{
|
||||
ksort($params);
|
||||
$accessKeySecret = $this->config->get('access_key_secret');
|
||||
$stringToSign = 'GET&%2F&'.urlencode(http_build_query($params, null, '&', PHP_QUERY_RFC3986));
|
||||
|
||||
return base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret.'&', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false|string
|
||||
*/
|
||||
protected function getTimestamp()
|
||||
{
|
||||
$timezone = date_default_timezone_get();
|
||||
date_default_timezone_set('GMT');
|
||||
$timestamp = date('Y-m-d\TH:i:s\Z');
|
||||
date_default_timezone_set($timezone);
|
||||
|
||||
return $timestamp;
|
||||
}
|
||||
}
|
||||
60
vendor/overtrue/easy-sms/src/Gateways/AvatardataGateway.php
vendored
Normal file
60
vendor/overtrue/easy-sms/src/Gateways/AvatardataGateway.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class AvatardataGateway.
|
||||
*
|
||||
* @see http://www.avatardata.cn/Docs/Api/fd475e40-7809-4be7-936c-5926dd41b0fe
|
||||
*/
|
||||
class AvatardataGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://v1.avatardata.cn/Sms/Send';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'mobile' => $to->getNumber(),
|
||||
'templateId' => $message->getTemplate($this),
|
||||
'param' => implode(',', $message->getData($this)),
|
||||
'dtype' => self::ENDPOINT_FORMAT,
|
||||
'key' => $config->get('app_key'),
|
||||
];
|
||||
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
|
||||
if ($result['error_code']) {
|
||||
throw new GatewayErrorException($result['reason'], $result['error_code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
165
vendor/overtrue/easy-sms/src/Gateways/BaiduGateway.php
vendored
Normal file
165
vendor/overtrue/easy-sms/src/Gateways/BaiduGateway.php
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class BaiduGateway.
|
||||
*
|
||||
* @see https://cloud.baidu.com/doc/SMS/API.html
|
||||
*/
|
||||
class BaiduGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_HOST = 'sms.bj.baidubce.com';
|
||||
|
||||
const ENDPOINT_URI = '/bce/v2/message';
|
||||
|
||||
const BCE_AUTH_VERSION = 'bce-auth-v1';
|
||||
|
||||
const DEFAULT_EXPIRATION_IN_SECONDS = 1800; //签名有效期默认1800秒
|
||||
|
||||
const SUCCESS_CODE = 1000;
|
||||
|
||||
/**
|
||||
* Send message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'invokeId' => $config->get('invoke_id'),
|
||||
'phoneNumber' => $to->getNumber(),
|
||||
'templateCode' => $message->getTemplate($this),
|
||||
'contentVar' => $message->getData($this),
|
||||
];
|
||||
|
||||
$datetime = date('Y-m-d\TH:i:s\Z');
|
||||
|
||||
$headers = [
|
||||
'host' => self::ENDPOINT_HOST,
|
||||
'content-type' => 'application/json',
|
||||
'x-bce-date' => $datetime,
|
||||
'x-bce-content-sha256' => hash('sha256', json_encode($params)),
|
||||
];
|
||||
//获得需要签名的数据
|
||||
$signHeaders = $this->getHeadersToSign($headers, ['host', 'x-bce-content-sha256']);
|
||||
|
||||
$headers['Authorization'] = $this->generateSign($signHeaders, $datetime, $config);
|
||||
|
||||
$result = $this->request('post', self::buildEndpoint($config), ['headers' => $headers, 'json' => $params]);
|
||||
|
||||
if (self::SUCCESS_CODE != $result['code']) {
|
||||
throw new GatewayErrorException($result['message'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint(Config $config)
|
||||
{
|
||||
return 'http://'.$config->get('domain', self::ENDPOINT_HOST).self::ENDPOINT_URI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Authorization header.
|
||||
*
|
||||
* @param array $signHeaders
|
||||
* @param int $datetime
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign(array $signHeaders, $datetime, Config $config)
|
||||
{
|
||||
// 生成 authString
|
||||
$authString = self::BCE_AUTH_VERSION.'/'.$config->get('ak').'/'
|
||||
.$datetime.'/'.self::DEFAULT_EXPIRATION_IN_SECONDS;
|
||||
|
||||
// 使用 sk 和 authString 生成 signKey
|
||||
$signingKey = hash_hmac('sha256', $authString, $config->get('sk'));
|
||||
// 生成标准化 URI
|
||||
// 根据 RFC 3986,除了:1.大小写英文字符 2.阿拉伯数字 3.点'.'、波浪线'~'、减号'-'以及下划线'_' 以外都要编码
|
||||
$canonicalURI = str_replace('%2F', '/', rawurlencode(self::ENDPOINT_URI));
|
||||
|
||||
// 生成标准化 QueryString
|
||||
$canonicalQueryString = ''; // 此 api 不需要此项。返回空字符串
|
||||
|
||||
// 整理 headersToSign,以 ';' 号连接
|
||||
$signedHeaders = empty($signHeaders) ? '' : strtolower(trim(implode(';', array_keys($signHeaders))));
|
||||
|
||||
// 生成标准化 header
|
||||
$canonicalHeader = $this->getCanonicalHeaders($signHeaders);
|
||||
|
||||
// 组成标准请求串
|
||||
$canonicalRequest = "POST\n{$canonicalURI}\n{$canonicalQueryString}\n{$canonicalHeader}";
|
||||
|
||||
// 使用 signKey 和标准请求串完成签名
|
||||
$signature = hash_hmac('sha256', $canonicalRequest, $signingKey);
|
||||
|
||||
// 组成最终签名串
|
||||
return "{$authString}/{$signedHeaders}/{$signature}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成标准化 http 请求头串.
|
||||
*
|
||||
* @param array $headers
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getCanonicalHeaders(array $headers)
|
||||
{
|
||||
$headerStrings = [];
|
||||
foreach ($headers as $name => $value) {
|
||||
//trim后再encode,之后使用':'号连接起来
|
||||
$headerStrings[] = rawurlencode(strtolower(trim($name))).':'.rawurlencode(trim($value));
|
||||
}
|
||||
|
||||
sort($headerStrings);
|
||||
|
||||
return implode("\n", $headerStrings);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 指定的 keys 过滤应该参与签名的 header.
|
||||
*
|
||||
* @param array $headers
|
||||
* @param array $keys
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getHeadersToSign(array $headers, array $keys)
|
||||
{
|
||||
return array_intersect_key($headers, array_flip($keys));
|
||||
}
|
||||
}
|
||||
133
vendor/overtrue/easy-sms/src/Gateways/ChuanglanGateway.php
vendored
Normal file
133
vendor/overtrue/easy-sms/src/Gateways/ChuanglanGateway.php
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class ChuanglanGateway.
|
||||
*
|
||||
* @see https://zz.253.com/v5.html#/api_doc
|
||||
*/
|
||||
class ChuanglanGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
/**
|
||||
* URL模板
|
||||
*/
|
||||
const ENDPOINT_URL_TEMPLATE = 'https://%s.253.com/msg/send/json';
|
||||
|
||||
/**
|
||||
* 验证码渠道code.
|
||||
*/
|
||||
const CHANNEL_VALIDATE_CODE = 'smsbj1';
|
||||
|
||||
/**
|
||||
* 会员营销渠道code.
|
||||
*/
|
||||
const CHANNEL_PROMOTION_CODE = 'smssh1';
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'account' => $config->get('account'),
|
||||
'password' => $config->get('password'),
|
||||
'phone' => $to->getNumber(),
|
||||
'msg' => $this->wrapChannelContent($message->getContent($this), $config),
|
||||
];
|
||||
|
||||
$result = $this->postJson($this->buildEndpoint($config), $params);
|
||||
|
||||
if (!isset($result['code']) || '0' != $result['code']) {
|
||||
throw new GatewayErrorException(json_encode($result, JSON_UNESCAPED_UNICODE), isset($result['code']) ? $result['code'] : 0, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Config $config
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function buildEndpoint(Config $config)
|
||||
{
|
||||
$channel = $this->getChannel($config);
|
||||
|
||||
return sprintf(self::ENDPOINT_URL_TEMPLATE, $channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Config $config
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function getChannel(Config $config)
|
||||
{
|
||||
$channel = $config->get('channel', self::CHANNEL_VALIDATE_CODE);
|
||||
|
||||
if (!in_array($channel, [self::CHANNEL_VALIDATE_CODE, self::CHANNEL_PROMOTION_CODE])) {
|
||||
throw new InvalidArgumentException('Invalid channel for ChuanglanGateway.');
|
||||
}
|
||||
|
||||
return $channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param Config $config
|
||||
*
|
||||
* @return string|string
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function wrapChannelContent($content, Config $config)
|
||||
{
|
||||
$channel = $this->getChannel($config);
|
||||
|
||||
if (self::CHANNEL_PROMOTION_CODE == $channel) {
|
||||
$sign = (string) $config->get('sign', '');
|
||||
if (empty($sign)) {
|
||||
throw new InvalidArgumentException('Invalid sign for ChuanglanGateway when using promotion channel');
|
||||
}
|
||||
|
||||
$unsubscribe = (string) $config->get('unsubscribe', '');
|
||||
if (empty($unsubscribe)) {
|
||||
throw new InvalidArgumentException('Invalid unsubscribe for ChuanglanGateway when using promotion channel');
|
||||
}
|
||||
|
||||
$content = $sign.$content.$unsubscribe;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
50
vendor/overtrue/easy-sms/src/Gateways/ErrorlogGateway.php
vendored
Normal file
50
vendor/overtrue/easy-sms/src/Gateways/ErrorlogGateway.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
|
||||
/**
|
||||
* Class ErrorlogGateway.
|
||||
*/
|
||||
class ErrorlogGateway extends Gateway
|
||||
{
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
if (is_array($to)) {
|
||||
$to = implode(',', $to);
|
||||
}
|
||||
|
||||
$message = sprintf(
|
||||
"[%s] to: %s | message: \"%s\" | template: \"%s\" | data: %s\n",
|
||||
date('Y-m-d H:i:s'),
|
||||
$to,
|
||||
$message->getContent($this),
|
||||
$message->getTemplate($this),
|
||||
json_encode($message->getData($this))
|
||||
);
|
||||
|
||||
$file = $this->config->get('file', ini_get('error_log'));
|
||||
$status = error_log($message, 3, $file);
|
||||
|
||||
return compact('status', 'file');
|
||||
}
|
||||
}
|
||||
95
vendor/overtrue/easy-sms/src/Gateways/Gateway.php
vendored
Normal file
95
vendor/overtrue/easy-sms/src/Gateways/Gateway.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\GatewayInterface;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
|
||||
/**
|
||||
* Class Gateway.
|
||||
*/
|
||||
abstract class Gateway implements GatewayInterface
|
||||
{
|
||||
const DEFAULT_TIMEOUT = 5.0;
|
||||
|
||||
/**
|
||||
* @var \Overtrue\EasySms\Support\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $timeout;
|
||||
|
||||
/**
|
||||
* Gateway constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->config = new Config($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return timeout.
|
||||
*
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->timeout ?: $this->config->get('timeout', self::DEFAULT_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timeout.
|
||||
*
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTimeout($timeout)
|
||||
{
|
||||
$this->timeout = floatval($timeout);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Overtrue\EasySms\Support\Config
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setConfig(Config $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return \strtolower(str_replace([__NAMESPACE__.'\\', 'Gateway'], '', \get_class($this)));
|
||||
}
|
||||
}
|
||||
73
vendor/overtrue/easy-sms/src/Gateways/HuaxinGateway.php
vendored
Normal file
73
vendor/overtrue/easy-sms/src/Gateways/HuaxinGateway.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class HuaxinGateway.
|
||||
*
|
||||
* @see http://www.ipyy.com/help/
|
||||
*/
|
||||
class HuaxinGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'http://%s/smsJson.aspx';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint($config->get('ip'));
|
||||
|
||||
$result = $this->post($endpoint, [
|
||||
'userid' => $config->get('user_id'),
|
||||
'account' => $config->get('account'),
|
||||
'password' => $config->get('password'),
|
||||
'mobile' => $to->getNumber(),
|
||||
'content' => $message->getContent($this),
|
||||
'sendTime' => '',
|
||||
'action' => 'send',
|
||||
'extno' => $config->get('ext_no'),
|
||||
]);
|
||||
|
||||
if ('Success' !== $result['returnstatus']) {
|
||||
throw new GatewayErrorException($result['message'], 400, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $ip
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($ip)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $ip);
|
||||
}
|
||||
}
|
||||
76
vendor/overtrue/easy-sms/src/Gateways/HuyiGateway.php
vendored
Normal file
76
vendor/overtrue/easy-sms/src/Gateways/HuyiGateway.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class HuyiGateway.
|
||||
*
|
||||
* @see http://www.ihuyi.com/api/sms.html
|
||||
*/
|
||||
class HuyiGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://106.ihuyi.com/webservice/sms.php?method=Submit';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
const SUCCESS_CODE = 2;
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'account' => $config->get('api_id'),
|
||||
'mobile' => $to->getIDDCode() ? \sprintf('%s %s', $to->getIDDCode(), $to->getNumber()) : $to->getNumber(),
|
||||
'content' => $message->getContent($this),
|
||||
'time' => time(),
|
||||
'format' => self::ENDPOINT_FORMAT,
|
||||
];
|
||||
|
||||
$params['password'] = $this->generateSign($params);
|
||||
|
||||
$result = $this->post(self::ENDPOINT_URL, $params);
|
||||
|
||||
if (self::SUCCESS_CODE != $result['code']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params)
|
||||
{
|
||||
return md5($params['account'].$this->config->get('api_key').$params['mobile'].$params['content'].$params['time']);
|
||||
}
|
||||
}
|
||||
76
vendor/overtrue/easy-sms/src/Gateways/JuheGateway.php
vendored
Normal file
76
vendor/overtrue/easy-sms/src/Gateways/JuheGateway.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class JuheGateway.
|
||||
*
|
||||
* @see https://www.juhe.cn/docs/api/id/54
|
||||
*/
|
||||
class JuheGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://v.juhe.cn/sms/send';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'mobile' => $to->getNumber(),
|
||||
'tpl_id' => $message->getTemplate($this),
|
||||
'tpl_value' => $this->formatTemplateVars($message->getData($this)),
|
||||
'dtype' => self::ENDPOINT_FORMAT,
|
||||
'key' => $config->get('app_key'),
|
||||
];
|
||||
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
|
||||
if ($result['error_code']) {
|
||||
throw new GatewayErrorException($result['reason'], $result['error_code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $vars
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatTemplateVars(array $vars)
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
foreach ($vars as $key => $value) {
|
||||
$formatted[sprintf('#%s#', trim($key, '#'))] = $value;
|
||||
}
|
||||
|
||||
return http_build_query($formatted);
|
||||
}
|
||||
}
|
||||
74
vendor/overtrue/easy-sms/src/Gateways/LuosimaoGateway.php
vendored
Normal file
74
vendor/overtrue/easy-sms/src/Gateways/LuosimaoGateway.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class LuosimaoGateway.
|
||||
*
|
||||
* @see https://luosimao.com/docs/api/
|
||||
*/
|
||||
class LuosimaoGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://%s.luosimao.com/%s/%s.%s';
|
||||
|
||||
const ENDPOINT_VERSION = 'v1';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint('sms-api', 'send');
|
||||
|
||||
$result = $this->post($endpoint, [
|
||||
'mobile' => $to->getNumber(),
|
||||
'message' => $message->getContent($this),
|
||||
], [
|
||||
'Authorization' => 'Basic '.base64_encode('api:key-'.$config->get('api_key')),
|
||||
]);
|
||||
|
||||
if ($result['error']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['error'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($type, $function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $type, self::ENDPOINT_VERSION, $function, self::ENDPOINT_FORMAT);
|
||||
}
|
||||
}
|
||||
104
vendor/overtrue/easy-sms/src/Gateways/QcloudGateway.php
vendored
Normal file
104
vendor/overtrue/easy-sms/src/Gateways/QcloudGateway.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class QcloudGateway.
|
||||
*
|
||||
* @see https://cloud.tencent.com/document/product/382/13297
|
||||
*/
|
||||
class QcloudGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://yun.tim.qq.com/v5/';
|
||||
|
||||
const ENDPOINT_METHOD = 'tlssmssvr/sendsms';
|
||||
|
||||
const ENDPOINT_VERSION = 'v5';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$type = !empty($message->getData($this)['type']) ? $message->getData($this)['type'] : 0;
|
||||
$params = [
|
||||
'tel' => [
|
||||
'nationcode' => $to->getIDDCode() ?: 86,
|
||||
'mobile' => $to->getNumber(),
|
||||
],
|
||||
'type' => $type,
|
||||
'msg' => $message->getContent($this),
|
||||
'time' => time(),
|
||||
'extend' => '',
|
||||
'ext' => '',
|
||||
];
|
||||
if (!is_null($message->getTemplate($this)) && is_array($message->getData($this))) {
|
||||
unset($params['msg']);
|
||||
$params['params'] = array_values($message->getData($this));
|
||||
$params['tpl_id'] = $message->getTemplate($this);
|
||||
$params['sign'] = $config->get('sign_name') ? $config->get('sign_name') : '';
|
||||
}
|
||||
$random = substr(uniqid(), -10);
|
||||
|
||||
$params['sig'] = $this->generateSign($params, $random);
|
||||
|
||||
$url = self::ENDPOINT_URL.self::ENDPOINT_METHOD.'?sdkappid='.$config->get('sdk_app_id').'&random='.$random;
|
||||
|
||||
$result = $this->request('post', $url, [
|
||||
'headers' => ['Accept' => 'application/json'],
|
||||
'json' => $params,
|
||||
]);
|
||||
|
||||
if (0 != $result['result']) {
|
||||
throw new GatewayErrorException($result['errmsg'], $result['result'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
* @param string $random
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params, $random)
|
||||
{
|
||||
ksort($params);
|
||||
|
||||
return hash('sha256', sprintf(
|
||||
'appkey=%s&random=%s&time=%s&mobile=%s',
|
||||
$this->config->get('app_key'),
|
||||
$random,
|
||||
$params['time'],
|
||||
$params['tel']['mobile']
|
||||
), false);
|
||||
}
|
||||
}
|
||||
134
vendor/overtrue/easy-sms/src/Gateways/RongcloudGateway.php
vendored
Normal file
134
vendor/overtrue/easy-sms/src/Gateways/RongcloudGateway.php
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class RongcloudGateway.
|
||||
*
|
||||
* @author Darren Gao <realgaodacheng@gmail.com>
|
||||
*
|
||||
* @see http://www.rongcloud.cn/docs/sms_service.html#send_sms_code
|
||||
*/
|
||||
class RongcloudGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'http://api.sms.ronghub.com/%s.%s';
|
||||
|
||||
const ENDPOINT_ACTION = 'sendCode';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
const ENDPOINT_REGION = '86'; // 中国区,目前只支持此国别
|
||||
|
||||
const SUCCESS_CODE = 200;
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData();
|
||||
$action = array_key_exists('action', $data) ? $data['action'] : self::ENDPOINT_ACTION;
|
||||
$endpoint = $this->buildEndpoint($action);
|
||||
|
||||
$headers = [
|
||||
'Nonce' => uniqid(),
|
||||
'App-Key' => $config->get('app_key'),
|
||||
'Timestamp' => time(),
|
||||
];
|
||||
$headers['Signature'] = $this->generateSign($headers, $config);
|
||||
|
||||
switch ($action) {
|
||||
case 'sendCode':
|
||||
$params = [
|
||||
'mobile' => $to->getNumber(),
|
||||
'region' => self::ENDPOINT_REGION,
|
||||
'templateId' => $message->getTemplate($this),
|
||||
];
|
||||
|
||||
break;
|
||||
case 'verifyCode':
|
||||
if (!array_key_exists('code', $data)
|
||||
or !array_key_exists('sessionId', $data)) {
|
||||
throw new GatewayErrorException('"code" or "sessionId" is not set', 0);
|
||||
}
|
||||
$params = [
|
||||
'code' => $data['code'],
|
||||
'sessionId' => $data['sessionId'],
|
||||
];
|
||||
|
||||
break;
|
||||
case 'sendNotify':
|
||||
$params = [
|
||||
'mobile' => $to->getNumber(),
|
||||
'region' => self::ENDPOINT_REGION,
|
||||
'templateId' => $message->getTemplate($this),
|
||||
];
|
||||
$params = array_merge($params, $data);
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new GatewayErrorException(sprintf('action: %s not supported', $action));
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->post($endpoint, $params, $headers);
|
||||
|
||||
if (self::SUCCESS_CODE !== $result['code']) {
|
||||
throw new GatewayErrorException($result['errorMessage'], $result['code'], $result);
|
||||
}
|
||||
} catch (ClientException $e) {
|
||||
throw new GatewayErrorException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params, Config $config)
|
||||
{
|
||||
return sha1(sprintf('%s%s%s', $config->get('app_secret'), $params['Nonce'], $params['Timestamp']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $action
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($action)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $action, self::ENDPOINT_FORMAT);
|
||||
}
|
||||
}
|
||||
95
vendor/overtrue/easy-sms/src/Gateways/SendcloudGateway.php
vendored
Normal file
95
vendor/overtrue/easy-sms/src/Gateways/SendcloudGateway.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class SendcloudGateway.
|
||||
*
|
||||
* @see http://sendcloud.sohu.com/doc/sms/
|
||||
*/
|
||||
class SendcloudGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'http://www.sendcloud.net/smsapi/%s';
|
||||
|
||||
/**
|
||||
* Send a short message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'smsUser' => $config->get('sms_user'),
|
||||
'templateId' => $message->getTemplate($this),
|
||||
'msgType' => $to->getIDDCode() ? 2 : 0,
|
||||
'phone' => $to->getNumber(),
|
||||
'vars' => $this->formatTemplateVars($message->getData($this)),
|
||||
];
|
||||
|
||||
if ($config->get('timestamp', false)) {
|
||||
$params['timestamp'] = time() * 1000;
|
||||
}
|
||||
|
||||
$params['signature'] = $this->sign($params, $config->get('sms_key'));
|
||||
|
||||
$result = $this->post(sprintf(self::ENDPOINT_TEMPLATE, 'send'), $params);
|
||||
|
||||
if (!$result['result']) {
|
||||
throw new GatewayErrorException($result['message'], $result['statusCode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $vars
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatTemplateVars(array $vars)
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
foreach ($vars as $key => $value) {
|
||||
$formatted[sprintf('%%%s%%', trim($key, '%'))] = $value;
|
||||
}
|
||||
|
||||
return json_encode($formatted, JSON_FORCE_OBJECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sign($params, $key)
|
||||
{
|
||||
ksort($params);
|
||||
|
||||
return md5(sprintf('%s&%s&%s', $key, urldecode(http_build_query($params)), $key));
|
||||
}
|
||||
}
|
||||
74
vendor/overtrue/easy-sms/src/Gateways/SubmailGateway.php
vendored
Normal file
74
vendor/overtrue/easy-sms/src/Gateways/SubmailGateway.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class SubmailGateway.
|
||||
*
|
||||
* @see https://www.mysubmail.com/chs/documents/developer/index
|
||||
*/
|
||||
class SubmailGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://api.mysubmail.com/%s.%s';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint($to->getIDDCode() ? 'internationalsms/xsend' : 'message/xsend');
|
||||
|
||||
$data = $message->getData($this);
|
||||
|
||||
$result = $this->post($endpoint, [
|
||||
'appid' => $config->get('app_id'),
|
||||
'signature' => $config->get('app_key'),
|
||||
'project' => !empty($data['project']) ? $data['project'] : $config->get('project'),
|
||||
'to' => $to->getUniversalNumber(),
|
||||
'vars' => json_encode($data, JSON_FORCE_OBJECT),
|
||||
]);
|
||||
|
||||
if ('success' != $result['status']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $function, self::ENDPOINT_FORMAT);
|
||||
}
|
||||
}
|
||||
84
vendor/overtrue/easy-sms/src/Gateways/TianyiwuxianGateway.php
vendored
Normal file
84
vendor/overtrue/easy-sms/src/Gateways/TianyiwuxianGateway.php
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class TianyiwuxianGateway.
|
||||
*
|
||||
* @author Darren Gao <realgaodacheng@gmail.com>
|
||||
*/
|
||||
class TianyiwuxianGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'http://jk.106api.cn/sms%s.aspx';
|
||||
|
||||
const ENDPOINT_ENCODE = 'UTF8';
|
||||
|
||||
const ENDPOINT_TYPE = 'send';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
const SUCCESS_STATUS = 'success';
|
||||
|
||||
const SUCCESS_CODE = '0';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint();
|
||||
|
||||
$params = [
|
||||
'gwid' => $config->get('gwid'),
|
||||
'type' => self::ENDPOINT_TYPE,
|
||||
'rece' => self::ENDPOINT_FORMAT,
|
||||
'mobile' => $to->getNumber(),
|
||||
'message' => $message->getContent($this),
|
||||
'username' => $config->get('username'),
|
||||
'password' => strtoupper(md5($config->get('password'))),
|
||||
];
|
||||
|
||||
$result = $this->post($endpoint, $params);
|
||||
|
||||
$result = json_decode($result, true);
|
||||
|
||||
if (self::SUCCESS_STATUS !== $result['returnstatus'] || self::SUCCESS_CODE !== $result['code']) {
|
||||
throw new GatewayErrorException($result['remark'], $result['code']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint()
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, self::ENDPOINT_ENCODE);
|
||||
}
|
||||
}
|
||||
91
vendor/overtrue/easy-sms/src/Gateways/TwilioGateway.php
vendored
Normal file
91
vendor/overtrue/easy-sms/src/Gateways/TwilioGateway.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class TwilioGateway.
|
||||
*
|
||||
* @see https://www.twilio.com/docs/api/messaging/send-messages
|
||||
*/
|
||||
class TwilioGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json';
|
||||
|
||||
protected $errorStatuses = [
|
||||
'failed',
|
||||
'undelivered',
|
||||
];
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'twilio';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$accountSid = $config->get('account_sid');
|
||||
$endpoint = $this->buildEndPoint($accountSid);
|
||||
|
||||
$params = [
|
||||
'To' => $to->getUniversalNumber(),
|
||||
'From' => $config->get('from'),
|
||||
'Body' => $message->getContent($this),
|
||||
];
|
||||
|
||||
try {
|
||||
$result = $this->request('post', $endpoint, [
|
||||
'auth' => [
|
||||
$accountSid,
|
||||
$config->get('token'),
|
||||
],
|
||||
'form_params' => $params,
|
||||
]);
|
||||
if (in_array($result['status'], $this->errorStatuses) || !is_null($result['error_code'])) {
|
||||
throw new GatewayErrorException($result['message'], $result['error_code'], $result);
|
||||
}
|
||||
} catch (ClientException $e) {
|
||||
throw new GatewayErrorException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* build endpoint url.
|
||||
*
|
||||
* @param string $accountSid
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndPoint($accountSid)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_URL, $accountSid);
|
||||
}
|
||||
}
|
||||
77
vendor/overtrue/easy-sms/src/Gateways/YunpianGateway.php
vendored
Normal file
77
vendor/overtrue/easy-sms/src/Gateways/YunpianGateway.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class YunpianGateway.
|
||||
*
|
||||
* @see https://www.yunpian.com/doc/zh_CN/intl/single_send.html
|
||||
*/
|
||||
class YunpianGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://%s.yunpian.com/%s/%s/%s.%s';
|
||||
|
||||
const ENDPOINT_VERSION = 'v2';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint('sms', 'sms', 'single_send');
|
||||
|
||||
$result = $this->request('post', $endpoint, [
|
||||
'form_params' => [
|
||||
'apikey' => $config->get('api_key'),
|
||||
'mobile' => $to->getUniversalNumber(),
|
||||
'text' => $message->getContent($this),
|
||||
],
|
||||
'exceptions' => false,
|
||||
]);
|
||||
|
||||
if ($result['code']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $resource
|
||||
* @param string $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($type, $resource, $function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $type, self::ENDPOINT_VERSION, $resource, $function, self::ENDPOINT_FORMAT);
|
||||
}
|
||||
}
|
||||
99
vendor/overtrue/easy-sms/src/Gateways/YuntongxunGateway.php
vendored
Normal file
99
vendor/overtrue/easy-sms/src/Gateways/YuntongxunGateway.php
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class YuntongxunGateway.
|
||||
*
|
||||
* @see http://www.yuntongxun.com/doc/rest/sms/3_2_2_2.html
|
||||
*/
|
||||
class YuntongxunGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://%s:%s/%s/%s/%s/%s/%s?sig=%s';
|
||||
|
||||
const SERVER_IP = 'app.cloopen.com';
|
||||
|
||||
const DEBUG_SERVER_IP = 'sandboxapp.cloopen.com';
|
||||
|
||||
const DEBUG_TEMPLATE_ID = 1;
|
||||
|
||||
const SERVER_PORT = '8883';
|
||||
|
||||
const SDK_VERSION = '2013-12-26';
|
||||
|
||||
const SUCCESS_CODE = '000000';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$datetime = date('YmdHis');
|
||||
|
||||
$endpoint = $this->buildEndpoint('SMS', 'TemplateSMS', $datetime, $config);
|
||||
|
||||
$result = $this->request('post', $endpoint, [
|
||||
'json' => [
|
||||
'to' => $to,
|
||||
'templateId' => (int) ($this->config->get('debug') ? self::DEBUG_TEMPLATE_ID : $message->getTemplate($this)),
|
||||
'appId' => $config->get('app_id'),
|
||||
'datas' => $message->getData($this),
|
||||
],
|
||||
'headers' => [
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json;charset=utf-8',
|
||||
'Authorization' => base64_encode($config->get('account_sid').':'.$datetime),
|
||||
],
|
||||
]);
|
||||
|
||||
if (self::SUCCESS_CODE != $result['statusCode']) {
|
||||
throw new GatewayErrorException($result['statusCode'], $result['statusCode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $resource
|
||||
* @param string $datetime
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($type, $resource, $datetime, Config $config)
|
||||
{
|
||||
$serverIp = $this->config->get('debug') ? self::DEBUG_SERVER_IP : self::SERVER_IP;
|
||||
|
||||
$accountType = $this->config->get('is_sub_account') ? 'SubAccounts' : 'Accounts';
|
||||
|
||||
$sig = strtoupper(md5($config->get('account_sid').$config->get('account_token').$datetime));
|
||||
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $serverIp, self::SERVER_PORT, self::SDK_VERSION, $accountType, $config->get('account_sid'), $type, $resource, $sig);
|
||||
}
|
||||
}
|
||||
187
vendor/overtrue/easy-sms/src/Message.php
vendored
Normal file
187
vendor/overtrue/easy-sms/src/Message.php
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms;
|
||||
|
||||
use Overtrue\EasySms\Contracts\GatewayInterface;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
|
||||
/**
|
||||
* Class Message.
|
||||
*/
|
||||
class Message implements MessageInterface
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $gateways = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $template;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Message constructor.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param string $type
|
||||
*/
|
||||
public function __construct(array $attributes = [], $type = MessageInterface::TEXT_MESSAGE)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
foreach ($attributes as $property => $value) {
|
||||
if (property_exists($this, $property)) {
|
||||
$this->$property = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the message type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMessageType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return message content.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(GatewayInterface $gateway = null)
|
||||
{
|
||||
return is_callable($this->content) ? call_user_func($this->content, $gateway) : $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the template id of message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate(GatewayInterface $gateway = null)
|
||||
{
|
||||
return is_callable($this->template) ? call_user_func($this->template, $gateway) : $this->template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setType(string $type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $content
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $template
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTemplate($template)
|
||||
{
|
||||
$this->template = $template;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getData(GatewayInterface $gateway = null)
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getGateways()
|
||||
{
|
||||
return $this->gateways;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGateways(array $gateways)
|
||||
{
|
||||
$this->gateways = $gateways;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $property
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __get($property)
|
||||
{
|
||||
if (property_exists($this, $property)) {
|
||||
return $this->$property;
|
||||
}
|
||||
}
|
||||
}
|
||||
89
vendor/overtrue/easy-sms/src/Messenger.php
vendored
Normal file
89
vendor/overtrue/easy-sms/src/Messenger.php
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;
|
||||
|
||||
/**
|
||||
* Class Messenger.
|
||||
*/
|
||||
class Messenger
|
||||
{
|
||||
const STATUS_SUCCESS = 'success';
|
||||
|
||||
const STATUS_FAILURE = 'failure';
|
||||
|
||||
/**
|
||||
* @var \Overtrue\EasySms\EasySms
|
||||
*/
|
||||
protected $easySms;
|
||||
|
||||
/**
|
||||
* Messenger constructor.
|
||||
*
|
||||
* @param \Overtrue\EasySms\EasySms $easySms
|
||||
*/
|
||||
public function __construct(EasySms $easySms)
|
||||
{
|
||||
$this->easySms = $easySms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\NoGatewayAvailableException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, array $gateways = [])
|
||||
{
|
||||
$results = [];
|
||||
$isSuccessful = false;
|
||||
|
||||
foreach ($gateways as $gateway => $config) {
|
||||
try {
|
||||
$results[$gateway] = [
|
||||
'gateway' => $gateway,
|
||||
'status' => self::STATUS_SUCCESS,
|
||||
'result' => $this->easySms->gateway($gateway)->send($to, $message, $config),
|
||||
];
|
||||
$isSuccessful = true;
|
||||
|
||||
break;
|
||||
} catch (\Exception $e) {
|
||||
$results[$gateway] = [
|
||||
'gateway' => $gateway,
|
||||
'status' => self::STATUS_FAILURE,
|
||||
'exception' => $e,
|
||||
];
|
||||
} catch (\Throwable $e) {
|
||||
$results[$gateway] = [
|
||||
'gateway' => $gateway,
|
||||
'status' => self::STATUS_FAILURE,
|
||||
'exception' => $e,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isSuccessful) {
|
||||
throw new NoGatewayAvailableException($results);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
115
vendor/overtrue/easy-sms/src/PhoneNumber.php
vendored
Normal file
115
vendor/overtrue/easy-sms/src/PhoneNumber.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms;
|
||||
|
||||
/**
|
||||
* Class PhoneNumberInterface.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class PhoneNumber implements \Overtrue\EasySms\Contracts\PhoneNumberInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $number;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $IDDCode;
|
||||
|
||||
/**
|
||||
* PhoneNumberInterface constructor.
|
||||
*
|
||||
* @param int $numberWithoutIDDCode
|
||||
* @param string $IDDCode
|
||||
*/
|
||||
public function __construct($numberWithoutIDDCode, $IDDCode = null)
|
||||
{
|
||||
$this->number = $numberWithoutIDDCode;
|
||||
$this->IDDCode = $IDDCode ? intval(ltrim($IDDCode, '+0')) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 86.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getIDDCode()
|
||||
{
|
||||
return $this->IDDCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 18888888888.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNumber()
|
||||
{
|
||||
return $this->number;
|
||||
}
|
||||
|
||||
/**
|
||||
* +8618888888888.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUniversalNumber()
|
||||
{
|
||||
return $this->getPrefixedIDDCode('+').$this->number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 008618888888888.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getZeroPrefixedNumber()
|
||||
{
|
||||
return $this->getPrefixedIDDCode('00').$this->number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getPrefixedIDDCode($prefix)
|
||||
{
|
||||
return $this->IDDCode ? $prefix.$this->IDDCode : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getUniversalNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify data which should be serialized to JSON.
|
||||
*
|
||||
* @see http://php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
*
|
||||
* @return mixed data which can be serialized by <b>json_encode</b>,
|
||||
* which is a value of any type other than a resource
|
||||
*
|
||||
* @since 5.4.0
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->getUniversalNumber();
|
||||
}
|
||||
}
|
||||
32
vendor/overtrue/easy-sms/src/Strategies/OrderStrategy.php
vendored
Normal file
32
vendor/overtrue/easy-sms/src/Strategies/OrderStrategy.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Strategies;
|
||||
|
||||
use Overtrue\EasySms\Contracts\StrategyInterface;
|
||||
|
||||
/**
|
||||
* Class OrderStrategy.
|
||||
*/
|
||||
class OrderStrategy implements StrategyInterface
|
||||
{
|
||||
/**
|
||||
* Apply the strategy and return result.
|
||||
*
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply(array $gateways)
|
||||
{
|
||||
return array_keys($gateways);
|
||||
}
|
||||
}
|
||||
34
vendor/overtrue/easy-sms/src/Strategies/RandomStrategy.php
vendored
Normal file
34
vendor/overtrue/easy-sms/src/Strategies/RandomStrategy.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Strategies;
|
||||
|
||||
use Overtrue\EasySms\Contracts\StrategyInterface;
|
||||
|
||||
/**
|
||||
* Class RandomStrategy.
|
||||
*/
|
||||
class RandomStrategy implements StrategyInterface
|
||||
{
|
||||
/**
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply(array $gateways)
|
||||
{
|
||||
uasort($gateways, function () {
|
||||
return mt_rand() - mt_rand();
|
||||
});
|
||||
|
||||
return array_keys($gateways);
|
||||
}
|
||||
}
|
||||
147
vendor/overtrue/easy-sms/src/Support/Config.php
vendored
Normal file
147
vendor/overtrue/easy-sms/src/Support/Config.php
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Support;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
/**
|
||||
* Class Config.
|
||||
*/
|
||||
class Config implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Config constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from an array using "dot" notation.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$config = $this->config;
|
||||
|
||||
if (is_null($key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($config[$key])) {
|
||||
return $config[$key];
|
||||
}
|
||||
|
||||
if (false === strpos($key, '.')) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
foreach (explode('.', $key) as $segment) {
|
||||
if (!is_array($config) || !array_key_exists($segment, $config)) {
|
||||
return $default;
|
||||
}
|
||||
$config = $config[$segment];
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a offset exists.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetexists.php
|
||||
*
|
||||
* @param mixed $offset <p>
|
||||
* An offset to check for.
|
||||
* </p>
|
||||
*
|
||||
* @return bool true on success or false on failure.
|
||||
* </p>
|
||||
* <p>
|
||||
* The return value will be casted to boolean if non-boolean was returned
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return array_key_exists($offset, $this->config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to retrieve.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetget.php
|
||||
*
|
||||
* @param mixed $offset <p>
|
||||
* The offset to retrieve.
|
||||
* </p>
|
||||
*
|
||||
* @return mixed Can return all value types
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to set.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetset.php
|
||||
*
|
||||
* @param mixed $offset <p>
|
||||
* The offset to assign the value to.
|
||||
* </p>
|
||||
* @param mixed $value <p>
|
||||
* The value to set.
|
||||
* </p>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (isset($this->config[$offset])) {
|
||||
$this->config[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to unset.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetunset.php
|
||||
*
|
||||
* @param mixed $offset <p>
|
||||
* The offset to unset.
|
||||
* </p>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
if (isset($this->config[$offset])) {
|
||||
unset($this->config[$offset]);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
vendor/overtrue/easy-sms/src/Traits/HasHttpRequest.php
vendored
Normal file
136
vendor/overtrue/easy-sms/src/Traits/HasHttpRequest.php
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Traits;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Trait HasHttpRequest.
|
||||
*/
|
||||
trait HasHttpRequest
|
||||
{
|
||||
/**
|
||||
* Make a get request.
|
||||
*
|
||||
* @param string $endpoint
|
||||
* @param array $query
|
||||
* @param array $headers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get($endpoint, $query = [], $headers = [])
|
||||
{
|
||||
return $this->request('get', $endpoint, [
|
||||
'headers' => $headers,
|
||||
'query' => $query,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a post request.
|
||||
*
|
||||
* @param string $endpoint
|
||||
* @param array $params
|
||||
* @param array $headers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function post($endpoint, $params = [], $headers = [])
|
||||
{
|
||||
return $this->request('post', $endpoint, [
|
||||
'headers' => $headers,
|
||||
'form_params' => $params,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a post request with json params.
|
||||
*
|
||||
* @param $endpoint
|
||||
* @param array $params
|
||||
* @param array $headers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function postJson($endpoint, $params = [], $headers = [])
|
||||
{
|
||||
return $this->request('post', $endpoint, [
|
||||
'headers' => $headers,
|
||||
'json' => $params,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a http request.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $endpoint
|
||||
* @param array $options http://docs.guzzlephp.org/en/latest/request-options.html
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function request($method, $endpoint, $options = [])
|
||||
{
|
||||
return $this->unwrapResponse($this->getHttpClient($this->getBaseOptions())->{$method}($endpoint, $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return base Guzzle options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getBaseOptions()
|
||||
{
|
||||
$options = [
|
||||
'base_uri' => method_exists($this, 'getBaseUri') ? $this->getBaseUri() : '',
|
||||
'timeout' => method_exists($this, 'getTimeout') ? $this->getTimeout() : 5.0,
|
||||
];
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return http client.
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return \GuzzleHttp\Client
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function getHttpClient(array $options = [])
|
||||
{
|
||||
return new Client($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert response contents to json.
|
||||
*
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
*
|
||||
* @return ResponseInterface|array|string
|
||||
*/
|
||||
protected function unwrapResponse(ResponseInterface $response)
|
||||
{
|
||||
$contentType = $response->getHeaderLine('Content-Type');
|
||||
$contents = $response->getBody()->getContents();
|
||||
|
||||
if (false !== stripos($contentType, 'json') || stripos($contentType, 'javascript')) {
|
||||
return json_decode($contents, true);
|
||||
} elseif (false !== stripos($contentType, 'xml')) {
|
||||
return json_decode(json_encode(simplexml_load_string($contents)), true);
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
}
|
||||
5
vendor/overtrue/laravel-follow/.gitignore
vendored
Normal file
5
vendor/overtrue/laravel-follow/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.idea
|
||||
/vendor/
|
||||
composer.lock
|
||||
.php_cs.cache
|
||||
/coverage/
|
||||
29
vendor/overtrue/laravel-follow/.php_cs
vendored
Normal file
29
vendor/overtrue/laravel-follow/.php_cs
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
$header = <<<EOF
|
||||
This file is part of the overtrue/laravel-follow.
|
||||
|
||||
(c) overtrue <i@overtrue.me>
|
||||
|
||||
This source file is subject to the MIT license that is bundled
|
||||
with this source code in the file LICENSE.
|
||||
EOF;
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setRiskyAllowed(true)
|
||||
->setRules(array(
|
||||
'header_comment' => array('header' => $header),
|
||||
'array_syntax' => array('syntax' => 'short'),
|
||||
'ordered_class_elements' => true,
|
||||
'list_syntax' => array('syntax' => 'long'),
|
||||
'ordered_imports' => true,
|
||||
'php_unit_strict' => true,
|
||||
'phpdoc_order' => true,
|
||||
'strict_comparison' => true,
|
||||
'strict_param' => true,
|
||||
))
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->in(__DIR__.'/src')
|
||||
)
|
||||
;
|
||||
13
vendor/overtrue/laravel-follow/.travis.yml
vendored
Normal file
13
vendor/overtrue/laravel-follow/.travis.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
install: travis_retry composer install --no-interaction --prefer-source
|
||||
|
||||
script: vendor/bin/phpunit --verbose
|
||||
23
vendor/overtrue/laravel-follow/LICENSE
vendored
Normal file
23
vendor/overtrue/laravel-follow/LICENSE
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 overtrue <i@overtrue.me>
|
||||
Copyright (c) 2016 Mohammed Isa <mohd.itcs@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
327
vendor/overtrue/laravel-follow/README.md
vendored
Normal file
327
vendor/overtrue/laravel-follow/README.md
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
<h1 align="center">Laravel 5 Follow System</h1>
|
||||
|
||||
<p align="center">:heart: This package helps you to add user based follow system to your model.</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/overtrue/laravel-follow"><img src="https://travis-ci.org/overtrue/laravel-follow.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/laravel-follow"><img src="https://poser.pugx.org/overtrue/laravel-follow/v/stable.svg" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/laravel-follow"><img src="https://poser.pugx.org/overtrue/laravel-follow/v/unstable.svg" alt="Latest Unstable Version"></a>
|
||||
<a href="https://scrutinizer-ci.com/g/overtrue/laravel-follow/build-status/master"><img src="https://scrutinizer-ci.com/g/overtrue/laravel-follow/badges/build.png?b=master" alt="Build Status"></a>
|
||||
<a href="https://scrutinizer-ci.com/g/overtrue/laravel-follow/?branch=master"><img src="https://scrutinizer-ci.com/g/overtrue/laravel-follow/badges/quality-score.png?b=master" alt="Scrutinizer Code Quality"></a>
|
||||
<a href="https://scrutinizer-ci.com/g/overtrue/laravel-follow/?branch=master"><img src="https://scrutinizer-ci.com/g/overtrue/laravel-follow/badges/coverage.png?b=master" alt="Code Coverage"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/laravel-follow"><img src="https://poser.pugx.org/overtrue/laravel-follow/downloads" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/laravel-follow"><img src="https://poser.pugx.org/overtrue/laravel-follow/license" alt="License"></a>
|
||||
</p>
|
||||
|
||||
## Features
|
||||
|
||||
- Support actions:
|
||||
- Follow
|
||||
- Like
|
||||
- Bookmark
|
||||
- Subscribe
|
||||
- Favorite
|
||||
- Vote (Upvote & Downvote)
|
||||
|
||||
## Installation
|
||||
|
||||
### Required
|
||||
|
||||
- PHP 7.0 +
|
||||
- Laravel 5.5 +
|
||||
|
||||
You can install the package using composer
|
||||
|
||||
```sh
|
||||
$ composer require overtrue/laravel-follow -vvv
|
||||
```
|
||||
|
||||
Then add the service provider to `config/app.php`
|
||||
|
||||
```php
|
||||
Overtrue\LaravelFollow\FollowServiceProvider::class
|
||||
```
|
||||
|
||||
Publish the migrations file:
|
||||
|
||||
```sh
|
||||
$ php artisan vendor:publish --provider='Overtrue\LaravelFollow\FollowServiceProvider' --tag="migrations"
|
||||
```
|
||||
|
||||
As optional if you want to modify the default configuration, you can publish the configuration file:
|
||||
|
||||
```sh
|
||||
$ php artisan vendor:publish --provider='Overtrue\LaravelFollow\FollowServiceProvider' --tag="config"
|
||||
```
|
||||
|
||||
And create tables:
|
||||
|
||||
```php
|
||||
$ php artisan migrate
|
||||
```
|
||||
|
||||
Finally, add feature trait into User model:
|
||||
|
||||
```php
|
||||
use Overtrue\LaravelFollow\Traits\CanFollow;
|
||||
use Overtrue\LaravelFollow\Traits\CanBeFollowed;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
use CanFollow, CanBeFollowed;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Add `CanXXX` Traits to User model.
|
||||
|
||||
```php
|
||||
use Overtrue\LaravelFollow\Traits\CanFollow;
|
||||
use Overtrue\LaravelFollow\Traits\CanLike;
|
||||
use Overtrue\LaravelFollow\Traits\CanFavorite;
|
||||
use Overtrue\LaravelFollow\Traits\CanSubscribe;
|
||||
use Overtrue\LaravelFollow\Traits\CanVote;
|
||||
use Overtrue\LaravelFollow\Traits\CanBookmark;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
use CanFollow, CanBookmark, CanLike, CanFavorite, CanSubscribe, CanVote;
|
||||
}
|
||||
```
|
||||
|
||||
Add `CanBeXXX` Trait to target model, such as 'Post' or 'Music' ...:
|
||||
|
||||
```php
|
||||
use Overtrue\LaravelFollow\Traits\CanBeLiked;
|
||||
use Overtrue\LaravelFollow\Traits\CanBeFavorited;
|
||||
use Overtrue\LaravelFollow\Traits\CanBeVoted;
|
||||
use Overtrue\LaravelFollow\Traits\CanBeBookmarked;
|
||||
|
||||
class Post extends Model
|
||||
{
|
||||
use CanBeLiked, CanBeFavorited, CanBeVoted, CanBeBookmarked;
|
||||
}
|
||||
```
|
||||
|
||||
All available APIs are listed below.
|
||||
|
||||
### Follow
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanFollow`
|
||||
|
||||
```php
|
||||
$user->follow($targets)
|
||||
$user->unfollow($targets)
|
||||
$user->toggleFollow($targets)
|
||||
$user->followings()->get() // App\User:class
|
||||
$user->followings(App\Post::class)->get()
|
||||
$user->areFollowingEachOther($anotherUser);
|
||||
$user->isFollowing($target)
|
||||
```
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanBeFollowed`
|
||||
|
||||
```php
|
||||
$object->followers()->get()
|
||||
$object->isFollowedBy($user)
|
||||
```
|
||||
|
||||
### Bookmark
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanBookmark`
|
||||
|
||||
```php
|
||||
$user->bookmark($targets)
|
||||
$user->unbookmark($targets)
|
||||
$user->toggleBookmark($targets)
|
||||
$user->hasBookmarked($target)
|
||||
$user->bookmarks()->get() // App\User:class
|
||||
$user->bookmarks(App\Post::class)->get()
|
||||
```
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanBeBookmarked`
|
||||
|
||||
```php
|
||||
$object->bookmarkers()->get() // or $object->bookmarkers
|
||||
$object->isBookmarkedBy($user)
|
||||
```
|
||||
|
||||
### Like
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanLike`
|
||||
|
||||
```php
|
||||
$user->like($targets)
|
||||
$user->unlike($targets)
|
||||
$user->toggleLike($targets)
|
||||
$user->hasLiked($target)
|
||||
$user->likes()->get() // default object: App\User:class
|
||||
$user->likes(App\Post::class)->get()
|
||||
```
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanBeLiked`
|
||||
|
||||
```php
|
||||
$object->likers()->get() // or $object->likers
|
||||
$object->fans()->get() // or $object->fans
|
||||
$object->isLikedBy($user)
|
||||
```
|
||||
|
||||
### Favorite
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanFavorite`
|
||||
|
||||
```php
|
||||
$user->favorite($targets)
|
||||
$user->unfavorite($targets)
|
||||
$user->toggleFavorite($targets)
|
||||
$user->hasFavorited($target)
|
||||
$user->favorites()->get() // App\User:class
|
||||
$user->favorites(App\Post::class)->get()
|
||||
```
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanBeFavorited`
|
||||
|
||||
```php
|
||||
$object->favoriters()->get() // or $object->favoriters
|
||||
$object->isFavoritedBy($user)
|
||||
```
|
||||
|
||||
### Subscribe
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanSubscribe`
|
||||
|
||||
```php
|
||||
$user->subscribe($targets)
|
||||
$user->unsubscribe($targets)
|
||||
$user->toggleSubscribe($targets)
|
||||
$user->hasSubscribed($target)
|
||||
$user->subscriptions()->get() // default object: App\User:class
|
||||
$user->subscriptions(App\Post::class)->get()
|
||||
```
|
||||
|
||||
#### `Overtrue\LaravelFollow\Traits\CanBeSubscribed`
|
||||
|
||||
```php
|
||||
$object->subscribers() // or $object->subscribers
|
||||
$object->isSubscribedBy($user)
|
||||
```
|
||||
|
||||
### Vote
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanVote`
|
||||
|
||||
```php
|
||||
$user->vote($target) // Vote with 'upvote' for default
|
||||
$user->upvote($target)
|
||||
$user->downvote($target)
|
||||
$user->cancelVote($target)
|
||||
$user->hasUpvoted($target)
|
||||
$user->hasDownvoted($target)
|
||||
$user->votes(App\Post::class)->get()
|
||||
$user->upvotes(App\Post::class)->get()
|
||||
$user->downvotes(App\Post::class)->get()
|
||||
```
|
||||
|
||||
#### `\Overtrue\LaravelFollow\Traits\CanBeVoted`
|
||||
|
||||
```php
|
||||
$object->voters()->get()
|
||||
$object->upvoters()->get()
|
||||
$object->downvoters()->get()
|
||||
$object->isVotedBy($user)
|
||||
$object->isUpvotedBy($user)
|
||||
$object->isDownvotedBy($user)
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
All of the above mentioned methods of creating relationships, such as 'follow', 'like', 'unfollow', 'unlike', their syntax is as follows:
|
||||
|
||||
```php
|
||||
follow(array|int|\Illuminate\Database\Eloquent\Model $targets, $class = __CLASS__)
|
||||
```
|
||||
|
||||
So you can call them like this:
|
||||
|
||||
```php
|
||||
// Id / Id array
|
||||
$user->follow(1); // targets: 1, $class = App\User
|
||||
$user->follow(1, App\Post::class); // targets: 1, $class = App\Post
|
||||
$user->follow([1, 2, 3]); // targets: [1, 2, 3], $class = App\User
|
||||
|
||||
// Model
|
||||
$post = App\Post::find(7);
|
||||
$user->follow($post); // targets: $post->id, $class = App\Post
|
||||
|
||||
// Model array
|
||||
$posts = App\Post::popular()->get();
|
||||
$user->follow($posts); // targets: [1, 2, ...], $class = App\Post
|
||||
```
|
||||
|
||||
### Query relations
|
||||
|
||||
```php
|
||||
$followers = $user->followers
|
||||
$followers = $user->followers()->where('id', '>', 10)->get()
|
||||
$followers = $user->followers()->orderByDesc('id')->get()
|
||||
```
|
||||
|
||||
The other is the same usage.
|
||||
|
||||
### Working with model.
|
||||
|
||||
```php
|
||||
use Overtrue\LaravelFollow\FollowRelation;
|
||||
|
||||
// get most popular object
|
||||
|
||||
// all types
|
||||
$relations = FollowRelation::popular()->get();
|
||||
|
||||
// followable_type = App\Post
|
||||
$relations = FollowRelation::popular(App\Post::class)->get();
|
||||
|
||||
// followable_type = App\User
|
||||
$relations = FollowRelation::popular('user')->get();
|
||||
|
||||
// followable_type = App\Post
|
||||
$relations = FollowRelation::popular('post')->get();
|
||||
|
||||
// Pagination
|
||||
$relations = FollowRelation::popular(App\Post::class)->paginate(15);
|
||||
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
- `Overtrue\LaravelFollow\RelationAttaching`
|
||||
- `Overtrue\LaravelFollow\RelationAttached`
|
||||
- `Overtrue\LaravelFollow\RelationDetaching`
|
||||
- `Overtrue\LaravelFollow\RelationDetached`
|
||||
- `Overtrue\LaravelFollow\RelationToggling`
|
||||
- `Overtrue\LaravelFollow\RelationToggled`
|
||||
|
||||
|
||||
```php
|
||||
Event::listen(\Overtrue\LaravelFollow\RelationAttached::class, function($event) {
|
||||
// $event->causer;
|
||||
// $event->getTargetsCollection();
|
||||
// $event->getRelationType();
|
||||
});
|
||||
```
|
||||
|
||||
# About toggled event.
|
||||
|
||||
There has a extra properties for `Overtrue\LaravelFollow\RelationToggled` event.
|
||||
|
||||
```php
|
||||
$event->results; // ['attached' => [1, 2, 3], 'detached' => [5, 6]]
|
||||
$event->attached; // [1, 2, 3]
|
||||
$event->detached; // [5, 6]
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
36
vendor/overtrue/laravel-follow/composer.json
vendored
Normal file
36
vendor/overtrue/laravel-follow/composer.json
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "overtrue/laravel-follow",
|
||||
"description": "Laravel 5 User Based System",
|
||||
"require": {
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/laravel": "~5.5",
|
||||
"phpunit/phpunit": "~5.0",
|
||||
"mockery/mockery": "1.0.x-dev"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"email": "i@overtrue.me"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Overtrue\\LaravelFollow\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Overtrue\\LaravelFollow\\Test\\": "tests"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Overtrue\\LaravelFollow\\FollowServiceProvider"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
52
vendor/overtrue/laravel-follow/config/follow.php
vendored
Normal file
52
vendor/overtrue/laravel-follow/config/follow.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
return [
|
||||
/*
|
||||
* Model class name of users.
|
||||
*/
|
||||
'user_model' => 'App\User',
|
||||
|
||||
/*
|
||||
* Table name of users table.
|
||||
*/
|
||||
'users_table_name' => 'users',
|
||||
|
||||
/*
|
||||
* Primary key of users table.
|
||||
*/
|
||||
'users_table_primary_key' => 'id',
|
||||
|
||||
/*
|
||||
* Foreign key of users table.
|
||||
*/
|
||||
'users_table_foreign_key' => 'user_id',
|
||||
|
||||
/*
|
||||
* Table name of followable relations.
|
||||
*/
|
||||
'followable_table' => 'followables',
|
||||
|
||||
/*
|
||||
* Prefix of many-to-many relation fields.
|
||||
*/
|
||||
'morph_prefix' => 'followable',
|
||||
|
||||
/*
|
||||
* Date format for created_at.
|
||||
*/
|
||||
'date_format' => 'Y-m-d H:i:s',
|
||||
|
||||
/*
|
||||
* Namespace of models.
|
||||
*/
|
||||
'model_namespace' => 'App',
|
||||
];
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateLaravelFollowTables extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create(config('follow.followable_table', 'followables'), function (Blueprint $table) {
|
||||
$userForeignKey = config('follow.users_table_foreign_key', 'user_id');
|
||||
$table->unsignedInteger($userForeignKey);
|
||||
$table->unsignedInteger('followable_id');
|
||||
$table->string('followable_type')->index();
|
||||
$table->string('relation')->default('follow')->comment('follow/like/subscribe/favorite/upvote/downvote');
|
||||
$table->softDeletes();
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign($userForeignKey)
|
||||
->references(config('follow.users_table_primary_key', 'id'))
|
||||
->on(config('follow.users_table_name', 'users'))
|
||||
->onUpdate('cascade')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table(config('follow.followable_table', 'followables'), function ($table) {
|
||||
$table->dropForeign(config('follow.followable_table', 'followables').'_user_id_foreign');
|
||||
});
|
||||
|
||||
Schema::drop(config('follow.followable_table', 'followables'));
|
||||
}
|
||||
}
|
||||
28
vendor/overtrue/laravel-follow/phpunit.xml
vendored
Normal file
28
vendor/overtrue/laravel-follow/phpunit.xml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="Follow Test Suite">
|
||||
<directory>./tests/</directory>
|
||||
<exclude>vendor</exclude>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src/</directory>
|
||||
<exclude>
|
||||
<directory>vendor/</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<php>
|
||||
<env name="APP_ENV" value="testing"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
62
vendor/overtrue/laravel-follow/src/Events/Event.php
vendored
Normal file
62
vendor/overtrue/laravel-follow/src/Events/Event.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Events;
|
||||
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Class Event.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class Event
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $causer;
|
||||
|
||||
public $relation;
|
||||
|
||||
public $targets;
|
||||
|
||||
public $class;
|
||||
|
||||
/**
|
||||
* Event constructor.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $causer
|
||||
* @param \Overtrue\LaravelFollow\Events\string $relation
|
||||
* @param int|array $targets
|
||||
* @param \Overtrue\LaravelFollow\Events\string $class
|
||||
*/
|
||||
public function __construct(Model $causer, string $relation, $targets, string $class)
|
||||
{
|
||||
$this->causer = $causer;
|
||||
$this->relation = $relation;
|
||||
$this->targets = $targets;
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
public function getRelationType()
|
||||
{
|
||||
return Follow::RELATION_TYPES[$this->relation];
|
||||
}
|
||||
|
||||
public function getTargetsCollection()
|
||||
{
|
||||
return \forward_static_call([$this->class, 'find'], (array) $this->targets);
|
||||
}
|
||||
}
|
||||
21
vendor/overtrue/laravel-follow/src/Events/RelationAttached.php
vendored
Normal file
21
vendor/overtrue/laravel-follow/src/Events/RelationAttached.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Events;
|
||||
|
||||
/**
|
||||
* Class RelationAttached.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class RelationAttached extends Event
|
||||
{
|
||||
}
|
||||
21
vendor/overtrue/laravel-follow/src/Events/RelationAttaching.php
vendored
Normal file
21
vendor/overtrue/laravel-follow/src/Events/RelationAttaching.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Events;
|
||||
|
||||
/**
|
||||
* Class RelationAttaching.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class RelationAttaching extends Event
|
||||
{
|
||||
}
|
||||
21
vendor/overtrue/laravel-follow/src/Events/RelationDetached.php
vendored
Normal file
21
vendor/overtrue/laravel-follow/src/Events/RelationDetached.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Events;
|
||||
|
||||
/**
|
||||
* Class RelationDetached.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class RelationDetached extends Event
|
||||
{
|
||||
}
|
||||
21
vendor/overtrue/laravel-follow/src/Events/RelationDetaching.php
vendored
Normal file
21
vendor/overtrue/laravel-follow/src/Events/RelationDetaching.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Events;
|
||||
|
||||
/**
|
||||
* Class RelationDetaching.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class RelationDetaching extends Event
|
||||
{
|
||||
}
|
||||
44
vendor/overtrue/laravel-follow/src/Events/RelationToggled.php
vendored
Normal file
44
vendor/overtrue/laravel-follow/src/Events/RelationToggled.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Events;
|
||||
|
||||
/**
|
||||
* Class RelationToggled.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class RelationToggled extends Event
|
||||
{
|
||||
public $results = [];
|
||||
|
||||
public $attached = [];
|
||||
|
||||
public $detached = [];
|
||||
|
||||
/**
|
||||
* RelationToggled constructor.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $causer
|
||||
* @param $relation
|
||||
* @param $targets
|
||||
* @param $class
|
||||
* @param array $results
|
||||
*/
|
||||
public function __construct(\Illuminate\Database\Eloquent\Model $causer, $relation, $targets, $class, array $results = [])
|
||||
{
|
||||
parent::__construct($causer, $relation, $targets, $class);
|
||||
|
||||
$this->results = $results;
|
||||
$this->attached = $results['attached'] ?? [];
|
||||
$this->detached = $results['detached'] ?? [];
|
||||
}
|
||||
}
|
||||
21
vendor/overtrue/laravel-follow/src/Events/RelationToggling.php
vendored
Normal file
21
vendor/overtrue/laravel-follow/src/Events/RelationToggling.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Events;
|
||||
|
||||
/**
|
||||
* Class RelationToggling.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class RelationToggling extends Event
|
||||
{
|
||||
}
|
||||
236
vendor/overtrue/laravel-follow/src/Follow.php
vendored
Normal file
236
vendor/overtrue/laravel-follow/src/Follow.php
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Overtrue\LaravelFollow\Events\RelationAttached;
|
||||
use Overtrue\LaravelFollow\Events\RelationAttaching;
|
||||
use Overtrue\LaravelFollow\Events\RelationDetached;
|
||||
use Overtrue\LaravelFollow\Events\RelationDetaching;
|
||||
use Overtrue\LaravelFollow\Events\RelationToggled;
|
||||
use Overtrue\LaravelFollow\Events\RelationToggling;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class Follow.
|
||||
*/
|
||||
class Follow
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
const RELATION_LIKE = 'like';
|
||||
|
||||
const RELATION_FOLLOW = 'follow';
|
||||
|
||||
const RELATION_BOOKMARK = 'bookmark';
|
||||
|
||||
const RELATION_SUBSCRIBE = 'subscribe';
|
||||
|
||||
const RELATION_FAVORITE = 'favorite';
|
||||
|
||||
const RELATION_UPVOTE = 'upvote';
|
||||
|
||||
const RELATION_DOWNVOTE = 'downvote';
|
||||
|
||||
const RELATION_TYPES = [
|
||||
'likes' => 'like',
|
||||
'likers' => 'like',
|
||||
'fans' => 'like',
|
||||
'followings' => 'follow',
|
||||
'followers' => 'follow',
|
||||
'favoriters' => 'favorite',
|
||||
'favorites' => 'favorite',
|
||||
'bookmarkers' => 'bookmark',
|
||||
'bookmarks' => 'bookmark',
|
||||
'subscriptions' => 'subscribe',
|
||||
'subscribers' => 'subscribe',
|
||||
'upvotes' => 'upvote',
|
||||
'upvoters' => 'upvote',
|
||||
'downvotes' => 'downvote',
|
||||
'downvoters' => 'downvote',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $relation
|
||||
* @param array|string|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRelationExists(Model $model, $relation, $target, $class = null)
|
||||
{
|
||||
$target = self::formatTargets($target, $class ?: config('follow.user_model'));
|
||||
|
||||
$relationKey = $class ? 'followable_id' : config('follow.users_table_foreign_key', 'user_id');
|
||||
|
||||
$relationKey = self::tablePrefixedField($relationKey);
|
||||
|
||||
if ($model->relationLoaded($relation)) {
|
||||
return $model->{$relation}->where($relationKey, head($target->ids))->isNotEmpty();
|
||||
}
|
||||
|
||||
return $model->{$relation}($target->classname)->where($relationKey, head($target->ids))->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $relation
|
||||
* @param array|string|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function attachRelations(Model $model, $relation, $targets, $class)
|
||||
{
|
||||
if (false === \event(new RelationAttaching($model, $relation, $targets, $class))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$targets = self::attachPivotsFromRelation($model->{$relation}(), $targets, $class);
|
||||
|
||||
if (false === \event(new RelationAttached($model, $relation, $targets, $class))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $model->{$relation}($targets->classname)->sync($targets->targets, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $relation
|
||||
* @param array|string|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function detachRelations(Model $model, $relation, $targets, $class)
|
||||
{
|
||||
if (false === \event(new RelationDetaching($model, $relation, $targets, $class))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$targets = self::formatTargets($targets, $class);
|
||||
|
||||
if (false === \event(new RelationDetached($model, $relation, $targets, $class))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $model->{$relation}($targets->classname)->detach($targets->ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $relation
|
||||
* @param array|string|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function toggleRelations(Model $model, $relation, $targets, $class)
|
||||
{
|
||||
if (false === \event(new RelationToggling($model, $relation, $targets, $class))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$targets = self::attachPivotsFromRelation($model->{$relation}(), $targets, $class);
|
||||
|
||||
$results = $model->{$relation}($targets->classname)->toggle($targets->targets);
|
||||
|
||||
if (false === \event(new RelationToggled($model, $relation, $targets, $class, $results))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphToMany $morph
|
||||
* @param array|string|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return \stdClass
|
||||
*/
|
||||
public static function attachPivotsFromRelation(MorphToMany $morph, $targets, $class)
|
||||
{
|
||||
return self::formatTargets($targets, $class, [
|
||||
'relation' => self::getRelationTypeFromRelation($morph),
|
||||
'created_at' => Carbon::now()->format(config('follow.date_format', 'Y-m-d H:i:s')),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $classname
|
||||
* @param array $update
|
||||
*
|
||||
* @return \stdClass
|
||||
*/
|
||||
public static function formatTargets($targets, $classname, array $update = [])
|
||||
{
|
||||
$result = new stdClass();
|
||||
$result->classname = $classname;
|
||||
|
||||
if (!is_array($targets)) {
|
||||
$targets = [$targets];
|
||||
}
|
||||
|
||||
$result->ids = array_map(function ($target) use ($result) {
|
||||
if ($target instanceof Model) {
|
||||
$result->classname = get_class($target);
|
||||
|
||||
return $target->getKey();
|
||||
}
|
||||
|
||||
return intval($target);
|
||||
}, $targets);
|
||||
|
||||
$result->targets = empty($update) ? $result->ids : array_combine($result->ids, array_pad([], count($result->ids), $update));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphToMany $relation
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function getRelationTypeFromRelation(MorphToMany $relation)
|
||||
{
|
||||
if (!\array_key_exists($relation->getRelationName(), self::RELATION_TYPES)) {
|
||||
throw new \Exception('Invalid relation definition.');
|
||||
}
|
||||
|
||||
return self::RELATION_TYPES[$relation->getRelationName()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function tablePrefixedField($field)
|
||||
{
|
||||
return \sprintf('%s.%s', config('follow.followable_table'), $field);
|
||||
}
|
||||
}
|
||||
112
vendor/overtrue/laravel-follow/src/FollowRelation.php
vendored
Normal file
112
vendor/overtrue/laravel-follow/src/FollowRelation.php
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class FollowRelation.
|
||||
*/
|
||||
class FollowRelation extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $with = ['followable'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function followable()
|
||||
{
|
||||
return $this->morphTo(config('follow.morph_prefix', 'followable'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string|null $type
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function scopePopular($query, $type = null)
|
||||
{
|
||||
$query->select('followable_id', 'followable_type', \DB::raw('COUNT(*) AS count'))
|
||||
->groupBy('followable_id', 'followable_type')
|
||||
->orderByDesc('count');
|
||||
|
||||
if ($type) {
|
||||
$query->where('followable_type', $this->normalizeFollowableType($type));
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTable()
|
||||
{
|
||||
if (!$this->table) {
|
||||
$this->table = config('follow.followable_table', 'followables');
|
||||
}
|
||||
|
||||
return parent::getTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return [parent::CREATED_AT];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function normalizeFollowableType($type)
|
||||
{
|
||||
$morphMap = Relation::morphMap();
|
||||
|
||||
if (!empty($morphMap) && in_array($type, $morphMap, true)) {
|
||||
$type = array_search($type, $morphMap, true);
|
||||
}
|
||||
|
||||
if (class_exists($type)) {
|
||||
return $type;
|
||||
}
|
||||
|
||||
$namespace = config('follow.model_namespace', 'App');
|
||||
|
||||
$modelName = $namespace.'\\'.studly_case($type);
|
||||
|
||||
if (!class_exists($modelName)) {
|
||||
throw new InvalidArgumentException("Model {$modelName} not exists. Please check your config 'follow.model_namespace'.");
|
||||
}
|
||||
|
||||
return $modelName;
|
||||
}
|
||||
}
|
||||
39
vendor/overtrue/laravel-follow/src/FollowServiceProvider.php
vendored
Normal file
39
vendor/overtrue/laravel-follow/src/FollowServiceProvider.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class FollowServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Application bootstrap event.
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->publishes([
|
||||
realpath(__DIR__.'/../config/follow.php') => config_path('follow.php'),
|
||||
], 'config');
|
||||
|
||||
$this->publishes([
|
||||
realpath(__DIR__.'/../database/migrations') => database_path('migrations'),
|
||||
], 'migrations');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->mergeConfigFrom(realpath(__DIR__.'/../config/follow.php'), 'follow');
|
||||
}
|
||||
}
|
||||
44
vendor/overtrue/laravel-follow/src/Traits/CanBeBookmarked.php
vendored
Normal file
44
vendor/overtrue/laravel-follow/src/Traits/CanBeBookmarked.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanBeBookmarked.
|
||||
*/
|
||||
trait CanBeBookmarked
|
||||
{
|
||||
/**
|
||||
* Check if user is bookmarked by given user.
|
||||
*
|
||||
* @param int $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBookmarkedBy($user)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'bookmarkers', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bookmarkers.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function bookmarkers()
|
||||
{
|
||||
return $this->morphToMany(config('follow.user_model'), config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_BOOKMARK)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
44
vendor/overtrue/laravel-follow/src/Traits/CanBeFavorited.php
vendored
Normal file
44
vendor/overtrue/laravel-follow/src/Traits/CanBeFavorited.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanBeFavorited.
|
||||
*/
|
||||
trait CanBeFavorited
|
||||
{
|
||||
/**
|
||||
* Check if user is favorited by given user.
|
||||
*
|
||||
* @param int $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFavoritedBy($user)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'favoriters', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return favoriters.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function favoriters()
|
||||
{
|
||||
return $this->morphToMany(config('follow.user_model'), config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_FAVORITE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
58
vendor/overtrue/laravel-follow/src/Traits/CanBeFollowed.php
vendored
Normal file
58
vendor/overtrue/laravel-follow/src/Traits/CanBeFollowed.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanBeFollowed.
|
||||
*/
|
||||
trait CanBeFollowed
|
||||
{
|
||||
/**
|
||||
* Check if user is followed by given user.
|
||||
*
|
||||
* @param int $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFollowedBy($user)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'followers', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return followers.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function followers()
|
||||
{
|
||||
$table = config('follow.followable_table');
|
||||
$class = \get_class($this);
|
||||
$userTable = config('follow.user_table', 'users');
|
||||
$foreignKey = config('follow.users_table_foreign_key', 'user_id');
|
||||
$tablePrefixedForeignKey = app('db.connection')->getQueryGrammar()->wrap(\sprintf('pivot_followables.%s', $foreignKey));
|
||||
$eachOtherKey = app('db.connection')->getQueryGrammar()->wrap('pivot_each_other');
|
||||
|
||||
return $this->morphToMany(config('follow.user_model'), config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_FOLLOW)
|
||||
->withPivot('followable_type', 'relation', 'created_at')
|
||||
->addSelect("{$userTable}.*", DB::raw("(CASE WHEN {$tablePrefixedForeignKey} IS NOT NULL THEN 1 ELSE 0 END) as {$eachOtherKey}"))
|
||||
->leftJoin("{$table} as pivot_followables", function ($join) use ($table, $class, $foreignKey) {
|
||||
$join->on('pivot_followables.followable_type', '=', DB::raw(\addcslashes("'{$class}'", '\\')))
|
||||
->on('pivot_followables.followable_id', '=', "{$table}.{$foreignKey}")
|
||||
->on("pivot_followables.{$foreignKey}", '=', "{$table}.followable_id");
|
||||
});
|
||||
}
|
||||
}
|
||||
54
vendor/overtrue/laravel-follow/src/Traits/CanBeLiked.php
vendored
Normal file
54
vendor/overtrue/laravel-follow/src/Traits/CanBeLiked.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanBeLiked.
|
||||
*/
|
||||
trait CanBeLiked
|
||||
{
|
||||
/**
|
||||
* Check if user is isLikedBy by given user.
|
||||
*
|
||||
* @param int $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLikedBy($user)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'likers', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return followers.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function likers()
|
||||
{
|
||||
return $this->morphToMany(config('follow.user_model'), config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_LIKE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of likers.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fans()
|
||||
{
|
||||
return $this->likers();
|
||||
}
|
||||
}
|
||||
44
vendor/overtrue/laravel-follow/src/Traits/CanBeSubscribed.php
vendored
Normal file
44
vendor/overtrue/laravel-follow/src/Traits/CanBeSubscribed.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanBeSubscribed.
|
||||
*/
|
||||
trait CanBeSubscribed
|
||||
{
|
||||
/**
|
||||
* Check if user is subscribed by given user.
|
||||
*
|
||||
* @param int $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSubscribedBy($user)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'subscribers', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return followers.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function subscribers()
|
||||
{
|
||||
return $this->morphToMany(config('follow.user_model'), config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_SUBSCRIBE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
92
vendor/overtrue/laravel-follow/src/Traits/CanBeVoted.php
vendored
Normal file
92
vendor/overtrue/laravel-follow/src/Traits/CanBeVoted.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanBeVoted.
|
||||
*/
|
||||
trait CanBeVoted
|
||||
{
|
||||
/**
|
||||
* Check if item is voted by given user.
|
||||
*
|
||||
* @param int $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isVotedBy($user, $type = null)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'voters', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if item is upvoted by given user.
|
||||
*
|
||||
* @param int $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isUpvotedBy($user)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'upvoters', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if item is downvoted by given user.
|
||||
*
|
||||
* @param int $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDownvotedBy($user)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'downvoters', $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return voters.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function voters()
|
||||
{
|
||||
return $this->morphToMany(config('follow.user_model'), config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivotIn('relation', [Follow::RELATION_UPVOTE, Follow::RELATION_DOWNVOTE])
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return upvoters.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function upvoters()
|
||||
{
|
||||
return $this->morphToMany(config('follow.user_model'), config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_UPVOTE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return downvoters.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function downvoters()
|
||||
{
|
||||
return $this->morphToMany(config('follow.user_model'), config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_DOWNVOTE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
90
vendor/overtrue/laravel-follow/src/Traits/CanBookmark.php
vendored
Normal file
90
vendor/overtrue/laravel-follow/src/Traits/CanBookmark.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanBookmark.
|
||||
*/
|
||||
trait CanBookmark
|
||||
{
|
||||
/**
|
||||
* Follow an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function bookmark($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::attachRelations($this, 'bookmarks', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbookmark an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function unbookmark($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::detachRelations($this, 'bookmarks', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle bookmark an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toggleBookmark($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::toggleRelations($this, 'bookmarks', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is bookmarked given item.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBookmarked($target, $class = __CLASS__)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'bookmarks', $target, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item bookmarks.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function bookmarks($class = __CLASS__)
|
||||
{
|
||||
return $this->morphedByMany($class, config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_BOOKMARK)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
86
vendor/overtrue/laravel-follow/src/Traits/CanFavorite.php
vendored
Normal file
86
vendor/overtrue/laravel-follow/src/Traits/CanFavorite.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanFavorite.
|
||||
*/
|
||||
trait CanFavorite
|
||||
{
|
||||
/**
|
||||
* Favorite an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function favorite($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::attachRelations($this, 'favorites', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfavorite an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function unfavorite($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::detachRelations($this, 'favorites', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle favorite an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toggleFavorite($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::toggleRelations($this, 'favorites', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is favorited given item.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasFavorited($target, $class = __CLASS__)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'favorites', $target, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item favorites.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function favorites($class = __CLASS__)
|
||||
{
|
||||
return $this->morphedByMany($class, config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_FAVORITE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
116
vendor/overtrue/laravel-follow/src/Traits/CanFollow.php
vendored
Normal file
116
vendor/overtrue/laravel-follow/src/Traits/CanFollow.php
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanFollow.
|
||||
*/
|
||||
trait CanFollow
|
||||
{
|
||||
/**
|
||||
* Follow an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function follow($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::attachRelations($this, 'followings', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfollow an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function unfollow($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::detachRelations($this, 'followings', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle follow an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toggleFollow($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::toggleRelations($this, 'followings', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is following given item.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFollowing($target, $class = __CLASS__)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'followings', $target, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user and target user is following each other.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function areFollowingEachOther($target, $class = __CLASS__)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'followings', $target, $class) && Follow::isRelationExists($target, 'followings', $this, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item followings.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function followings($class = __CLASS__)
|
||||
{
|
||||
$table = config('follow.followable_table');
|
||||
$foreignKey = config('follow.users_table_foreign_key', 'user_id');
|
||||
$targetTable = (new $class())->getTable();
|
||||
$tablePrefixedForeignKey = app('db.connection')->getQueryGrammar()->wrap(\sprintf('pivot_followables.%s', $foreignKey));
|
||||
$eachOtherKey = app('db.connection')->getQueryGrammar()->wrap('pivot_each_other');
|
||||
|
||||
return $this->morphedByMany($class, config('follow.morph_prefix'), $table)
|
||||
->wherePivot('relation', '=', Follow::RELATION_FOLLOW)
|
||||
->withPivot('followable_type', 'relation', 'created_at')
|
||||
->addSelect("{$targetTable}.*", DB::raw("(CASE WHEN {$tablePrefixedForeignKey} IS NOT NULL THEN 1 ELSE 0 END) as {$eachOtherKey}"))
|
||||
->leftJoin("{$table} as pivot_followables", function ($join) use ($table, $class, $foreignKey) {
|
||||
$join->on('pivot_followables.followable_type', '=', DB::raw(\addcslashes("'{$class}'", '\\')))
|
||||
->on('pivot_followables.followable_id', '=', "{$table}.{$foreignKey}")
|
||||
->on("pivot_followables.{$foreignKey}", '=', "{$table}.followable_id");
|
||||
});
|
||||
}
|
||||
}
|
||||
90
vendor/overtrue/laravel-follow/src/Traits/CanLike.php
vendored
Normal file
90
vendor/overtrue/laravel-follow/src/Traits/CanLike.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanLike.
|
||||
*/
|
||||
trait CanLike
|
||||
{
|
||||
/**
|
||||
* Like an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function like($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::attachRelations($this, 'likes', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function unlike($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::detachRelations($this, 'likes', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle like an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toggleLike($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::toggleRelations($this, 'likes', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is liked given item.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLiked($target, $class = __CLASS__)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'likes', $target, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item likes.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function likes($class = __CLASS__)
|
||||
{
|
||||
return $this->morphedByMany($class, config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_LIKE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
90
vendor/overtrue/laravel-follow/src/Traits/CanSubscribe.php
vendored
Normal file
90
vendor/overtrue/laravel-follow/src/Traits/CanSubscribe.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanSubscribe.
|
||||
*/
|
||||
trait CanSubscribe
|
||||
{
|
||||
/**
|
||||
* Subscribe an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function subscribe($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::attachRelations($this, 'subscriptions', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function unsubscribe($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::detachRelations($this, 'subscriptions', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle subscribe an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toggleSubscribe($targets, $class = __CLASS__)
|
||||
{
|
||||
return Follow::toggleRelations($this, 'subscriptions', $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is subscribed given item.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasSubscribed($target, $class = __CLASS__)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'subscriptions', $target, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user subscriptions.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function subscriptions($class = __CLASS__)
|
||||
{
|
||||
return $this->morphedByMany($class, config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_SUBSCRIBE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
152
vendor/overtrue/laravel-follow/src/Traits/CanVote.php
vendored
Normal file
152
vendor/overtrue/laravel-follow/src/Traits/CanVote.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
/**
|
||||
* Trait CanVote.
|
||||
*/
|
||||
trait CanVote
|
||||
{
|
||||
/**
|
||||
* Vote an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $type
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vote($targets, $type = 'upvote', $class = __CLASS__)
|
||||
{
|
||||
$this->cancelVote($targets);
|
||||
|
||||
return Follow::attachRelations($this, str_plural($type), $targets, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upvote an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function upvote($targets, $class = __CLASS__)
|
||||
{
|
||||
return $this->vote($targets, 'upvote', $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downvote an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function downvote($targets, $class = __CLASS__)
|
||||
{
|
||||
return $this->vote($targets, 'downvote', $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel vote for an item or items.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $targets
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Overtrue\LaravelFollow\Traits\CanVote
|
||||
*/
|
||||
public function cancelVote($targets, $class = __CLASS__)
|
||||
{
|
||||
Follow::detachRelations($this, 'upvotes', $targets, $class);
|
||||
Follow::detachRelations($this, 'downvotes', $targets, $class);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is upvoted given item.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasUpvoted($target, $class = __CLASS__)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'upvotes', $target, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is downvoted given item.
|
||||
*
|
||||
* @param int|array|\Illuminate\Database\Eloquent\Model $target
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDownvoted($target, $class = __CLASS__)
|
||||
{
|
||||
return Follow::isRelationExists($this, 'downvotes', $target, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item votes.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function votes($class = __CLASS__)
|
||||
{
|
||||
return $this->morphedByMany($class, config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivotIn('relation', [Follow::RELATION_UPVOTE, Follow::RELATION_DOWNVOTE])
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item upvotes.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function upvotes($class = __CLASS__)
|
||||
{
|
||||
return $this->morphedByMany($class, config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_UPVOTE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item downvotes.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function downvotes($class = __CLASS__)
|
||||
{
|
||||
return $this->morphedByMany($class, config('follow.morph_prefix'), config('follow.followable_table'))
|
||||
->wherePivot('relation', '=', Follow::RELATION_DOWNVOTE)
|
||||
->withPivot('followable_type', 'relation', 'created_at');
|
||||
}
|
||||
}
|
||||
133
vendor/overtrue/laravel-follow/tests/FollowTest.php
vendored
Normal file
133
vendor/overtrue/laravel-follow/tests/FollowTest.php
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Test;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Overtrue\LaravelFollow\Follow;
|
||||
|
||||
class FollowTest extends TestCase
|
||||
{
|
||||
public function testIsRelationExists()
|
||||
{
|
||||
$user = User::create(['name' => 'overtrue']);
|
||||
$other = Other::create(['name' => 'php']);
|
||||
|
||||
$user->follow($other);
|
||||
|
||||
$this->assertTrue(Follow::isRelationExists($user, 'followings', $other->id, \get_class($other)));
|
||||
|
||||
$user1 = User::create(['name' => 'overtrue']);
|
||||
$user2 = User::create(['name' => 'anzhengchao']);
|
||||
$user1->follow($user2);
|
||||
|
||||
$this->assertTrue(Follow::isRelationExists($user1, 'followings', $user2->id, User::class));
|
||||
}
|
||||
|
||||
public function testAttachAndDetachRelations()
|
||||
{
|
||||
$user1 = User::create(['name' => 'overtrue']);
|
||||
$user2 = User::create(['name' => 'anzhengchao']);
|
||||
$user3 = User::create(['name' => 'allen']);
|
||||
$user4 = User::create(['name' => 'taylor']);
|
||||
$user1->follow($user2);
|
||||
$user1->follow([$user3, $user4]);
|
||||
|
||||
$this->assertTrue(Follow::isRelationExists($user1, 'followings', $user2->id, User::class));
|
||||
$this->assertTrue(Follow::isRelationExists($user1, 'followings', $user3->id, User::class));
|
||||
$this->assertTrue(Follow::isRelationExists($user1, 'followings', $user4->id, User::class));
|
||||
|
||||
$user1->unfollow($user2);
|
||||
$this->assertFalse(Follow::isRelationExists($user1, 'followings', $user2->id, User::class));
|
||||
}
|
||||
|
||||
public function testToggleRelations()
|
||||
{
|
||||
$user1 = User::create(['name' => 'overtrue']);
|
||||
$user2 = User::create(['name' => 'anzhengchao']);
|
||||
$user1->follow($user2);
|
||||
|
||||
$this->assertTrue(Follow::isRelationExists($user1, 'followings', $user2->id, User::class));
|
||||
|
||||
$user1->toggleFollow($user2);
|
||||
$this->assertFalse(Follow::isRelationExists($user1, 'followings', $user2->id, User::class));
|
||||
|
||||
$user1->toggleFollow($user2);
|
||||
$this->assertTrue(Follow::isRelationExists($user1, 'followings', $user2->id, User::class));
|
||||
}
|
||||
|
||||
public function testEagerLoading()
|
||||
{
|
||||
$sqls = \collect([]);
|
||||
|
||||
$user1 = User::create(['name' => 'overtrue']);
|
||||
$user2 = User::create(['name' => 'anzhengchao']);
|
||||
$user3 = User::create(['name' => 'allen']);
|
||||
$user4 = User::create(['name' => 'taylor']);
|
||||
$user1->follow($user2);
|
||||
$user1->follow([$user3, $user4]);
|
||||
|
||||
// start recording
|
||||
\DB::listen(function ($query) use ($sqls) {
|
||||
$sqls->push($query->sql);
|
||||
});
|
||||
|
||||
$user1->isFollowing($user2);
|
||||
$user1->isFollowing($user3);
|
||||
$user1->isFollowing($user4);
|
||||
|
||||
$this->assertCount(3, $sqls);
|
||||
|
||||
// eager loading
|
||||
$user1->load('followings');
|
||||
|
||||
// cleanup
|
||||
$sqls = \collect([]);
|
||||
|
||||
$user1->isFollowing($user2);
|
||||
$user1->isFollowing($user3);
|
||||
$user1->isFollowing($user4);
|
||||
|
||||
$this->assertCount(0, $sqls);
|
||||
}
|
||||
|
||||
public function testFormatTargets()
|
||||
{
|
||||
// 1. !is_array
|
||||
$result = Follow::formatTargets(1, 'App\Foo');
|
||||
$this->assertSame('App\Foo', $result->classname);
|
||||
$this->assertSame([1], $result->ids);
|
||||
$this->assertSame([1], $result->targets);
|
||||
|
||||
// 2. Model
|
||||
$user = new User();
|
||||
$user->id = 3;
|
||||
$result = Follow::formatTargets([1, $user], 'App\Foo');
|
||||
$this->assertSame(User::class, $result->classname);
|
||||
$this->assertSame([1, 3], $result->ids);
|
||||
$this->assertSame([1, 3], $result->targets);
|
||||
|
||||
$other = new Other();
|
||||
$other->id = 45;
|
||||
|
||||
$result = Follow::formatTargets([1, $user, $other], 'App\Foo');
|
||||
$this->assertSame(Other::class, $result->classname);
|
||||
$this->assertSame([1, 3, 45], $result->ids);
|
||||
$this->assertSame([1, 3, 45], $result->targets);
|
||||
|
||||
// 3. $update
|
||||
$update = ['relation' => 'like'];
|
||||
$result = Follow::formatTargets([1, 2], 'App\Foo', $update);
|
||||
$this->assertSame('App\Foo', $result->classname);
|
||||
$this->assertSame([1, 2], $result->ids);
|
||||
$this->assertSame([1 => $update, 2 => $update], $result->targets);
|
||||
}
|
||||
}
|
||||
26
vendor/overtrue/laravel-follow/tests/Other.php
vendored
Normal file
26
vendor/overtrue/laravel-follow/tests/Other.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Test;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Overtrue\LaravelFollow\Traits\CanBeFollowed;
|
||||
|
||||
class Other extends Model
|
||||
{
|
||||
use CanBeFollowed;
|
||||
|
||||
protected $follow = User::class;
|
||||
|
||||
protected $table = 'others';
|
||||
|
||||
protected $fillable = ['name'];
|
||||
}
|
||||
97
vendor/overtrue/laravel-follow/tests/TestCase.php
vendored
Normal file
97
vendor/overtrue/laravel-follow/tests/TestCase.php
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Test;
|
||||
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class TestCase extends \Illuminate\Foundation\Testing\TestCase
|
||||
{
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Creates the application.
|
||||
*
|
||||
* Needs to be implemented by subclasses.
|
||||
*
|
||||
* @return \Symfony\Component\HttpKernel\HttpKernelInterface
|
||||
*/
|
||||
public function createApplication()
|
||||
{
|
||||
$app = require __DIR__.'/../vendor/laravel/laravel/bootstrap/app.php';
|
||||
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
|
||||
|
||||
$app['config']->set('database.default', 'sqlite');
|
||||
$app['config']->set('database.connections.sqlite.database', ':memory:');
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup DB before each test.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (empty($this->config)) {
|
||||
$this->config = require __DIR__.'/../config/follow.php';
|
||||
}
|
||||
|
||||
$this->app['config']->set('follow', $this->config);
|
||||
$this->app['config']->set('follow.user_model', User::class);
|
||||
|
||||
$this->migrate();
|
||||
$this->seed();
|
||||
}
|
||||
|
||||
/**
|
||||
* run package database migrations.
|
||||
*/
|
||||
public function migrate()
|
||||
{
|
||||
$fileSystem = new Filesystem();
|
||||
|
||||
$fileSystem->copy(
|
||||
__DIR__.'/../database/migrations/2018_06_29_032244_create_laravel_follow_tables.php',
|
||||
__DIR__.'/database/migrations/create_laravel_follow_tables.php'
|
||||
);
|
||||
|
||||
foreach ($fileSystem->files(__DIR__.'/database/migrations') as $file) {
|
||||
$fileSystem->requireOnce($file);
|
||||
}
|
||||
|
||||
(new \CreateLaravelFollowTables())->up();
|
||||
(new \CreateUsersTable())->up();
|
||||
(new \CreateOthersTable())->up();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unlink(__DIR__.'/database/migrations/create_laravel_follow_tables.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed testing database.
|
||||
*/
|
||||
public function seed($classname = null)
|
||||
{
|
||||
User::create(['name' => 'John']);
|
||||
User::create(['name' => 'Allison']);
|
||||
User::create(['name' => 'Ron']);
|
||||
|
||||
Other::create(['name' => 'Laravel']);
|
||||
Other::create(['name' => 'Vuejs']);
|
||||
Other::create(['name' => 'Ruby']);
|
||||
}
|
||||
}
|
||||
71
vendor/overtrue/laravel-follow/tests/Traits/CanBeFollowedTest.php
vendored
Normal file
71
vendor/overtrue/laravel-follow/tests/Traits/CanBeFollowedTest.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Test\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Test\Other;
|
||||
use Overtrue\LaravelFollow\Test\TestCase;
|
||||
use Overtrue\LaravelFollow\Test\User;
|
||||
|
||||
class CanBeFollowedTest extends TestCase
|
||||
{
|
||||
public function test_user_can_follow_by_id()
|
||||
{
|
||||
$user1 = User::find(1);
|
||||
$user2 = User::find(2);
|
||||
|
||||
$user1->follow($user2->id);
|
||||
|
||||
$this->assertCount(1, $user2->followers);
|
||||
}
|
||||
|
||||
public function test_user_can_follow_multiple_users()
|
||||
{
|
||||
$user1 = User::find(1);
|
||||
$user2 = User::find(2);
|
||||
$user3 = User::find(3);
|
||||
|
||||
$user1->follow([$user2->id, $user3->id]);
|
||||
|
||||
$this->assertCount(1, $user2->followers);
|
||||
$this->assertCount(1, $user3->followers);
|
||||
}
|
||||
|
||||
public function test_is_followed_by()
|
||||
{
|
||||
$user1 = User::find(1);
|
||||
$user2 = User::find(2);
|
||||
|
||||
$user1->follow($user2->id);
|
||||
|
||||
$this->assertTrue($user2->isFollowedBy($user1->id));
|
||||
}
|
||||
|
||||
public function test_user_can_follow_other_by_id()
|
||||
{
|
||||
$user = User::find(1);
|
||||
$other = Other::find(1);
|
||||
|
||||
$user->follow($other);
|
||||
|
||||
$this->assertCount(1, $other->followers);
|
||||
}
|
||||
|
||||
public function test_is_followed_by_user()
|
||||
{
|
||||
$user = User::find(1);
|
||||
$other = Other::find(1);
|
||||
|
||||
$user->follow($other);
|
||||
|
||||
$this->assertTrue($other->isFollowedBy($user));
|
||||
}
|
||||
}
|
||||
105
vendor/overtrue/laravel-follow/tests/Traits/CanFollowTest.php
vendored
Normal file
105
vendor/overtrue/laravel-follow/tests/Traits/CanFollowTest.php
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Test\Traits;
|
||||
|
||||
use Overtrue\LaravelFollow\Test\Other;
|
||||
use Overtrue\LaravelFollow\Test\TestCase;
|
||||
use Overtrue\LaravelFollow\Test\User;
|
||||
|
||||
class CanFollowTest extends TestCase
|
||||
{
|
||||
public function test_user_can_follow_by_id()
|
||||
{
|
||||
$user1 = User::find(1);
|
||||
$user2 = User::find(2);
|
||||
|
||||
$user1->follow($user2->id);
|
||||
|
||||
$this->assertCount(1, $user1->followings);
|
||||
}
|
||||
|
||||
public function test_user_can_follow_multiple_users()
|
||||
{
|
||||
$user1 = User::find(1);
|
||||
$user2 = User::find(2);
|
||||
$user3 = User::find(3);
|
||||
|
||||
$user1->follow([$user2->id, $user3->id]);
|
||||
|
||||
$this->assertCount(2, $user1->followings);
|
||||
}
|
||||
|
||||
public function test_unfollow_user()
|
||||
{
|
||||
$user1 = User::find(1);
|
||||
$user2 = User::find(2);
|
||||
|
||||
$user1->follow($user2->id);
|
||||
$this->assertCount(1, $user2->followers);
|
||||
$user1->unfollow($user2->id);
|
||||
$this->assertCount(0, $user1->followings);
|
||||
}
|
||||
|
||||
public function test_is_following()
|
||||
{
|
||||
$user1 = User::find(1);
|
||||
$user2 = User::find(2);
|
||||
|
||||
$user1->follow($user2->id);
|
||||
|
||||
$this->assertTrue($user1->isFollowing($user2->id));
|
||||
}
|
||||
|
||||
public function test_user_can_follow_other_by_id()
|
||||
{
|
||||
$user = User::find(1);
|
||||
$other = Other::find(1);
|
||||
|
||||
$user->follow($other);
|
||||
|
||||
$this->assertCount(1, $user->followings(Other::class)->get());
|
||||
}
|
||||
|
||||
public function test_unfollow_other()
|
||||
{
|
||||
$user = User::find(1);
|
||||
$other = Other::find(1);
|
||||
|
||||
$user->follow($other);
|
||||
$user->unfollow($other);
|
||||
|
||||
$this->assertCount(0, $user->followings);
|
||||
}
|
||||
|
||||
public function test_is_following_other()
|
||||
{
|
||||
$user = User::find(1);
|
||||
$other = Other::find(1);
|
||||
|
||||
$user->follow($other);
|
||||
|
||||
$this->assertTrue($user->isFollowing($other));
|
||||
}
|
||||
|
||||
public function test_following_each_other()
|
||||
{
|
||||
$user1 = User::find(1);
|
||||
$user2 = User::find(2);
|
||||
|
||||
$user1->follow($user2);
|
||||
|
||||
$this->assertFalse($user1->areFollowingEachOther($user2));
|
||||
|
||||
$user2->follow($user1);
|
||||
$this->assertTrue($user1->areFollowingEachOther($user2));
|
||||
}
|
||||
}
|
||||
25
vendor/overtrue/laravel-follow/tests/User.php
vendored
Normal file
25
vendor/overtrue/laravel-follow/tests/User.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelFollow\Test;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Overtrue\LaravelFollow\Traits\CanFollow;
|
||||
use Overtrue\LaravelFollow\Traits\CanBeFollowed;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
use CanFollow, CanBeFollowed;
|
||||
|
||||
protected $table = 'users';
|
||||
|
||||
protected $fillable = ['name'];
|
||||
}
|
||||
36
vendor/overtrue/laravel-follow/tests/database/migrations/create_others_table.php
vendored
Normal file
36
vendor/overtrue/laravel-follow/tests/database/migrations/create_others_table.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class CreateOthersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('others', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('others');
|
||||
}
|
||||
}
|
||||
36
vendor/overtrue/laravel-follow/tests/database/migrations/create_users_table.php
vendored
Normal file
36
vendor/overtrue/laravel-follow/tests/database/migrations/create_users_table.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-follow
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class CreateUsersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('users');
|
||||
}
|
||||
}
|
||||
3
vendor/overtrue/laravel-wechat/.gitignore
vendored
Normal file
3
vendor/overtrue/laravel-wechat/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/vendor/
|
||||
composer.lock
|
||||
.php_cs.cache
|
||||
28
vendor/overtrue/laravel-wechat/.php_cs
vendored
Normal file
28
vendor/overtrue/laravel-wechat/.php_cs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$header = <<<EOF
|
||||
This file is part of the overtrue/laravel-wechat.
|
||||
|
||||
(c) overtrue <i@overtrue.me>
|
||||
|
||||
This source file is subject to the MIT license that is bundled
|
||||
with this source code in the file LICENSE.
|
||||
EOF;
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setRiskyAllowed(true)
|
||||
->setRules(array(
|
||||
'@Symfony' => true,
|
||||
'header_comment' => array('header' => $header),
|
||||
'array_syntax' => array('syntax' => 'short'),
|
||||
'ordered_imports' => true,
|
||||
'no_useless_else' => true,
|
||||
'no_useless_return' => true,
|
||||
'php_unit_construct' => true,
|
||||
'php_unit_strict' => true,
|
||||
))
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->exclude('vendor')
|
||||
->in(__DIR__)
|
||||
)
|
||||
;
|
||||
22
vendor/overtrue/laravel-wechat/LICENSE
vendored
Normal file
22
vendor/overtrue/laravel-wechat/LICENSE
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 安正超
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
255
vendor/overtrue/laravel-wechat/README.md
vendored
Normal file
255
vendor/overtrue/laravel-wechat/README.md
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
# laravel-wechat
|
||||
|
||||
微信 SDK for Laravel 5 / Lumen, 基于 [overtrue/wechat](https://github.com/overtrue/wechat)
|
||||
|
||||
> 注意:此版本为 4.x 版本,不兼容 3.x,与 [overtrue/wechat 4.x](https://github.com/overtrue/wechat) 同步
|
||||
>
|
||||
> 如果你用的 3.x 版本,请从这里查看文档 https://github.com/overtrue/laravel-wechat/tree/3.1.10
|
||||
>
|
||||
> Laravel 5.6 以上不支持 3.x 请使用 4.0 以上版本。
|
||||
>
|
||||
> 交流QQ群:319502940
|
||||
|
||||
|
||||
## 框架要求
|
||||
|
||||
Laravel/Lumen >= 5.1
|
||||
|
||||
## 安装
|
||||
|
||||
```shell
|
||||
composer require "overtrue/laravel-wechat:~4.0"
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
### Laravel 应用
|
||||
|
||||
1. 在 `config/app.php` 注册 ServiceProvider 和 Facade (Laravel 5.5 无需手动注册)
|
||||
|
||||
```php
|
||||
'providers' => [
|
||||
// ...
|
||||
Overtrue\LaravelWeChat\ServiceProvider::class,
|
||||
],
|
||||
'aliases' => [
|
||||
// ...
|
||||
'EasyWeChat' => Overtrue\LaravelWeChat\Facade::class,
|
||||
],
|
||||
```
|
||||
|
||||
2. 创建配置文件:
|
||||
|
||||
```shell
|
||||
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
|
||||
```
|
||||
|
||||
3. 修改应用根目录下的 `config/wechat.php` 中对应的参数即可。
|
||||
|
||||
4. 每个模块基本都支持多账号,默认为 `default`。
|
||||
|
||||
### Lumen 应用
|
||||
|
||||
1. 在 `bootstrap/app.php` 中 82 行左右:
|
||||
|
||||
```php
|
||||
$app->register(Overtrue\LaravelWeChat\ServiceProvider::class);
|
||||
```
|
||||
|
||||
2. 如果你习惯使用 `config/wechat.php` 来配置的话,将 `vendor/overtrue/laravel-wechat/src/config.php` 拷贝到`项目根目录/config`目录下,并将文件名改成`wechat.php`。
|
||||
|
||||
## 使用
|
||||
|
||||
:rotating_light: 在中间件 `App\Http\Middleware\VerifyCsrfToken` 排除微信相关的路由,如:
|
||||
|
||||
```php
|
||||
protected $except = [
|
||||
// ...
|
||||
'wechat',
|
||||
];
|
||||
```
|
||||
|
||||
下面以接收普通消息为例写一个例子:
|
||||
|
||||
> 假设您的域名为 `overtrue.me` 那么请登录微信公众平台 “开发者中心” 修改 “URL(服务器配置)” 为: `http://overtrue.me/wechat`。
|
||||
|
||||
路由:
|
||||
|
||||
```php
|
||||
Route::any('/wechat', 'WeChatController@serve');
|
||||
```
|
||||
|
||||
> 注意:一定是 `Route::any`, 因为微信服务端认证的时候是 `GET`, 接收用户消息时是 `POST` !
|
||||
|
||||
然后创建控制器 `WeChatController`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Log;
|
||||
|
||||
class WeChatController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* 处理微信的请求消息
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serve()
|
||||
{
|
||||
Log::info('request arrived.'); # 注意:Log 为 Laravel 组件,所以它记的日志去 Laravel 日志看,而不是 EasyWeChat 日志
|
||||
|
||||
$app = app('wechat.official_account');
|
||||
$app->server->push(function($message){
|
||||
return "欢迎关注 overtrue!";
|
||||
});
|
||||
|
||||
return $app->server->serve();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 上面例子里的 Log 是 Laravel 组件,所以它的日志不会写到 EasyWeChat 里的,建议把 wechat 的日志配置到 Laravel 同一个日志文件,便于调试。
|
||||
|
||||
### 我们有以下方式获取 SDK 的服务实例
|
||||
|
||||
##### 使用外观
|
||||
|
||||
```php
|
||||
$officialAccount = EasyWeChat::officialAccount(); // 公众号
|
||||
$work = EasyWeChat::work(); // 企业微信
|
||||
$payment = EasyWeChat::payment(); // 微信支付
|
||||
$openPlatform = EasyWeChat::openPlatform(); // 开放平台
|
||||
$miniProgram = EasyWeChat::miniProgram(); // 小程序
|
||||
|
||||
// 均支持传入配置账号名称
|
||||
EasyWeChat::officialAccount('foo'); // `foo` 为配置文件中的名称,默认为 `default`
|
||||
//...
|
||||
```
|
||||
|
||||
|
||||
## OAuth 中间件
|
||||
|
||||
使用中间件的情况下 `app/config/wechat.php` 中的 `oauth.callback` 就随便填写吧(因为用不着了 :smile:)。
|
||||
|
||||
1. 在 `app/Http/Kernel.php` 中添加路由中间件:
|
||||
|
||||
```php
|
||||
protected $routeMiddleware = [
|
||||
// ...
|
||||
'wechat.oauth' => \Overtrue\LaravelWeChat\Middleware\OAuthAuthenticate::class,
|
||||
];
|
||||
```
|
||||
|
||||
2. 在路由中添加中间件:
|
||||
|
||||
```php
|
||||
//...
|
||||
Route::group(['middleware' => ['web', 'wechat.oauth']], function () {
|
||||
Route::get('/user', function () {
|
||||
$user = session('wechat.oauth_user'); // 拿到授权用户资料
|
||||
|
||||
dd($user);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
中间件支持指定配置名称:`'wechat.oauth:default'`,当然,你也可以在中间件参数指定当前的 `scopes`:
|
||||
|
||||
```php
|
||||
Route::group(['middleware' => ['wechat.oauth:snsapi_userinfo']], function () {
|
||||
// ...
|
||||
});
|
||||
|
||||
// 或者指定账户的同时指定 scopes:
|
||||
Route::group(['middleware' => ['wechat.oauth:default,snsapi_userinfo']], function () {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
上面的路由定义了 `/user` 是需要微信授权的,那么在这条路由的**回调 或 控制器对应的方法里**, 你就可以从 `session('wechat.oauth_user.default')` 拿到已经授权的用户信息了。
|
||||
|
||||
## 模拟授权
|
||||
|
||||
有时候我们希望在本地开发完成后线上才真实的走微信授权流程,这将减少我们的开发成本,那么你需要做以下两步:
|
||||
|
||||
1. 准备假资料:
|
||||
|
||||
> 以下字段在 scope 为 `snsapi_userinfo` 时尽可能配置齐全哦,当然,如果你的模式只是 `snsapi_base` 的话只需要 `openid` 就好了。
|
||||
|
||||
```php
|
||||
use Overtrue\Socialite\User as SocialiteUser;
|
||||
|
||||
$user = new SocialiteUser([
|
||||
'id' => array_get($user, 'openid'),
|
||||
'name' => array_get($user, 'nickname'),
|
||||
'nickname' => array_get($user, 'nickname'),
|
||||
'avatar' => array_get($user, 'headimgurl'),
|
||||
'email' => null,
|
||||
'original' => [],
|
||||
'provider' => 'WeChat',
|
||||
]);
|
||||
|
||||
```
|
||||
|
||||
2. 将资料写入 session:
|
||||
|
||||
> 注意:一定要在 OAuth 中间件之前写入,比如你可以创建一个全局中间件来完成这件事儿,当然了,只在开发环境启用即可。
|
||||
|
||||
```php
|
||||
session(['wechat.oauth_user.default' => $user]); // 同理,`default` 可以更换为您对应的其它配置名
|
||||
```
|
||||
|
||||
## 事件
|
||||
|
||||
> 你可以监听相应的事件,并对事件发生后执行相应的操作。
|
||||
|
||||
- OAuth 网页授权:`Overtrue\LaravelWeChat\Events\WeChatUserAuthorized`
|
||||
|
||||
```php
|
||||
// 该事件有以下属性
|
||||
$event->user; // 同 session('wechat.oauth_user.default') 一样
|
||||
$event->isNewSession; // 是不是新的会话(第一次创建 session 时为 true)
|
||||
$event->account; // 当前中间件所使用的账号,对应在配置文件中的配置项名称
|
||||
```
|
||||
|
||||
|
||||
## 开放平台路由支持
|
||||
|
||||
在配置文件 `route` 处取消注释即可启用。
|
||||
|
||||
```php
|
||||
'open_platform' => [
|
||||
'uri' => 'serve',
|
||||
'action' => Overtrue\LaravelWeChat\Controllers\OpenPlatformController::class,
|
||||
'attributes' => [
|
||||
'prefix' => 'open-platform',
|
||||
'middleware' => null,
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
Tips: 默认的控制器会根据微信开放平台的推送内容触发如下事件,你可以监听相应的事件并进行处理:
|
||||
|
||||
- 授权方成功授权:`Overtrue\LaravelWeChat\Events\OpenPlatform\Authorized`
|
||||
- 授权方更新授权:`Overtrue\LaravelWeChat\Events\OpenPlatform\UpdateAuthorized`
|
||||
- 授权方取消授权:`Overtrue\LaravelWeChat\Events\OpenPlatform\Unauthorized`
|
||||
- 开放平台推送 VerifyTicket:`Overtrue\LaravelWeChat\Events\OpenPlatform\VerifyTicketRefreshed`
|
||||
|
||||
```php
|
||||
// 事件有如下属性
|
||||
$message = $event->payload; // 开放平台事件通知内容
|
||||
```
|
||||
|
||||
配置后 `http://example.com/open-platform/serve` 则为开放平台第三方应用设置的授权事件接收 URL。
|
||||
|
||||
|
||||
|
||||
更多 SDK 的具体使用请参考:https://easywechat.com
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
31
vendor/overtrue/laravel-wechat/composer.json
vendored
Normal file
31
vendor/overtrue/laravel-wechat/composer.json
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "overtrue/laravel-wechat",
|
||||
"description": "微信 SDK for Laravel",
|
||||
"keywords": ["wechat", "weixin","laravel", "sdk"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"email": "anzhengchao@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"illuminate/container": "^5.1",
|
||||
"overtrue/wechat": "^4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Overtrue\\LaravelWeChat\\": "src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Overtrue\\LaravelWeChat\\ServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"EasyWeChat": "Overtrue\\LaravelWeChat\\Facade"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
vendor/overtrue/laravel-wechat/src/CacheBridge.php
vendored
Normal file
73
vendor/overtrue/laravel-wechat/src/CacheBridge.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat;
|
||||
|
||||
use Illuminate\Cache\Repository;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
class CacheBridge implements CacheInterface
|
||||
{
|
||||
/**
|
||||
* @var \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Cache\Repository $repository
|
||||
*/
|
||||
public function __construct(Repository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
return $this->repository->get($key, $default);
|
||||
}
|
||||
|
||||
public function set($key, $value, $ttl = null)
|
||||
{
|
||||
return $this->repository->put($key, $value, $this->toMinutes($ttl));
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
}
|
||||
|
||||
public function getMultiple($keys, $default = null)
|
||||
{
|
||||
}
|
||||
|
||||
public function setMultiple($values, $ttl = null)
|
||||
{
|
||||
}
|
||||
|
||||
public function deleteMultiple($keys)
|
||||
{
|
||||
}
|
||||
|
||||
public function has($key)
|
||||
{
|
||||
return $this->repository->has($key);
|
||||
}
|
||||
|
||||
protected function toMinutes($ttl = null)
|
||||
{
|
||||
if (!is_null($ttl)) {
|
||||
return $ttl / 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
vendor/overtrue/laravel-wechat/src/Controllers/Controller.php
vendored
Normal file
24
vendor/overtrue/laravel-wechat/src/Controllers/Controller.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Controllers;
|
||||
|
||||
use Barryvdh\Debugbar\LaravelDebugbar;
|
||||
|
||||
class Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
if (class_exists(LaravelDebugbar::class)) {
|
||||
resolve(LaravelDebugbar::class)->disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
47
vendor/overtrue/laravel-wechat/src/Controllers/OpenPlatformController.php
vendored
Normal file
47
vendor/overtrue/laravel-wechat/src/Controllers/OpenPlatformController.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Controllers;
|
||||
|
||||
use EasyWeChat\OpenPlatform\Application;
|
||||
use EasyWeChat\OpenPlatform\Server\Guard;
|
||||
use Event;
|
||||
use Overtrue\LaravelWeChat\Events\OpenPlatform as Events;
|
||||
|
||||
class OpenPlatformController extends Controller
|
||||
{
|
||||
/**
|
||||
* Register for open platform.
|
||||
*
|
||||
* @param \EasyWeChat\OpenPlatform\Application $application
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function __invoke(Application $application)
|
||||
{
|
||||
$server = $application->server;
|
||||
|
||||
$server->on(Guard::EVENT_AUTHORIZED, function ($payload) {
|
||||
Event::fire(new Events\Authorized($payload));
|
||||
});
|
||||
$server->on(Guard::EVENT_UNAUTHORIZED, function ($payload) {
|
||||
Event::fire(new Events\Unauthorized($payload));
|
||||
});
|
||||
$server->on(Guard::EVENT_UPDATE_AUTHORIZED, function ($payload) {
|
||||
Event::fire(new Events\UpdateAuthorized($payload));
|
||||
});
|
||||
$server->on(Guard::EVENT_COMPONENT_VERIFY_TICKET, function ($payload) {
|
||||
Event::fire(new Events\VerifyTicketRefreshed($payload));
|
||||
});
|
||||
|
||||
return $server->serve();
|
||||
}
|
||||
}
|
||||
25
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/Authorized.php
vendored
Normal file
25
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/Authorized.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Events\OpenPlatform;
|
||||
|
||||
/**
|
||||
* @method string getAppId()
|
||||
* @method string getCreateTime()
|
||||
* @method string getInfoType()
|
||||
* @method string getAuthorizerAppid()
|
||||
* @method string getAuthorizationCode()
|
||||
* @method string getAuthorizationCodeExpiredTime()
|
||||
* @method string getPreAuthCode()
|
||||
*/
|
||||
class Authorized extends OpenPlatformEvent
|
||||
{
|
||||
}
|
||||
35
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/OpenPlatformEvent.php
vendored
Normal file
35
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/OpenPlatformEvent.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Events\OpenPlatform;
|
||||
|
||||
abstract class OpenPlatformEvent
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $payload;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param mixed $payload
|
||||
*/
|
||||
public function __construct($payload)
|
||||
{
|
||||
$this->payload = $payload;
|
||||
}
|
||||
|
||||
public function __call($name, $args)
|
||||
{
|
||||
return $this->payload[substr($name, 3)] ?? null;
|
||||
}
|
||||
}
|
||||
22
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/Unauthorized.php
vendored
Normal file
22
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/Unauthorized.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Events\OpenPlatform;
|
||||
|
||||
/**
|
||||
* @method string getAppId()
|
||||
* @method string getCreateTime()
|
||||
* @method string getInfoType()
|
||||
* @method string getAuthorizerAppid()
|
||||
*/
|
||||
class Unauthorized extends OpenPlatformEvent
|
||||
{
|
||||
}
|
||||
25
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/UpdateAuthorized.php
vendored
Normal file
25
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/UpdateAuthorized.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Events\OpenPlatform;
|
||||
|
||||
/**
|
||||
* @method string getAppId()
|
||||
* @method string getCreateTime()
|
||||
* @method string getInfoType()
|
||||
* @method string getAuthorizerAppid()
|
||||
* @method string getAuthorizationCode()
|
||||
* @method string getAuthorizationCodeExpiredTime()
|
||||
* @method string getPreAuthCode()
|
||||
*/
|
||||
class UpdateAuthorized extends OpenPlatformEvent
|
||||
{
|
||||
}
|
||||
22
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/VerifyTicketRefreshed.php
vendored
Normal file
22
vendor/overtrue/laravel-wechat/src/Events/OpenPlatform/VerifyTicketRefreshed.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Events\OpenPlatform;
|
||||
|
||||
/**
|
||||
* @method string getAppId()
|
||||
* @method string getCreateTime()
|
||||
* @method string getInfoType()
|
||||
* @method string getComponentVerifyTicket()
|
||||
*/
|
||||
class VerifyTicketRefreshed extends OpenPlatformEvent
|
||||
{
|
||||
}
|
||||
79
vendor/overtrue/laravel-wechat/src/Events/WeChatUserAuthorized.php
vendored
Normal file
79
vendor/overtrue/laravel-wechat/src/Events/WeChatUserAuthorized.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Overtrue\Socialite\User;
|
||||
|
||||
class WeChatUserAuthorized
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $user;
|
||||
|
||||
public $isNewSession;
|
||||
|
||||
public $account;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Overtrue\Socialite\User $user
|
||||
* @param bool $isNewSession
|
||||
*/
|
||||
public function __construct(User $user, $isNewSession = false, string $account)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->isNewSession = $isNewSession;
|
||||
$this->account = $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the authorized user.
|
||||
*
|
||||
* @return \Overtrue\Socialite\User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of official account.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAccount()
|
||||
{
|
||||
return $this->account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the user session is first created.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNewSession()
|
||||
{
|
||||
return $this->isNewSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should be broadcast on.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
72
vendor/overtrue/laravel-wechat/src/Facade.php
vendored
Normal file
72
vendor/overtrue/laravel-wechat/src/Facade.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat;
|
||||
|
||||
use Illuminate\Support\Facades\Facade as LaravelFacade;
|
||||
|
||||
/**
|
||||
* Class Facade.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class Facade extends LaravelFacade
|
||||
{
|
||||
/**
|
||||
* 默认为 Server.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getFacadeAccessor()
|
||||
{
|
||||
return 'wechat.official_account';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \EasyWeChat\OfficialAccount\Application
|
||||
*/
|
||||
public static function officialAccount($name = '')
|
||||
{
|
||||
return $name ? app('wechat.official_account.'.$name) : app('wechat.official_account');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \EasyWeChat\Work\AgentFactory
|
||||
*/
|
||||
public static function work($name = '')
|
||||
{
|
||||
return $name ? app('wechat.work.'.$name) : app('wechat.work');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \EasyWeChat\Payment\Application
|
||||
*/
|
||||
public static function payment($name = '')
|
||||
{
|
||||
return $name ? app('wechat.payment.'.$name) : app('wechat.payment');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \EasyWeChat\MiniProgram\Application
|
||||
*/
|
||||
public static function miniProgram($name = '')
|
||||
{
|
||||
return $name ? app('wechat.mini_program.'.$name) : app('wechat.mini_program');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \EasyWeChat\OpenPlatform\Application
|
||||
*/
|
||||
public static function openPlatform($name = '')
|
||||
{
|
||||
return $name ? app('wechat.open_platform.'.$name) : app('wechat.open_platform');
|
||||
}
|
||||
}
|
||||
86
vendor/overtrue/laravel-wechat/src/Middleware/OAuthAuthenticate.php
vendored
Normal file
86
vendor/overtrue/laravel-wechat/src/Middleware/OAuthAuthenticate.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use http\Env\Request;
|
||||
use Overtrue\LaravelWeChat\Events\WeChatUserAuthorized;
|
||||
|
||||
/**
|
||||
* Class OAuthAuthenticate.
|
||||
*/
|
||||
class OAuthAuthenticate
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $scopes
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $account = 'default', $scopes = null)
|
||||
{
|
||||
// $account 与 $scopes 写反的情况
|
||||
if (is_array($scopes) || (\is_string($account) && str_is('snsapi_*', $account))) {
|
||||
list($account, $scopes) = [$scopes, $account];
|
||||
$account || $account = 'default';
|
||||
}
|
||||
|
||||
$isNewSession = false;
|
||||
$sessionKey = \sprintf('wechat.oauth_user.%s', $account);
|
||||
$config = config(\sprintf('wechat.official_account.%s', $account), []);
|
||||
$officialAccount = app(\sprintf('wechat.official_account.%s', $account));
|
||||
$scopes = $scopes ?: array_get($config, 'oauth.scopes', ['snsapi_base']);
|
||||
|
||||
if (is_string($scopes)) {
|
||||
$scopes = array_map('trim', explode(',', $scopes));
|
||||
}
|
||||
|
||||
$session = session($sessionKey, []);
|
||||
|
||||
if (!$session) {
|
||||
if ($request->has('code')) {
|
||||
session([$sessionKey => $officialAccount->oauth->user() ?? []]);
|
||||
$isNewSession = true;
|
||||
|
||||
Event::fire(new WeChatUserAuthorized(session($sessionKey), $isNewSession, $account));
|
||||
|
||||
return redirect()->to($this->getTargetUrl($request));
|
||||
}
|
||||
|
||||
session()->forget($sessionKey);
|
||||
|
||||
return $officialAccount->oauth->scopes($scopes)->redirect($request->fullUrl());
|
||||
}
|
||||
|
||||
Event::fire(new WeChatUserAuthorized(session($sessionKey), $isNewSession, $account));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the target business url.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getTargetUrl($request)
|
||||
{
|
||||
$queries = array_except($request->query(), ['code', 'state']);
|
||||
|
||||
return $request->url().(empty($queries) ? '' : '?'.http_build_query($queries));
|
||||
}
|
||||
}
|
||||
115
vendor/overtrue/laravel-wechat/src/ServiceProvider.php
vendored
Normal file
115
vendor/overtrue/laravel-wechat/src/ServiceProvider.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\LaravelWeChat;
|
||||
|
||||
use EasyWeChat\MiniProgram\Application as MiniProgram;
|
||||
use EasyWeChat\OfficialAccount\Application as OfficialAccount;
|
||||
use EasyWeChat\OpenPlatform\Application as OpenPlatform;
|
||||
use EasyWeChat\Payment\Application as Payment;
|
||||
use EasyWeChat\Work\Application as Work;
|
||||
use Illuminate\Foundation\Application as LaravelApplication;
|
||||
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
|
||||
use Laravel\Lumen\Application as LumenApplication;
|
||||
|
||||
/**
|
||||
* Class ServiceProvider.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class ServiceProvider extends LaravelServiceProvider
|
||||
{
|
||||
/**
|
||||
* Boot the provider.
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the config.
|
||||
*/
|
||||
protected function setupConfig()
|
||||
{
|
||||
$source = realpath(__DIR__.'/config.php');
|
||||
|
||||
if ($this->app instanceof LaravelApplication && $this->app->runningInConsole()) {
|
||||
$this->publishes([$source => config_path('wechat.php')], 'laravel-wechat');
|
||||
} elseif ($this->app instanceof LumenApplication) {
|
||||
$this->app->configure('wechat');
|
||||
}
|
||||
|
||||
$this->mergeConfigFrom($source, 'wechat');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->setupConfig();
|
||||
|
||||
$apps = [
|
||||
'official_account' => OfficialAccount::class,
|
||||
'work' => Work::class,
|
||||
'mini_program' => MiniProgram::class,
|
||||
'payment' => Payment::class,
|
||||
'open_platform' => OpenPlatform::class,
|
||||
];
|
||||
|
||||
foreach ($apps as $name => $class) {
|
||||
if (empty(config('wechat.'.$name))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($config = config('wechat.route.'.$name)) {
|
||||
$this->getRouter()->group($config['attributes'], function ($router) use ($config) {
|
||||
$router->post($config['uri'], $config['action']);
|
||||
});
|
||||
}
|
||||
|
||||
if (!empty(config('wechat.'.$name.'.app_id')) || !empty(config('wechat.'.$name.'.corp_id'))) {
|
||||
$accounts = [
|
||||
'default' => config('wechat.'.$name),
|
||||
];
|
||||
config(['wechat.'.$name.'.default' => $accounts['default']]);
|
||||
} else {
|
||||
$accounts = config('wechat.'.$name);
|
||||
}
|
||||
|
||||
foreach ($accounts as $account => $config) {
|
||||
$this->app->singleton("wechat.{$name}.{$account}", function ($laravelApp) use ($name, $account, $config, $class) {
|
||||
$app = new $class(array_merge(config('wechat.defaults', []), $config));
|
||||
if (config('wechat.defaults.use_laravel_cache')) {
|
||||
$app['cache'] = new CacheBridge($laravelApp['cache.store']);
|
||||
}
|
||||
$app['request'] = $laravelApp['request'];
|
||||
|
||||
return $app;
|
||||
});
|
||||
}
|
||||
$this->app->alias("wechat.{$name}.default", 'wechat.'.$name);
|
||||
$this->app->alias("wechat.{$name}.default", 'easywechat.'.$name);
|
||||
|
||||
$this->app->alias('wechat.'.$name, $class);
|
||||
$this->app->alias('easywechat.'.$name, $class);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRouter()
|
||||
{
|
||||
if ($this->app instanceof LumenApplication && !class_exists('Laravel\Lumen\Routing\Router')) {
|
||||
return $this->app;
|
||||
}
|
||||
|
||||
return $this->app->router;
|
||||
}
|
||||
}
|
||||
131
vendor/overtrue/laravel-wechat/src/config.php
vendored
Normal file
131
vendor/overtrue/laravel-wechat/src/config.php
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/laravel-wechat.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
return [
|
||||
/*
|
||||
* 默认配置,将会合并到各模块中
|
||||
*/
|
||||
'defaults' => [
|
||||
/*
|
||||
* 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
|
||||
*/
|
||||
'response_type' => 'array',
|
||||
|
||||
/*
|
||||
* 使用 Laravel 的缓存系统
|
||||
*/
|
||||
'use_laravel_cache' => true,
|
||||
|
||||
/*
|
||||
* 日志配置
|
||||
*
|
||||
* level: 日志级别,可选为:
|
||||
* debug/info/notice/warning/error/critical/alert/emergency
|
||||
* file:日志文件位置(绝对路径!!!),要求可写权限
|
||||
*/
|
||||
'log' => [
|
||||
'level' => env('WECHAT_LOG_LEVEL', 'debug'),
|
||||
'file' => env('WECHAT_LOG_FILE', storage_path('logs/wechat.log')),
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
* 路由配置
|
||||
*/
|
||||
'route' => [
|
||||
/*
|
||||
* 开放平台第三方平台路由配置
|
||||
*/
|
||||
// 'open_platform' => [
|
||||
// 'uri' => 'serve',
|
||||
// 'action' => Overtrue\LaravelWeChat\Controllers\OpenPlatformController::class,
|
||||
// 'attributes' => [
|
||||
// 'prefix' => 'open-platform',
|
||||
// 'middleware' => null,
|
||||
// ],
|
||||
// ],
|
||||
],
|
||||
|
||||
/*
|
||||
* 公众号
|
||||
*/
|
||||
'official_account' => [
|
||||
'default' => [
|
||||
'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', 'your-app-id'), // AppID
|
||||
'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', 'your-app-secret'), // AppSecret
|
||||
'token' => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', 'your-token'), // Token
|
||||
'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', ''), // EncodingAESKey
|
||||
|
||||
/*
|
||||
* OAuth 配置
|
||||
*
|
||||
* scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
|
||||
* callback:OAuth授权完成后的回调页地址(如果使用中间件,则随便填写。。。)
|
||||
*/
|
||||
// 'oauth' => [
|
||||
// 'scopes' => array_map('trim', explode(',', env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_SCOPES', 'snsapi_userinfo'))),
|
||||
// 'callback' => env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_CALLBACK', '/examples/oauth_callback.php'),
|
||||
// ],
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
* 开放平台第三方平台
|
||||
*/
|
||||
// 'open_platform' => [
|
||||
// 'default' => [
|
||||
// 'app_id' => env('WECHAT_OPEN_PLATFORM_APPID', ''),
|
||||
// 'secret' => env('WECHAT_OPEN_PLATFORM_SECRET', ''),
|
||||
// 'token' => env('WECHAT_OPEN_PLATFORM_TOKEN', ''),
|
||||
// 'aes_key' => env('WECHAT_OPEN_PLATFORM_AES_KEY', ''),
|
||||
// ],
|
||||
// ],
|
||||
|
||||
/*
|
||||
* 小程序
|
||||
*/
|
||||
// 'mini_program' => [
|
||||
// 'default' => [
|
||||
// 'app_id' => env('WECHAT_MINI_PROGRAM_APPID', ''),
|
||||
// 'secret' => env('WECHAT_MINI_PROGRAM_SECRET', ''),
|
||||
// 'token' => env('WECHAT_MINI_PROGRAM_TOKEN', ''),
|
||||
// 'aes_key' => env('WECHAT_MINI_PROGRAM_AES_KEY', ''),
|
||||
// ],
|
||||
// ],
|
||||
|
||||
/*
|
||||
* 微信支付
|
||||
*/
|
||||
// 'payment' => [
|
||||
// 'default' => [
|
||||
// 'sandbox' => env('WECHAT_PAYMENT_SANDBOX', false),
|
||||
// 'app_id' => env('WECHAT_PAYMENT_APPID', ''),
|
||||
// 'mch_id' => env('WECHAT_PAYMENT_MCH_ID', 'your-mch-id'),
|
||||
// 'key' => env('WECHAT_PAYMENT_KEY', 'key-for-signature'),
|
||||
// 'cert_path' => env('WECHAT_PAYMENT_CERT_PATH', 'path/to/cert/apiclient_cert.pem'), // XXX: 绝对路径!!!!
|
||||
// 'key_path' => env('WECHAT_PAYMENT_KEY_PATH', 'path/to/cert/apiclient_key.pem'), // XXX: 绝对路径!!!!
|
||||
// 'notify_url' => 'http://example.com/payments/wechat-notify', // 默认支付结果通知地址
|
||||
// ],
|
||||
// // ...
|
||||
// ],
|
||||
|
||||
/*
|
||||
* 企业微信
|
||||
*/
|
||||
// 'work' => [
|
||||
// 'default' => [
|
||||
// 'corp_id' => 'xxxxxxxxxxxxxxxxx',
|
||||
/// 'agent_id' => 100020,
|
||||
// 'secret' => env('WECHAT_WORK_AGENT_CONTACTS_SECRET', ''),
|
||||
// //...
|
||||
// ],
|
||||
// ],
|
||||
];
|
||||
9
vendor/overtrue/socialite/.gitignore
vendored
Normal file
9
vendor/overtrue/socialite/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/vendor
|
||||
composer.phar
|
||||
composer.lock
|
||||
.DS_Store
|
||||
/.idea
|
||||
Thumbs.db
|
||||
/*.php
|
||||
sftp-config.json
|
||||
.php_cs.cache
|
||||
28
vendor/overtrue/socialite/.php_cs
vendored
Normal file
28
vendor/overtrue/socialite/.php_cs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$header = <<<EOF
|
||||
This file is part of the overtrue/socialite.
|
||||
|
||||
(c) overtrue <i@overtrue.me>
|
||||
|
||||
This source file is subject to the MIT license that is bundled
|
||||
with this source code in the file LICENSE.
|
||||
EOF;
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setRiskyAllowed(true)
|
||||
->setRules(array(
|
||||
'@Symfony' => true,
|
||||
'header_comment' => array('header' => $header),
|
||||
'array_syntax' => array('syntax' => 'short'),
|
||||
'ordered_imports' => true,
|
||||
'no_useless_else' => true,
|
||||
'no_useless_return' => true,
|
||||
'php_unit_construct' => true,
|
||||
'php_unit_strict' => true,
|
||||
))
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->exclude('vendor')
|
||||
->in(__DIR__)
|
||||
)
|
||||
;
|
||||
13
vendor/overtrue/socialite/.travis.yml
vendored
Normal file
13
vendor/overtrue/socialite/.travis.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
|
||||
sudo: false
|
||||
dist: trusty
|
||||
|
||||
install: travis_retry composer install --no-interaction --prefer-source
|
||||
|
||||
script: vendor/bin/phpunit --verbose
|
||||
21
vendor/overtrue/socialite/LICENSE.txt
vendored
Normal file
21
vendor/overtrue/socialite/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) overtrue <i@overtrue.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
256
vendor/overtrue/socialite/README.md
vendored
Normal file
256
vendor/overtrue/socialite/README.md
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
<h1 align="center"> Socialite</h1>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/overtrue/socialite"><img src="https://travis-ci.org/overtrue/socialite.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/socialite"><img src="https://poser.pugx.org/overtrue/socialite/v/stable.svg" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/socialite"><img src="https://poser.pugx.org/overtrue/socialite/v/unstable.svg" alt="Latest Unstable Version"></a>
|
||||
<a href="https://scrutinizer-ci.com/g/overtrue/socialite/build-status/master"><img src="https://scrutinizer-ci.com/g/overtrue/socialite/badges/build.png?b=master" alt="Build Status"></a>
|
||||
<a href="https://scrutinizer-ci.com/g/overtrue/socialite/?branch=master"><img src="https://scrutinizer-ci.com/g/overtrue/socialite/badges/quality-score.png?b=master" alt="Scrutinizer Code Quality"></a>
|
||||
<a href="https://scrutinizer-ci.com/g/overtrue/socialite/?branch=master"><img src="https://scrutinizer-ci.com/g/overtrue/socialite/badges/coverage.png?b=master" alt="Code Coverage"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/socialite"><img src="https://poser.pugx.org/overtrue/socialite/downloads" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/overtrue/socialite"><img src="https://poser.pugx.org/overtrue/socialite/license" alt="License"></a>
|
||||
</p>
|
||||
|
||||
|
||||
<p align="center">Socialite is an OAuth2 Authentication tool. It is inspired by <a href="https://github.com/laravel/socialite">laravel/socialite</a>, You can easily use it in any PHP project.</p>
|
||||
|
||||
|
||||
<p align="center">
|
||||
<br>
|
||||
<b>创造不息,交付不止</b>
|
||||
<br>
|
||||
<a href="https://www.yousails.com">
|
||||
<img src="https://yousails.com/banners/brand.png" width=350>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
# Requirement
|
||||
|
||||
```
|
||||
PHP >= 7.0
|
||||
```
|
||||
# Installation
|
||||
|
||||
```shell
|
||||
$ composer require "overtrue/socialite" -vvv
|
||||
```
|
||||
|
||||
# Usage
|
||||
|
||||
For Laravel 5: [overtrue/laravel-socialite](https://github.com/overtrue/laravel-socialite)
|
||||
|
||||
`authorize.php`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
use Overtrue\Socialite\SocialiteManager;
|
||||
|
||||
$config = [
|
||||
'github' => [
|
||||
'client_id' => 'your-app-id',
|
||||
'client_secret' => 'your-app-secret',
|
||||
'redirect' => 'http://localhost/socialite/callback.php',
|
||||
],
|
||||
];
|
||||
|
||||
$socialite = new SocialiteManager($config);
|
||||
|
||||
$response = $socialite->driver('github')->redirect();
|
||||
|
||||
echo $response;// or $response->send();
|
||||
```
|
||||
|
||||
`callback.php`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
// ...
|
||||
$user = $socialite->driver('github')->user();
|
||||
|
||||
$user->getId(); // 1472352
|
||||
$user->getNickname(); // "overtrue"
|
||||
$user->getName(); // "安正超"
|
||||
$user->getEmail(); // "anzhengchao@gmail.com"
|
||||
$user->getProviderName(); // GitHub
|
||||
...
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Now we support the following sites:
|
||||
|
||||
`facebook`, `github`, `google`, `linkedin`, `outlook`, `weibo`, `qq`, `wechat`, `wechat_open`, and `douban`.
|
||||
|
||||
Each drive uses the same configuration keys: `client_id`, `client_secret`, `redirect`.
|
||||
|
||||
Example:
|
||||
```
|
||||
...
|
||||
'weibo' => [
|
||||
'client_id' => 'your-app-id',
|
||||
'client_secret' => 'your-app-secret',
|
||||
'redirect' => 'http://localhost/socialite/callback.php',
|
||||
],
|
||||
...
|
||||
```
|
||||
|
||||
### Scope
|
||||
|
||||
Before redirecting the user, you may also set "scopes" on the request using the scope method. This method will overwrite all existing scopes:
|
||||
|
||||
```php
|
||||
$response = $socialite->driver('github')
|
||||
->scopes(['scope1', 'scope2'])->redirect();
|
||||
|
||||
```
|
||||
|
||||
### Redirect URL
|
||||
|
||||
You may also want to dynamic set `redirect`,you can use the following methods to change the `redirect` URL:
|
||||
|
||||
```php
|
||||
$socialite->redirect($url);
|
||||
// or
|
||||
$socialite->withRedirectUrl($url)->redirect();
|
||||
// or
|
||||
$socialite->setRedirectUrl($url)->redirect();
|
||||
```
|
||||
|
||||
> WeChat scopes:
|
||||
- `snsapi_base`, `snsapi_userinfo` - Used to Media Platform Authentication.
|
||||
- `snsapi_login` - Used to web Authentication.
|
||||
|
||||
### Additional parameters
|
||||
|
||||
To include any optional parameters in the request, call the with method with an associative array:
|
||||
|
||||
```php
|
||||
$response = $socialite->driver('google')
|
||||
->with(['hd' => 'example.com'])->redirect();
|
||||
```
|
||||
|
||||
### User interface
|
||||
|
||||
#### Standard user api:
|
||||
|
||||
```php
|
||||
|
||||
$user = $socialite->driver('weibo')->user();
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1472352,
|
||||
"nickname": "overtrue",
|
||||
"name": "安正超",
|
||||
"email": "anzhengchao@gmail.com",
|
||||
"avatar": "https://avatars.githubusercontent.com/u/1472352?v=3",
|
||||
"original": {
|
||||
"login": "overtrue",
|
||||
"id": 1472352,
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1472352?v=3",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/overtrue",
|
||||
"html_url": "https://github.com/overtrue",
|
||||
...
|
||||
},
|
||||
"token": {
|
||||
"access_token": "5b1dc56d64fffbd052359f032716cc4e0a1cb9a0",
|
||||
"token_type": "bearer",
|
||||
"scope": "user:email"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can fetch the user attribute as a array key like this:
|
||||
|
||||
```php
|
||||
$user['id']; // 1472352
|
||||
$user['nickname']; // "overtrue"
|
||||
$user['name']; // "安正超"
|
||||
$user['email']; // "anzhengchao@gmail.com"
|
||||
...
|
||||
```
|
||||
|
||||
Or using method:
|
||||
|
||||
```php
|
||||
$user->getId();
|
||||
$user->getNickname();
|
||||
$user->getName();
|
||||
$user->getEmail();
|
||||
$user->getAvatar();
|
||||
$user->getOriginal();
|
||||
$user->getToken();// or $user->getAccessToken()
|
||||
$user->getProviderName(); // GitHub/Google/Facebook...
|
||||
```
|
||||
|
||||
#### Get original response from OAuth API
|
||||
|
||||
The `$user->getOriginal()` method will return an array of the API raw response.
|
||||
|
||||
#### Get access token Object
|
||||
|
||||
You can get the access token instance of current session by call `$user->getToken()` or `$user->getAccessToken()` or `$user['token']` .
|
||||
|
||||
|
||||
### Get user with access token
|
||||
|
||||
```php
|
||||
$accessToken = new AccessToken(['access_token' => $accessToken]);
|
||||
$user = $socialite->user($accessToken);
|
||||
```
|
||||
|
||||
|
||||
### Custom Session or Request instance.
|
||||
|
||||
You can set the request with your custom `Request` instance which instanceof `Symfony\Component\HttpFoundation\Request` before you call `driver` method.
|
||||
|
||||
|
||||
```php
|
||||
|
||||
$request = new Request(); // or use AnotherCustomRequest.
|
||||
|
||||
$socialite = new SocialiteManager($config, $request);
|
||||
```
|
||||
|
||||
Or set request to `SocialiteManager` instance:
|
||||
|
||||
```php
|
||||
$socialite->setRequest($request);
|
||||
```
|
||||
|
||||
You can get the request from `SocialiteManager` instance by `getRequest()`:
|
||||
|
||||
```php
|
||||
$request = $socialite->getRequest();
|
||||
```
|
||||
|
||||
#### Set custom session manager.
|
||||
|
||||
By default, the `SocialiteManager` use `Symfony\Component\HttpFoundation\Session\Session` instance as session manager, you can change it as following lines:
|
||||
|
||||
```php
|
||||
$session = new YourCustomSessionManager();
|
||||
$socialite->getRequest()->setSession($session);
|
||||
```
|
||||
|
||||
> Your custom session manager must be implement the [`Symfony\Component\HttpFoundation\Session\SessionInterface`](http://api.symfony.com/3.0/Symfony/Component/HttpFoundation/Session/SessionInterface.html).
|
||||
|
||||
Enjoy it! :heart:
|
||||
|
||||
# Reference
|
||||
|
||||
- [Google - OpenID Connect](https://developers.google.com/identity/protocols/OpenIDConnect)
|
||||
- [Facebook - Graph API](https://developers.facebook.com/docs/graph-api)
|
||||
- [Linkedin - Authenticating with OAuth 2.0](https://developer.linkedin.com/docs/oauth2)
|
||||
- [微博 - OAuth 2.0 授权机制说明](http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E)
|
||||
- [QQ - OAuth 2.0 登录QQ](http://wiki.connect.qq.com/oauth2-0%E7%AE%80%E4%BB%8B)
|
||||
- [微信公众平台 - OAuth文档](http://mp.weixin.qq.com/wiki/9/01f711493b5a02f24b04365ac5d8fd95.html)
|
||||
- [微信开放平台 - 网站应用微信登录开发指南](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN)
|
||||
- [微信开放平台 - 代公众号发起网页授权](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318590&token=&lang=zh_CN)
|
||||
- [豆瓣 - OAuth 2.0 授权机制说明](http://developers.douban.com/wiki/?title=oauth2)
|
||||
|
||||
# License
|
||||
|
||||
MIT
|
||||
26
vendor/overtrue/socialite/composer.json
vendored
Normal file
26
vendor/overtrue/socialite/composer.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "overtrue/socialite",
|
||||
"description": "A collection of OAuth 2 packages that extracts from laravel/socialite.",
|
||||
"keywords": ["OAuth", "social", "login", "Weibo", "WeChat", "QQ"],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Overtrue\\Socialite\\": "src/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0",
|
||||
"guzzlehttp/guzzle": "~5.0|~6.0",
|
||||
"symfony/http-foundation": "^2.7|^3.0|^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9",
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"email": "anzhengchao@gmail.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user