Merge pull request #235 from XedinUnknown/task/refactor-for-psr-4

Refactor for PSR-4
This commit is contained in:
Emili Castells 2021-09-30 14:26:42 +02:00 committed by GitHub
commit 40058b4b30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
243 changed files with 10646 additions and 8118 deletions

View file

@ -16,8 +16,8 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: composer:v1
php-version: ${{ matrix.php-versions }}
tools: composer:v1
- name: Validate composer.json and composer.lock
run: composer validate

View file

@ -29,8 +29,8 @@ You can also use the Docker environment which includes WP, WC and all developmen
0. Install Docker and Docker Compose.
1. `$ cp .env.example .env` and edit the configuration in the `.env` file if needed.
2. `$ yarn run docker:build` (or copy the commands from [package.json](/package.json) if you do not have `yarn`).
3. `$ yarn docker:install`
4. `$ yarn docker:start`
3. `$ yarn run docker:install`
4. `$ yarn run docker:start`
5. Add `127.0.0.1 wc-pp.myhost` to your `hosts` file and open http://wc-pp.myhost (the default value of `WP_DOMAIN` in `.env`).
Tests and code style:
@ -44,30 +44,21 @@ After some changes in `.env` (such as PHP, WP versions) you may need to rebuild
See [package.json](/package.json) for other useful commands.
## Preparation for wordpress.org release
## Building a release package
If you want to deploy a new version, you need to do some preparation:
If you want to build a release package
(that can be used for deploying a new version on wordpress.org or manual installation on a WP website via ZIP uploading),
follow these steps:
### Clone
Clone the repository and `cd` into it
### Build
The following command should get you a ZIP file ready to be used on a WordPress site.
1. Clone the repository and `cd` into it.
2. Make sure you have the version in the plugin root file updated.
3. Update the PayPal JavaScript SDK integration date by using the current date for the `PAYPAL_INTEGRATION_DATE` constant.
4. The following command should get you a ZIP file ready to be used on a WordPress site:
```
npm run build
$ yarn run build
```
### Update version
Make sure you have the version in the plugin root file updated.
### Fixate integration date
Fix the PayPal JavaScript SDK integration date by using the current date for the `PAYPAL_INTEGRATION_DATE` constant.
## License
[GPL-2.0 License](LICENSE)

View file

@ -1,5 +1,19 @@
*** Changelog ***
= 1.6.0 - 2021-09-29 =
* Add - Webhook status. #246 #273
* Add - Show CC gateway in admin payments list. #236
* Add - Add 3d secure contingency settings. #230
* Add - Improve logging. #252 #275
* Add - Do not send payee email. #231
* Add - Allow customers to see and delete their saved payments in My Account. #274
* Fix - PayPal Payments generates multiple orders. #244
* Fix - Saved credit card does not auto fill. #242
* Fix - Incorrect webhooks registration. #254
* Fix - Disable funding credit cards affecting hosted fields, unset for GB. #249
* Fix - REFUND_CAPTURE_CURRENCY_MISMATCH on multicurrency sites. #225
* Fix - Can't checkout to certain countries with optional postcode. #224
= 1.5.1 - 2021-08-19 =
* Fix - Set 3DS contingencies to "SCA_WHEN_REQUIRED". #178
* Fix - Plugin conflict blocking line item details. #221

View file

@ -4,14 +4,15 @@
"description": "PayPal Commerce Platform for WooCommerce",
"license": "GPL-2.0",
"require": {
"dhii/module-interface": "^0.2 || ^0.3",
"psr/container": "1.0.0",
"container-interop/service-provider": "^0.4.0",
"dhii/containers": "v0.1.0-alpha1",
"dhii/wp-containers": "v0.1.0-alpha1",
"psr/log": "^1.1",
"php": "^7.1 | ^8.0",
"ext-json": "*",
"ralouphie/getallheaders": "^3.0"
"dhii/module-interface": "^0.2 || ^0.3",
"psr/container": "^1.0",
"container-interop/service-provider": "^0.4.0",
"dhii/containers": "^0.1.0-alpha1",
"psr/log": "^1.1",
"ralouphie/getallheaders": "^3.0",
"wikimedia/composer-merge-plugin": "^1.4"
},
"require-dev": {
"woocommerce/woocommerce-sniffs": "^0.1.0",
@ -19,10 +20,9 @@
"brain/monkey": "^2.4"
},
"autoload": {
"classmap": [
"modules/",
"src/"
]
"psr-4": {
"WooCommerce\\PayPalCommerce\\": "src"
}
},
"autoload-dev": {
"psr-4": {
@ -46,6 +46,11 @@
"type:inpsyde-module"
]
},
"merge-plugin": {
"include": [
"modules/*/composer.json"
]
},
"hooks": {
"pre-commit": [
"vendor/bin/phpcbf"

527
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6f1528613bfae64666db050d9fead669",
"content-hash": "0b4f7dd4cc7706bd902a10f64dbd095e",
"packages": [
{
"name": "container-interop/service-provider",
@ -35,10 +35,6 @@
],
"description": "Promoting container interoperability through standard service providers",
"homepage": "https://github.com/container-interop/service-provider",
"support": {
"issues": "https://github.com/container-interop/service-provider/issues",
"source": "https://github.com/container-interop/service-provider/tree/master"
},
"time": "2017-09-20T14:13:36+00:00"
},
{
@ -90,36 +86,34 @@
}
],
"description": "A highly ISP-compliant collection of interfaces that represent maps and lists.",
"support": {
"issues": "https://github.com/Dhii/collections-interface/issues",
"source": "https://github.com/Dhii/collections-interface/tree/v0.3.0-alpha4"
},
"time": "2021-03-09T17:36:34+00:00"
},
{
"name": "dhii/containers",
"version": "v0.1.0-alpha1",
"version": "v0.1.2",
"source": {
"type": "git",
"url": "https://github.com/Dhii/containers.git",
"reference": "73eed5422e106006c81ca1fa8b7213c6be33efbc"
"reference": "b753f1d8eee7bf58ebbeb815b55a634785bcdb64"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dhii/containers/zipball/73eed5422e106006c81ca1fa8b7213c6be33efbc",
"reference": "73eed5422e106006c81ca1fa8b7213c6be33efbc",
"url": "https://api.github.com/repos/Dhii/containers/zipball/b753f1d8eee7bf58ebbeb815b55a634785bcdb64",
"reference": "b753f1d8eee7bf58ebbeb815b55a634785bcdb64",
"shasum": ""
},
"require": {
"container-interop/service-provider": "^0.4",
"dhii/collections-interface": "^0.3.0-alpha1",
"dhii/collections-interface": "^0.3.0-alpha2",
"php": "^7.1 | ^8.0"
},
"require-dev": {
"gmazzap/andrew": "^1.1",
"phpunit/phpunit": "^7.0",
"psr/container": "^1.0",
"slevomat/coding-standard": "~4.0"
"psr/simple-cache": "^1.0",
"slevomat/coding-standard": "~4.0",
"wildwolf/psr-memory-cache": "^1.0"
},
"type": "library",
"extra": {
@ -147,177 +141,7 @@
"PSR-11",
"container"
],
"support": {
"issues": "https://github.com/Dhii/containers/issues",
"source": "https://github.com/Dhii/containers/tree/v0.1.0-alpha1"
},
"time": "2020-09-14T18:27:47+00:00"
},
{
"name": "dhii/data-container-interface",
"version": "v0.2.1-alpha1",
"source": {
"type": "git",
"url": "https://github.com/Dhii/data-container-interface.git",
"reference": "6be46e427184b95785d9dd563d6acf2e0700cc31"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dhii/data-container-interface/zipball/6be46e427184b95785d9dd563d6acf2e0700cc31",
"reference": "6be46e427184b95785d9dd563d6acf2e0700cc31",
"shasum": ""
},
"require": {
"dhii/exception-interface": "^0.1 | ^0.2",
"dhii/factory-interface": "^0.1-alpha1",
"php": "^5.3 | ^7.0",
"psr/container": "^1.0"
},
"require-dev": {
"codeclimate/php-test-reporter": "<=0.3.2",
"dhii/php-cs-fixer-config": "dev-php-5.3",
"dhii/stringable-interface": "^0.1",
"phpunit/phpunit": "^4.8",
"ptrofimov/xpmock": "^1.1"
},
"suggest": {
"dhii/stringable-interface": "To be able to pass Stringables as keys"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-develop": "0.2.x-dev"
}
},
"autoload": {
"psr-4": {
"Dhii\\Data\\Container\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dhii Team",
"email": "development@dhii.co"
}
],
"description": "Interfaces for working with data containers",
"support": {
"issues": "https://github.com/Dhii/data-container-interface/issues",
"source": "https://github.com/Dhii/data-container-interface/tree/v0.2.1-alpha1"
},
"abandoned": "dhii/collections-interface",
"time": "2019-05-10T14:17:29+00:00"
},
{
"name": "dhii/exception-interface",
"version": "v0.2",
"source": {
"type": "git",
"url": "https://github.com/Dhii/exception-interface.git",
"reference": "b69feebf7cb2879cd43977a03342e2393b73f7fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dhii/exception-interface/zipball/b69feebf7cb2879cd43977a03342e2393b73f7fb",
"reference": "b69feebf7cb2879cd43977a03342e2393b73f7fb",
"shasum": ""
},
"require": {
"dhii/stringable-interface": "^0.1",
"php": "^5.3 | ^7.0"
},
"require-dev": {
"codeclimate/php-test-reporter": "<=0.3.2",
"dhii/php-cs-fixer-config": "dev-php-5.3",
"phpunit/phpunit": "^4.8",
"ptrofimov/xpmock": "^1.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-develop": "0.2.x-dev"
}
},
"autoload": {
"psr-4": {
"Dhii\\Exception\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dhii Team",
"email": "development@dhii.co"
}
],
"description": "Interfaces for most common exceptions",
"support": {
"issues": "https://github.com/Dhii/exception-interface/issues",
"source": "https://github.com/Dhii/exception-interface/tree/develop"
},
"time": "2018-08-29T10:42:04+00:00"
},
{
"name": "dhii/factory-interface",
"version": "v0.1",
"source": {
"type": "git",
"url": "https://github.com/Dhii/factory-interface.git",
"reference": "b8d217aec8838e64ccaa770cb03dc164bf6f0515"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dhii/factory-interface/zipball/b8d217aec8838e64ccaa770cb03dc164bf6f0515",
"reference": "b8d217aec8838e64ccaa770cb03dc164bf6f0515",
"shasum": ""
},
"require": {
"dhii/exception-interface": "^0.1|^0.2",
"php": "^5.3 | ^7.0"
},
"require-dev": {
"codeclimate/php-test-reporter": "<=0.3.2",
"dhii/php-cs-fixer-config": "dev-php-5.3",
"dhii/stringable-interface": "^0.1",
"phpunit/phpunit": "^4.8",
"psr/container": "^1.0",
"ptrofimov/xpmock": "^1.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-develop": "0.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Dhii\\Factory\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dhii Team",
"email": "development@dhii.co"
}
],
"description": "Interfaces for working with factories.",
"support": {
"issues": "https://github.com/Dhii/factory-interface/issues",
"source": "https://github.com/Dhii/factory-interface/tree/master"
},
"abandoned": true,
"time": "2018-08-29T11:15:09+00:00"
"time": "2020-10-22T10:20:26+00:00"
},
{
"name": "dhii/module-interface",
@ -365,119 +189,8 @@
}
],
"description": "Interfaces for modules",
"support": {
"issues": "https://github.com/Dhii/module-interface/issues",
"source": "https://github.com/Dhii/module-interface/tree/v0.3.0-alpha2"
},
"time": "2021-08-23T08:23:01+00:00"
},
{
"name": "dhii/stringable-interface",
"version": "v0.1",
"source": {
"type": "git",
"url": "https://github.com/Dhii/stringable-interface.git",
"reference": "b6653905eef2ebf377749feb80a6d18abbe913ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dhii/stringable-interface/zipball/b6653905eef2ebf377749feb80a6d18abbe913ef",
"reference": "b6653905eef2ebf377749feb80a6d18abbe913ef",
"shasum": ""
},
"require": {
"php": "^5.3 | ^7.0"
},
"require-dev": {
"codeclimate/php-test-reporter": "<=0.3.2",
"dhii/php-cs-fixer-config": "dev-php-5.3",
"phpunit/phpunit": "^4.8",
"ptrofimov/xpmock": "^1.1"
},
"type": "library",
"autoload": {
"psr-4": {
"Dhii\\Util\\String\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dhii Team",
"email": "development@dhii.co"
}
],
"description": "Interoperability interface for objects that can be cast to string",
"support": {
"issues": "https://github.com/Dhii/stringable-interface/issues",
"source": "https://github.com/Dhii/stringable-interface/tree/master"
},
"abandoned": "symfony/polyfill-php80",
"time": "2017-01-23T15:08:20+00:00"
},
{
"name": "dhii/wp-containers",
"version": "v0.1.0-alpha1",
"source": {
"type": "git",
"url": "https://github.com/Dhii/wp-containers.git",
"reference": "e91a6f741622770ed724a2b594145fa917811f0c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dhii/wp-containers/zipball/e91a6f741622770ed724a2b594145fa917811f0c",
"reference": "e91a6f741622770ed724a2b594145fa917811f0c",
"shasum": ""
},
"require": {
"dhii/data-container-interface": "^0.2.1-alpha1",
"php": "^7.0 | ^8.0",
"psr/container": "^1.0"
},
"require-dev": {
"brain/monkey": "^2",
"gmazzap/andrew": "^1.1",
"phpunit/phpunit": "^6",
"slevomat/coding-standard": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-develop": "0.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Dhii\\Wp\\Containers\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dhii Team",
"email": "development@dhii.co"
}
],
"description": "PSR-11 container implementations that wrap some WP features, for convenience and interoperability.",
"keywords": [
"container",
"dependency injection",
"di",
"wordpress"
],
"support": {
"issues": "https://github.com/Dhii/wp-containers/issues",
"source": "https://github.com/Dhii/wp-containers/tree/v0.1.0-alpha1"
},
"abandoned": "wp-oop/containers",
"time": "2019-05-10T15:04:22+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
@ -525,10 +238,6 @@
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/master"
},
"time": "2017-02-14T16:28:37+00:00"
},
{
@ -576,9 +285,6 @@
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/1.1.4"
},
"time": "2021-05-03T11:20:27+00:00"
},
{
@ -619,11 +325,56 @@
}
],
"description": "A polyfill for getallheaders.",
"support": {
"issues": "https://github.com/ralouphie/getallheaders/issues",
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
},
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "wikimedia/composer-merge-plugin",
"version": "v1.4.1",
"source": {
"type": "git",
"url": "https://github.com/wikimedia/composer-merge-plugin.git",
"reference": "81c6ac72a24a67383419c7eb9aa2b3437f2ab100"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/wikimedia/composer-merge-plugin/zipball/81c6ac72a24a67383419c7eb9aa2b3437f2ab100",
"reference": "81c6ac72a24a67383419c7eb9aa2b3437f2ab100",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0",
"php": ">=5.3.2"
},
"require-dev": {
"composer/composer": "~1.0.0",
"jakub-onderka/php-parallel-lint": "~0.8",
"phpunit/phpunit": "~4.8|~5.0",
"squizlabs/php_codesniffer": "~2.1.0"
},
"type": "composer-plugin",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
},
"class": "Wikimedia\\Composer\\MergePlugin"
},
"autoload": {
"psr-4": {
"Wikimedia\\Composer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bryan Davis",
"email": "bd808@wikimedia.org"
}
],
"description": "Composer plugin to merge multiple composer.json files",
"time": "2017-04-25T02:31:25+00:00"
}
],
"packages-dev": [
@ -669,10 +420,6 @@
"runkit",
"testing"
],
"support": {
"issues": "https://github.com/antecedent/patchwork/issues",
"source": "https://github.com/antecedent/patchwork/tree/2.1.15"
},
"time": "2021-08-22T08:00:13+00:00"
},
{
@ -739,10 +486,6 @@
"test",
"testing"
],
"support": {
"issues": "https://github.com/Brain-WP/BrainMonkey/issues",
"source": "https://github.com/Brain-WP/BrainMonkey"
},
"time": "2020-10-13T17:56:14+00:00"
},
{
@ -809,10 +552,6 @@
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2020-12-07T18:04:37+00:00"
},
{
@ -864,10 +603,6 @@
"constructor",
"instantiate"
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.0"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
@ -929,10 +664,6 @@
"keywords": [
"test"
],
"support": {
"issues": "https://github.com/hamcrest/hamcrest-php/issues",
"source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1"
},
"time": "2020-07-09T08:09:16+00:00"
},
{
@ -998,10 +729,6 @@
"test double",
"testing"
],
"support": {
"issues": "https://github.com/mockery/mockery/issues",
"source": "https://github.com/mockery/mockery/tree/1.3.4"
},
"time": "2021-02-24T09:51:00+00:00"
},
{
@ -1050,10 +777,6 @@
"object",
"object graph"
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.10.2"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
@ -1115,10 +838,6 @@
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
"source": "https://github.com/phar-io/manifest/tree/master"
},
"time": "2018-07-08T19:23:20+00:00"
},
{
@ -1166,10 +885,6 @@
}
],
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/master"
},
"time": "2018-07-08T19:19:57+00:00"
},
{
@ -1228,10 +943,6 @@
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
"source": "https://github.com/PHPCompatibility/PHPCompatibility"
},
"time": "2019-12-27T09:44:58+00:00"
},
{
@ -1284,10 +995,6 @@
"polyfill",
"standards"
],
"support": {
"issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues",
"source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie"
},
"time": "2021-02-15T10:24:51+00:00"
},
{
@ -1338,10 +1045,6 @@
"standards",
"wordpress"
],
"support": {
"issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues",
"source": "https://github.com/PHPCompatibility/PHPCompatibilityWP"
},
"time": "2021-07-21T11:09:57+00:00"
},
{
@ -1391,10 +1094,6 @@
"reflection",
"static analysis"
],
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master"
},
"time": "2020-04-27T09:25:28+00:00"
},
{
@ -1447,10 +1146,6 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/4.x"
},
"time": "2019-12-28T18:55:12+00:00"
},
{
@ -1498,10 +1193,6 @@
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/0.7.2"
},
"time": "2019-08-22T18:11:29+00:00"
},
{
@ -1565,10 +1256,6 @@
"spy",
"stub"
],
"support": {
"issues": "https://github.com/phpspec/prophecy/issues",
"source": "https://github.com/phpspec/prophecy/tree/v1.10.3"
},
"time": "2020-03-05T15:02:03+00:00"
},
{
@ -1632,10 +1319,6 @@
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/master"
},
"time": "2018-10-31T16:06:48+00:00"
},
{
@ -1686,10 +1369,6 @@
"filesystem",
"iterator"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -1737,10 +1416,6 @@
"keywords": [
"template"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1"
},
"time": "2015-06-21T13:50:34+00:00"
},
{
@ -1790,10 +1465,6 @@
"keywords": [
"timer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
"source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -1849,10 +1520,6 @@
"keywords": [
"tokenizer"
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
"source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -1944,10 +1611,6 @@
"testing",
"xunit"
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/7.5.20"
},
"time": "2020-01-08T08:45:45+00:00"
},
{
@ -1993,10 +1656,6 @@
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2067,10 +1726,6 @@
"compare",
"equality"
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"source": "https://github.com/sebastianbergmann/comparator/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2133,10 +1788,6 @@
"unidiff",
"unified diff"
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"source": "https://github.com/sebastianbergmann/diff/tree/3.0.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2196,10 +1847,6 @@
"environment",
"hhvm"
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/4.2.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2273,10 +1920,6 @@
"export",
"exporter"
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2334,10 +1977,6 @@
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/2.0.0"
},
"time": "2017-04-27T15:39:26+00:00"
},
{
@ -2385,10 +2024,6 @@
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2440,10 +2075,6 @@
],
"description": "Allows reflection of object attributes, including inherited and non-public ones",
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
"source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2503,10 +2134,6 @@
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2555,10 +2182,6 @@
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
"source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
@ -2608,10 +2231,6 @@
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"source": "https://github.com/sebastianbergmann/version/tree/master"
},
"time": "2016-10-03T07:35:21+00:00"
},
{
@ -2663,11 +2282,6 @@
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2021-04-09T00:54:41+00:00"
},
{
@ -2730,9 +2344,6 @@
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
@ -2787,10 +2398,6 @@
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/master"
},
"time": "2019-06-13T22:48:21+00:00"
},
{
@ -2840,10 +2447,6 @@
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.9.1"
},
"time": "2020-07-08T17:02:28+00:00"
},
{
@ -2884,10 +2487,6 @@
"woocommerce",
"wordpress"
],
"support": {
"issues": "https://github.com/woocommerce/woocommerce-sniffs/issues",
"source": "https://github.com/woocommerce/woocommerce-sniffs/tree/0.1.1"
},
"time": "2021-07-29T17:25:16+00:00"
},
{
@ -2934,11 +2533,6 @@
"standards",
"wordpress"
],
"support": {
"issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues",
"source": "https://github.com/WordPress/WordPress-Coding-Standards",
"wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki"
},
"time": "2020-05-13T23:57:56+00:00"
}
],
@ -2948,8 +2542,9 @@
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": "^7.1 | ^8.0",
"ext-json": "*"
},
"platform-dev": [],
"plugin-api-version": "2.1.0"
"plugin-api-version": "1.1.0"
}

View file

@ -23,6 +23,7 @@ return function ( string $root_dir ): iterable {
( require "$modules_dir/ppcp-subscription/module.php" )(),
( require "$modules_dir/ppcp-wc-gateway/module.php" )(),
( require "$modules_dir/ppcp-webhooks/module.php" )(),
( require "$modules_dir/ppcp-vaulting/module.php" )(),
);
return $modules;

View file

@ -0,0 +1,17 @@
{
"name": "woocommerce/ppcp-admin-notices",
"type": "dhii-mod",
"description": "Admin notices module for PPCP",
"license": "GPL-2.0",
"require": {
"php": "^7.1 | ^8.0",
"dhii/module-interface": "^0.3.0-alpha1"
},
"autoload": {
"psr-4": {
"WooCommerce\\PayPalCommerce\\AdminNotices\\": "src"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View file

@ -9,19 +9,19 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\AdminNotices;
use Dhii\Data\Container\ContainerInterface;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\AdminNotices\Renderer\Renderer;
use WooCommerce\PayPalCommerce\AdminNotices\Renderer\RendererInterface;
use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository;
use WooCommerce\PayPalCommerce\AdminNotices\Repository\RepositoryInterface;
return array(
'admin-notices.renderer' => static function ( $container ): RendererInterface {
'admin-notices.renderer' => static function ( ContainerInterface $container ): RendererInterface {
$repository = $container->get( 'admin-notices.repository' );
return new Renderer( $repository );
},
'admin-notices.repository' => static function ( $container ): RepositoryInterface {
'admin-notices.repository' => static function ( ContainerInterface $container ): RepositoryInterface {
return new Repository();
},

View file

@ -20,9 +20,7 @@ use Psr\Container\ContainerInterface;
class AdminNotices implements ModuleInterface {
/**
* Sets up the module.
*
* @return ServiceProviderInterface
* {@inheritDoc}
*/
public function setup(): ServiceProviderInterface {
return new ServiceProvider(
@ -32,15 +30,13 @@ class AdminNotices implements ModuleInterface {
}
/**
* Runs the module.
*
* @param ContainerInterface $container The container.
* {@inheritDoc}
*/
public function run( ContainerInterface $container ): void {
public function run( ContainerInterface $c ): void {
add_action(
'admin_notices',
function() use ( $container ) {
$renderer = $container->get( 'admin-notices.renderer' );
function() use ( $c ) {
$renderer = $c->get( 'admin-notices.renderer' );
$renderer->render();
}
);

View file

@ -0,0 +1,17 @@
{
"name": "woocommerce/ppcp-api-client",
"type": "dhii-mod",
"description": "API client module for PPCP",
"license": "GPL-2.0",
"require": {
"php": "^7.1 | ^8.0",
"dhii/module-interface": "^0.3.0-alpha1"
},
"autoload": {
"psr-4": {
"WooCommerce\\PayPalCommerce\\ApiClient\\": "src"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View file

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\IdentityToken;
@ -35,6 +36,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\SellerStatusFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookEventFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory;
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
@ -46,10 +48,10 @@ use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
return array(
'api.host' => function( $container ) : string {
'api.host' => function( ContainerInterface $container ) : string {
return PAYPAL_API_URL;
},
'api.paypal-host' => function( $container ) : string {
'api.paypal-host' => function( ContainerInterface $container ) : string {
return PAYPAL_API_URL;
},
'api.partner_merchant_id' => static function () : string {
@ -70,23 +72,23 @@ return array(
'api.prefix' => static function (): string {
return 'WC-';
},
'api.bearer' => static function ( $container ): Bearer {
'api.bearer' => static function ( ContainerInterface $container ): Bearer {
$cache = new Cache( 'ppcp-paypal-bearer' );
$key = $container->get( 'api.key' );
$secret = $container->get( 'api.secret' );
$host = $container->get( 'api.host' );
$logger = $container->get( 'woocommerce.logger.woocommerce' );
$settings = $container->get( 'wcgateway.settings' );
return new PayPalBearer(
$cache,
$host,
$key,
$secret,
$logger
$logger,
$settings
);
},
'api.endpoint.partners' => static function ( $container ) : PartnersEndpoint {
'api.endpoint.partners' => static function ( ContainerInterface $container ) : PartnersEndpoint {
return new PartnersEndpoint(
$container->get( 'api.host' ),
$container->get( 'api.bearer' ),
@ -96,10 +98,10 @@ return array(
$container->get( 'api.merchant_id' )
);
},
'api.factory.sellerstatus' => static function ( $container ) : SellerStatusFactory {
'api.factory.sellerstatus' => static function ( ContainerInterface $container ) : SellerStatusFactory {
return new SellerStatusFactory();
},
'api.endpoint.payment-token' => static function ( $container ) : PaymentTokenEndpoint {
'api.endpoint.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenEndpoint {
return new PaymentTokenEndpoint(
$container->get( 'api.host' ),
$container->get( 'api.bearer' ),
@ -108,16 +110,17 @@ return array(
$container->get( 'api.prefix' )
);
},
'api.endpoint.webhook' => static function ( $container ) : WebhookEndpoint {
'api.endpoint.webhook' => static function ( ContainerInterface $container ) : WebhookEndpoint {
return new WebhookEndpoint(
$container->get( 'api.host' ),
$container->get( 'api.bearer' ),
$container->get( 'api.factory.webhook' ),
$container->get( 'api.factory.webhook-event' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
},
'api.endpoint.partner-referrals' => static function ( $container ) : PartnerReferrals {
'api.endpoint.partner-referrals' => static function ( ContainerInterface $container ) : PartnerReferrals {
return new PartnerReferrals(
$container->get( 'api.host' ),
@ -126,7 +129,7 @@ return array(
$container->get( 'woocommerce.logger.woocommerce' )
);
},
'api.endpoint.identity-token' => static function ( $container ) : IdentityToken {
'api.endpoint.identity-token' => static function ( ContainerInterface $container ) : IdentityToken {
$logger = $container->get( 'woocommerce.logger.woocommerce' );
$prefix = $container->get( 'api.prefix' );
@ -137,7 +140,7 @@ return array(
$prefix
);
},
'api.endpoint.payments' => static function ( $container ): PaymentsEndpoint {
'api.endpoint.payments' => static function ( ContainerInterface $container ): PaymentsEndpoint {
$authorizations_factory = $container->get( 'api.factory.authorization' );
$logger = $container->get( 'woocommerce.logger.woocommerce' );
@ -148,7 +151,7 @@ return array(
$logger
);
},
'api.endpoint.login-seller' => static function ( $container ) : LoginSeller {
'api.endpoint.login-seller' => static function ( ContainerInterface $container ) : LoginSeller {
$logger = $container->get( 'woocommerce.logger.woocommerce' );
return new LoginSeller(
@ -157,7 +160,7 @@ return array(
$logger
);
},
'api.endpoint.order' => static function ( $container ): OrderEndpoint {
'api.endpoint.order' => static function ( ContainerInterface $container ): OrderEndpoint {
$order_factory = $container->get( 'api.factory.order' );
$patch_collection_factory = $container->get( 'api.factory.patch-collection-factory' );
$logger = $container->get( 'woocommerce.logger.woocommerce' );
@ -182,44 +185,47 @@ return array(
$paypal_request_id
);
},
'api.repository.paypal-request-id' => static function( $container ) : PayPalRequestIdRepository {
'api.repository.paypal-request-id' => static function( ContainerInterface $container ) : PayPalRequestIdRepository {
return new PayPalRequestIdRepository();
},
'api.repository.application-context' => static function( $container ) : ApplicationContextRepository {
'api.repository.application-context' => static function( ContainerInterface $container ) : ApplicationContextRepository {
$settings = $container->get( 'wcgateway.settings' );
return new ApplicationContextRepository( $settings );
},
'api.repository.partner-referrals-data' => static function ( $container ) : PartnerReferralsData {
'api.repository.partner-referrals-data' => static function ( ContainerInterface $container ) : PartnerReferralsData {
$merchant_email = $container->get( 'api.merchant_email' );
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
return new PartnerReferralsData( $merchant_email, $dcc_applies );
},
'api.repository.cart' => static function ( $container ): CartRepository {
'api.repository.cart' => static function ( ContainerInterface $container ): CartRepository {
$factory = $container->get( 'api.factory.purchase-unit' );
return new CartRepository( $factory );
},
'api.repository.payee' => static function ( $container ): PayeeRepository {
'api.repository.payee' => static function ( ContainerInterface $container ): PayeeRepository {
$merchant_email = $container->get( 'api.merchant_email' );
$merchant_id = $container->get( 'api.merchant_id' );
return new PayeeRepository( $merchant_email, $merchant_id );
},
'api.factory.application-context' => static function ( $container ) : ApplicationContextFactory {
'api.factory.application-context' => static function ( ContainerInterface $container ) : ApplicationContextFactory {
return new ApplicationContextFactory();
},
'api.factory.payment-token' => static function ( $container ) : PaymentTokenFactory {
'api.factory.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenFactory {
return new PaymentTokenFactory();
},
'api.factory.webhook' => static function ( $container ): WebhookFactory {
'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory {
return new WebhookFactory();
},
'api.factory.webhook-event' => static function ( $container ): WebhookEventFactory {
return new WebhookEventFactory();
},
'api.factory.capture' => static function ( $container ): CaptureFactory {
$amount_factory = $container->get( 'api.factory.amount' );
return new CaptureFactory( $amount_factory );
},
'api.factory.purchase-unit' => static function ( $container ): PurchaseUnitFactory {
'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory {
$amount_factory = $container->get( 'api.factory.amount' );
$payee_repository = $container->get( 'api.repository.payee' );
@ -239,34 +245,34 @@ return array(
$prefix
);
},
'api.factory.patch-collection-factory' => static function ( $container ): PatchCollectionFactory {
'api.factory.patch-collection-factory' => static function ( ContainerInterface $container ): PatchCollectionFactory {
return new PatchCollectionFactory();
},
'api.factory.payee' => static function ( $container ): PayeeFactory {
'api.factory.payee' => static function ( ContainerInterface $container ): PayeeFactory {
return new PayeeFactory();
},
'api.factory.item' => static function ( $container ): ItemFactory {
'api.factory.item' => static function ( ContainerInterface $container ): ItemFactory {
return new ItemFactory();
},
'api.factory.shipping' => static function ( $container ): ShippingFactory {
'api.factory.shipping' => static function ( ContainerInterface $container ): ShippingFactory {
$address_factory = $container->get( 'api.factory.address' );
return new ShippingFactory( $address_factory );
},
'api.factory.amount' => static function ( $container ): AmountFactory {
'api.factory.amount' => static function ( ContainerInterface $container ): AmountFactory {
$item_factory = $container->get( 'api.factory.item' );
return new AmountFactory( $item_factory );
},
'api.factory.payer' => static function ( $container ): PayerFactory {
'api.factory.payer' => static function ( ContainerInterface $container ): PayerFactory {
$address_factory = $container->get( 'api.factory.address' );
return new PayerFactory( $address_factory );
},
'api.factory.address' => static function ( $container ): AddressFactory {
'api.factory.address' => static function ( ContainerInterface $container ): AddressFactory {
return new AddressFactory();
},
'api.factory.payment-source' => static function ( $container ): PaymentSourceFactory {
'api.factory.payment-source' => static function ( ContainerInterface $container ): PaymentSourceFactory {
return new PaymentSourceFactory();
},
'api.factory.order' => static function ( $container ): OrderFactory {
'api.factory.order' => static function ( ContainerInterface $container ): OrderFactory {
$purchase_unit_factory = $container->get( 'api.factory.purchase-unit' );
$payer_factory = $container->get( 'api.factory.payer' );
$application_context_repository = $container->get( 'api.repository.application-context' );
@ -280,15 +286,15 @@ return array(
$payment_source_factory
);
},
'api.factory.payments' => static function ( $container ): PaymentsFactory {
'api.factory.payments' => static function ( ContainerInterface $container ): PaymentsFactory {
$authorizations_factory = $container->get( 'api.factory.authorization' );
$capture_factory = $container->get( 'api.factory.capture' );
return new PaymentsFactory( $authorizations_factory, $capture_factory );
},
'api.factory.authorization' => static function ( $container ): AuthorizationFactory {
'api.factory.authorization' => static function ( ContainerInterface $container ): AuthorizationFactory {
return new AuthorizationFactory();
},
'api.helpers.dccapplies' => static function ( $container ) : DccApplies {
'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies {
return new DccApplies();
},
);

View file

@ -20,9 +20,7 @@ use Psr\Container\ContainerInterface;
class ApiModule implements ModuleInterface {
/**
* Sets up the module.
*
* @return ServiceProviderInterface
* {@inheritDoc}
*/
public function setup(): ServiceProviderInterface {
return new ServiceProvider(
@ -32,11 +30,9 @@ class ApiModule implements ModuleInterface {
}
/**
* Runs the module.
*
* @param ContainerInterface $container The container.
* {@inheritDoc}
*/
public function run( ContainerInterface $container ): void {
public function run( ContainerInterface $c ): void {
add_action(
'woocommerce_after_calculate_totals',
function ( \WC_Cart $cart ) {

View file

@ -390,7 +390,7 @@ class OrderEndpoint {
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 201 !== $status_code ) {
if ( ! in_array( $status_code, array( 200, 201 ), true ) ) {
if ( false !== strpos( $response['body'], ErrorResponse::ORDER_ALREADY_AUTHORIZED ) ) {
return $this->order( $order->id() );
}

View file

@ -139,24 +139,7 @@ class PaymentTokenEndpoint {
foreach ( $json->payment_tokens as $token_value ) {
$tokens[] = $this->factory->from_paypal_response( $token_value );
}
if ( empty( $tokens ) ) {
$error = new RuntimeException(
sprintf(
// translators: %d is the customer id.
__( 'No token stored for customer %d.', 'woocommerce-paypal-payments' ),
$id
)
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
return $tokens;
}

View file

@ -0,0 +1,83 @@
<?php
/**
* The RequestTrait wraps the wp_remote_get functionality for the API client.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
/**
* Trait RequestTrait
*/
trait RequestTrait {
/**
* Performs a request
*
* @param string $url The URL to request.
* @param array $args The arguments by which to request.
*
* @return array|\WP_Error
*/
private function request( string $url, array $args ) {
$args['timeout'] = 30;
/**
* This filter can be used to alter the request args.
* For example, during testing, the PayPal-Mock-Response header could be
* added here.
*/
$args = apply_filters( 'ppcp_request_args', $args, $url );
if ( ! isset( $args['headers']['PayPal-Partner-Attribution-Id'] ) ) {
$args['headers']['PayPal-Partner-Attribution-Id'] = 'Woo_PPCP';
}
$response = wp_remote_get( $url, $args );
$this->logger->debug( $this->request_response_string( $url, $args, $response ) );
return $response;
}
/**
* Returns request and response information as string.
*
* @param string $url The request URL.
* @param array $args The request arguments.
* @param array $response The response.
* @return string
*/
private function request_response_string( string $url, array $args, array $response ): string {
$method = $args['method'] ?? '';
$output = $method . ' ' . $url . "\n";
if ( isset( $args['body'] ) ) {
if ( ! in_array(
$url,
array(
trailingslashit( $this->host ) . 'v1/oauth2/token/',
trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials',
),
true
) ) {
$output .= 'Request Body: ' . wc_print_r( $args['body'], true ) . "\n";
}
}
if ( isset( $response['headers']->getAll()['paypal-debug-id'] ) ) {
$output .= 'Response Debug ID: ' . $response['headers']->getAll()['paypal-debug-id'] . "\n";
}
if ( isset( $response['response'] ) ) {
$output .= 'Response: ' . wc_print_r( $response['response'], true ) . "\n";
if ( isset( $response['body'] )
&& isset( $response['response']['code'] )
&& ! in_array( $response['response']['code'], array( 200, 201, 202, 204 ), true ) ) {
$output .= 'Response Body: ' . wc_print_r( $response['body'], true ) . "\n";
}
}
return $output;
}
}

View file

@ -11,8 +11,10 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Webhook;
use WooCommerce\PayPalCommerce\ApiClient\Entity\WebhookEvent;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookEventFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory;
use Psr\Log\LoggerInterface;
@ -44,6 +46,13 @@ class WebhookEndpoint {
*/
private $webhook_factory;
/**
* The webhook event factory.
*
* @var WebhookEventFactory
*/
private $webhook_event_factory;
/**
* The logger.
*
@ -54,22 +63,25 @@ class WebhookEndpoint {
/**
* WebhookEndpoint constructor.
*
* @param string $host The host.
* @param Bearer $bearer The bearer.
* @param WebhookFactory $webhook_factory The webhook factory.
* @param LoggerInterface $logger The logger.
* @param string $host The host.
* @param Bearer $bearer The bearer.
* @param WebhookFactory $webhook_factory The webhook factory.
* @param WebhookEventFactory $webhook_event_factory The webhook event factory.
* @param LoggerInterface $logger The logger.
*/
public function __construct(
string $host,
Bearer $bearer,
WebhookFactory $webhook_factory,
WebhookEventFactory $webhook_event_factory,
LoggerInterface $logger
) {
$this->host = $host;
$this->bearer = $bearer;
$this->webhook_factory = $webhook_factory;
$this->logger = $logger;
$this->host = $host;
$this->bearer = $bearer;
$this->webhook_factory = $webhook_factory;
$this->webhook_event_factory = $webhook_event_factory;
$this->logger = $logger;
}
/**
@ -79,14 +91,14 @@ class WebhookEndpoint {
*
* @return Webhook
* @throws RuntimeException If the request fails.
* @throws PayPalApiException If the request fails.
*/
public function create( Webhook $hook ): Webhook {
/**
* An hook, which has an ID has already been created.
*/
// The hook was already created.
if ( $hook->id() ) {
return $hook;
}
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/notifications/webhooks';
$args = array(
@ -100,42 +112,64 @@ class WebhookEndpoint {
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
$error = new RuntimeException(
throw new RuntimeException(
__( 'Not able to create a webhook.', 'woocommerce-paypal-payments' )
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 201 !== $status_code ) {
$error = new PayPalApiException(
throw new PayPalApiException(
$json,
$status_code
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
$hook = $this->webhook_factory->from_paypal_response( $json );
return $hook;
}
/**
* Loads the webhooks list for the current auth token.
*
* @return Webhook[]
* @throws RuntimeException If the request fails.
* @throws PayPalApiException If the request fails.
*/
public function list(): array {
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/notifications/webhooks';
$args = array(
'method' => 'GET',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
),
);
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
throw new RuntimeException(
__( 'Not able to load webhooks list.', 'woocommerce-paypal-payments' )
);
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
throw new PayPalApiException(
$json,
$status_code
);
}
return array_map(
array( $this->webhook_factory, 'from_paypal_response' ),
$json->webhooks
);
}
/**
* Deletes a webhook.
*
@ -160,22 +194,61 @@ class WebhookEndpoint {
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
$error = new RuntimeException(
throw new RuntimeException(
__( 'Not able to delete the webhook.', 'woocommerce-paypal-payments' )
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
return wp_remote_retrieve_response_code( $response ) === 204;
}
/**
* Request a simulated webhook to be sent.
*
* @param Webhook $hook The webhook subscription to use.
* @param string $event_type The event type, such as CHECKOUT.ORDER.APPROVED.
* @param string|null $resource_version The event resource version, such as 2.0.
*
* @return WebhookEvent
* @throws RuntimeException If the request fails.
* @throws PayPalApiException If the request fails.
*/
public function simulate( Webhook $hook, string $event_type, ?string $resource_version ): WebhookEvent {
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/notifications/simulate-event';
$data = array(
'webhook_id' => $hook->id(),
'event_type' => $event_type,
);
if ( $resource_version ) {
$data['resource_version'] = $resource_version;
}
$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( $data ),
);
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
throw new RuntimeException(
__( 'Not able to simulate webhook.', 'woocommerce-paypal-payments' )
);
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 202 !== $status_code ) {
throw new PayPalApiException(
$json,
$status_code
);
}
return $this->webhook_event_factory->from_paypal_response( $json );
}
/**
* Verifies if a webhook event is legitimate.
*

View file

@ -1,41 +0,0 @@
<?php
/**
* The RequestTrait wraps the wp_remote_get functionality for the API client.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
/**
* Trait RequestTrait
*/
trait RequestTrait {
/**
* Performs a request
*
* @param string $url The URL to request.
* @param array $args The arguments by which to request.
*
* @return array|\WP_Error
*/
private function request( string $url, array $args ) {
$args['timeout'] = 30;
/**
* This filter can be used to alter the request args.
* For example, during testing, the PayPal-Mock-Response header could be
* added here.
*/
$args = apply_filters( 'ppcp_request_args', $args, $url );
if ( ! isset( $args['headers']['PayPal-Partner-Attribution-Id'] ) ) {
$args['headers']['PayPal-Partner-Attribution-Id'] = 'Woo_PPCP';
}
return wp_remote_get( $url, $args );
}
}

View file

@ -112,7 +112,7 @@ class CardAuthenticationResult {
$data['liability_shift'] = $this->liability_shift();
$data['three_d_secure'] = array(
'enrollment_status' => $this->enrollment_status(),
'authentication_result' => $this->authentication_result(),
'authentication_status' => $this->authentication_result(),
);
return $data;
}

View file

@ -317,8 +317,8 @@ class PurchaseUnit {
}
}
$fee_items_total = round( $fee_items_total, 2 );
$fee_tax_total = round( $fee_tax_total, 2 );
$fee_items_total = round( (float) $fee_items_total, 2 );
$fee_tax_total = round( (float) $fee_tax_total, 2 );
if ( 0.0 !== $fee_items_total || 0.0 !== $fee_tax_total ) {
return true;

View file

@ -9,6 +9,8 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
use stdClass;
/**
* Class Webhook
*/
@ -71,13 +73,38 @@ class Webhook {
/**
* Returns the event types.
*
* @return array
* @return stdClass[]
*/
public function event_types(): array {
return $this->event_types;
}
/**
* Returns the human-friendly names of the event types.
*
* @return string[]
*/
public function humanfriendly_event_names(): array {
return array_map(
function ( $event ): string {
return Webhook::get_humanfriendly_event_name( $event->name );
},
$this->event_types
);
}
/**
* Converts event names to more human-friendly form.
*
* @param string $name The event name like 'CHECKOUT.ORDER.APPROVED'.
* @return string
*/
public static function get_humanfriendly_event_name( string $name ): string {
return strtolower( str_replace( '.', ' ', $name ) );
}
/**
* Returns the object as array.
*

View file

@ -0,0 +1,170 @@
<?php
/**
* The Webhook event notification object.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
use DateTime;
use stdClass;
/**
* Class WebhookEvent
*/
class WebhookEvent {
/**
* The ID of the event notification.
*
* @var string
*/
private $id;
/**
* The date and time when the event notification was created.
*
* @var DateTime|null
*/
private $create_time;
/**
* The name of the resource related to the webhook notification event, such as 'checkout-order'.
*
* @var string
*/
private $resource_type;
/**
* The event version in the webhook notification, such as '1.0'.
*
* @var string
*/
private $event_version;
/**
* The event that triggered the webhook event notification, such as 'CHECKOUT.ORDER.APPROVED'.
*
* @var string
*/
private $event_type;
/**
* A summary description for the event notification.
*
* @var string
*/
private $summary;
/**
* The resource version in the webhook notification, such as '1.0'.
*
* @var string
*/
private $resource_version;
/**
* The resource that triggered the webhook event notification.
*
* @var stdClass
*/
private $resource;
/**
* WebhookEvent constructor.
*
* @param string $id The ID of the event notification.
* @param DateTime|null $create_time The date and time when the event notification was created.
* @param string $resource_type The name of the resource related to the webhook notification event, such as 'checkout-order'.
* @param string $event_version The event version in the webhook notification, such as '1.0'.
* @param string $event_type The event that triggered the webhook event notification, such as 'CHECKOUT.ORDER.APPROVED'.
* @param string $summary A summary description for the event notification.
* @param string $resource_version The resource version in the webhook notification, such as '1.0'.
* @param stdClass $resource The resource that triggered the webhook event notification.
*/
public function __construct( string $id, ?DateTime $create_time, string $resource_type, string $event_version, string $event_type, string $summary, string $resource_version, stdClass $resource ) {
$this->id = $id;
$this->create_time = $create_time;
$this->resource_type = $resource_type;
$this->event_version = $event_version;
$this->event_type = $event_type;
$this->summary = $summary;
$this->resource_version = $resource_version;
$this->resource = $resource;
}
/**
* The ID of the event notification.
*
* @return string
*/
public function id(): string {
return $this->id;
}
/**
* The date and time when the event notification was created.
*
* @return DateTime|null
*/
public function create_time(): ?DateTime {
return $this->create_time;
}
/**
* The name of the resource related to the webhook notification event, such as 'checkout-order'.
*
* @return string
*/
public function resource_type(): string {
return $this->resource_type;
}
/**
* The event version in the webhook notification, such as '1.0'.
*
* @return string
*/
public function event_version(): string {
return $this->event_version;
}
/**
* The event that triggered the webhook event notification, such as 'CHECKOUT.ORDER.APPROVED'.
*
* @return string
*/
public function event_type(): string {
return $this->event_type;
}
/**
* A summary description for the event notification.
*
* @return string
*/
public function summary(): string {
return $this->summary;
}
/**
* The resource version in the webhook notification, such as '1.0'.
*
* @return string
*/
public function resource_version(): string {
return $this->resource_version;
}
/**
* The resource that triggered the webhook event notification.
*
* @return stdClass
*/
public function resource(): stdClass {
return $this->resource;
}
}

View file

@ -37,8 +37,8 @@ class PaymentSourceFactory {
(string) $data->card->authentication_result->liability_shift : '',
isset( $data->card->authentication_result->three_d_secure->enrollment_status ) ?
(string) $data->card->authentication_result->three_d_secure->enrollment_status : '',
isset( $data->card->authentication_result->three_d_secure->authentication_result ) ?
(string) $data->card->authentication_result->three_d_secure->authentication_result : ''
isset( $data->card->authentication_result->three_d_secure->authentication_status ) ?
(string) $data->card->authentication_result->three_d_secure->authentication_status : ''
);
}
$card = new PaymentSourceCard(

View file

@ -158,6 +158,8 @@ class PurchaseUnitFactory {
$shipping = $this->shipping_factory->from_wc_customer( \WC()->customer );
if (
2 !== strlen( $shipping->address()->country_code() )
|| ( ! $shipping->address()->postal_code() )
|| $this->country_without_postal_code( $shipping->address()->country_code() )
) {
$shipping = null;
}
@ -264,4 +266,18 @@ class PurchaseUnitFactory {
}
return false;
}
/**
* Check if country does not have postal code.
*
* @param string $country_code The country code.
* @return bool Whether country has postal code or not.
*/
private function country_without_postal_code( string $country_code ): bool {
$countries = array( 'AE', 'AF', 'AG', 'AI', 'AL', 'AN', 'AO', 'AW', 'BB', 'BF', 'BH', 'BI', 'BJ', 'BM', 'BO', 'BS', 'BT', 'BW', 'BZ', 'CD', 'CF', 'CG', 'CI', 'CK', 'CL', 'CM', 'CO', 'CR', 'CV', 'DJ', 'DM', 'DO', 'EC', 'EG', 'ER', 'ET', 'FJ', 'FK', 'GA', 'GD', 'GH', 'GI', 'GM', 'GN', 'GQ', 'GT', 'GW', 'GY', 'HK', 'HN', 'HT', 'IE', 'IQ', 'IR', 'JM', 'JO', 'KE', 'KH', 'KI', 'KM', 'KN', 'KP', 'KW', 'KY', 'LA', 'LB', 'LC', 'LK', 'LR', 'LS', 'LY', 'ML', 'MM', 'MO', 'MR', 'MS', 'MT', 'MU', 'MW', 'MZ', 'NA', 'NE', 'NG', 'NI', 'NP', 'NR', 'NU', 'OM', 'PA', 'PE', 'PF', 'PY', 'QA', 'RW', 'SA', 'SB', 'SC', 'SD', 'SL', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SY', 'TC', 'TD', 'TG', 'TL', 'TO', 'TT', 'TV', 'TZ', 'UG', 'UY', 'VC', 'VE', 'VG', 'VN', 'VU', 'WS', 'XA', 'XB', 'XC', 'XE', 'XL', 'XM', 'XN', 'XS', 'YE', 'ZM', 'ZW' );
if ( in_array( $country_code, $countries, true ) ) {
return true;
}
return false;
}
}

View file

@ -0,0 +1,74 @@
<?php
/**
* Creates WebhookEvent.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
use DateTime;
use stdClass;
use WooCommerce\PayPalCommerce\ApiClient\Entity\WebhookEvent;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
/**
* Class WebhookEventFactory
*/
class WebhookEventFactory {
/**
* Returns a webhook from a given data array.
*
* @param array $data The data array.
*
* @return WebhookEvent
*/
public function from_array( array $data ): WebhookEvent {
return $this->from_paypal_response( (object) $data );
}
/**
* Returns a Webhook based of a PayPal JSON response.
*
* @param stdClass $data The JSON object.
*
* @return WebhookEvent
* @throws RuntimeException When JSON object is malformed.
*/
public function from_paypal_response( stdClass $data ): WebhookEvent {
if ( ! isset( $data->id ) ) {
throw new RuntimeException(
__( 'ID for webhook event not found.', 'woocommerce-paypal-payments' )
);
}
if ( ! isset( $data->event_type ) ) {
throw new RuntimeException(
__( 'Event type for webhook event not found.', 'woocommerce-paypal-payments' )
);
}
$create_time = ( isset( $data->create_time ) ) ?
DateTime::createFromFormat( 'Y-m-d\TH:i:sO', $data->create_time )
: null;
// Sometimes the time may be in weird format 2018-12-19T22:20:32.000Z (at least in simulation),
// we do not care much about time, so just ignore on failure.
if ( false === $create_time ) {
$create_time = null;
}
return new WebhookEvent(
(string) $data->id,
$create_time,
(string) $data->resource_type ?? '',
(string) $data->event_version ?? '',
(string) $data->event_type,
(string) $data->summary ?? '',
(string) $data->resource_version ?? '',
(object) $data->resource ?? ( new stdClass() )
);
}
}

View file

@ -0,0 +1,17 @@
{
"name": "woocommerce/ppcp-button",
"type": "dhii-mod",
"description": "Button module for PPCP",
"license": "GPL-2.0",
"require": {
"php": "^7.1 | ^8.0",
"dhii/module-interface": "^0.3.0-alpha1"
},
"autoload": {
"psr-4": {
"WooCommerce\\PayPalCommerce\\Button\\": "src"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View file

@ -7,13 +7,13 @@
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"babel-loader": "^8.1.0",
"cross-env": "^5.0.1",
"file-loader": "^4.2.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.1.2",
"babel-plugin-transform-object-rest-spread": "^6.26.0"
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"cross-env": "^7.0.3",
"file-loader": "^6.2.0",
"sass": "^1.42.1",
"sass-loader": "^12.1.0",
"webpack": "^5.55.0",
"webpack-cli": "^4.8.0"
},
"scripts": {
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",

View file

@ -7,3 +7,7 @@
.payments-sdk-contingency-handler {
z-index: 1000 !important;
}
.ppcp-credit-card-gateway-form-field-disabled {
opacity: .5 !important;
}

View file

@ -24,9 +24,11 @@ class CheckoutBootstap {
})
jQuery('#saved-credit-card').on('change', () => {
this.displayPlaceOrderButtonForSavedCreditCards()
})
jQuery(document).on('hosted_fields_loaded', () => {
jQuery('#saved-credit-card').on('change', () => {
this.displayPlaceOrderButtonForSavedCreditCards()
})
});
this.switchBetweenPayPalandOrderButton()
this.displayPlaceOrderButtonForSavedCreditCards()
@ -100,13 +102,41 @@ class CheckoutBootstap {
this.renderer.hideButtons(this.gateway.messages.wrapper)
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper)
jQuery('#place_order').show()
this.disableCreditCardFields()
} else {
jQuery('#place_order').hide()
this.renderer.hideButtons(this.gateway.button.wrapper)
this.renderer.hideButtons(this.gateway.messages.wrapper)
this.renderer.showButtons(this.gateway.hosted_fields.wrapper)
this.enableCreditCardFields()
}
}
disableCreditCardFields() {
jQuery('label[for="ppcp-credit-card-gateway-card-number"]').addClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-gateway-card-number').addClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('label[for="ppcp-credit-card-gateway-card-expiry"]').addClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-gateway-card-expiry').addClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('label[for="ppcp-credit-card-gateway-card-cvc"]').addClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-gateway-card-cvc').addClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('label[for="vault"]').addClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-vault').addClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-vault').attr("disabled", true)
this.renderer.disableCreditCardFields()
}
enableCreditCardFields() {
jQuery('label[for="ppcp-credit-card-gateway-card-number"]').removeClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-gateway-card-number').removeClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('label[for="ppcp-credit-card-gateway-card-expiry"]').removeClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-gateway-card-expiry').removeClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('label[for="ppcp-credit-card-gateway-card-cvc"]').removeClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-gateway-card-cvc').removeClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('label[for="vault"]').removeClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-vault').removeClass('ppcp-credit-card-gateway-form-field-disabled')
jQuery('#ppcp-credit-card-vault').attr("disabled", false)
this.renderer.enableCreditCardFields()
}
}
export default CheckoutBootstap

View file

@ -100,6 +100,7 @@ class CreditCardRenderer {
}
}
}).then(hostedFields => {
document.dispatchEvent(new CustomEvent("hosted_fields_loaded"));
this.currentHostedFieldsInstance = hostedFields;
hostedFields.on('inputSubmitRequest', () => {
@ -141,6 +142,40 @@ class CreditCardRenderer {
)
}
disableFields() {
if( this.currentHostedFieldsInstance) {
this.currentHostedFieldsInstance.setAttribute({
field: 'number',
attribute: 'disabled'
})
this.currentHostedFieldsInstance.setAttribute({
field: 'cvv',
attribute: 'disabled'
})
this.currentHostedFieldsInstance.setAttribute({
field: 'expirationDate',
attribute: 'disabled'
})
}
}
enableFields() {
if( this.currentHostedFieldsInstance) {
this.currentHostedFieldsInstance.removeAttribute({
field: 'number',
attribute: 'disabled'
})
this.currentHostedFieldsInstance.removeAttribute({
field: 'cvv',
attribute: 'disabled'
})
this.currentHostedFieldsInstance.removeAttribute({
field: 'expirationDate',
attribute: 'disabled'
})
}
}
_submit(contextConfig) {
this.spinner.block();
this.errorHandler.clear();
@ -162,7 +197,6 @@ class CreditCardRenderer {
return contextConfig.onApprove(payload);
}).catch(err => {
console.error(err);
this.errorHandler.genericError();
this.spinner.unblock();
});
} else {

View file

@ -43,6 +43,14 @@ class Renderer {
domElement.style.display = 'block';
return true;
}
disableCreditCardFields() {
this.creditCardRenderer.disableFields();
}
enableCreditCardFields() {
this.creditCardRenderer.enableFields();
}
}
export default Renderer;
export default Renderer;

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