Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sunaoka committed Jul 3, 2024
0 parents commit e77de20
Show file tree
Hide file tree
Showing 15 changed files with 575 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/.github export-ignore
/.phpstan export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/phpstan.neon.dist export-ignore
/phpunit.xml.dist export-ignore
/tests export-ignore
53 changes: 53 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Test

on:
push:
workflow_dispatch:
schedule:
- cron: '20 2 * * *'

jobs:

test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
php: [ '8.1', '8.2', '8.3' ]
laravel: [ 10, 11 ]
exclude:
- php: 8.1
laravel: 11

name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}

steps:
- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
ini-values: error_reporting=E_ALL
tools: composer:v2

- name: Checkout
uses: actions/checkout@v4

- name: Install dependencies
run: |
composer require "illuminate/support=^${{ matrix.laravel }}" --no-update
composer update --prefer-dist --no-interaction --no-progress
- name: Migrate phpunit XML configuration
continue-on-error: true
run: vendor/bin/phpunit --migrate-configuration

- name: Run test suite
run: vendor/bin/phpunit --coverage-clover=coverage.xml

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
fail_ci_if_error: false
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/composer.lock
/vendor
3 changes: 3 additions & 0 deletions .phpstan/classAliases.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

class_alias(\Sunaoka\Laravel\PayPay\Facade\PayPay::class, 'PayPay');
53 changes: 53 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"name": "sunaoka/laravel-paypayopa-sdk-php",
"description": "PayPay's Open Payment API Service Provider for Laravel",
"type": "library",
"keywords": ["paypay", "opa", "php", "laravel"],
"license": "Apache-2.0",
"authors": [
{
"name": "sunaoka",
"email": "sunaoka@pocari.org"
}
],
"require": {
"php": "^8.1",
"illuminate/support": "^10.0 || ^11.0",
"paypayopa/php-sdk": "^2.0"
},
"require-dev": {
"laravel/pint": "^1.16",
"orchestra/testbench": "^8.23 || ^9.0",
"phpstan/phpstan": "^1.11"
},
"autoload": {
"psr-4": {
"Sunaoka\\Laravel\\PayPay\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-main": "1.0-dev"
},
"laravel": {
"providers": [
"Sunaoka\\Laravel\\PayPay\\Provider\\ServiceProvider"
],
"aliases": {
"AmazonPay": "Sunaoka\\Laravel\\PayPay\\Facade\\PayPay"
}
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
},
"minimum-stability": "stable",
"prefer-stable": true
}
8 changes: 8 additions & 0 deletions config/paypay.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

return [
'api_key' => env('PAYPAY_API_KEY'),
'api_secret' => env('PAYPAY_API_SECRET'),
'merchant_id' => env('PAYPAY_MERCHANT_ID'),
'production_mode' => (bool) env('PAYPAY_PRODUCTION_MODE', false),
];
13 changes: 13 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
parameters:

bootstrapFiles:
- .phpstan/classAliases.php

level: 9

paths:
- src/
- tests/

ignoreErrors:
- identifier: missingType.iterableValue
19 changes: 19 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
beStrictAboutTestsThatDoNotTestAnything="false"
colors="true">

<testsuites>
<testsuite name="test">
<directory>./tests</directory>
</testsuite>
</testsuites>

<source>
<include>
<directory>./src</directory>
</include>
</source>

</phpunit>
75 changes: 75 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace Sunaoka\Laravel\PayPay;

use GuzzleHttp\Client as GuzzleHttpClient;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Promise\PromiseInterface;
use PayPay\OpenPaymentAPI\ClientException;
use PayPay\OpenPaymentAPI\Controller\Controller;
use Psr\Http\Message\ResponseInterface;

/**
* @method \PayPay\OpenPaymentAPI\Controller\CashBack cashback()
* @method \PayPay\OpenPaymentAPI\Controller\Code code()
* @method \PayPay\OpenPaymentAPI\Controller\Payment payment()
* @method \PayPay\OpenPaymentAPI\Controller\Refund refund()
* @method \PayPay\OpenPaymentAPI\Controller\User user()
* @method \PayPay\OpenPaymentAPI\Controller\Wallet wallet()
*/
class Client extends \PayPay\OpenPaymentAPI\Client
{
/**
* @var array<int, ResponseInterface|PromiseInterface|callable|\Throwable[]>|null
*/
private ?array $fakeResponse;

/**
* @param array{API_KEY: string, API_SECRET: string, MERCHANT_ID: string} $auth
* @param bool $productionmode
* @param GuzzleHttpClient|false $requestHandler
*
* @throws ClientException
*/
public function __construct($auth = null, $productionmode = false, $requestHandler = false)
{
$this->fakeResponse = null;

parent::__construct($auth, $productionmode, $requestHandler);
}

public function http(): GuzzleHttpClient
{
if (empty($this->fakeResponse)) {
return parent::http();
}

$mockHandler = new MockHandler([array_shift($this->fakeResponse)]);
$handlerStack = HandlerStack::create($mockHandler);

return new GuzzleHttpClient([
'base_uri' => $this->GetConfig('API_URL'),
'handler' => $handlerStack,
]);
}

/**
* @param array<int, ResponseInterface|PromiseInterface|callable|\Throwable[]>|null $response
*/
public function fake(?array $response = null): void
{
$this->fakeResponse = $response;
}

public function __call(string $name, array $arguments): Controller
{
if (property_exists($this, $name) && $this->{$name} instanceof Controller) {
return $this->{$name};
}

throw new \LogicException('Call to undefined method: '.$name);
}
}
29 changes: 29 additions & 0 deletions src/Facade/PayPay.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Sunaoka\Laravel\PayPay\Facade;

use Illuminate\Support\Facades\Facade;
use Sunaoka\Laravel\PayPay\Client;

/**
* @method static \Mockery\MockInterface spy() Convert the facade into a Mockery spy.
* @method static \Mockery\MockInterface partialMock() Initiate a partial mock on the facade.
* @method static \Mockery\Expectation shouldReceive(string|array ...$methodNames) Initiate a mock expectation on the facade.
* @method static void swap($instance) Hotswap the underlying instance behind the facade.
* @method static void clearResolvedInstance(string $name) Clear a resolved facade instance.
* @method static void clearResolvedInstances() Clear all of the resolved instances.
*
* @mixin Client
*/
class PayPay extends Facade
{
/**
* Get the registered name of the component.
*/
protected static function getFacadeAccessor(): string
{
return Client::class;
}
}
53 changes: 53 additions & 0 deletions src/Provider/PayPayServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Sunaoka\Laravel\PayPay\Provider;

use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
use Sunaoka\Laravel\PayPay\Client;

class PayPayServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register any application services.
*/
public function register(): void
{
$this->mergeConfigFrom(
dirname(__DIR__, 2).'/config/paypay.php',
'paypay'
);

$this->app->singleton('PayPay', static function ($app) {
$config = $app->make('config')->get('paypay');

return new Client([
'API_KEY' => $config['api_key'],
'API_SECRET' => $config['api_secret'],
'MERCHANT_ID' => $config['merchant_id'],
], $config['production_mode']);
});

$this->app->alias('PayPay', Client::class);
}

/**
* Bootstrap services.
*/
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->publishes(
[dirname(__DIR__, 2).'/config/paypay.php' => $this->app->configPath('paypay.php')],
'paypay-config'
);
}
}

public function provides(): array
{
return [Client::class]; // @codeCoverageIgnore
}
}
Loading

0 comments on commit e77de20

Please sign in to comment.