├── .github └── workflows │ ├── codacy-analysis.yml │ └── shiftleft-analysis.yml ├── .gitignore ├── LICENSE ├── README.md ├── composer.json └── src ├── Channels ├── DingtalkRobotChannel.php ├── LarkRobotChannel.php ├── WechatRobotChannel.php └── WechatTemplateMessageChannel.php ├── Config ├── helpers-pinyin.php └── helpers.php ├── Console ├── Commands │ ├── ExtendCommand.php │ └── GenerateCommand.php └── stubs │ ├── Controller.stub │ ├── DingtalkRobotNotification.stub │ ├── LarkRobotNotification.stub │ ├── Model.stub │ ├── WechatNotification.stub │ └── WechatTemplateMessageNotification.stub ├── Exchange └── Exchange.php ├── Facade └── Helper.php ├── Notifications ├── DingtalkRobotNotification.php ├── LarkRobotNotification.php ├── WechatRobotNotification.php └── WechatTemplateMessageNotification.php ├── PhpHelps └── LaravelHelp.php ├── Providers └── HelpPluginServiceProvider.php └── Services └── TTV2Service.php /.github/workflows/codacy-analysis.yml: -------------------------------------------------------------------------------- 1 | # This workflow checks out code, performs a Codacy security scan 2 | # and integrates the results with the 3 | # GitHub Advanced Security code scanning feature. For more information on 4 | # the Codacy security scan action usage and parameters, see 5 | # https://github.com/codacy/codacy-analysis-cli-action. 6 | # For more information on Codacy Analysis CLI in general, see 7 | # https://github.com/codacy/codacy-analysis-cli. 8 | 9 | name: Codacy Security Scan 10 | 11 | on: 12 | push: 13 | branches: [ master ] 14 | pull_request: 15 | # The branches below must be a subset of the branches above 16 | branches: [ master ] 17 | schedule: 18 | - cron: '23 7 * * 2' 19 | 20 | jobs: 21 | codacy-security-scan: 22 | name: Codacy Security Scan 23 | runs-on: ubuntu-latest 24 | steps: 25 | # Checkout the repository to the GitHub Actions runner 26 | - name: Checkout code 27 | uses: actions/checkout@v2 28 | 29 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis 30 | - name: Run Codacy Analysis CLI 31 | uses: codacy/codacy-analysis-cli-action@1.1.0 32 | with: 33 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository 34 | # You can also omit the token and run the tools that support default configurations 35 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 36 | verbose: true 37 | output: results.sarif 38 | format: sarif 39 | # Adjust severity of non-security issues 40 | gh-code-scanning-compat: true 41 | # Force 0 exit code to allow SARIF file generation 42 | # This will handover control about PR rejection to the GitHub side 43 | max-allowed-issues: 2147483647 44 | 45 | # Upload the SARIF file generated in the previous step 46 | - name: Upload SARIF results file 47 | uses: github/codeql-action/upload-sarif@v1 48 | with: 49 | sarif_file: results.sarif 50 | -------------------------------------------------------------------------------- /.github/workflows/shiftleft-analysis.yml: -------------------------------------------------------------------------------- 1 | # This workflow integrates Scan with GitHub's code scanning feature 2 | # Scan is a free open-source security tool for modern DevOps teams from ShiftLeft 3 | # Visit https://slscan.io/en/latest/integrations/code-scan for help 4 | name: SL Scan 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | # The branches below must be a subset of the branches above 11 | branches: [ master ] 12 | schedule: 13 | - cron: '23 5 * * 0' 14 | 15 | jobs: 16 | Scan-Build: 17 | # Scan runs on ubuntu, mac and windows 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v2 21 | # Instructions 22 | # 1. Setup JDK, Node.js, Python etc depending on your project type 23 | # 2. Compile or build the project before invoking scan 24 | # Example: mvn compile, or npm install or pip install goes here 25 | # 3. Invoke Scan with the github token. Leave the workspace empty to use relative url 26 | 27 | - name: Perform Scan 28 | uses: ShiftLeftSecurity/scan-action@master 29 | env: 30 | WORKSPACE: "" 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | SCAN_AUTO_BUILD: true 33 | with: 34 | output: reports 35 | # Scan auto-detects the languages in your project. To override uncomment the below variable and set the type 36 | # type: credscan,java 37 | # type: python 38 | 39 | - name: Upload report 40 | uses: github/codeql-action/upload-sarif@v1 41 | with: 42 | sarif_file: reports 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /vendor 3 | composer.lock 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Zhou Jiawei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | * [x] 通知发送(包括但不限于以下频道【更多待接入】) 3 | - * [x] 钉钉机器人 4 | - * [x] 企业微信机器人 5 | - * [x] 微信模板消息 6 | - * [x] 飞书机器人 7 | * [x] 威妥码拼音互转获取 8 | * [x] 汇率实时互转获取(Openexchangerates Api) 9 | * [x] 全球城市中英互转获取 及更新 10 | * [x] 抖音新交易系统 (非旧交易系统 目前旧交易系统已经被官方废弃 ,正在更新) 11 | 本包将持续更新!请详细文档托管 https://learnku.com/docs/laravel-help-plugin 12 | 13 | 如发现bug 请直接提issue或者直接提pr,造成的不便请谅解。 14 | 15 | 16 | 17 | # Laravel辅助工具包 18 | 19 |
24 | 25 | #### 目录 26 | 27 | - [安装说明](#composer) 28 | - [发布配置文件](#config) 29 | - [注册门面方法](#facade) 30 | - [消息驱动](#channel) 31 | - [钉钉机器人](#dingtalk) 32 | - [企业微信机器人](#wechat) 33 | - [微信模板消息](#wechatTemp) 34 | - [直接消息推送](#usem) 35 | - [钉钉机器人](#usedingtalk) 36 | - [企业微信机器人](#usewechat) 37 | - [微信模板消息](#usewechatTemp) 38 | - [Artisan命令示例](#artisan) 39 | - [国家获取转换](#country) 40 | - [Openexchangerates汇率实时获取](#openexchangerates) 41 | - [扩展Artisan命令](#extend) 42 | - [代码生成器](#generate) 43 | - [钉钉Notification模板生成](#generateDingtalk) 44 | - [企业微信Notification模板生成](#generateWechat) 45 | - [微信模板消息Notification模板生成](#generateWechat) 46 | - [威妥码互转汉语拼音-移步详细文档查看](#pinyin) 47 | - [抖音新交易系统](#tiktokPay) 48 | 49 | ## JetBrains 支持的项目 50 | 51 | 非常感谢 Jetbrains 为我提供了从事这个和其他开源项目的许可。 52 | 53 | [](https://www.jetbrains.com/?from=https://github.com/overtrue) 54 | 55 | 56 | 57 | 58 | 59 | # 安装说明 60 | 61 | 环境要求 本包依托于Laravel框架,其他框架暂不适用 62 | 63 | - php => ^7.0 64 | - guzzlehttp/guzzle => ^6.3" 65 | - laravel/framework => ~5.5|~6.0|~7.0|~8.0|~9.0 66 | - overtrue/laravel-wechat => ~5.0 67 | 68 | 使用composer安装 69 | 70 | `composer require chowjiawei/laravel-help-plugin` 71 | 72 | 73 | # 发布配置文件 74 | 75 | - 使用工具包请运行Artisan命令 76 | 77 | `php artisan vendor:publish --provider="Chowjiawei\Helpers\Providers\HelpPluginServiceProvider"` 78 | 79 | - 如若使用微信模板消息则需要发布easywechat配置,本包默认内置easywechat: 80 | 81 | `php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"` 82 | 微信包的配置 按需填写 公共号配置 `official_account` 配置省略 83 | 84 | 85 | 86 | # 注册facade 87 | 88 | 本报提供laravel Facade便捷,如需使用可按如下配置 89 | 90 | 打开`config/app.php` 91 | 92 | 找到 `providers` 项添加 93 | 94 | ``` 95 | \Chowjiawei\Helpers\Providers\HelpPluginServiceProvider::class, 96 | ``` 97 | 98 | 找到 'aliases'添加 99 | 100 | ``` 101 | 'Helper'=>\Chowjiawei\Helpers\Facade\Helper::class 102 | ``` 103 | 104 | 105 | 106 | # 消息驱动 107 | 108 | - [钉钉机器人](#dingtalk) 109 | - [企业微信机器人](#wechat) 110 | - [微信模板消息](#wechatTemp) 111 | - [飞书机器人](#lark) 112 | 113 | 114 | ## 钉钉机器人消息发送驱动 115 | 116 | ``` 117 | use Chowjiawei\Helpers\Channels\DingtalkRobotChannel; 118 | 119 | public function via($notifiable) 120 | { 121 | return [DingtalkRobotChannel::class]; 122 | } 123 | ``` 124 | 125 | 126 | 127 | ## 微信机器人消息发送驱动 128 | 129 | ``` 130 | use Chowjiawei\Helpers\Channels\WechatRobotChannel; 131 | 132 | public function via($notifiable) 133 | { 134 | return [WechatRobotChannel::class]; 135 | } 136 | ``` 137 | 138 | 139 | ## 微信模板消息发送驱动 140 | 141 | 该驱动支持单用户发送和广播功能 142 | 143 | ``` 144 | use Chowjiawei\Helpers\Channels\WechatTemplateMessageChannel; 145 | 146 | public function via($notifiable) 147 | { 148 | return [WechatTemplateMessageChannel::class]; 149 | } 150 | ``` 151 | 152 | ``` 153 | Notification::route('dingtalk_robot', $key)->notify(new YourNotification()); 154 | Notification::route('wechat_robot', $key)->notify(new YourNotification()); 155 | Notification::route('Wechat_template_message', $key)->notify(new YourNotification()); 156 | ``` 157 | 158 | 159 | ## 飞书机器人消息发送驱动 160 | 161 | ``` 162 | use Chowjiawei\Helpers\Channels\DingtalkRobotChannel; 163 | 164 | public function via($notifiable) 165 | { 166 | return [DingtalkRobotChannel::class]; 167 | } 168 | ``` 169 | 170 | 171 | 172 | # 直接消息推送 173 | 174 | - [钉钉机器人](#usedingtalk) 175 | - [企业微信机器人](#usewechat) 176 | - [微信模板消息](#usewechatTemp) 177 | - [飞书机器人](#uselark) 178 | 179 | 180 | ### 钉钉: 181 | 182 | `use Chowjiawei\Helpers\Notifications\DingtalkRobotNotification;` 183 | 184 | `Notification::route('dingtalk_robot', env("DINGTALK_ROBOT")) 185 | ->notify(new DingtalkRobotNotification($message,$title));` 186 | 187 | 188 | ### 企业微信: 189 | 190 | `use Chowjiawei\Helpers\Notifications\WechatRobotNotification;` 191 | 192 | `Notification::route('wechat_robot', env("WECHAT_ROBOT)")) 193 | ->notify(new WechatRobotNotification($message));` 194 | 195 | 196 | ### 微信模板消息: 197 | 198 | 199 | 200 | `use Chowjiawei\Helpers\Notifications\WechatTemplateMessageNotification;` 201 | 202 | - 不指定用户(广播用户) 203 | 204 | `Notification::route('WechatTemplateMessage', null)->notify(new WechatTemplateMessageNotification($data));` 205 | 206 | - 指定用户 207 | 208 | ``` 209 | $user=['odAYnxOVy7vS266666666','odAYnxEuuTCf66666fov276666']; 210 | 211 | $template="iA2V1K45vS8IgUEvE666666EH3R-V-66666"; 212 | 213 | $data=[ 214 | 215 | "order_id"=>[ 216 | 217 | "value"=>"20200414234478934343", 218 | 219 | "color"=>"#173177" 220 | 221 | ], 222 | 223 | "package_id"=>[ 224 | 225 | "value"=>"SF4345454534", 226 | 227 | "color"=>"#173177" 228 | 229 | ], 230 | 231 | "remark"=>[ 232 | 233 | "value"=>'模板消息发送', 234 | 235 | "color"=>"#173177" 236 | 237 | ] 238 | 239 | ]; 240 | 241 | Notification::route('WechatTemplateMessage', $user)->notify(new WechatTemplateMessageNotification($data, $template)); 242 | 243 | ``` 244 | 245 | 246 | ### 飞书: 247 | 248 | `use Chowjiawei\Helpers\Notifications\LarkRobotNotification;` 249 | 250 | `Notification::route('lark', env("LARK_ROBOT")) 251 | ->notify(new DingtalkRobotNotification($message));` 252 | 253 | 254 | 255 | ### Artisan命令示例: 256 | 257 | 由于业务不同,工具默认提供了通知Notification模板,可以通过extend Artisan命令选择代码生成器生成 258 | 259 | 260 | 261 | 262 | # 国家获取转换 263 | 264 | 265 | ``` 266 | use Chowjiawei\Helpers\PhpHelps\LaravelHelp; 267 | 268 | 初始化辅助工具 269 | $help=new LaravelHelp(); 270 | 271 | 获取所有国家 272 | $help->getAllCountry(); 273 | 274 | 根据国家代码转国家名字 275 | $help->getCountryName('CN'); 276 | 根据国家名字转国家代码 277 | $help->getCountryName('China'); 278 | ``` 279 | 280 | or 281 | 还有更多可以下载包后体验哦 282 | 283 | ``` 284 | Helper::allCountry(); 285 | 286 | ``` 287 | 288 | # Openexchangerates汇率实时获取 289 | 290 | ``` 291 | use Chowjiawei\Helpers\Exchange\Exchange; 292 | //获取实时汇率 293 | $help->getChangerates(); 294 | ``` 295 | 将为您返回完整的汇率及接口信息,以下省略篇幅 296 | ``` 297 | { 298 | "disclaimer": "Usage subject to terms: https://openexchangerates.org/terms", 299 | "license": "https://openexchangerates.org/license", 300 | "timestamp": 1622097300, 301 | "base": "USD", 302 | "rates": { 303 | "AED": 3.6731, 304 | "AFN": 79.130257, 305 | "ALL": 101.073262, 306 | "AMD": 520.828816, 307 | "ANG": 1.796011, 308 | "AOA": 643.121, 309 | "ARS": 94.4963, 310 | "AUD": 1.291358, 311 | "AWG": 1.8, 312 | "AZN": 1.700805, 313 | "BAM": 1.604705, 314 | "BBD": 2, 315 | "BDT": 85.048855, 316 | "BGN": 1.601902, 317 | "BHD": 0.377012, 318 | "BIF": 1974.680206, 319 | 320 | ``` 321 | ``` 322 | use Chowjiawei\Helpers\Exchange\Exchange; 323 | //获取特定汇率 324 | $help->getSymbolChangerates(['GBP','EUR','AED','CAD']); 325 | ``` 326 | 将为您返回指定的汇率及接口信息 327 | ``` 328 | { 329 | disclaimer: "https://openexchangerates.org/terms/", 330 | license: "https://openexchangerates.org/license/", 331 | "timestamp": 1424127600, 332 | "base": "USD", 333 | "rates": { 334 | "AED": 3.67295, 335 | "CAD": 0.99075, 336 | "EUR": 0.793903, 337 | "GBP": 0.62885 338 | } 339 | } 340 | 341 | ``` 342 | 343 | 344 | 345 | 346 | 347 | # 扩展Artisan命令 348 | 插件为您提供了一个支持中文和英文的扩展命令,您可以用命令呼出,命令提供了以下功能 349 | 350 | ```php artisan extend --chinese ```中文 351 | 352 | ```php artisan extend ```英文 353 | 354 | - [钉钉Notification模板生成](#generateDingtalk) 355 | - [企业微信Notification模板生成](#generateWechat) 356 | - [微信模板消息Notification模板生成](#generateWechat) 357 | 358 | 359 | ## 威妥码拼音 360 | 361 | 单汉语拼音转威妥码拼音 362 | 363 | ``` 364 | Helper::changeHWWord("zhou"); 365 | ``` 366 | 367 | 368 |  369 | 370 | 371 | 372 | 长句汉语拼音转威妥码拼音 373 | 374 | ``` 375 | Helper::changeHWWord("zhou jia wei hao shuai"); 376 | ``` 377 | 378 | 379 |  380 | 381 | 单汉语拼音转威妥码拼音 382 | 383 | ``` 384 | Helper::changeWHWord("chou"); 385 | ``` 386 | 387 | 388 | 389 |  390 | 391 | 392 | 393 | 394 | 长句汉语拼音转威妥码拼音 395 | 396 | ``` 397 | Helper::changeWHWord("chou chia wei hao shuai a"); 398 | ``` 399 | 400 | 401 |  402 | 403 | 404 | ## 抖音新交易系统 405 | ```use Chowjiawei\Helpers\Services\TTV2Service;``` 406 | 407 | `helpers.php` 配置文件中 `tiktok` 选项 全部需要配置完全才可以使用 408 | 409 | - 查询订单 410 | 411 | ```php 412 | $tiktokService= new TTV2Service(); 413 | $tiktokService->query("站内订单号,非抖音侧订单号"); 414 | 正确时返回数组 其余返回空数组 415 | ``` 416 | 417 | - 发起退款 (单个订单单个订单项) 418 | 419 | ```php 420 | $tiktokService= new TTV2Service(); 421 | $tiktokService->refund("站内订单号,非抖音侧订单号", '价格 为分', '$itemOrderId'); 422 | 正确时返回true 其余返回false 423 | ``` 424 | 425 | - 发起退款 (单个订单多个订单项) 426 | 427 | ```php 428 | $item= [ 429 | [ 430 | "item_order_id" => '', 431 | "refund_amount" => (int)$price 432 | ], 433 | [ 434 | "item_order_id" => '', 435 | "refund_amount" => (int)$price 436 | ], 437 | ]; 438 | 439 | $tiktokService= new TTV2Service(); 440 | $tiktokService->refundManyItem("站内订单号,非抖音侧订单号",$item); 441 | 正确时返回true 其余返回false 442 | ``` 443 | - 同意退款 444 | 445 | ```php 446 | $tiktokService= new TTV2Service(); 447 | $tiktokService->agreeRefund("站内订单号,非抖音侧订单号"); 448 | 正确时返回true 其余返回false 449 | ``` 450 | 451 | - 查询退款 452 | 453 | ```php 454 | $tiktokService= new TTV2Service(); 455 | $tiktokService->getRefund("站内订单号,非抖音侧订单号"); 456 | 返回数组 457 | ``` 458 | 459 | - 发起分账 460 | 461 | ```php 462 | $tiktokService= new TTV2Service(); 463 | $tiktokService->settle("站内订单号,非抖音侧订单号", "分账描述"); 464 | 正确时返回true 其余返回false 465 | ``` 466 | 467 | - 设置回调配置 468 | 469 | #### `config`中配置完成后 `$settingData`可以不传 470 | 如果需要再次自定义或者扩展更多糊掉参数 可以传详细参数 更多参数参考抖音 471 | ```php 472 | 473 | $settingData = [ 474 | 'create_order_callback' => "", 475 | 'refund_callback' => "", 476 | 'pay_callback' => "", 477 | ]; 478 | 479 | $tiktokService= new TTV2Service(); 480 | $tiktokService->settingReturn(array $settingData=[]); 481 | 正确时返回true 其余返回false 482 | ``` 483 | 484 | - 查询回调配置 485 | 486 | ```php 487 | $tiktokService= new TTV2Service(); 488 | $tiktokService->getSettingReturn(); 489 | 正确时返回数组,其余返回空数组 490 | ``` 491 | 492 | - 支付回调 493 | 494 | ```php 495 | $tiktokService= new TTV2Service(); 496 | $tiktokService->return($request); //控制器内 直接将接受的Request $request 传入return方法,即可自动验签,并返回接收参数 497 | 498 | 返回 `status` 正确为`true` 附带 `data`数据 错误为 `false` 499 | ``` 500 | 501 | 如果业务处理失败 需要手动返回抖音成功 502 | 503 | ```php 504 | $tiktokService->returnOK(); 505 | ``` 506 | 507 | 如果业务处理失败 需要手动返回抖音失败 508 | 509 | ```php 510 | $tiktokService->returnError($result='失败原因,可省略'); 511 | ``` 512 | 513 | - 预下单回调 514 | 515 | ```php 516 | $tiktokService= new TTV2Service(); 517 | $tiktokService->return($request); //控制器内 直接将接受的Request $request 传入return方法,即可自动验签,并返回接收参数 518 | ``` 519 | 520 | 如果业务处理失败 需要手动返回抖音成功 521 | ```php 522 | $tiktokService->returnOK(); 523 | ``` 524 | 如果业务处理失败 需要手动返回抖音失败 525 | ```php 526 | $tiktokService->returnError($result='失败原因,可省略'); 527 | ``` 528 | 529 | ### 建议将数组内数据 存起来 后续退款等操作都需要用 抖音不支持二次查询某些字段 530 | 如果需要退款 必须存储 item_order_id_list 获取如下: 531 | ```php 532 | $itemOrderId = json_decode($extendItem['msg'], true)['goods'][0]['item_order_id_list'][0]; 533 | ``` 534 | 535 | - 退款回调 536 | 537 | ```php 538 | $tiktokService= new TTV2Service(); 539 | $tiktokService->refundReturn($request); 540 | ``` 541 | 542 | 如果业务处理失败 需要手动返回抖音成功 543 | ```php 544 | $tiktokService->returnOK(); 545 | ``` 546 | 如果业务处理失败 需要手动返回抖音失败 547 | ```php 548 | $tiktokService->returnError($result='失败原因,可省略'); 549 | ``` 550 | 551 | - 分账回调 552 | 553 | ```php 554 | $tiktokService= new TTV2Service(); 555 | $tiktokService->settleCallback($request); 556 | ``` 557 | 558 | 如果业务处理失败 需要手动返回抖音成功 559 | ```php 560 | $tiktokService->returnOK(); 561 | ``` 562 | 如果业务处理失败 需要手动返回抖音失败 563 | ```php 564 | $tiktokService->returnError($result='失败原因,可省略'); 565 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chowjiawei/laravel-help-plugin", 3 | "type": "library", 4 | "description": "Integrating useful auxiliary functions into laravel,Assistant tools based on laravel.", 5 | "keywords": ["laravel", "plugin", "dingtalk", "wechat", "robot", "exchange"], 6 | "homepage": "https://github.com/chowjiawei/laravel-help-plugin", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "chowjiawei", 11 | "email": "1084186870@qq.com" 12 | } 13 | ], 14 | "require": { 15 | "php": "^7.0|^8.0", 16 | "guzzlehttp/guzzle": "^6.3|^7.0", 17 | "laravel/framework": "^6.0|^7.0|^8.0|^9.0", 18 | "overtrue/laravel-wechat":"^5.0|^6.0", 19 | "torann/geoip": "^3.0.2" 20 | }, 21 | "require-dev": { 22 | "squizlabs/php_codesniffer": "^3.6" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Chowjiawei\\Helpers\\": "src/" 27 | } 28 | }, 29 | "scripts": { 30 | "lint": "phpcs --standard=PSR1,PSR12,./ruleset.xml app/ routes/ config/", 31 | "lint-fix": "phpcbf --standard=PSR1,PSR12 src/" 32 | }, 33 | "extra": { 34 | "laravel": { 35 | "providers": [ 36 | "Chowjiawei\\Helpers\\Providers\\HelpPluginServiceProvider" 37 | ] 38 | } 39 | }, 40 | "config": { 41 | "allow-plugins": { 42 | "easywechat-composer/easywechat-composer": true 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Channels/DingtalkRobotChannel.php: -------------------------------------------------------------------------------- 1 | toDingtalkRobot($notifiable); 20 | $keys = $notifiable->routes['dingtalk_robot']; 21 | if (is_array($message)) { 22 | $data = array("msgtype" => "markdown", "markdown" => [ 23 | "title" => $message[1], 24 | "text" => $message[0], 25 | ]); 26 | } else { 27 | $data = array("msgtype" => "markdown", "markdown" => [ 28 | "title" => '通知', 29 | "text" => $message, 30 | ]); 31 | } 32 | $client = new Client(); 33 | if (strstr($keys, ',')) { 34 | $keys = explode(",", $keys); 35 | foreach ($keys as $key) { 36 | $url = 'https://oapi.dingtalk.com/robot/send?access_token=' . $key; 37 | $response = $client->post($url, [\GuzzleHttp\RequestOptions::JSON => $data]); 38 | } 39 | return; 40 | } 41 | $keys = is_array($keys) ? $keys : array($keys); 42 | foreach ($keys as $key) { 43 | $url = 'https://oapi.dingtalk.com/robot/send?access_token=' . $key; 44 | $response = $client->post($url, [\GuzzleHttp\RequestOptions::JSON => $data]); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Channels/LarkRobotChannel.php: -------------------------------------------------------------------------------- 1 | toLarkRobot($notifiable); 20 | $key = $notifiable->routes['lark']; 21 | $data = array( 22 | "msg_type" => "text", 23 | "content" => [ 24 | "text" => $message 25 | ] 26 | ); 27 | $client = new Client(); 28 | $key = is_array($key) ? $key : array($key); 29 | foreach ($key as $keys) { 30 | $url = 'https://open.feishu.cn/open-apis/bot/v2/hook/' . $keys; 31 | $response = $client->post($url, [\GuzzleHttp\RequestOptions::JSON => $data ]); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Channels/WechatRobotChannel.php: -------------------------------------------------------------------------------- 1 | toWechatRobot($notifiable); 21 | $inUserBroadcast = $notification->toWechatRobotBroadcast($notifiable); 22 | $key = $notifiable->routes['wechat_robot']; 23 | if (!$inUserBroadcast) { 24 | $data = array("msgtype" => "markdown", "markdown" => [ 25 | "content" => $message, 26 | ]); 27 | } 28 | if ($inUserBroadcast) { 29 | $data = array("msgtype" => "text", "text" => [ 30 | "content" => $message, 31 | "mentioned_list" => ["@all"], 32 | ]); 33 | } 34 | $client = new Client(); 35 | $key = is_array($key) ? $key : array($key); 36 | foreach ($key as $keys) { 37 | $url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' . $keys; 38 | $client->post($url, [\GuzzleHttp\RequestOptions::JSON => $data ]); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Channels/WechatTemplateMessageChannel.php: -------------------------------------------------------------------------------- 1 | toWechatTemplateMessage($notifiable); 34 | $data = $allData[0]; 35 | $template = $allData[1]; 36 | $openId = isset($notifiable->routes['Wechat_template_message']) ? $notifiable->routes['Wechat_template_message'] : null; 37 | $broad = false; 38 | if (!$openId) { 39 | $broad = true; 40 | } 41 | if ($openId) { 42 | $openId = is_array($openId) ? $openId : array($openId); 43 | } 44 | if ($broad == false) { 45 | foreach ($openId as $keys) { 46 | $app->template_message->send( 47 | [ 48 | 'touser' => $keys, 49 | 'template_id' => $template, 50 | "data" => $data 51 | ] 52 | ); 53 | } 54 | } 55 | // 没有指定用户,就广播 56 | if ($broad) { 57 | $app->broadcasting->sendText($data); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Config/helpers-pinyin.php: -------------------------------------------------------------------------------- 1 | [ 5 | "a" => "a", 6 | 7 | "ai" => "ai", 8 | 9 | "an" => "an", 10 | 11 | "ang" => "ang", 12 | 13 | "ao" => "ao", 14 | 15 | "ba" => "pa", 16 | 17 | "bai" => "pai", 18 | 19 | "ban" => "pan", 20 | 21 | "bang" => "pang", 22 | 23 | "bao" => "pao", 24 | 25 | "bei" => "pei", 26 | 27 | "ben" => "pen", 28 | 29 | "beng" => "peng", 30 | 31 | "bi" => "pi", 32 | 33 | "bian" => "pien", 34 | 35 | "biao" => "piao", 36 | 37 | "bie" => "pieh", 38 | 39 | "bin" => "pin", 40 | 41 | "bing" => "ping", 42 | 43 | "bo" => "po", 44 | 45 | "bu" => "pu", 46 | 47 | "ca" => "ts'a", 48 | 49 | "cai" => "ts'ai", 50 | 51 | "can" => "ts'an", 52 | 53 | "cang" => "ts'ang", 54 | 55 | "cao" => "ts'ao", 56 | 57 | "ce" => "ts'e", 58 | 59 | "cen" => "ts'en", 60 | 61 | "ceng" => "ts'eng", 62 | 63 | "cha" => "ch'a", 64 | 65 | "chai" => "ch'ai", 66 | 67 | "chan" => "ch'an", 68 | 69 | "chang" => "ch'ang", 70 | 71 | "chao" => "ch'ao", 72 | 73 | "che" => "ch'e", 74 | 75 | "chen" => "ch'en", 76 | 77 | "cheng" => "ch'eng", 78 | 79 | "chi" => "ch'ih", 80 | 81 | "chong" => "ch'ung", 82 | 83 | "chou" => "ch'ou", 84 | 85 | "chu" => "ch'u", 86 | 87 | "chuai" => "ch'uai", 88 | 89 | "chuan" => "ch'uan", 90 | 91 | "chuang" => "ch'uang", 92 | 93 | "chui" => "ch'ui", 94 | 95 | "chun" => "ch'un", 96 | 97 | "chuo" => "ch'o", 98 | 99 | "ci" => "tz'u", 100 | 101 | "cong" => "ts'ung", 102 | 103 | "cou" => "ts'ou", 104 | 105 | "cu" => "ts'u", 106 | 107 | "cuan" => "ts'uan", 108 | 109 | "cui" => "ts'ui", 110 | 111 | "cun" => "ts'un", 112 | 113 | "cuo" => "ts'o", 114 | 115 | "da" => "ta", 116 | 117 | "dai" => "tai", 118 | 119 | "dan" => "tan", 120 | 121 | "dang" => "tang", 122 | 123 | "dao" => "tao", 124 | 125 | "de" => "te", 126 | 127 | "deng" => "teng", 128 | 129 | "di" => "ti", 130 | 131 | "dian" => "tien", 132 | 133 | "diao" => "tiao", 134 | 135 | "die" => "tieh", 136 | 137 | "ding" => "ting", 138 | 139 | "diu" => "tiu", 140 | 141 | "dong" => "tung", 142 | 143 | "dou" => "tou", 144 | 145 | "du" => "tu", 146 | 147 | "duan" => "tuan", 148 | 149 | "dui" => "tui", 150 | 151 | "dun" => "tun", 152 | 153 | "duo" => "to", 154 | 155 | "e" => "o", 156 | 157 | "en" => "en", 158 | 159 | "er" => "erh", 160 | 161 | "fa" => "fa", 162 | 163 | "fan" => "fan", 164 | 165 | "fang" => "fang", 166 | 167 | "fei" => "fei", 168 | 169 | "fen" => "fen", 170 | 171 | "feng" => "feng", 172 | 173 | "fo" => "fo", 174 | 175 | "fou" => "fou", 176 | 177 | "fu" => "fu", 178 | 179 | "ga" => "ka", 180 | 181 | "gai" => "kai", 182 | 183 | "gan" => "kan", 184 | 185 | "gang" => "kang", 186 | 187 | "gao" => "kao", 188 | 189 | "ge" => "ko", 190 | 191 | "gen" => "ken", 192 | 193 | "geng" => "keng", 194 | 195 | "gong" => "kung", 196 | 197 | "gou" => "kou", 198 | 199 | "gu" => "ku", 200 | 201 | "gua" => "kua", 202 | 203 | "guai" => "kuai", 204 | 205 | "guan" => "kuan", 206 | 207 | "guang" => "kuang", 208 | 209 | "gui" => "kuei", 210 | 211 | "gun" => "kun", 212 | 213 | "guo" => "kuo", 214 | 215 | "ha" => "ha", 216 | 217 | "hai" => "hai", 218 | 219 | "han" => "han", 220 | 221 | "hang" => "hang", 222 | 223 | "hao" => "hao", 224 | 225 | "he" => "ho", 226 | 227 | "hei" => "hei", 228 | 229 | "hen" => "hen", 230 | 231 | "heng" => "heng", 232 | 233 | "hong" => "hung", 234 | 235 | "hou" => "hou", 236 | 237 | "hu" => "hu", 238 | 239 | "hua" => "hua", 240 | 241 | "huai" => "huai", 242 | 243 | "huan" => "huan", 244 | 245 | "huang" => "huang", 246 | 247 | "hui" => "hui", 248 | 249 | "hun" => "hun", 250 | 251 | "huo" => "huo", 252 | 253 | "ji" => "chi", 254 | 255 | "jia" => "chia", 256 | 257 | "jian" => "chien", 258 | 259 | "jiang" => "chiang", 260 | 261 | "jiao" => "chiao", 262 | 263 | "jie" => "chieh", 264 | 265 | "jin" => "chin", 266 | 267 | "jing" => "ching", 268 | 269 | "jiong" => "chiung", 270 | 271 | "jiu" => "chiu", 272 | 273 | "ju" => "chü", 274 | 275 | "juan" => "chüan", 276 | 277 | "jue" => "chüeh", 278 | 279 | "jun" => "chün", 280 | 281 | "ka" => "k'a", 282 | 283 | "kai" => "k'ai", 284 | 285 | "kan" => "k'an", 286 | 287 | "kang" => "k'ang", 288 | 289 | "kao" => "k'ao", 290 | 291 | "ke" => "k'o", 292 | 293 | "ken" => "k'en", 294 | 295 | "keng" => "k'eng", 296 | 297 | "kong" => "k'ung", 298 | 299 | "kou" => "k'ou", 300 | 301 | "ku" => "k'u", 302 | 303 | "kua" => "k'ua", 304 | 305 | "kuai" => "k'uai", 306 | 307 | "kuan" => "k'uan", 308 | 309 | "kuang" => "k'uang", 310 | 311 | "kui" => "k'uei", 312 | 313 | "kun" => "k'un", 314 | 315 | "kuo" => "k'uo", 316 | 317 | "lü" => "lü", 318 | 319 | "la" => "la", 320 | 321 | "lai" => "lai", 322 | 323 | "lan" => "lan", 324 | 325 | "lang" => "lang", 326 | 327 | "lao" => "lao", 328 | 329 | "le" => "le", 330 | 331 | "lei" => "lei", 332 | 333 | "leng" => "leng", 334 | 335 | "li" => "li", 336 | 337 | "lian" => "lien", 338 | 339 | "liang" => "liang", 340 | 341 | "liao" => "liao", 342 | 343 | "lie" => "lieh", 344 | 345 | "lin" => "lin", 346 | 347 | "ling" => "ling", 348 | 349 | "liu" => "liu", 350 | 351 | "long" => "lung", 352 | 353 | "lou" => "lou", 354 | 355 | "lu" => "lu", 356 | 357 | "luan" => "luan", 358 | 359 | // "luan" => "lüan", 360 | 361 | "lue" => "lüeh", 362 | 363 | "lun" => "lun", 364 | 365 | "luo" => "lo", 366 | 367 | "ma" => "ma", 368 | 369 | "mai" => "mai", 370 | 371 | "man" => "man", 372 | 373 | "mang" => "mang", 374 | 375 | "mao" => "mao", 376 | 377 | "mei" => "mei", 378 | 379 | "men" => "men", 380 | 381 | "meng" => "meng", 382 | 383 | "mi" => "mi", 384 | 385 | "mian" => "mien", 386 | 387 | "miao" => "miao", 388 | 389 | "mie" => "mieh", 390 | 391 | "min" => "min", 392 | 393 | "ming" => "ming", 394 | 395 | "miu" => "miu", 396 | 397 | "mo" => "mo", 398 | 399 | "mou" => "mou", 400 | 401 | "mu" => "mu", 402 | 403 | "nü" => "nü", 404 | 405 | "na" => "na", 406 | 407 | "nai" => "nai", 408 | 409 | "nan" => "nan", 410 | 411 | "nang" => "nang", 412 | 413 | "nao" => "nao", 414 | 415 | "nei" => "nei", 416 | 417 | "nen" => "nen", 418 | 419 | "neng" => "neng", 420 | 421 | "ni" => "ni", 422 | 423 | "nian" => "nien", 424 | 425 | "niang" => "niang", 426 | 427 | "niao" => "niao", 428 | 429 | "nie" => "nieh", 430 | 431 | "nin" => "nin", 432 | 433 | "ning" => "ning", 434 | 435 | "niu" => "niu", 436 | 437 | "nong" => "nung", 438 | 439 | "nou" => "nou", 440 | 441 | "nu" => "nu", 442 | 443 | "nuan" => "nuan", 444 | 445 | "nue" => "nüeh", 446 | 447 | "nuo" => "no", 448 | 449 | "ou" => "ou", 450 | 451 | "pa" => "p'a", 452 | 453 | "pai" => "p'ai", 454 | 455 | "pan" => "p'an", 456 | 457 | "pang" => "p'ang", 458 | 459 | "pao" => "p'ao", 460 | 461 | "pei" => "p'ei", 462 | 463 | "pen" => "p'en", 464 | 465 | "peng" => "p'eng", 466 | 467 | "pi" => "p'i", 468 | 469 | "pian" => "p'ien", 470 | 471 | "piao" => "p'iao", 472 | 473 | "pie" => "p'ieh", 474 | 475 | "pin" => "p'in", 476 | 477 | "ping" => "p'ing", 478 | 479 | "po" => "p'o", 480 | 481 | "pou" => "p'ou", 482 | 483 | "pu" => "p'u", 484 | 485 | "qi" => "ch'i", 486 | 487 | "qia" => "ch'ia", 488 | 489 | "qian" => "ch'ien", 490 | 491 | "qiang" => "ch'iang", 492 | 493 | "qiao" => "ch'iao", 494 | 495 | "qie" => "ch'ieh", 496 | 497 | "qin" => "ch'in", 498 | 499 | "qing" => "ch'ing", 500 | 501 | "qiong" => "ch'iung", 502 | 503 | "qiu" => "ch'iu", 504 | 505 | "qu" => "ch'ü", 506 | 507 | "quan" => "ch'üan", 508 | 509 | "que" => "ch'üeh", 510 | 511 | "qun" => "ch'ün", 512 | 513 | "ran" => "jan", 514 | 515 | "rang" => "jang", 516 | 517 | "rao" => "jao", 518 | 519 | "re" => "je", 520 | 521 | "ren" => "jen", 522 | 523 | "reng" => "jeng", 524 | 525 | "ri" => "jih", 526 | 527 | "rong" => "jung", 528 | 529 | "rou" => "jou", 530 | 531 | "ru" => "ju", 532 | 533 | "ruan" => "juan", 534 | 535 | "rui" => "jui", 536 | 537 | "run" => "jun", 538 | 539 | "ruo" => "jo", 540 | 541 | "sa" => "sa", 542 | 543 | "sai" => "sai", 544 | 545 | "san" => "san", 546 | 547 | "sang" => "sang", 548 | 549 | "sao" => "sao", 550 | 551 | "se" => "se", 552 | 553 | "sen" => "sen", 554 | 555 | "seng" => "seng", 556 | 557 | "sha" => "sha", 558 | 559 | "shai" => "shai", 560 | 561 | "shan" => "shan", 562 | 563 | "shang" => "shang", 564 | 565 | "shao" => "shao", 566 | 567 | "she" => "she", 568 | 569 | "shen" => "shen", 570 | 571 | "sheng" => "sheng", 572 | 573 | "shi" => "shih", 574 | 575 | "shou" => "shou", 576 | 577 | "shu" => "shu", 578 | 579 | "shua" => "shua", 580 | 581 | "shuai" => "shuai", 582 | 583 | "shuan" => "shuan", 584 | 585 | "shuang" => "shuang", 586 | 587 | "shui" => "shui", 588 | 589 | "shun" => "shun", 590 | 591 | "shuo" => "shuo", 592 | 593 | "si" => "ssu", 594 | 595 | "song" => "sung", 596 | 597 | "sou" => "sou", 598 | 599 | "su" => "su", 600 | 601 | "suan" => "suan", 602 | 603 | "sui" => "sui", 604 | 605 | "sun" => "sun", 606 | 607 | "suo" => "so", 608 | 609 | "ta" => "t'a", 610 | 611 | "tai" => "t'ai", 612 | 613 | "tan" => "t'an", 614 | 615 | "tang" => "t'ang", 616 | 617 | "tao" => "t'ao", 618 | 619 | "te" => "t'e", 620 | 621 | "teng" => "t'eng", 622 | 623 | "ti" => "t'i", 624 | 625 | "tian" => "t'ien", 626 | 627 | "tiao" => "t'iao", 628 | 629 | "tie" => "t'ieh", 630 | 631 | "ting" => "t'ing", 632 | 633 | "tong" => "t'ung", 634 | 635 | "tou" => "t'ou", 636 | 637 | "tu" => "t'u", 638 | 639 | "tuan" => "t'uan", 640 | 641 | "tui" => "t'ui", 642 | 643 | "tun" => "t'un", 644 | 645 | "tuo" => "t'o", 646 | 647 | "wa" => "wa", 648 | 649 | "wai" => "wai", 650 | 651 | "wan" => "wan", 652 | 653 | "wang" => "wang", 654 | 655 | "wei" => "wei", 656 | 657 | "wen" => "wen", 658 | 659 | "weng" => "weng", 660 | 661 | "wo" => "wo", 662 | 663 | "wu" => "wu", 664 | 665 | "xi" => "hsi", 666 | 667 | "xia" => "hsia", 668 | 669 | "xian" => "hsien", 670 | 671 | "xiang" => "hsiang", 672 | 673 | "xiao" => "hsiao", 674 | 675 | "xie" => "hsieh", 676 | 677 | "xin" => "hsin", 678 | 679 | "xing" => "hsing", 680 | 681 | "xiong" => "hsiung", 682 | 683 | "xiu" => "hsiu", 684 | 685 | "xu" => "hsü", 686 | 687 | "xuan" => "hsüan", 688 | 689 | "xue" => "hsüeh", 690 | 691 | "xun" => "hsün", 692 | 693 | "ya" => "ya", 694 | 695 | "yai" => "yai", 696 | 697 | "yan" => "yen", 698 | 699 | "yang" => "yang", 700 | 701 | "yao" => "yao", 702 | 703 | "ye" => "yeh", 704 | 705 | "yi" => "i", 706 | 707 | "yin" => "yin", 708 | 709 | "ying" => "ying", 710 | 711 | "yo" => "yo", 712 | 713 | "yong" => "yung", 714 | 715 | "you" => "yu", 716 | 717 | "yu" => "yü", 718 | 719 | "yuan" => "yüen", 720 | 721 | "yue" => "yüeh", 722 | 723 | "yun" => "yün", 724 | 725 | "za" => "tsa", 726 | 727 | "zai" => "tsai", 728 | 729 | "zan" => "tsan", 730 | 731 | "zang" => "tsang", 732 | 733 | "zao" => "tsao", 734 | 735 | "ze" => "tse", 736 | 737 | "zei" => "tsei", 738 | 739 | "zen" => "tsen", 740 | 741 | "zeng" => "tseng", 742 | 743 | "zha" => "cha", 744 | 745 | "zhai" => "chai", 746 | 747 | "zhan" => "chan", 748 | 749 | "zhang" => "chang", 750 | 751 | "zhao" => "chao", 752 | 753 | "zhe" => "che", 754 | 755 | "zhen" => "chen", 756 | 757 | "zheng" => "cheng", 758 | 759 | "zhi" => "chih", 760 | 761 | "zhong" => "chung", 762 | 763 | "zhou" => "chou", 764 | 765 | "zhu" => "chu", 766 | 767 | "zhua" => "chua", 768 | 769 | "zhuai" => "chuai", 770 | 771 | "zhuan" => "chuan", 772 | 773 | "zhuang" => "chuang", 774 | 775 | "zhui" => "chui", 776 | 777 | "zhun" => "chun", 778 | ], 779 | "wh" => [ 780 | "a" => "a", 781 | "ai" => "ai", 782 | "an" => "an", 783 | "ang" => "ang", 784 | "ao" => "ao", 785 | "pa" => "ba", 786 | "pai" => "bai", 787 | "pan" => "ban", 788 | "pang" => "bang", 789 | "pao" => "bao", 790 | "pei" => "bei", 791 | "pen" => "ben", 792 | "peng" => "beng", 793 | "pi" => "bi", 794 | "pien" => "bian", 795 | "piao" => "biao", 796 | "pieh" => "bie", 797 | "pin" => "bin", 798 | "ping" => "bing", 799 | "po" => "bo", 800 | "pu" => "bu", 801 | "ts'a" => "ca", 802 | "ts'ai" => "cai", 803 | "ts'an" => "can", 804 | "ts'ang" => "cang", 805 | "ts'ao" => "cao", 806 | "ts'e" => "ce", 807 | "ts'en" => "cen", 808 | "ts'eng" => "ceng", 809 | "ch'a" => "cha", 810 | "ch'ai" => "chai", 811 | "ch'an" => "chan", 812 | "ch'ang" => "chang", 813 | "ch'ao" => "chao", 814 | "ch'e" => "che", 815 | "ch'en" => "chen", 816 | "ch'eng" => "cheng", 817 | "ch'ih" => "chi", 818 | "ch'ung" => "chong", 819 | "ch'ou" => "chou", 820 | "ch'u" => "chu", 821 | "ch'uai" => "chuai", 822 | "ch'uan" => "chuan", 823 | "ch'uang" => "chuang", 824 | "ch'ui" => "chui", 825 | "ch'un" => "chun", 826 | "ch'o" => "chuo", 827 | "tz'u" => "ci", 828 | "ts'ung" => "cong", 829 | "ts'ou" => "cou", 830 | "ts'u" => "cu", 831 | "ts'uan" => "cuan", 832 | "ts'ui" => "cui", 833 | "ts'un" => "cun", 834 | "ts'o" => "cuo", 835 | "ta" => "da", 836 | "tai" => "dai", 837 | "tan" => "dan", 838 | "tang" => "dang", 839 | "tao" => "dao", 840 | "te" => "de", 841 | "teng" => "deng", 842 | "ti" => "di", 843 | "tien" => "dian", 844 | "tiao" => "diao", 845 | "tieh" => "die", 846 | "ting" => "ding", 847 | "tiu" => "diu", 848 | "tung" => "dong", 849 | "tou" => "dou", 850 | "tu" => "du", 851 | "tuan" => "duan", 852 | "tui" => "dui", 853 | "tun" => "dun", 854 | "to" => "duo", 855 | "o" => "e", 856 | "en" => "en", 857 | "erh" => "er", 858 | "fa" => "fa", 859 | "fan" => "fan", 860 | "fang" => "fang", 861 | "fei" => "fei", 862 | "fen" => "fen", 863 | "feng" => "feng", 864 | "fo" => "fo", 865 | "fou" => "fou", 866 | "fu" => "fu", 867 | "ka" => "ga", 868 | "kai" => "gai", 869 | "kan" => "gan", 870 | "kang" => "gang", 871 | "kao" => "gao", 872 | "ko" => "ge", 873 | "ken" => "gen", 874 | "keng" => "geng", 875 | "kung" => "gong", 876 | "kou" => "gou", 877 | "ku" => "gu", 878 | "kua" => "gua", 879 | "kuai" => "guai", 880 | "kuan" => "guan", 881 | "kuang" => "guang", 882 | "kuei" => "gui", 883 | "kun" => "gun", 884 | "kuo" => "guo", 885 | "ha" => "ha", 886 | "hai" => "hai", 887 | "han" => "han", 888 | "hang" => "hang", 889 | "hao" => "hao", 890 | "ho" => "he", 891 | "hei" => "hei", 892 | "hen" => "hen", 893 | "heng" => "heng", 894 | "hung" => "hong", 895 | "hou" => "hou", 896 | "hu" => "hu", 897 | "hua" => "hua", 898 | "huai" => "huai", 899 | "huan" => "huan", 900 | "huang" => "huang", 901 | "hui" => "hui", 902 | "hun" => "hun", 903 | "huo" => "huo", 904 | "chi" => "ji", 905 | "chia" => "jia", 906 | "chien" => "jian", 907 | "chiang" => "jiang", 908 | "chiao" => "jiao", 909 | "chieh" => "jie", 910 | "chin" => "jin", 911 | "ching" => "jing", 912 | "chiung" => "jiong", 913 | "chiu" => "jiu", 914 | "chü" => "ju", 915 | "chüan" => "juan", 916 | "chüeh" => "jue", 917 | "chün" => "jun", 918 | "k'a" => "ka", 919 | "k'ai" => "kai", 920 | "k'an" => "kan", 921 | "k'ang" => "kang", 922 | "k'ao" => "kao", 923 | "k'o" => "ke", 924 | "k'en" => "ken", 925 | "k'eng" => "keng", 926 | "k'ung" => "kong", 927 | "k'ou" => "kou", 928 | "k'u" => "ku", 929 | "k'ua" => "kua", 930 | "k'uai" => "kuai", 931 | "k'uan" => "kuan", 932 | "k'uang" => "kuang", 933 | "k'uei" => "kui", 934 | "k'un" => "kun", 935 | "k'uo" => "kuo", 936 | "lü" => "lü", 937 | "la" => "la", 938 | "lai" => "lai", 939 | "lan" => "lan", 940 | "lang" => "lang", 941 | "lao" => "lao", 942 | "le" => "le", 943 | "lei" => "lei", 944 | "leng" => "leng", 945 | "li" => "li", 946 | "lien" => "lian", 947 | "liang" => "liang", 948 | "liao" => "liao", 949 | "lieh" => "lie", 950 | "lin" => "lin", 951 | "ling" => "ling", 952 | "liu" => "liu", 953 | "lung" => "long", 954 | "lou" => "lou", 955 | "lu" => "lu", 956 | "luan" => "luan", 957 | "lüeh" => "lue", 958 | "lun" => "lun", 959 | "lo" => "luo", 960 | "ma" => "ma", 961 | "mai" => "mai", 962 | "man" => "man", 963 | "mang" => "mang", 964 | "mao" => "mao", 965 | "mei" => "mei", 966 | "men" => "men", 967 | "meng" => "meng", 968 | "mi" => "mi", 969 | "mien" => "mian", 970 | "miao" => "miao", 971 | "mieh" => "mie", 972 | "min" => "min", 973 | "ming" => "ming", 974 | "miu" => "miu", 975 | "mo" => "mo", 976 | "mou" => "mou", 977 | "mu" => "mu", 978 | "nü" => "nü", 979 | "na" => "na", 980 | "nai" => "nai", 981 | "nan" => "nan", 982 | "nang" => "nang", 983 | "nao" => "nao", 984 | "nei" => "nei", 985 | "nen" => "nen", 986 | "neng" => "neng", 987 | "ni" => "ni", 988 | "nien" => "nian", 989 | "niang" => "niang", 990 | "niao" => "niao", 991 | "nieh" => "nie", 992 | "nin" => "nin", 993 | "ning" => "ning", 994 | "niu" => "niu", 995 | "nung" => "nong", 996 | "nou" => "nou", 997 | "nu" => "nu", 998 | "nuan" => "nuan", 999 | "nüeh" => "nue", 1000 | "no" => "nuo", 1001 | "ou" => "ou", 1002 | "p'a" => "pa", 1003 | "p'ai" => "pai", 1004 | "p'an" => "pan", 1005 | "p'ang" => "pang", 1006 | "p'ao" => "pao", 1007 | "p'ei" => "pei", 1008 | "p'en" => "pen", 1009 | "p'eng" => "peng", 1010 | "p'i" => "pi", 1011 | "p'ien" => "pian", 1012 | "p'iao" => "piao", 1013 | "p'ieh" => "pie", 1014 | "p'in" => "pin", 1015 | "p'ing" => "ping", 1016 | "p'o" => "po", 1017 | "p'ou" => "pou", 1018 | "p'u" => "pu", 1019 | "ch'i" => "qi", 1020 | "ch'ia" => "qia", 1021 | "ch'ien" => "qian", 1022 | "ch'iang" => "qiang", 1023 | "ch'iao" => "qiao", 1024 | "ch'ieh" => "qie", 1025 | "ch'in" => "qin", 1026 | "ch'ing" => "qing", 1027 | "ch'iung" => "qiong", 1028 | "ch'iu" => "qiu", 1029 | "ch'ü" => "qu", 1030 | "ch'üan" => "quan", 1031 | "ch'üeh" => "que", 1032 | "ch'ün" => "qun", 1033 | "jan" => "ran", 1034 | "jang" => "rang", 1035 | "jao" => "rao", 1036 | "je" => "re", 1037 | "jen" => "ren", 1038 | "jeng" => "reng", 1039 | "jih" => "ri", 1040 | "jung" => "rong", 1041 | "jou" => "rou", 1042 | "ju" => "ru", 1043 | "juan" => "ruan", 1044 | "jui" => "rui", 1045 | "jun" => "run", 1046 | "jo" => "ruo", 1047 | "sa" => "sa", 1048 | "sai" => "sai", 1049 | "san" => "san", 1050 | "sang" => "sang", 1051 | "sao" => "sao", 1052 | "se" => "se", 1053 | "sen" => "sen", 1054 | "seng" => "seng", 1055 | "sha" => "sha", 1056 | "shai" => "shai", 1057 | "shan" => "shan", 1058 | "shang" => "shang", 1059 | "shao" => "shao", 1060 | "she" => "she", 1061 | "shen" => "shen", 1062 | "sheng" => "sheng", 1063 | "shih" => "shi", 1064 | "shou" => "shou", 1065 | "shu" => "shu", 1066 | "shua" => "shua", 1067 | "shuai" => "shuai", 1068 | "shuan" => "shuan", 1069 | "shuang" => "shuang", 1070 | "shui" => "shui", 1071 | "shun" => "shun", 1072 | "shuo" => "shuo", 1073 | "ssu" => "si", 1074 | "sung" => "song", 1075 | "sou" => "sou", 1076 | "su" => "su", 1077 | "suan" => "suan", 1078 | "sui" => "sui", 1079 | "sun" => "sun", 1080 | "so" => "suo", 1081 | "t'a" => "ta", 1082 | "t'ai" => "tai", 1083 | "t'an" => "tan", 1084 | "t'ang" => "tang", 1085 | "t'ao" => "tao", 1086 | "t'e" => "te", 1087 | "t'eng" => "teng", 1088 | "t'i" => "ti", 1089 | "t'ien" => "tian", 1090 | "t'iao" => "tiao", 1091 | "t'ieh" => "tie", 1092 | "t'ing" => "ting", 1093 | "t'ung" => "tong", 1094 | "t'ou" => "tou", 1095 | "t'u" => "tu", 1096 | "t'uan" => "tuan", 1097 | "t'ui" => "tui", 1098 | "t'un" => "tun", 1099 | "t'o" => "tuo", 1100 | "wa" => "wa", 1101 | "wai" => "wai", 1102 | "wan" => "wan", 1103 | "wang" => "wang", 1104 | "wei" => "wei", 1105 | "wen" => "wen", 1106 | "weng" => "weng", 1107 | "wo" => "wo", 1108 | "wu" => "wu", 1109 | "hsi" => "xi", 1110 | "hsia" => "xia", 1111 | "hsien" => "xian", 1112 | "hsiang" => "xiang", 1113 | "hsiao" => "xiao", 1114 | "hsieh" => "xie", 1115 | "hsin" => "xin", 1116 | "hsing" => "xing", 1117 | "hsiung" => "xiong", 1118 | "hsiu" => "xiu", 1119 | "hsü" => "xu", 1120 | "hsüan" => "xuan", 1121 | "hsüeh" => "xue", 1122 | "hsün" => "xun", 1123 | "ya" => "ya", 1124 | "yai" => "yai", 1125 | "yen" => "yan", 1126 | "yang" => "yang", 1127 | "yao" => "yao", 1128 | "yeh" => "ye", 1129 | "i" => "yi", 1130 | "yin" => "yin", 1131 | "ying" => "ying", 1132 | "yo" => "yo", 1133 | "yung" => "yong", 1134 | "yu" => "you", 1135 | "yü" => "yu", 1136 | "yüen" => "yuan", 1137 | "yüeh" => "yue", 1138 | "yün" => "yun", 1139 | "tsa" => "za", 1140 | "tsai" => "zai", 1141 | "tsan" => "zan", 1142 | "tsang" => "zang", 1143 | "tsao" => "zao", 1144 | "tse" => "ze", 1145 | "tsei" => "zei", 1146 | "tsen" => "zen", 1147 | "tseng" => "zeng", 1148 | "cha" => "zha", 1149 | "chai" => "zhai", 1150 | "chan" => "zhan", 1151 | "chang" => "zhang", 1152 | "chao" => "zhao", 1153 | "che" => "zhe", 1154 | "chen" => "zhen", 1155 | "cheng" => "zheng", 1156 | "chih" => "zhi", 1157 | "chung" => "zhong", 1158 | "chou" => "zhou", 1159 | "chu" => "zhu", 1160 | "chua" => "zhua", 1161 | "chuai" => "zhuai", 1162 | "chuan" => "zhuan", 1163 | "chuang" => "zhuang", 1164 | "chui" => "zhui", 1165 | "chun" => "zhun" 1166 | ] 1167 | ]; 1168 | -------------------------------------------------------------------------------- /src/Config/helpers.php: -------------------------------------------------------------------------------- 1 | [ 10 | "appid" => env('EXCHANGE_APPID', null), //Openexchangerates Appid 11 | "base_currency" => env('EXCHANGE_BASE_CURRENY', 'USD'), //Set Openexchangerates Api Base Currency 12 | ], 13 | 14 | //****************************************************************************************************************************** 15 | //============================================================================================================================== 16 | 17 | 18 | 19 | //configuration DingTalk Robot ************************************************************************************************* 20 | 21 | "dingtalk" => env('DINGTALK_ROBOT', null), //Webhooks Access Token 22 | 23 | //****************************************************************************************************************************** 24 | //============================================================================================================================== 25 | 26 | 27 | //configuration Enterprise Wechat Robot ************************************************************************************** 28 | 29 | "wechat" => env('WECHAT_ROBOT', null), //Webhooks Access Token 30 | 31 | //****************************************************************************************************************************** 32 | //============================================================================================================================== 33 | 34 | 35 | //configuration Enterprise Wechat Robot ************************************************************************************** 36 | 37 | "lark" => env('LARK_ROBOT', null), //Webhooks Access Token 38 | 39 | //****************************************************************************************************************************** 40 | //============================================================================================================================== 41 | 42 | 43 | 44 | 45 | //Don't move the following information ************************************************************************************** 46 | 47 | //Return All Country Code and Name 48 | 'country' => [ 49 | "AO" => "Angola", 50 | "BF" => "Burkina Faso", 51 | "BI" => "Burundi", 52 | "BJ" => "Benin", 53 | "BW" => "Botswana", 54 | "CD" => "Congo (Kinshasa)", 55 | "CF" => "Central African Republic", 56 | "CG" => "Congo (Brazzaville)", 57 | "CI" => "Ivory Coast", 58 | "CM" => "Cameroon", 59 | "CV" => "Cape Verde", 60 | "DJ" => "Djibouti", 61 | "DZ" => "Algeria", 62 | "EG" => "Egypt", 63 | "EH" => "Western Sahara", 64 | "ER" => "Eritrea", 65 | "ET" => "Ethiopia", 66 | "GA" => "Gabon", 67 | "GH" => "Ghana", 68 | "GM" => "Gambia", 69 | "GN" => "Guinea", 70 | "GQ" => "Equatorial Guinea", 71 | "GW" => "Guinea-Bissau", 72 | "KE" => "Kenya", 73 | "KM" => "Comoros", 74 | "LR" => "Liberia", 75 | "LS" => "Lesotho", 76 | "LY" => "Libya", 77 | "MA" => "Morocco", 78 | "MG" => "Madagascar", 79 | "ML" => "Mali", 80 | "MR" => "Mauritania", 81 | "MU" => "Mauritius", 82 | "MW" => "Malawi", 83 | "MZ" => "Mozambique", 84 | "NA" => "Namibia", 85 | "NE" => "Niger", 86 | "NG" => "Nigeria", 87 | "RE" => "Reunion", 88 | "RW" => "Rwanda", 89 | "SC" => "Seychelles", 90 | "SD" => "Sudan", 91 | "SH" => "Saint Helena", 92 | "SL" => "Sierra Leone", 93 | "SN" => "Senegal", 94 | "SO" => "Somalia", 95 | "SS" => "South Sudan", 96 | "ST" => "São Tomé and Príncipe", 97 | "SZ" => "Swaziland", 98 | "TD" => "Chad", 99 | "TG" => "Togo", 100 | "TN" => "Tunisia", 101 | "TZ" => "Tanzania", 102 | "UG" => "Uganda", 103 | "YT" => "Mayotte", 104 | "ZA" => "South Africa", 105 | "ZM" => "Zambia", 106 | "ZW" => "Zimbabwe", 107 | "AQ" => "Antarctica", 108 | "BV" => "Bouvet Island", 109 | "GS" => "South Georgia/Sandwich Islands", 110 | "HM" => "Heard Island and McDonald Islands", 111 | "TF" => "French Southern Territories", 112 | "AE" => "United Arab Emirates", 113 | "AF" => "Afghanistan", 114 | "AM" => "Armenia", 115 | "AZ" => "Azerbaijan", 116 | "BD" => "Bangladesh", 117 | "BH" => "Bahrain", 118 | "BN" => "Brunei", 119 | "BT" => "Bhutan", 120 | "CC" => "Cocos (Keeling) Islands", 121 | "CN" => "China", 122 | "CX" => "Christmas Island", 123 | "GE" => "Georgia", 124 | "HK" => "Hong Kong", 125 | "ID" => "Indonesia", 126 | "IL" => "Israel", 127 | "IN" => "India", 128 | "IO" => "British Indian Ocean Territory", 129 | "IQ" => "Iraq", 130 | "IR" => "Iran", 131 | "JO" => "Jordan", 132 | "JP" => "Japan", 133 | "KG" => "Kyrgyzstan", 134 | "KH" => "Cambodia", 135 | "KP" => "North Korea", 136 | "KR" => "South Korea", 137 | "KW" => "Kuwait", 138 | "KZ" => "Kazakhstan", 139 | "LA" => "Laos", 140 | "LB" => "Lebanon", 141 | "LK" => "Sri Lanka", 142 | "MM" => "Myanmar", 143 | "MN" => "Mongolia", 144 | "MO" => "Macao", 145 | "MV" => "Maldives", 146 | "MY" => "Malaysia", 147 | "NP" => "Nepal", 148 | "OM" => "Oman", 149 | "PH" => "Philippines", 150 | "PK" => "Pakistan", 151 | "PS" => "Palestinian Territory", 152 | "QA" => "Qatar", 153 | "SA" => "Saudi Arabia", 154 | "SG" => "Singapore", 155 | "SY" => "Syria", 156 | "TH" => "Thailand", 157 | "TJ" => "Tajikistan", 158 | "TL" => "Timor-Leste", 159 | "TM" => "Turkmenistan", 160 | "TW" => "Taiwan", 161 | "UZ" => "Uzbekistan", 162 | "VN" => "Vietnam", 163 | "YE" => "Yemen", 164 | "AD" => "Andorra", 165 | "AL" => "Albania", 166 | "AT" => "Austria", 167 | "AX" => "Åland Islands", 168 | "BA" => "Bosnia and Herzegovina", 169 | "BE" => "Belgium", 170 | "BG" => "Bulgaria", 171 | "BY" => "Belarus", 172 | "CH" => "Switzerland", 173 | "CY" => "Cyprus", 174 | "CZ" => "Czech Republic", 175 | "DE" => "Germany", 176 | "DK" => "Denmark", 177 | "EE" => "Estonia", 178 | "ES" => "Spain", 179 | "FI" => "Finland", 180 | "FO" => "Faroe Islands", 181 | "FR" => "France", 182 | "GB" => "United Kingdom (UK)", 183 | "GG" => "Guernsey", 184 | "GI" => "Gibraltar", 185 | "GR" => "Greece", 186 | "HR" => "Croatia", 187 | "HU" => "Hungary", 188 | "IE" => "Ireland", 189 | "IM" => "Isle of Man", 190 | "IS" => "Iceland", 191 | "IT" => "Italy", 192 | "JE" => "Jersey", 193 | "LI" => "Liechtenstein", 194 | "LT" => "Lithuania", 195 | "LU" => "Luxembourg", 196 | "LV" => "Latvia", 197 | "MC" => "Monaco", 198 | "MD" => "Moldova", 199 | "ME" => "Montenegro", 200 | "MK" => "North Macedonia", 201 | "MT" => "Malta", 202 | "NL" => "Netherlands", 203 | "NO" => "Norway", 204 | "PL" => "Poland", 205 | "PT" => "Portugal", 206 | "RO" => "Romania", 207 | "RS" => "Serbia", 208 | "RU" => "Russia", 209 | "SE" => "Sweden", 210 | "SI" => "Slovenia", 211 | "SJ" => "Svalbard and Jan Mayen", 212 | "SK" => "Slovakia", 213 | "SM" => "San Marino", 214 | "TR" => "Turkey", 215 | "UA" => "Ukraine", 216 | "VA" => "Vatican", 217 | "AG" => "Antigua and Barbuda", 218 | "AI" => "Anguilla", 219 | "AW" => "Aruba", 220 | "BB" => "Barbados", 221 | "BL" => "Saint Barthélemy", 222 | "BM" => "Bermuda", 223 | "BQ" => "Bonaire, Saint Eustatius and Saba", 224 | "BS" => "Bahamas", 225 | "BZ" => "Belize", 226 | "CA" => "Canada", 227 | "CR" => "Costa Rica", 228 | "CU" => "Cuba", 229 | "CW" => "Curaçao", 230 | "DM" => "Dominica", 231 | "DO" => "Dominican Republic", 232 | "GD" => "Grenada", 233 | "GL" => "Greenland", 234 | "GP" => "Guadeloupe", 235 | "GT" => "Guatemala", 236 | "HN" => "Honduras", 237 | "HT" => "Haiti", 238 | "JM" => "Jamaica", 239 | "KN" => "Saint Kitts and Nevis", 240 | "KY" => "Cayman Islands", 241 | "LC" => "Saint Lucia", 242 | "MF" => "Saint Martin (French part)", 243 | "MQ" => "Martinique", 244 | "MS" => "Montserrat", 245 | "MX" => "Mexico", 246 | "NI" => "Nicaragua", 247 | "PA" => "Panama", 248 | "PM" => "Saint Pierre and Miquelon", 249 | "PR" => "Puerto Rico", 250 | "SV" => "El Salvador", 251 | "SX" => "Saint Martin (Dutch part)", 252 | "TC" => "Turks and Caicos Islands", 253 | "TT" => "Trinidad and Tobago", 254 | "US" => "United States (US)", 255 | "VC" => "Saint Vincent and the Grenadines", 256 | "VG" => "Virgin Islands (British)", 257 | "VI" => "Virgin Islands (US)", 258 | "AS" => "American Samoa", 259 | "AU" => "Australia", 260 | "CK" => "Cook Islands", 261 | "FJ" => "Fiji", 262 | "FM" => "Micronesia", 263 | "GU" => "Guam", 264 | "KI" => "Kiribati", 265 | "MH" => "Marshall Islands", 266 | "MP" => "Northern Mariana Islands", 267 | "NC" => "New Caledonia", 268 | "NF" => "Norfolk Island", 269 | "NR" => "Nauru", 270 | "NU" => "Niue", 271 | "NZ" => "New Zealand", 272 | "PF" => "French Polynesia", 273 | "PG" => "Papua New Guinea", 274 | "PN" => "Pitcairn", 275 | "PW" => "Belau", 276 | "SB" => "Solomon Islands", 277 | "TK" => "Tokelau", 278 | "TO" => "Tonga", 279 | "TV" => "Tuvalu", 280 | "UM" => "United States (US) Minor Outlying Islands", 281 | "VU" => "Vanuatu", 282 | "WF" => "Wallis and Futuna", 283 | "WS" => "Samoa", 284 | "AR" => "Argentina", 285 | "BO" => "Bolivia", 286 | "BR" => "Brazil", 287 | "CL" => "Chile", 288 | "CO" => "Colombia", 289 | "EC" => "Ecuador", 290 | "FK" => "Falkland Islands", 291 | "GF" => "French Guiana", 292 | "GY" => "Guyana", 293 | "PE" => "Peru", 294 | "PY" => "Paraguay", 295 | "SR" => "Suriname", 296 | "UY" => "Uruguay", 297 | "VE" => "Venezuela", 298 | ], 299 | 300 | //Return All Exchange Code 301 | 'exchangeCode' => [ 302 | "AED", 303 | "AFN", 304 | "ALL", 305 | "AMD", 306 | "ANG", 307 | "AOA", 308 | "ARS", 309 | "AUD", 310 | "AWG", 311 | "AZN", 312 | "BAM", 313 | "BBD", 314 | "BDT", 315 | "BGN", 316 | "BHD", 317 | "BIF", 318 | "BMD", 319 | "BND", 320 | "BOB", 321 | "BRL", 322 | "BSD", 323 | "BTC", 324 | "BTN", 325 | "BWP", 326 | "BYN", 327 | "BZD", 328 | "CAD", 329 | "CDF", 330 | "CHF", 331 | "CLF", 332 | "CLP", 333 | "CNH", 334 | "CNY", 335 | "COP", 336 | "CRC", 337 | "CUC", 338 | "CUP", 339 | "CVE", 340 | "CZK", 341 | "DJF", 342 | "DKK", 343 | "DOP", 344 | "DZD", 345 | "EGP", 346 | "ERN", 347 | "ETB", 348 | "EUR", 349 | "FJD", 350 | "FKP", 351 | "GBP", 352 | "GEL", 353 | "GGP", 354 | "GHS", 355 | "GIP", 356 | "GMD", 357 | "GNF", 358 | "GTQ", 359 | "GYD", 360 | "HKD", 361 | "HNL", 362 | "HRK", 363 | "HTG", 364 | "HUF", 365 | "IDR", 366 | "ILS", 367 | "IMP", 368 | "INR", 369 | "IQD", 370 | "IRR", 371 | "ISK", 372 | "JEP", 373 | "JMD", 374 | "JOD", 375 | "JPY", 376 | "KES", 377 | "KGS", 378 | "KHR", 379 | "KMF", 380 | "KPW", 381 | "KRW", 382 | "KWD", 383 | "KYD", 384 | "KZT", 385 | "LAK", 386 | "LBP", 387 | "LKR", 388 | "LRD", 389 | "LSL", 390 | "LYD", 391 | "MAD", 392 | "MDL", 393 | "MGA", 394 | "MKD", 395 | "MMK", 396 | "MNT", 397 | "MOP", 398 | "MRO", 399 | "MRU", 400 | "MUR", 401 | "MVR", 402 | "MWK", 403 | "MXN", 404 | "MYR", 405 | "MZN", 406 | "NAD", 407 | "NGN", 408 | "NIO", 409 | "NOK", 410 | "NPR", 411 | "NZD", 412 | "OMR", 413 | "PAB", 414 | "PEN", 415 | "PGK", 416 | "PHP", 417 | "PKR", 418 | "PLN", 419 | "PYG", 420 | "QAR", 421 | "RON", 422 | "RSD", 423 | "RUB", 424 | "RWF", 425 | "SAR", 426 | "SBD", 427 | "SCR", 428 | "SDG", 429 | "SEK", 430 | "SGD", 431 | "SHP", 432 | "SLL", 433 | "SOS", 434 | "SRD", 435 | "SSP", 436 | "STD", 437 | "STN", 438 | "SVC", 439 | "SYP", 440 | "SZL", 441 | "THB", 442 | "TJS", 443 | "TMT", 444 | "TND", 445 | "TOP", 446 | "TRY", 447 | "TTD", 448 | "TWD", 449 | "TZS", 450 | "UAH", 451 | "UGX", 452 | "USD", 453 | "UYU", 454 | "UZS", 455 | "VES", 456 | "VND", 457 | "VUV", 458 | "WST", 459 | "XAF", 460 | "XAG", 461 | "XAU", 462 | "XCD", 463 | "XDR", 464 | "XOF", 465 | "XPD", 466 | "XPF", 467 | "XPT", 468 | "YER", 469 | "ZAR", 470 | "ZMW", 471 | "ZWL", 472 | ], 473 | "extend" => [ 474 | "chinese" => [ 475 | "storeRestController" => '创建Rest风格资源控制器', 476 | "dbBackup" => '备份数据库', 477 | "choose" => '请选择', 478 | "exit" => '退出?', 479 | "dbResult" => '数据库备份成功,可以前往storage/backup文件夹中查看', 480 | "dbAlert" => '备份期间将临时更改网站为维护模式,备份完成后将恢复', 481 | "dbResultAlert" => '为您创建了', 482 | "storeRestControllerAlert" => '请输入创建的控制器名字,请以大写开头,如:', 483 | "success" => '您的操作已完成', 484 | "generateDingtalk" => '生成DinktalkNotification', 485 | "generateWechat" => '生成WechatNotification', 486 | "generateWechatTemplateMessage" => '生成WechatTemplateMessageNotification', 487 | "generateLarkRobot" => '生成LarkRobotNotification', 488 | "generate" => '代码生成器', 489 | ], 490 | "english" => [ 491 | "storeRestController" => 'Create rest style resource controller', 492 | "dbBackup" => 'Backup database', 493 | "choose" => 'Please select', 494 | "exit" => 'Exit?', 495 | "dbResult" => 'If the database backup is successful, you can go to the storage/backup folder to view it', 496 | "dbAlert" => 'During the backup, the website will be temporarily changed to maintenance mode, and will be restored after the backup is completed', 497 | "dbResultAlert" => 'Created for you', 498 | "storeRestControllerAlert" => 'Please enter the name of the created controller, starting with uppercase, such as:', 499 | "success" => 'SUCCESS', 500 | "generateDingtalk" => 'Generate DinktalkNotification', 501 | "generateWechat" => 'Generate WechatNotification', 502 | "generateWechatTemplateMessage" => 'Generate WechatTemplateMessageNotification', 503 | "generateLarkRobot" => 'Generate LarkRobotNotification', 504 | "generate" => 'Generate Code', 505 | ], 506 | ], 507 | 'tiktok' => [ //抖音的支付 单位全部为分 508 | 'token' => '', //支付token 509 | 'salt' => '', //盐值 510 | 'merchant_id' => '', //商户号 511 | 'app_id' => '', 512 | 'secret' => '', 513 | 'notify_url' => '', //支付链接 如果在设置回调链接中设置了支付回调链接 则设置的优先 这个配置不生效 514 | 'private_key_url' => storage_path() . '/pay/tt/private_key.pem', 515 | 'platform_public_key_url' => storage_path() . '/pay/tt/platform_public_key.pem', 516 | 'public_key_url' => storage_path() . '/pay/tt/public_key.pem', 517 | 'version' => '',//支付版本号 518 | 'settle_notify_url' => '',//分账回调url 519 | 'refund_notify_url' => '',//退款回调url 520 | 'agree_refund_notify_url' => '',//同意退款回调url 521 | 'create_order_callback' => '',//创建订单回调地址 522 | 'pay_callback' => '',//支付回调地址 523 | ], 524 | 525 | 526 | ]; 527 | -------------------------------------------------------------------------------- /src/Console/Commands/ExtendCommand.php: -------------------------------------------------------------------------------- 1 | option('chinese')) { 57 | $language = $this->languageChange('chinese'); 58 | } else { 59 | $language = $this->languageChange(); 60 | } 61 | if (!$language) { 62 | $this->info('Please Run `php artisan vendor:publish --provider="Chowjiawei\Helpers\Providers\HelpPluginServiceProvider" ` '); 63 | return; 64 | } 65 | do { 66 | $option = $this->choice($language['choose'], [ 67 | $language['generate'], 68 | ], 0); 69 | 70 | $this->line($option); 71 | switch ($option) { 72 | case $language['generate']: 73 | $generateType = $this->choice( 74 | $language['generate'], 75 | ['Dingtalk', 'Wechat', 'WechatTemplateMessageNotification','LarkRobot'], 76 | 0 77 | ); 78 | 79 | switch ($generateType) { 80 | case 'Dingtalk': 81 | $this->output->title($language['generateDingtalk']); 82 | Artisan::call("generate Dingtalk"); 83 | break; 84 | case 'Wechat': 85 | $this->output->title($language['generateWechat']); 86 | Artisan::call("generate Wechat"); 87 | break; 88 | case 'WechatTemplateMessageNotification': 89 | $this->output->title($language['generateWechatTemplateMessage']); 90 | Artisan::call("generate WechatTemplateMessage"); 91 | break; 92 | case 'LarkRobot': 93 | $this->output->title($language['generateLarkRobot']); 94 | Artisan::call("generate LarkRobot"); 95 | break; 96 | } 97 | 98 | break; 99 | 100 | default: 101 | $message = $language['choose']; 102 | } 103 | $this->info($language['success']); 104 | $this->output->title($message ?? $language['exit']); 105 | $exit = $this->confirm($language['exit'], 'yes'); 106 | } while ($exit != 'yes'); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Console/Commands/GenerateCommand.php: -------------------------------------------------------------------------------- 1 | argument('name')); 56 | if ($name !== 'dingtalk' && $name !== 'wechat' && $name !== 'wechattemplatemessage' && $name !== 'larkrobot') { 57 | $isModel = $this->option('model'); 58 | $isController = $this->option('controller'); 59 | if (!$isModel && !$isController) { 60 | $this->error("必须指定一个类型"); 61 | return true; 62 | } 63 | if ($isController) { 64 | $result = $this->generateName($name, 'controller'); 65 | } 66 | if ($isModel) { 67 | $result = $this->generateName($name, 'model'); 68 | } 69 | $name = $result[0]; 70 | $path = $result[1]; 71 | 72 | if (!$this->files->isDirectory($path)) { 73 | $this->files->makeDirectory($path, 0755, true, true); 74 | } 75 | 76 | $this->files = new Filesystem(); 77 | $this->composer = new Composer($this->files); 78 | $this->date = date('Y-m-d'); 79 | $this->time = date('H:i'); 80 | 81 | $nameSpace = str_replace('/', '\\', $path); 82 | $stub = $this->files->get($this->getStub()); 83 | if ($isController) { 84 | $templateData = [ 85 | 'date' => $this->date, 86 | 'time' => $this->time, 87 | 'className' => $name . 'Controller', 88 | 'nameSpace' => $nameSpace, 89 | ]; 90 | $renderStub = $this->getRenderStub($templateData, $stub); 91 | $path .= DIRECTORY_SEPARATOR . $name . 'Controller.php'; 92 | } 93 | if ($isModel) { 94 | $templateData = [ 95 | 'date' => $this->date, 96 | 'time' => $this->time, 97 | 'className' => $name, 98 | 'nameSpace' => $nameSpace, 99 | ]; 100 | $renderStub = $this->getRenderStub($templateData, $stub); 101 | $path .= DIRECTORY_SEPARATOR . $name . '.php'; 102 | } 103 | $path = lcfirst($path); 104 | if (!$this->files->exists($path)) { 105 | $this->files->put($path, $renderStub); 106 | $filename = substr(strrchr($path, "/"), 1); 107 | $this->info('create : ' . $filename . ' success'); 108 | } else { 109 | $filename = substr(strrchr($path, "/"), 1); 110 | $this->info('The file : ' . $filename . ' already exists'); 111 | } 112 | return true; 113 | } 114 | if ($name == 'dingtalk') { 115 | $path = 'app/Notifications/DingtalkRobotNotification.php'; 116 | $stub = $this->files->get($this->getStub()); 117 | } 118 | if ($name == 'wechat') { 119 | $path = 'app/Notifications/WechatNotification.php'; 120 | $stub = $this->files->get($this->getStub()); 121 | } 122 | if ($name == 'wechattemplatemessage') { 123 | $path = 'app/Notifications/WechatTemplateMessageNotification.php'; 124 | $stub = $this->files->get($this->getStub()); 125 | } 126 | 127 | if ($name == 'larkrobot') { 128 | $path = 'app/Notifications/LarkRobotNotification.php'; 129 | $stub = $this->files->get($this->getStub()); 130 | } 131 | 132 | 133 | if (!$this->files->exists($path)) { 134 | $this->files->put($path, $stub); 135 | $filename = substr(strrchr($path, "/"), 1); 136 | $this->info('create : ' . $filename . ' success'); 137 | } else { 138 | $filename = substr(strrchr($path, "/"), 1); 139 | $this->info('The file : ' . $filename . ' already exists'); 140 | } 141 | return true; 142 | } 143 | 144 | protected function getRenderStub($templateData, $stub) 145 | { 146 | foreach ($templateData as $search => $replace) { 147 | $stub = str_replace('$' . $search, $replace, $stub); 148 | } 149 | return $stub; 150 | } 151 | 152 | protected function getStub() 153 | { 154 | if ($this->option('controller')) { 155 | return dirname(__DIR__) . '/stubs/Controller.stub'; 156 | } 157 | if ($this->option('model')) { 158 | return dirname(__DIR__) . '/stubs/Model.stub'; 159 | } 160 | 161 | if ($this->argument('name') == 'Dingtalk') { 162 | return dirname(__DIR__) . '/stubs/DingtalkRobotNotification.stub'; 163 | } 164 | 165 | if ($this->argument('name') == 'Wechat') { 166 | return dirname(__DIR__) . '/stubs/WechatNotification.stub'; 167 | } 168 | 169 | if ($this->argument('name') == 'WechatTemplateMessage') { 170 | return dirname(__DIR__) . '/stubs/WechatTemplateMessageNotification.stub'; 171 | } 172 | 173 | if ($this->argument('name') == 'LarkRobot') { 174 | return dirname(__DIR__) . '/stubs/LarkRobotNotification.stub'; 175 | } 176 | } 177 | 178 | 179 | public function generateName($name, $type) 180 | { 181 | $nameArr = explode('/', $name); 182 | $nameCount = count($nameArr); 183 | $path = ''; 184 | if ($type == 'controller') { 185 | $path = self::CONTROLLER_PATH; 186 | } 187 | if ($type == 'model') { 188 | $path = self::MODEL_PATH; 189 | } 190 | if ($nameCount > 1) { 191 | for ($i = 0; $i < $nameCount - 1; $i++) { 192 | $path .= DIRECTORY_SEPARATOR . ucfirst($nameArr[$i]); 193 | } 194 | } 195 | return [ucfirst(end($nameArr)), $path]; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/Console/stubs/Controller.stub: -------------------------------------------------------------------------------- 1 | text=$text; 16 | } 17 | 18 | public function via($notifiable) 19 | { 20 | return [DingtalkRobotChannel::class]; 21 | } 22 | 23 | public function toDingtalkRobot($notifiable) 24 | { 25 | return $this->text; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Console/stubs/LarkRobotNotification.stub: -------------------------------------------------------------------------------- 1 | message = $message; 18 | } 19 | 20 | public function via($notifiable) 21 | { 22 | return [LarkRobotChannel::class]; 23 | } 24 | 25 | public function toLarkRobot($notifiable) 26 | { 27 | return $this->message; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Console/stubs/Model.stub: -------------------------------------------------------------------------------- 1 | test=$test; 16 | } 17 | 18 | public function via($notifiable) 19 | { 20 | return [WechatRobotChannel::class]; 21 | } 22 | 23 | public function toWechatRobot($notifiable) 24 | { 25 | return $this->text; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Console/stubs/WechatTemplateMessageNotification.stub: -------------------------------------------------------------------------------- 1 | data = $data; 16 | $this->template = $template; 17 | } 18 | 19 | public function via($notifiable) 20 | { 21 | return [WechatTemplateMessageChannel::class]; 22 | } 23 | 24 | public function toWechatTemplateMessage($notifiable) 25 | { 26 | $data=$this->data; 27 | $template=$this->template; 28 | $allData=[$data,$template]; 29 | return $allData; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Exchange/Exchange.php: -------------------------------------------------------------------------------- 1 | 52.0, 24 | ]); 25 | $url = 'https://openexchangerates.org/api/latest.json?app_id=' . $appid . '&base=' . $baseCurrency; 26 | $response = $client->request('GET', $url); 27 | return json_decode($response->getBody()->getContents(), true); 28 | } 29 | 30 | /** 31 | * Get Exchange 32 | * 33 | * $symbols array 34 | * @return \Illuminate\Http\Response 35 | */ 36 | public function getSymbolChangerates($symbols = []) 37 | { 38 | $symbol = implode(" ", $symbols); 39 | $appid = config('helpers.exchange.appid'); 40 | $baseCurrency = config('helpers.exchange.base_currency'); 41 | if ($symbols) { 42 | $url = 'https://openexchangerates.org/api/latest.json?app_id=' . $appid . '&base=' . $baseCurrency . '&symbols=' . $symbol; 43 | } else { 44 | $url = 'https://openexchangerates.org/api/latest.json?app_id=' . $appid . '&base=' . $baseCurrency; 45 | } 46 | $client = new Client([ 47 | 'timeout' => 52.0, 48 | ]); 49 | $response = $client->request('GET', $url); 50 | return json_decode($response->getBody()->getContents(), true); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Facade/Helper.php: -------------------------------------------------------------------------------- 1 | $v) { 129 | if (strlen($array[$index]) < strlen($v)) { 130 | $index = $k; 131 | } 132 | } 133 | return $array[$index]; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Notifications/DingtalkRobotNotification.php: -------------------------------------------------------------------------------- 1 | text = $text; 20 | $this->title = $title; 21 | } 22 | 23 | public function via($notifiable) 24 | { 25 | return [DingtalkRobotChannel::class]; 26 | } 27 | 28 | public function toDingtalkRobot($notifiable) 29 | { 30 | return [ 31 | $this->text, 32 | $this->title 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Notifications/LarkRobotNotification.php: -------------------------------------------------------------------------------- 1 | message = $message; 18 | } 19 | 20 | public function via($notifiable) 21 | { 22 | return [LarkRobotChannel::class]; 23 | } 24 | 25 | public function toLarkRobot($notifiable) 26 | { 27 | return $this->message; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Notifications/WechatRobotNotification.php: -------------------------------------------------------------------------------- 1 | message = $message; 19 | 20 | $this->isUserBroadcast = $isUserBroadcast; 21 | } 22 | 23 | public function via($notifiable) 24 | { 25 | return [WechatRobotChannel::class]; 26 | } 27 | 28 | public function toWechatRobot($notifiable) 29 | { 30 | return $this->message; 31 | } 32 | public function toWechatRobotBroadcast($notifiable) 33 | { 34 | return $this->isUserBroadcast; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Notifications/WechatTemplateMessageNotification.php: -------------------------------------------------------------------------------- 1 | data = $data; 22 | $this->template = $template; 23 | } 24 | 25 | public function via($notifiable) 26 | { 27 | return [WechatTemplateMessageChannel::class]; 28 | } 29 | 30 | public function toWechatTemplateMessage($notifiable) 31 | { 32 | $data = $this->data; 33 | $template = $this->template; 34 | return [$data, $template]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/PhpHelps/LaravelHelp.php: -------------------------------------------------------------------------------- 1 | country = config('helpers.country'); 14 | } 15 | 16 | 17 | /** 18 | * Get All Country. 19 | * 20 | * @return array 21 | */ 22 | public function getAllCountry(): array 23 | { 24 | return $this->country; 25 | } 26 | 27 | /** 28 | * Get Country Name. 29 | * 30 | * @return string 31 | */ 32 | public function getCountryName($countryCode): string 33 | { 34 | if (isset($this->country[$countryCode])) { 35 | return $this->country[$countryCode]; 36 | } 37 | } 38 | 39 | /** 40 | * Get Country Code. 41 | * 42 | * @return string 43 | */ 44 | public function getCountryCode($countryName) 45 | { 46 | if (array_search($countryName, $this->country) !== false) { 47 | return array_search($countryName, $this->country); 48 | } 49 | return null; 50 | } 51 | 52 | /** 53 | * Get All Exchange Code. 54 | * 55 | * @return array 56 | */ 57 | public function getAllExchangeCode(): array 58 | { 59 | return config('helpers.exchangeCode'); 60 | } 61 | 62 | 63 | public function changeHWWord($text) 64 | { 65 | $words = config('helpers-pinyin')['hw']; 66 | $chinesePinYins = array_keys($words); 67 | $wPinYins = array_values($words); 68 | $wWord = ''; 69 | $allIns = []; 70 | foreach ($chinesePinYins as $chinesePinYin) { 71 | if (stripos($text, $chinesePinYin) !== false) { 72 | $allIns[] = $chinesePinYin; 73 | } 74 | } 75 | if (!empty($allIns)) { 76 | $longWord = $this->getLongItem($allIns); 77 | $wWord = $wWord . $words[$longWord]; 78 | $newText = substr($text, mb_strlen($longWord)); 79 | return $wWord; 80 | } 81 | return false; 82 | } 83 | 84 | public function changeWHWord($text) 85 | { 86 | $words = config('helpers-pinyin')['wh']; 87 | $chinesePinYins = array_keys($words); 88 | $wPinYins = array_values($words); 89 | $wWord = ''; 90 | $allIns = []; 91 | foreach ($chinesePinYins as $chinesePinYin) { 92 | if (stripos($text, $chinesePinYin) !== false) { 93 | $allIns[] = $chinesePinYin; 94 | } 95 | } 96 | if (!empty($allIns)) { 97 | $longWord = $this->getLongItem($allIns); 98 | $wWord = $wWord . $words[$longWord]; 99 | $newText = substr($text, mb_strlen($longWord)); 100 | return $wWord; 101 | } 102 | return false; 103 | } 104 | 105 | public function changeLongWHWord($text) 106 | { 107 | try { 108 | $texts = explode(' ', $text); 109 | $result = []; 110 | foreach ($texts as $t) { 111 | $result[] = $this->changeWHWord($t); 112 | } 113 | return implode(' ', $result); 114 | } catch (\Exception $exception) { 115 | throw new \Exception('Pinyin is connected with spaces'); 116 | } 117 | } 118 | 119 | 120 | public function changeLongHWWord($text) 121 | { 122 | try { 123 | $texts = explode(' ', $text); 124 | $result = []; 125 | foreach ($texts as $t) { 126 | $result[] = $this->changeHWWord($t); 127 | } 128 | return implode(' ', $result); 129 | } catch (\Exception $exception) { 130 | throw new \Exception('Pinyin is connected with spaces'); 131 | } 132 | } 133 | 134 | public function getLongItem($array) 135 | { 136 | $index = 0; 137 | foreach ($array as $k => $v) { 138 | if (strlen($array[$index]) < strlen($v)) { 139 | $index = $k; 140 | } 141 | } 142 | return $array[$index]; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Providers/HelpPluginServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind('Helper', function () { 17 | return new Helper(); 18 | }); 19 | 20 | $this->app->singleton('Chowjiawei.generate', function ($app) { 21 | return new GenerateCommand($app['files']); 22 | }); 23 | $this->app->singleton('Chowjiawei.extend', function ($app) { 24 | return new ExtendCommand($app['files']); 25 | }); 26 | $this->commands('Chowjiawei.generate'); 27 | $this->commands('Chowjiawei.extend'); 28 | } 29 | 30 | public function boot() 31 | { 32 | $this->publishes([ 33 | __DIR__ . '/../Config/helpers.php' => config_path('helpers.php'), 34 | __DIR__ . '/../Config/helpers-pinyin.php' => config_path('helpers-pinyin.php'), 35 | ]); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Services/TTV2Service.php: -------------------------------------------------------------------------------- 1 | config = [ 14 | 'token' => config('helpers.tiktok.token'), 15 | 'salt' => config('helpers.tiktok.salt'), 16 | 'merchant_id' => config('helpers.tiktok.merchant_id'), 17 | 'app_id' => config('helpers.tiktok.client_id'), 18 | 'secret' => config('helpers.tiktok.client_secret'), 19 | 'notify_url' => config('helpers.tiktok.notify_url'), 20 | 'private_key_url' => config('helpers.tiktok.private_key_url'), 21 | 'platform_public_key_url' => config('helpers.tiktok.platform_public_key_url'), 22 | 'public_key_url' => config('helpers.tiktok.public_key_url'), 23 | 'version' => config('helpers.tiktok.version'), 24 | 'settle_notify_url' => config('helpers.tiktok.settle_notify_url'),//分账回调url 25 | 'refund_notify_url' => config('helpers.tiktok.refund_notify_url'),//退款回调url 26 | 'agree_refund_notify_url' => config('helpers.tiktok.agree_refund_notify_url'),//同意退款回调url 27 | 'create_order_callback' => config('helpers.tiktok.create_order_callback'),//创建订单回调地址 28 | 'pay_callback' => config('helpers.tiktok.pay_callback'),//支付回调地址 29 | ]; 30 | } 31 | //查询订单 32 | public function query($trackNumber) 33 | { 34 | $config = $this->config; 35 | $order = ['out_order_no' => $trackNumber]; 36 | $timestamp = Carbon::now()->timestamp; 37 | $str = substr(md5($timestamp), 5, 15); 38 | $body = json_encode($order); 39 | $sign = $this->makeSign('POST', '/api/apps/trade/v2/query_order', $body, $timestamp, $str); 40 | $client = new Client(); 41 | $url = 'https://developer.toutiao.com/api/apps/trade/v2/query_order'; 42 | $response = $client->post($url, [ 43 | 'json' => $order , 44 | 'headers' => [ 45 | 'Content-Type' => 'application/json', 46 | 'Accept' => 'application/json', 47 | 'Byte-Authorization' => 'SHA256-RSA2048 appid="' . $config['app_id'] . '",nonce_str=' . $str . ',timestamp="' . $timestamp . '",key_version="' . $config["version"] . '",signature="' . $sign . '"' 48 | ]]); 49 | $data = json_decode($response->getBody()->getContents(), true); 50 | if ($data['err_no'] == 0) { 51 | return $data['data']; 52 | } 53 | return []; 54 | } 55 | 56 | 57 | //发起退款(单个订单单个订单项) 发起后还需要审核 同意退款 58 | public function refund($trackNumber, $price, $itemOrderId) 59 | { 60 | $config = $this->config; 61 | $order = [ 62 | 'out_order_no' => $trackNumber, 63 | 'out_refund_no' => $trackNumber, 64 | 'order_entry_schema' => [ 65 | 'path' => 'pages/courseDetail/courseDetail', 66 | 'params' => '{\"id\":\"96f8bbf8-57c6-4348-baf2-caffe18a9277\"}' 67 | ], 68 | "item_order_detail" => [ 69 | [ 70 | "item_order_id" => $itemOrderId, 71 | "refund_amount" => (int)$price 72 | ] 73 | ], 74 | 'notify_url' => $config['refund_notify_url'] 75 | ]; 76 | 77 | $timestamp = Carbon::now()->timestamp; 78 | $str = substr(md5($timestamp), 5, 15); 79 | $body = json_encode($order); 80 | 81 | $sign = $this->makeSign('POST', '/api/apps/trade/v2/create_refund', $body, $timestamp, $str); 82 | $client = new Client(); 83 | $url = 'https://developer.toutiao.com/api/apps/trade/v2/create_refund'; 84 | $response = $client->post($url, [ 85 | 'json' => $order , 86 | 'headers' => [ 87 | 'Content-Type' => 'application/json', 88 | 'Accept' => 'application/json', 89 | 'Byte-Authorization' => 'SHA256-RSA2048 appid="' . $config['app_id'] . '",nonce_str=' . $str . ',timestamp="' . $timestamp . '",key_version="' . $config["version"] . '",signature="' . $sign . '"' 90 | ]]); 91 | $data = json_decode($response->getBody()->getContents(), true); 92 | if ($data['err_no'] == 0) { 93 | return true; 94 | } 95 | return false; 96 | } 97 | 98 | 99 | //发起退款(单个订单多个订单项) 发起后还需要审核 同意退款 100 | public function refundManyItem($trackNumber, $item) 101 | { 102 | // $item= [ 103 | // [ 104 | // "item_order_id" => '', 105 | // "refund_amount" => (int)$price 106 | // ], 107 | // [ 108 | // "item_order_id" => '', 109 | // "refund_amount" => (int)$price 110 | // ], 111 | // ]; 112 | $config = $this->config; 113 | $order = [ 114 | 'out_order_no' => $trackNumber, 115 | 'out_refund_no' => $trackNumber, 116 | 'order_entry_schema' => [ 117 | 'path' => 'pages/courseDetail/courseDetail', 118 | 'params' => '{\"id\":\"96f8bbf8-57c6-4348-baf2-caffe18a9277\"}' 119 | ], 120 | "item_order_detail" => $item, 121 | 'notify_url' => $config['refund_notify_url'] 122 | ]; 123 | 124 | $timestamp = Carbon::now()->timestamp; 125 | $str = substr(md5($timestamp), 5, 15); 126 | $body = json_encode($order); 127 | 128 | $sign = $this->makeSign('POST', '/api/apps/trade/v2/create_refund', $body, $timestamp, $str); 129 | $client = new Client(); 130 | $url = 'https://developer.toutiao.com/api/apps/trade/v2/create_refund'; 131 | $response = $client->post($url, [ 132 | 'json' => $order , 133 | 'headers' => [ 134 | 'Content-Type' => 'application/json', 135 | 'Accept' => 'application/json', 136 | 'Byte-Authorization' => 'SHA256-RSA2048 appid="' . $config['app_id'] . '",nonce_str=' . $str . ',timestamp="' . $timestamp . '",key_version="' . $config["version"] . '",signature="' . $sign . '"' 137 | ]]); 138 | $data = json_decode($response->getBody()->getContents(), true); 139 | if ($data['err_no'] == 0) { 140 | return true; 141 | } 142 | return false; 143 | } 144 | 145 | 146 | //同意退款 钱在这里就会直接退回去 147 | public function agreeRefund($trackNumber) 148 | { 149 | $config = $this->config; 150 | 151 | $order = [ 152 | 'out_refund_no' => $trackNumber, 153 | 'refund_audit_status' => 1, 154 | ]; 155 | $timestamp = Carbon::now()->timestamp; 156 | $str = substr(md5($timestamp), 5, 15); 157 | $body = json_encode($order); 158 | 159 | $sign = $this->makeSign('POST', '/api/apps/trade/v2/merchant_audit_callback', $body, $timestamp, $str); 160 | $client = new Client(); 161 | $url = 'https://developer.toutiao.com/api/apps/trade/v2/merchant_audit_callback'; 162 | $response = $client->post($url, [ 163 | 'json' => $order , 164 | 'headers' => [ 165 | 'Content-Type' => 'application/json', 166 | 'Accept' => 'application/json', 167 | 'Byte-Authorization' => 'SHA256-RSA2048 appid="' . $config['app_id'] . '",nonce_str=' . $str . ',timestamp="' . $timestamp . '",key_version="' . $config["version"] . '",signature="' . $sign . '"' 168 | ]]); 169 | $data = json_decode($response->getBody()->getContents(), true); 170 | if ($data['err_no'] == 0) { 171 | return true; 172 | } 173 | return false; 174 | } 175 | 176 | 177 | 178 | //发起分账 179 | public function settle($trackNumber, $desc) 180 | { 181 | // $trackNumber 分账的时候 财务写 这是分账的自定义id $desc 分账描述 182 | $config = $this->config; 183 | 184 | $order = [ 185 | 'out_order_no' => $trackNumber, 186 | 'out_settle_no' => $trackNumber, 187 | 'settle_desc' => $desc, 188 | // 'settle_params'=>"[{\"merchant_uid\":\"71034295218686712630\",\"amount\":".$amount."}]", 189 | 'notify_url' => $config['settle_notify_url'] 190 | ]; 191 | 192 | 193 | 194 | $timestamp = Carbon::now()->timestamp; 195 | $str = substr(md5($timestamp), 5, 15); 196 | $body = json_encode($order); 197 | 198 | $sign = $this->makeSign('POST', '/api/apps/trade/v2/create_settle', $body, $timestamp, $str); 199 | $client = new Client(); 200 | $url = 'https://developer.toutiao.com/api/apps/trade/v2/create_settle'; 201 | $response = $client->post($url, [ 202 | 'json' => $order , 203 | 'headers' => [ 204 | 'Content-Type' => 'application/json', 205 | 'Accept' => 'application/json', 206 | 'Byte-Authorization' => 'SHA256-RSA2048 appid="' . $config['app_id'] . '",nonce_str=' . $str . ',timestamp="' . $timestamp . '",key_version="' . $config["version"] . '",signature="' . $sign . '"' 207 | ]]); 208 | $data = json_decode($response->getBody()->getContents(), true); 209 | if ($data['err_no'] == 0) { 210 | return true; 211 | } 212 | return false; 213 | } 214 | 215 | 216 | //查询退款 217 | public function getRefund($trackNumber) 218 | { 219 | $config = $this->config; 220 | 221 | $order = [ 222 | 'out_refund_no' => $trackNumber, 223 | ]; 224 | $timestamp = Carbon::now()->timestamp; 225 | $str = substr(md5($timestamp), 5, 15); 226 | $body = json_encode($order); 227 | 228 | $sign = $this->makeSign('POST', '/api/apps/trade/v2/query_refund', $body, $timestamp, $str); 229 | $client = new Client(); 230 | $url = 'https://developer.toutiao.com/api/apps/trade/v2/query_refund'; 231 | $response = $client->post($url, [ 232 | 'json' => $order , 233 | 'headers' => [ 234 | 'Content-Type' => 'application/json', 235 | 'Accept' => 'application/json', 236 | 'Byte-Authorization' => 'SHA256-RSA2048 appid="' . $config['app_id'] . '",nonce_str=' . $str . ',timestamp="' . $timestamp . '",key_version="' . $config["version"] . '",signature="' . $sign . '"' 237 | ]]); 238 | $data = json_decode($response->getBody()->getContents(), true); 239 | return $data; 240 | } 241 | 242 | 243 | //设置回调 244 | public function settingReturn(array $settingData = []) 245 | { 246 | $config = $this->config; 247 | if (empty($settingData)) { 248 | $settingData = [ 249 | 'create_order_callback' => $config['create_order_callback'], 250 | 'refund_callback' => $config['refund_notify_url'], 251 | 'pay_callback' => $config['pay_callback'], 252 | ]; 253 | } 254 | $timestamp = Carbon::now()->timestamp; 255 | $str = substr(md5($timestamp), 5, 15); 256 | $body = json_encode($settingData); 257 | $sign = $this->makeSign('POST', '/api/apps/trade/v2/settings', $body, $timestamp, $str); 258 | $client = new Client(); 259 | $url = 'https://developer.toutiao.com/api/apps/trade/v2/settings'; 260 | $response = $client->post($url, [ 261 | 'json' => $settingData , 262 | 'headers' => [ 263 | 'Content-Type' => 'application/json', 264 | 'Accept' => 'application/json', 265 | 'Byte-Authorization' => 'SHA256-RSA2048 appid="' . $config['app_id'] . '",nonce_str=' . $str . ',timestamp="' . $timestamp . '",key_version="' . $config["version"] . '",signature="' . $sign . '"' 266 | ]]); 267 | $data = json_decode($response->getBody()->getContents(), true); 268 | return $data; 269 | } 270 | 271 | 272 | //查询设置的回调 273 | public function getSettingReturn() 274 | { 275 | $config = $this->config; 276 | $order = []; 277 | $timestamp = Carbon::now()->timestamp; 278 | $str = substr(md5($timestamp), 5, 15); 279 | $body = json_encode($order); 280 | $sign = $this->makeSign('POST', '/api/apps/trade/v2/query_settings', $body, $timestamp, $str); 281 | $client = new Client(); 282 | $url = 'https://developer.toutiao.com/api/apps/trade/v2/query_settings'; 283 | $response = $client->post($url, [ 284 | 'json' => $order , 285 | 'headers' => [ 286 | 'Content-Type' => 'application/json', 287 | 'Accept' => 'application/json', 288 | 'Byte-Authorization' => 'SHA256-RSA2048 appid="' . $config['app_id'] . '",nonce_str=' . $str . ',timestamp="' . $timestamp . '",key_version="' . $config["version"] . '",signature="' . $sign . '"' 289 | ]]); 290 | $data = json_decode($response->getBody()->getContents(), true); 291 | if ($data['err_no'] == 0) { 292 | return $data['data']; 293 | } 294 | return []; 295 | } 296 | 297 | 298 | //支付回调 处理支付的事情 299 | public function return(Request $request) 300 | { 301 | $status = $this->verify(json_encode($request->post()), $request->header()['byte-timestamp'][0], $request->header()['byte-nonce-str'][0], $request->header()['byte-signature'][0]); 302 | //搬运原来旧的逻辑 303 | if ($status) { 304 | return [ 305 | 'data' => $request->post(), 306 | 'status' => true 307 | ]; 308 | } 309 | return [ 310 | 'status' => false 311 | ]; 312 | } 313 | 314 | //预下单回调 315 | public function returnCallback(Request $request) 316 | { 317 | $status = $this->verify(str_replace("\\/", "/", json_encode($request->post(), JSON_UNESCAPED_UNICODE)), $request->header()['byte-timestamp'][0], $request->header()['byte-nonce-str'][0], $request->header()['byte-signature'][0]); 318 | if ($status) { 319 | $data = $request->post(); 320 | // $product = json_decode($data['msg'], true); 321 | // $goodsId = $product['goods'][0]['goods_id']; 322 | // $bytedanceOpenid = $product['union_id']; 323 | //全部数据要存起来 后续退款等操作都需要用 抖音不支持二次查询某些字段 324 | } 325 | return $data ?? []; 326 | } 327 | 328 | //退款回调 329 | public function refundReturn(Request $request) 330 | { 331 | $status = $this->verify(str_replace("\\/", "/", json_encode($request->post(), JSON_UNESCAPED_UNICODE)), $request->header()['byte-timestamp'][0], $request->header()['byte-nonce-str'][0], $request->header()['byte-signature'][0]); 332 | if ($status) { 333 | return true; 334 | } 335 | return false; 336 | } 337 | 338 | public function settleCallback(Request $request) 339 | { 340 | $status = $this->verify(str_replace("\\/", "/", json_encode($request->post(), JSON_UNESCAPED_UNICODE)), $request->header()['byte-timestamp'][0], $request->header()['byte-nonce-str'][0], $request->header()['byte-signature'][0]); 341 | if ($status) { 342 | return true; 343 | } 344 | return false; 345 | } 346 | 347 | public function makeSign($method, $url, $body, $timestamp, $nonce_str) 348 | { 349 | $config = $this->config; 350 | $text = $method . "\n" . $url . "\n" . $timestamp . "\n" . $nonce_str . "\n" . $body . "\n"; 351 | $priKey = file_get_contents($config['private_key_url']); 352 | $privateKey = openssl_get_privatekey($priKey, ''); 353 | openssl_sign($text, $sign, $privateKey, OPENSSL_ALGO_SHA256); 354 | $sign = base64_encode($sign); 355 | return $sign; 356 | } 357 | 358 | public function verify($http_body, $timestamp, $nonce_str, $sign) 359 | { 360 | $config = $this->config; 361 | $data = $timestamp . "\n" . $nonce_str . "\n" . $http_body . "\n"; 362 | $publicKey = file_get_contents($config['platform_public_key_url']); 363 | if (!$publicKey) { 364 | return null; 365 | } 366 | $res = openssl_get_publickey($publicKey); 367 | $result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256); 368 | openssl_free_key($res); 369 | return $result; //bool 370 | } 371 | 372 | 373 | 374 | public function returnOK() 375 | { 376 | return [ 377 | "err_no" => 0, 378 | "err_tips" => "success" 379 | ]; 380 | } 381 | 382 | public function returnError($result='') 383 | { 384 | return [ 385 | "err_no" => 400, 386 | "err_tips" => $result??"business fail" 387 | ]; 388 | } 389 | } 390 | --------------------------------------------------------------------------------