Commit d5781cdc by Julien Jorry

Merge branch 'dev-paiement-mobile' into 'dev'

Dev paiement mobile

See merge request Kohinos/kohinos!3
parents 6c790f14 81227837
...@@ -33,3 +33,11 @@ CORS_ALLOW_ORIGIN=^https?://localhost(:[0-9]+)?$ ...@@ -33,3 +33,11 @@ CORS_ALLOW_ORIGIN=^https?://localhost(:[0-9]+)?$
#JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem #JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
#JWT_PASSPHRASE=2162f52d0600275e618fccd274c080f2 #JWT_PASSPHRASE=2162f52d0600275e618fccd274c080f2
###< lexik/jwt-authentication-bundle ### ###< lexik/jwt-authentication-bundle ###
## PAYUM GATEWAYS CONFIGURATION ##
###> payum-payzen ###
PAYZEN_SITE_ID=ChangeMeWithYourPayzenCredentials
PAYZEN_CERTIFICATE=ChangeMeWithYourPayzenCredentials
PAYZEN_CTX_MODE=PRODUCTION
PAYZEN_DEBUG=false
###< payum-payzen ###
...@@ -35,3 +35,7 @@ yarn-error.log ...@@ -35,3 +35,7 @@ yarn-error.log
/mlc.test-access.log /mlc.test-access.log
/mlc.test-error.log /mlc.test-error.log
###< symfony/webpack-encore-bundle ### ###< symfony/webpack-encore-bundle ###
###> payum ###
/transactions/
###< payum ###
...@@ -14,29 +14,35 @@ ...@@ -14,29 +14,35 @@
"php": "^7.4", "php": "^7.4",
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"ext-intl" : "*", "ext-intl": "*",
"api-platform/api-pack": "^1.2", "api-platform/api-pack": "^1.2",
"beberlei/doctrineextensions": "^1.2", "beberlei/doctrineextensions": "^1.2",
"doctrine/annotations": "^1.8", "doctrine/annotations": "^1.8",
"doctrine/migrations": "^3.0", "doctrine/doctrine-fixtures-bundle": "^3.0",
"doctrine/doctrine-migrations-bundle": "^3.0", "doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/migrations": "^3.0",
"ekyna/payum-payzen": "@dev",
"friendsofsymfony/user-bundle": "^2.1", "friendsofsymfony/user-bundle": "^2.1",
"geocoder-php/cache-provider": "^4.1", "geocoder-php/cache-provider": "^4.1",
"geocoder-php/google-maps-provider": "^4.3", "geocoder-php/google-maps-provider": "^4.3",
"geocoder-php/nominatim-provider": "^5.0", "geocoder-php/nominatim-provider": "^5.0",
"hautelook/alice-bundle": "^2.3",
"knplabs/knp-paginator-bundle": "^2.8", "knplabs/knp-paginator-bundle": "^2.8",
"lexik/translation-bundle": "~4.0", "lexik/translation-bundle": "~4.0",
"liip/imagine-bundle": "^2.1", "liip/imagine-bundle": "^2.1",
"nelmio/api-doc-bundle": "^3.3", "nelmio/api-doc-bundle": "^3.3",
"payum/offline": "^1.6",
"payum/payum-bundle": "^2.4",
"php-http/guzzle6-adapter": "^2.0", "php-http/guzzle6-adapter": "^2.0",
"php-http/message": "^1.7", "php-http/message": "^1.7",
"pixassociates/sortable-behavior-bundle": "^1.5", "pixassociates/sortable-behavior-bundle": "^1.5",
"prodigious/sonata-menu-bundle": "^3.0", "prodigious/sonata-menu-bundle": "^3.0",
"sensio/framework-extra-bundle": "^5.1", "sensio/framework-extra-bundle": "^5.1",
"sensiolabs/security-checker": "^5.0",
"sonata-project/admin-bundle": "^3.65", "sonata-project/admin-bundle": "^3.65",
"sonata-project/block-bundle": "^3.18", "sonata-project/block-bundle": "^3.18",
"sonata-project/core-bundle": "^3.18",
"sonata-project/classification-bundle": "^3.11", "sonata-project/classification-bundle": "^3.11",
"sonata-project/core-bundle": "^3.18",
"sonata-project/doctrine-orm-admin-bundle": "^3.6", "sonata-project/doctrine-orm-admin-bundle": "^3.6",
"sonata-project/easy-extends-bundle": "^2.5", "sonata-project/easy-extends-bundle": "^2.5",
"sonata-project/formatter-bundle": "^4.1", "sonata-project/formatter-bundle": "^4.1",
...@@ -49,6 +55,7 @@ ...@@ -49,6 +55,7 @@
"symfony/asset": "4.4.*", "symfony/asset": "4.4.*",
"symfony/cache": "4.4.*", "symfony/cache": "4.4.*",
"symfony/console": "4.4.*", "symfony/console": "4.4.*",
"symfony/dotenv": "4.4.*",
"symfony/expression-language": "4.4.*", "symfony/expression-language": "4.4.*",
"symfony/flex": "^1.1", "symfony/flex": "^1.1",
"symfony/form": "4.4.*", "symfony/form": "4.4.*",
...@@ -67,11 +74,7 @@ ...@@ -67,11 +74,7 @@
"symfony/webpack-encore-bundle": "^1.7", "symfony/webpack-encore-bundle": "^1.7",
"symfony/yaml": "4.4.*", "symfony/yaml": "4.4.*",
"vich/uploader-bundle": "^1.8", "vich/uploader-bundle": "^1.8",
"willdurand/geocoder-bundle": "^5.0", "willdurand/geocoder-bundle": "^5.0"
"doctrine/doctrine-fixtures-bundle": "^3.0",
"symfony/dotenv": "4.4.*",
"sensiolabs/security-checker": "^5.0",
"hautelook/alice-bundle": "^2.3"
}, },
"require-dev": { "require-dev": {
"symfony/browser-kit": "4.4.*", "symfony/browser-kit": "4.4.*",
...@@ -126,8 +129,14 @@ ...@@ -126,8 +129,14 @@
}, },
"extra": { "extra": {
"symfony": { "symfony": {
"allow-contrib": false, "allow-contrib": true,
"require": "4.4.*" "require": "4.4.*"
} }
} },
"repositories": [
{
"type": "path",
"url": "./lib/ekyna/payum-payzen"
}
]
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "9ad1e1c8dfb7b89b9c6cc6be310ee478", "content-hash": "f569a61c588e9ba0313fa37c884eba02",
"packages": [ "packages": [
{ {
"name": "api-platform/api-pack", "name": "api-platform/api-pack",
...@@ -2081,6 +2081,46 @@ ...@@ -2081,6 +2081,46 @@
"time": "2020-06-16T20:11:17+00:00" "time": "2020-06-16T20:11:17+00:00"
}, },
{ {
"name": "ekyna/payum-payzen",
"version": "1.5.x-dev",
"dist": {
"type": "path",
"url": "./lib/ekyna/payum-payzen",
"reference": "17c280ea86308a430cc355578264a1c1f0800edd"
},
"require": {
"payum/core": "^1.5",
"php": "^7.0",
"php-http/guzzle6-adapter": "^2.0",
"psr/log": "~1.0",
"symfony/process": "4.4.*"
},
"type": "component",
"autoload": {
"psr-4": {
"Ekyna\\Component\\Payum\\Payzen\\": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Etienne Dauvergne",
"homepage": "http://ekyna.com"
}
],
"description": "PayZen Payum gateway",
"homepage": "https://github.com/ekyna/PayumPayzen",
"keywords": [
"payum",
"payzen"
],
"transport-options": {
"relative": true
}
},
{
"name": "exsyst/swagger", "name": "exsyst/swagger",
"version": "v0.4.1", "version": "v0.4.1",
"source": { "source": {
...@@ -3928,6 +3968,481 @@ ...@@ -3928,6 +3968,481 @@
"time": "2020-05-20T16:45:56+00:00" "time": "2020-05-20T16:45:56+00:00"
}, },
{ {
"name": "league/uri",
"version": "5.3.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri.git",
"reference": "f2bceb755f1108758cf4cf925e4cd7699ce686aa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri/zipball/f2bceb755f1108758cf4cf925e4cd7699ce686aa",
"reference": "f2bceb755f1108758cf4cf925e4cd7699ce686aa",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"ext-intl": "*",
"ext-mbstring": "*",
"league/uri-components": "^1.8",
"league/uri-hostname-parser": "^1.1",
"league/uri-interfaces": "^1.0",
"league/uri-manipulations": "^1.5",
"league/uri-parser": "^1.4",
"league/uri-schemes": "^1.2",
"php": ">=7.0.13",
"psr/http-message": "^1.0"
},
"type": "metapackage",
"extra": {
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ignace Nyamagana Butera",
"email": "nyamsprod@gmail.com",
"homepage": "https://nyamsprod.com"
}
],
"description": "URI manipulation library",
"homepage": "http://uri.thephpleague.com",
"keywords": [
"data-uri",
"file-uri",
"ftp",
"hostname",
"http",
"https",
"middleware",
"parse_str",
"parse_url",
"psr-7",
"query-string",
"querystring",
"rfc3986",
"rfc3987",
"uri",
"url",
"ws"
],
"time": "2018-03-14T17:19:39+00:00"
},
{
"name": "league/uri-components",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-components.git",
"reference": "d0412fd730a54a8284009664188cf239070eae64"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-components/zipball/d0412fd730a54a8284009664188cf239070eae64",
"reference": "d0412fd730a54a8284009664188cf239070eae64",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-fileinfo": "*",
"ext-intl": "*",
"league/uri-hostname-parser": "^1.1.0",
"php": ">=7.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.3",
"phpstan/phpstan": "^0.9.2",
"phpstan/phpstan-phpunit": "^0.9.4",
"phpstan/phpstan-strict-rules": "^0.9.0",
"phpunit/phpunit": "^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"League\\Uri\\": "src"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ignace Nyamagana Butera",
"email": "nyamsprod@gmail.com",
"homepage": "https://nyamsprod.com"
}
],
"description": "URI components manipulation library",
"homepage": "http://uri.thephpleague.com",
"keywords": [
"authority",
"components",
"fragment",
"host",
"path",
"port",
"query",
"rfc3986",
"scheme",
"uri",
"url",
"userinfo"
],
"time": "2018-10-24T11:31:02+00:00"
},
{
"name": "league/uri-hostname-parser",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-hostname-parser.git",
"reference": "7a6be3d06d0ed08dcb51f666aa60f3b66cd51325"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-hostname-parser/zipball/7a6be3d06d0ed08dcb51f666aa60f3b66cd51325",
"reference": "7a6be3d06d0ed08dcb51f666aa60f3b66cd51325",
"shasum": ""
},
"require": {
"ext-intl": "*",
"php": ">=7.0",
"psr/simple-cache": "^1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.7",
"mikey179/vfsstream": "^1.6",
"phpunit/phpunit": "^6.3"
},
"suggest": {
"ext-curl": "To use the bundle cURL HTTP client",
"psr/simple-cache-implementation": "To enable using other cache providers"
},
"bin": [
"bin/update-psl-icann-section"
],
"type": "library",
"autoload": {
"psr-4": {
"League\\Uri\\": "src"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jeremy Kendall",
"homepage": "http://about.me/jeremykendall",
"role": "Developer"
},
{
"name": "Ignace Nyamagana Butera",
"homepage": "http://nyamsprod.com",
"role": "Developer"
},
{
"name": "Contributors",
"homepage": "https://github.com/phpleague/uri-hostname-parser/graphs/contributors"
}
],
"description": "ICANN base hostname parsing implemented in PHP.",
"homepage": "https://github.com/thephphleague/uri-hostname-parser",
"keywords": [
"Public Suffix List",
"domain parsing",
"icann"
],
"time": "2018-02-16T07:29:26+00:00"
},
{
"name": "league/uri-interfaces",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-interfaces.git",
"reference": "081760c53a4ce76c9935a755a21353610f5495f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/081760c53a4ce76c9935a755a21353610f5495f6",
"reference": "081760c53a4ce76c9935a755a21353610f5495f6",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"League\\Uri\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ignace Nyamagana Butera",
"email": "nyamsprod@gmail.com",
"homepage": "https://nyamsprod.com"
}
],
"description": "Common interface for URI representation",
"homepage": "http://github.com/thephpleague/uri-interfaces",
"keywords": [
"rfc3986",
"rfc3987",
"uri",
"url"
],
"time": "2018-11-05T14:00:06+00:00"
},
{
"name": "league/uri-manipulations",
"version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-manipulations.git",
"reference": "ae8d49a3203ccf7a1e39aaf7fae9f08bfbc454a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-manipulations/zipball/ae8d49a3203ccf7a1e39aaf7fae9f08bfbc454a2",
"reference": "ae8d49a3203ccf7a1e39aaf7fae9f08bfbc454a2",
"shasum": ""
},
"require": {
"ext-intl": "*",
"league/uri-components": "^1.8.0",
"league/uri-interfaces": "^1.0",
"php": ">=7.0",
"psr/http-message": "^1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.0",
"guzzlehttp/psr7": "^1.2",
"league/uri-schemes": "^1.2",
"phpstan/phpstan": "^0.9.2",
"phpstan/phpstan-phpunit": "^0.9.4",
"phpstan/phpstan-strict-rules": "^0.9.0",
"phpunit/phpunit": "^6.0",
"zendframework/zend-diactoros": "1.4.0"
},
"suggest": {
"league/uri-schemes": "Allow manipulating URI objects"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"League\\Uri\\": "src"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ignace Nyamagana Butera",
"email": "nyamsprod@gmail.com",
"homepage": "https://nyamsprod.com"
}
],
"description": "URI manipulation library",
"homepage": "http://url.thephpleague.com",
"keywords": [
"formatter",
"manipulation",
"manipulations",
"middlewares",
"modifiers",
"psr-7",
"references",
"rfc3986",
"rfc3987",
"uri",
"url"
],
"time": "2018-03-14T16:44:57+00:00"
},
{
"name": "league/uri-parser",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-parser.git",
"reference": "671548427e4c932352d9b9279fdfa345bf63fa00"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-parser/zipball/671548427e4c932352d9b9279fdfa345bf63fa00",
"reference": "671548427e4c932352d9b9279fdfa345bf63fa00",
"shasum": ""
},
"require": {
"php": ">=7.0.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.0",
"phpstan/phpstan": "^0.9.2",
"phpstan/phpstan-phpunit": "^0.9.4",
"phpstan/phpstan-strict-rules": "^0.9.0",
"phpunit/phpunit": "^6.0"
},
"suggest": {
"ext-intl": "Allow parsing RFC3987 compliant hosts",
"league/uri-schemes": "Allow validating and normalizing URI parsing results"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"League\\Uri\\": "src"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ignace Nyamagana Butera",
"email": "nyamsprod@gmail.com",
"homepage": "https://nyamsprod.com"
}
],
"description": "userland URI parser RFC 3986 compliant",
"homepage": "https://github.com/thephpleague/uri-parser",
"keywords": [
"parse_url",
"parser",
"rfc3986",
"rfc3987",
"uri",
"url"
],
"time": "2018-11-22T07:55:51+00:00"
},
{
"name": "league/uri-schemes",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-schemes.git",
"reference": "f821a444785724bcc9bc244b1173b9d6ca4d71e6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-schemes/zipball/f821a444785724bcc9bc244b1173b9d6ca4d71e6",
"reference": "f821a444785724bcc9bc244b1173b9d6ca4d71e6",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"league/uri-interfaces": "^1.1",
"league/uri-parser": "^1.4.0",
"php": ">=7.0.13",
"psr/http-message": "^1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.0",
"phpstan/phpstan": "^0.9.2",
"phpstan/phpstan-phpunit": "^0.9.4",
"phpstan/phpstan-strict-rules": "^0.9.0",
"phpunit/phpunit": "^6.0"
},
"suggest": {
"ext-intl": "Allow parsing RFC3987 compliant hosts",
"league/uri-manipulations": "Needed to easily manipulate URI objects"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"League\\Uri\\": "src"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ignace Nyamagana Butera",
"email": "nyamsprod@gmail.com",
"homepage": "https://nyamsprod.com"
}
],
"description": "URI manipulation library",
"homepage": "http://uri.thephpleague.com",
"keywords": [
"data-uri",
"file",
"ftp",
"http",
"https",
"parse_url",
"psr-7",
"rfc3986",
"uri",
"url",
"ws",
"wss"
],
"time": "2018-11-26T08:09:30+00:00"
},
{
"name": "lexik/translation-bundle", "name": "lexik/translation-bundle",
"version": "v4.0.14", "version": "v4.0.14",
"source": { "source": {
...@@ -4661,6 +5176,342 @@ ...@@ -4661,6 +5176,342 @@
"time": "2020-04-13T14:42:16+00:00" "time": "2020-04-13T14:42:16+00:00"
}, },
{ {
"name": "payum/core",
"version": "1.6.0",
"target-dir": "Payum/Core",
"source": {
"type": "git",
"url": "https://github.com/Payum/Core.git",
"reference": "43954de6415e1a29fa09d7ca7949b071741afbc6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Payum/Core/zipball/43954de6415e1a29fa09d7ca7949b071741afbc6",
"reference": "43954de6415e1a29fa09d7ca7949b071741afbc6",
"shasum": ""
},
"require": {
"league/uri": "^5.0",
"payum/iso4217": "^1.0",
"php": "^7.0",
"php-http/client-implementation": "^1.0",
"php-http/message": "^1.0",
"twig/twig": "^1.0|^2.0"
},
"require-dev": {
"defuse/php-encryption": "^2",
"doctrine/orm": "2.*",
"ext-curl": "*",
"ext-pdo_sqlite": "*",
"omnipay/common": "^3@dev",
"omnipay/dummy": "^3@alpha",
"payum/omnipay-v3-bridge": "^1@alpha",
"php-http/guzzle6-adapter": "^1.0",
"phpunit/phpunit": "^5.7",
"propel/propel1": "~1.7",
"psr/log": "~1.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/form": "^4.4|^5.0",
"symfony/http-foundation": "^4.4|^5.0",
"symfony/http-kernel": "^4.4|^5.0",
"symfony/phpunit-bridge": "^4.4|^5.0",
"symfony/routing": "^4.4|^5.0",
"symfony/validator": "^4.4|^5.0",
"zendframework/zend-db": "~2"
},
"suggest": {
"defuse/php-encryption": "^2 If you want to encrypt gateways credentials in database",
"doctrine/mongodb-odm": "~1.1 If you want to store models to mongo doctrin2 ODM",
"doctrine/orm": "~2.3 If you want to store models to database using doctrin2 ORM",
"monolog/monolog": "~1.0 If you want to use PSR-3 logger",
"payum/authorize-net-aim": "self.version If you want to use Authorize.Net AIM payment gateway",
"payum/be2bill": "self.version If you want to use be2bill payment gateway",
"payum/omnipay-v3-bridge": "^1 If you want to use omnipay's gateways",
"payum/payex": "self.version If you want to use payex payment gateway",
"payum/paypal-express-checkout-nvp": "self.version If you want to use paypal express checkout, digital goods or recurring payments",
"payum/paypal-ipn": "self.version If you want to use paypal instant payment notifications(Paypal IPN)",
"payum/paypal-pro-checkout-nvp": "self.version If you want to use paypal pro checkout",
"payum/paypal-rest": "self.version If you want to use paypal rest gateway",
"propel/propel": "If you want to store models to Propel2 ORM",
"propel/propel1": "~1.7 If you want to store models to Propel1 ORM",
"symfony/dependency-injection": "~2.8|~3.0 If you want to use container aware stuff",
"symfony/form": "~2.8|~3.0 If you want to use forms",
"symfony/http-foundation": "~2.8|~3.0 If you want to use HttpRequestVerifier or HttpResponse reply from symfony's bridge",
"symfony/http-kernel": "~2.8|~3.0 If you want to use HttpRequestVerifier from symfony's bridge",
"symfony/routing": "~2.8|~3.0 If you want to use TokenFactory from symfony's bridge",
"zendframework/zend-db": "~2.0 If you want to store models to Zend Db ORM"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.5-dev"
}
},
"autoload": {
"psr-0": {
"Payum\\Core\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kotlyar Maksim",
"email": "kotlyar.maksim@gmail.com"
},
{
"name": "Payum project",
"homepage": "https://payum.forma-pro.com/"
},
{
"name": "Community contributions",
"homepage": "https://github.com/Payum/Payum/contributors"
}
],
"description": "One million downloads of Payum already! Payum offers everything you need to work with payments. Friendly for all PHP frameworks (Symfony, Laravel, Zend, Yii, Silex). Check more visiting site.",
"homepage": "https://payum.forma-pro.com/",
"keywords": [
"authorize",
"capture",
"notify",
"payment",
"payout",
"recurring payment",
"refund",
"subscription",
"withdrawal"
],
"time": "2020-02-11T22:12:10+00:00"
},
{
"name": "payum/iso4217",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/Payum/iso4217.git",
"reference": "6a45480e2818350dea58b7a076d0115aa7ff5789"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Payum/iso4217/zipball/6a45480e2818350dea58b7a076d0115aa7ff5789",
"reference": "6a45480e2818350dea58b7a076d0115aa7ff5789",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Payum\\ISO4217\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com"
},
{
"name": "Community contributions",
"homepage": "https://github.com/Payum/Payum/contributors"
},
{
"name": "Kotlyar Maksim",
"email": "kotlyar.maksim@gmail.com"
},
{
"name": "Payum project",
"homepage": "http://payum.org/"
}
],
"description": "ISO 4217 PHP Library",
"homepage": "http://payum.org",
"keywords": [
"4217",
"ISO 4217",
"currencies",
"iso",
"library"
],
"time": "2016-08-04T08:15:12+00:00"
},
{
"name": "payum/offline",
"version": "1.6.0",
"target-dir": "Payum/Offline",
"source": {
"type": "git",
"url": "https://github.com/Payum/Offline.git",
"reference": "b92fabfe2b1842f752250dacdb2e17217f2941c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Payum/Offline/zipball/b92fabfe2b1842f752250dacdb2e17217f2941c7",
"reference": "b92fabfe2b1842f752250dacdb2e17217f2941c7",
"shasum": ""
},
"require": {
"payum/core": "^1.5"
},
"require-dev": {
"payum/core": "^1.5",
"phpunit/phpunit": "^5.7",
"symfony/phpunit-bridge": "^3.1|^4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.5-dev"
}
},
"autoload": {
"psr-0": {
"Payum\\Offline": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kotlyar Maksim",
"email": "kotlyar.maksim@gmail.com"
},
{
"name": "Payum project",
"homepage": "https://payum.forma-pro.com/"
},
{
"name": "Community contributions",
"homepage": "https://github.com/Payum/Offline/contributors"
}
],
"description": "The Payum extension. It provides Offline payment integration.",
"homepage": "https://payum.forma-pro.com",
"keywords": [
"invoice",
"offlile",
"payment"
],
"time": "2019-11-23T14:41:43+00:00"
},
{
"name": "payum/payum-bundle",
"version": "2.4.1",
"source": {
"type": "git",
"url": "https://github.com/Payum/PayumBundle.git",
"reference": "08416446c546d3aca218b91b237c2a25d147afbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Payum/PayumBundle/zipball/08416446c546d3aca218b91b237c2a25d147afbc",
"reference": "08416446c546d3aca218b91b237c2a25d147afbc",
"shasum": ""
},
"require": {
"payum/core": "^1.5",
"php": "^7.1.3",
"symfony/form": "^4.4|^5",
"symfony/framework-bundle": "^4.4|^5",
"symfony/security-csrf": "^4.4|^5",
"symfony/validator": "^4.4|^5"
},
"require-dev": {
"defuse/php-encryption": "^2",
"doctrine/orm": "~2.5",
"ext-curl": "*",
"ext-pdo_sqlite": "*",
"ext-soap": "*",
"fp/klarna-invoice": "0.1.*",
"klarna/checkout": "~1|~2.0",
"omnipay/common": "^3@dev",
"omnipay/dummy": "^3@alpha",
"omnipay/paypal": "^3@dev",
"paypal/rest-api-sdk-php": "0.5.*",
"payum/omnipay-v3-bridge": "^1@alpha",
"payum/payum": "^1.5@dev",
"php-http/guzzle6-adapter": "^1",
"phpunit/phpunit": "^7.5",
"stripe/stripe-php": "~1.0",
"symfony/browser-kit": "^4.4|^5",
"symfony/expression-language": "^4.4|^5",
"symfony/phpunit-bridge": "^4.4|^5",
"symfony/templating": "^4.4|^5",
"symfony/twig-bundle": "^4.4|^5",
"symfony/yaml": "^4.4|^5",
"twig/twig": "^1.16|^2.0"
},
"suggest": {
"sonata-project/admin-bundle": "^3 If you want to configure payments in the backend."
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"psr-4": {
"Payum\\Bundle\\PayumBundle\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kotlyar Maksim",
"email": "kotlyar.maksim@gmail.com"
},
{
"name": "Payum project",
"homepage": "https://payum.forma-pro.com/"
},
{
"name": "Community contributions",
"homepage": "https://github.com/Payum/PayumBundle/contributors"
}
],
"description": "One million downloads of Payum already! Payum offers everything you need to work with payments. Check more visiting site.",
"homepage": "https://payum.forma-pro.com/",
"keywords": [
"authorize.net",
"be2bill",
"instant notifications",
"klarna",
"offline",
"omnipay",
"payex",
"payment",
"paypal",
"paypal express checkout",
"paypal pro checkout",
"recurring payment",
"stripe",
"stripe checkout",
"stripe.js",
"symfony"
],
"time": "2020-02-11T19:51:20+00:00"
},
{
"name": "php-http/discovery", "name": "php-http/discovery",
"version": "1.8.0", "version": "1.8.0",
"source": { "source": {
...@@ -12748,31 +13599,31 @@ ...@@ -12748,31 +13599,31 @@
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v2.12.5", "version": "v2.13.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "18772e0190734944277ee97a02a9a6c6555fcd94" "reference": "46a612ba1bbf6ee1c58acabacd868212ff8a2911"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/18772e0190734944277ee97a02a9a6c6555fcd94", "url": "https://api.github.com/repos/twigphp/Twig/zipball/46a612ba1bbf6ee1c58acabacd868212ff8a2911",
"reference": "18772e0190734944277ee97a02a9a6c6555fcd94", "reference": "46a612ba1bbf6ee1c58acabacd868212ff8a2911",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.0", "php": ">=7.1.3",
"symfony/polyfill-ctype": "^1.8", "symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-mbstring": "^1.3" "symfony/polyfill-mbstring": "^1.3"
}, },
"require-dev": { "require-dev": {
"psr/container": "^1.0", "psr/container": "^1.0",
"symfony/phpunit-bridge": "^4.4|^5.0" "symfony/phpunit-bridge": "^4.4.9|^5.0.9"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.12-dev" "dev-master": "2.13-dev"
} }
}, },
"autoload": { "autoload": {
...@@ -12809,7 +13660,29 @@ ...@@ -12809,7 +13660,29 @@
"keywords": [ "keywords": [
"templating" "templating"
], ],
"time": "2020-02-11T15:31:23+00:00" "funding": [
{
"url": "https://certification.symfony.com/",
"type": "custom"
},
{
"url": "https://live.symfony.com/",
"type": "custom"
},
{
"url": "https://symfony.com/cloud/",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
"type": "tidelift"
}
],
"time": "2020-07-05T13:08:05+00:00"
}, },
{ {
"name": "vich/uploader-bundle", "name": "vich/uploader-bundle",
...@@ -14048,7 +14921,9 @@ ...@@ -14048,7 +14921,9 @@
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": [], "stability-flags": {
"ekyna/payum-payzen": 20
},
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
......
...@@ -49,4 +49,5 @@ return [ ...@@ -49,4 +49,5 @@ return [
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
Sonata\ClassificationBundle\SonataClassificationBundle::class => ['all' => true], Sonata\ClassificationBundle\SonataClassificationBundle::class => ['all' => true],
App\Application\Sonata\ClassificationBundle\ApplicationSonataClassificationBundle::class => ['all' => true], App\Application\Sonata\ClassificationBundle\ApplicationSonataClassificationBundle::class => ['all' => true],
Payum\Bundle\PayumBundle\PayumBundle::class => ['all' => true],
]; ];
payum:
storages:
App\Entity\Payment: { doctrine: orm }
security:
token_storage:
App\Entity\PaymentToken: { doctrine: orm }
gateways:
offline:
factory: offline
payzen:
factory: payzen
site_id: '%env(PAYZEN_SITE_ID)%'
certificate: '%env(PAYZEN_CERTIFICATE)%' # Clé de TEST ou PRODUCTION
ctx_mode: '%env(PAYZEN_CTX_MODE)%' # TEST ou PRODUCTION
directory: '%kernel.project_dir%/transactions'
debug: '%env(bool:PAYZEN_DEBUG)%'
...@@ -236,6 +236,7 @@ sonata_admin: ...@@ -236,6 +236,7 @@ sonata_admin:
items: items:
- admin.flux.gerer - admin.flux.gerer
- admin.all.cotisations - admin.all.cotisations
- admin.all.achatsmonnaie
- admin.transfert.gerer - admin.transfert.gerer
- admin.transaction.gerer - admin.transaction.gerer
- admin.reconversion.gerer - admin.reconversion.gerer
......
...@@ -30,3 +30,6 @@ app.swagger_ui: ...@@ -30,3 +30,6 @@ app.swagger_ui:
path: /api/doc path: /api/doc
methods: GET methods: GET
defaults: { _controller: nelmio_api_doc.controller.swagger_ui } defaults: { _controller: nelmio_api_doc.controller.swagger_ui }
payum_all:
resource: "@PayumBundle/Resources/config/routing/all.xml"
...@@ -167,6 +167,14 @@ services: ...@@ -167,6 +167,14 @@ services:
calls: calls:
- [setManager, ['@doctrine.orm.entity_manager']] - [setManager, ['@doctrine.orm.entity_manager']]
app.payzen_gateway_factory:
class: Payum\Core\Bridge\Symfony\Builder\GatewayFactoryBuilder
arguments: [Ekyna\Component\Payum\Payzen\PayzenGatewayFactory]
tags:
- { name: payum.gateway_factory_builder, factory: payzen }
###### Configuration de l'admin ######
admin.block.dashboard: admin.block.dashboard:
class: App\Block\DashboardKohinosBlock class: App\Block\DashboardKohinosBlock
arguments: arguments:
...@@ -174,8 +182,6 @@ services: ...@@ -174,8 +182,6 @@ services:
tags: tags:
- { name: sonata.block } - { name: sonata.block }
###### Configuration de l'admin ######
admin.adherent.gerer: admin.adherent.gerer:
class: App\Admin\AdherentAdmin class: App\Admin\AdherentAdmin
# arguments: [~, App\Entity\OBJECT, 'PixSortableBehaviorBundle:SortableAdmin'] # arguments: [~, App\Entity\OBJECT, 'PixSortableBehaviorBundle:SortableAdmin']
...@@ -206,6 +212,18 @@ services: ...@@ -206,6 +212,18 @@ services:
calls: calls:
- [ setSecurity, ['@security.helper']] - [ setSecurity, ['@security.helper']]
admin.all.achatsmonnaie:
class: App\Admin\AchatMonnaieAdmin
arguments: [~, App\Entity\AchatMonnaie, ~]
tags:
- name: sonata.admin
manager_type: orm
group: "Flux"
label: "Achats de monnaie"
public: true
calls:
- [ setSecurity, ['@security.helper']]
admin.adherent.cotisations: admin.adherent.cotisations:
class: App\Admin\CotisationAdherentAdmin class: App\Admin\CotisationAdherentAdmin
arguments: [~, App\Entity\CotisationAdherent, ~] arguments: [~, App\Entity\CotisationAdherent, ~]
...@@ -364,7 +382,7 @@ services: ...@@ -364,7 +382,7 @@ services:
pager_type: "simple" pager_type: "simple"
public: true public: true
calls: calls:
- [ setSubClasses, [{transaction: 'App\Entity\Transaction', transfert: 'App\Entity\Transfert', cotisation: 'App\Entity\Cotisation'}]] - [ setSubClasses, [{transaction: 'App\Entity\Transaction', transfert: 'App\Entity\Transfert', cotisation: 'App\Entity\Cotisation', achat_monnaie: 'App\Entity\AchatMonnaie'}]]
- [ setSecurity, ['@security.helper']] - [ setSecurity, ['@security.helper']]
admin.transfert.gerer: admin.transfert.gerer:
......
...@@ -22,7 +22,7 @@ App\Entity\TypePrestataire: ...@@ -22,7 +22,7 @@ App\Entity\TypePrestataire:
name: 'Prestataire' name: 'Prestataire'
typepresta2: typepresta2:
name: 'Partenaire' name: 'Partenaire'
App\Entity\Usergroup: App\Entity\Usergroup:
usergroup_adherent: usergroup_adherent:
__construct: ['Adherent', ['ROLE_ADHERENT']] __construct: ['Adherent', ['ROLE_ADHERENT']]
...@@ -35,6 +35,7 @@ App\Entity\Usergroup: ...@@ -35,6 +35,7 @@ App\Entity\Usergroup:
'ROLE_SONATA_USER_ADMIN_GROUP_ALL', 'ROLE_SONATA_USER_ADMIN_GROUP_ALL',
'ROLE_ADMIN_ADHERENT_GERER_ALL', 'ROLE_ADMIN_ADHERENT_GERER_ALL',
'ROLE_ADMIN_ALL_COTISATIONS_ALL', 'ROLE_ADMIN_ALL_COTISATIONS_ALL',
'ROLE_ADMIN_ALL_ACHATSMONNAIE_ALL',
'ROLE_ADMIN_GROUPE_GERER_ALL', 'ROLE_ADMIN_GROUPE_GERER_ALL',
'ROLE_ADMIN_GLOBALPARAMETER_GERER_ALL', 'ROLE_ADMIN_GLOBALPARAMETER_GERER_ALL',
'ROLE_ADMIN_TRANSFERT_GERER_ALL']] 'ROLE_ADMIN_TRANSFERT_GERER_ALL']]
...@@ -61,6 +62,7 @@ App\Entity\Usergroup: ...@@ -61,6 +62,7 @@ App\Entity\Usergroup:
__construct: ['Trésorier', [ __construct: ['Trésorier', [
'ROLE_TRESORIER', 'ROLE_TRESORIER',
'ROLE_ADMIN_ALL_COTISATIONS_ALL', 'ROLE_ADMIN_ALL_COTISATIONS_ALL',
'ROLE_ADMIN_ALL_ACHATSMONNAIE_ALL',
'ROLE_ADMIN_RECONVERSION_GERER_ALL', 'ROLE_ADMIN_RECONVERSION_GERER_ALL',
'ROLE_ADMIN_TRANSFERT_GERER_ALL']] 'ROLE_ADMIN_TRANSFERT_GERER_ALL']]
usergroup_gestiongroupe: usergroup_gestiongroupe:
...@@ -823,4 +825,3 @@ App\Entity\Rubrique: ...@@ -823,4 +825,3 @@ App\Entity\Rubrique:
# name: 'Vins' # name: 'Vins'
# content: <text(50)> # content: <text(50)>
# enabled: true # enabled: true
...@@ -22,7 +22,7 @@ App\Entity\TypePrestataire: ...@@ -22,7 +22,7 @@ App\Entity\TypePrestataire:
name: 'Prestataire' name: 'Prestataire'
typepresta2: typepresta2:
name: 'Partenaire' name: 'Partenaire'
App\Entity\Usergroup: App\Entity\Usergroup:
usergroup_adherent: usergroup_adherent:
__construct: ['Adherent', ['ROLE_ADHERENT']] __construct: ['Adherent', ['ROLE_ADHERENT']]
...@@ -35,6 +35,7 @@ App\Entity\Usergroup: ...@@ -35,6 +35,7 @@ App\Entity\Usergroup:
'ROLE_SONATA_USER_ADMIN_GROUP_ALL', 'ROLE_SONATA_USER_ADMIN_GROUP_ALL',
'ROLE_ADMIN_ADHERENT_GERER_ALL', 'ROLE_ADMIN_ADHERENT_GERER_ALL',
'ROLE_ADMIN_ALL_COTISATIONS_ALL', 'ROLE_ADMIN_ALL_COTISATIONS_ALL',
'ROLE_ADMIN_ALL_ACHATSMONNAIE_ALL',
'ROLE_ADMIN_GROUPE_GERER_ALL', 'ROLE_ADMIN_GROUPE_GERER_ALL',
'ROLE_ADMIN_GLOBALPARAMETER_GERER_ALL', 'ROLE_ADMIN_GLOBALPARAMETER_GERER_ALL',
'ROLE_ADMIN_TRANSFERT_GERER_ALL']] 'ROLE_ADMIN_TRANSFERT_GERER_ALL']]
...@@ -61,6 +62,7 @@ App\Entity\Usergroup: ...@@ -61,6 +62,7 @@ App\Entity\Usergroup:
__construct: ['Trésorier', [ __construct: ['Trésorier', [
'ROLE_TRESORIER', 'ROLE_TRESORIER',
'ROLE_ADMIN_ALL_COTISATIONS_ALL', 'ROLE_ADMIN_ALL_COTISATIONS_ALL',
'ROLE_ADMIN_ALL_ACHATSMONNAIE_ALL',
'ROLE_ADMIN_RECONVERSION_GERER_ALL', 'ROLE_ADMIN_RECONVERSION_GERER_ALL',
'ROLE_ADMIN_TRANSFERT_GERER_ALL']] 'ROLE_ADMIN_TRANSFERT_GERER_ALL']]
usergroup_gestiongroupe: usergroup_gestiongroupe:
...@@ -629,6 +631,10 @@ App\Entity\GlobalParameter: ...@@ -629,6 +631,10 @@ App\Entity\GlobalParameter:
name: "MAP_ZOOM" name: "MAP_ZOOM"
value: '9' value: '9'
mandatory: 1 mandatory: 1
gp14:
name: "USE_PAYZEN"
value: 'true'
mandatory: 1
App\Entity\Siege: App\Entity\Siege:
siege_1: siege_1:
...@@ -643,7 +649,7 @@ App\Entity\Groupe: ...@@ -643,7 +649,7 @@ App\Entity\Groupe:
content: '<text(200)>' content: '<text(200)>'
compte: '<randomFloat(2, 1000, 2000)>' compte: '<randomFloat(2, 1000, 2000)>'
siege: '@siege_1' siege: '@siege_1'
App\Entity\Geoloc: App\Entity\Geoloc:
geoloc{1..50}: geoloc{1..50}:
adresse: '<streetAddress()>' adresse: '<streetAddress()>'
......
<?php
namespace Ekyna\Component\Payum\Payzen\Action\Api;
use Ekyna\Component\Payum\Payzen\Api\Api;
use Payum\Core\Action\ActionInterface;
use Payum\Core\ApiAwareInterface;
use Payum\Core\Exception\UnsupportedApiException;
use Payum\Core\GatewayAwareInterface;
use Payum\Core\GatewayAwareTrait;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
/**
* Class AbstractApiAction
* @package Ekyna\Component\Payum\Payzen\Action\Api
* @author Etienne Dauvergne <contact@ekyna.com>
*/
abstract class AbstractApiAction implements ActionInterface, GatewayAwareInterface, ApiAwareInterface, LoggerAwareInterface
{
use GatewayAwareTrait;
/**
* @var Api
*/
protected $api;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @inheritDoc
*/
public function setApi($api)
{
if (false == $api instanceof Api) {
throw new UnsupportedApiException('Not supported.');
}
$this->api = $api;
}
/**
* {@inheritDoc}
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* Logs the given message.
*
* @param string $message
*/
protected function log($message)
{
if (!$this->logger) {
return;
}
$this->logger->debug($message);
}
/**
* Logs the given message and data.
*
* @param string $message
* @param array $data
* @param array $filterKeys
*/
protected function logData($message, array $data, array $filterKeys = [])
{
if (!$this->logger) {
return;
}
if (!empty($filterKeys)) {
$data = array_intersect_key($data, array_flip($filterKeys));
}
$data = array_map(function($key, $value) {
return "$key: $value";
}, array_keys($data), $data);
$this->logger->debug($message . ': ' . implode(', ', $data));
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action\Api;
use Ekyna\Component\Payum\Payzen\Request\Request;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Reply\HttpRedirect;
/**
* Class RequestAction
* @package Ekyna\Component\Payum\Payzen\Action\Api
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class ApiRequestAction extends AbstractApiAction
{
/**
* @inheritdoc
*
* @throws \Payum\Core\Reply\HttpRedirect
*/
public function execute($request)
{
/** @var Request $request */
RequestNotSupportedException::assertSupports($this, $request);
$model = ArrayObject::ensureArrayObject($request->getModel());
if ($model['vads_trans_id']) {
return;
}
$model['vads_trans_id'] = $this->api->getTransactionId();
// Current UTC date time
$model['vads_trans_date'] = (new \DateTime('now', new \DateTimeZone('UTC')))->format('YmdHis');
$data = $model->getArrayCopy();
$this->logRequestData($data);
$url = $this->api->createRequestUrl($data);
throw new HttpRedirect($url);
}
/**
* Logs the request data.
*
* @param array $data
*/
private function logRequestData(array $data)
{
$this->logData("[Payzen] Request", $data, [
'vads_order_id',
'vads_amount',
'vads_ctx_mode',
'vads_currency',
'vads_payment_config',
'vads_site_id',
'vads_trans_date',
'vads_trans_id',
'vads_version',
]);
}
/**
* @inheritdoc
*/
public function supports($request)
{
return $request instanceof Request
&& $request->getModel() instanceof \ArrayAccess;
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action\Api;
use Ekyna\Component\Payum\Payzen\Request\Response;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\GetHttpRequest;
/**
* Class ResponseAction
* @package Ekyna\Component\Payum\Payzen\Action\Api
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class ApiResponseAction extends AbstractApiAction
{
/**
* @inheritdoc
*/
public function execute($request)
{
/** @var Response $request */
RequestNotSupportedException::assertSupports($this, $request);
$model = ArrayObject::ensureArrayObject($request->getModel());
$this->gateway->execute($httpRequest = new GetHttpRequest());
if (isset($httpRequest->request['vads_result'])) {
$data = $httpRequest->request;
} elseif (isset($httpRequest->query['vads_result'])) {
$data = $httpRequest->query;
} else {
return;
}
$this->logResponseData($data);
// Check amount
if ($model['vads_amount'] != $data['vads_amount']) {
return;
}
// Check the response signature
if ($this->api->checkResponseIntegrity($data)) {
// Update the payment details
$model->replace($data);
$request->setModel($model);
}
}
/**
* Logs the response data.
*
* @param array $data
*/
private function logResponseData(array $data)
{
$this->logData("[Payzen] Response", $data, [
'vads_order_id',
'vads_trans_id',
'vads_amount',
'vads_auth_result',
'vads_auth_mode',
'vads_auth_number',
'vads_validation_mode',
'vads_result',
'vads_extra_result',
'vads_warranty_result',
]);
}
/**
* @inheritdec
*/
public function supports($request)
{
return $request instanceof Response
&& $request->getModel() instanceof \ArrayAccess;
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action;
use Ekyna\Component\Commerce\Bridge\Payum\Request\GetHumanStatus;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\GatewayAwareInterface;
use Payum\Core\GatewayAwareTrait;
use Payum\Core\Request\Cancel;
/**
* Class CancelAction
* @package Ekyna\Component\Payum\Payzen\Action
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class CancelAction implements ActionInterface, GatewayAwareInterface
{
use GatewayAwareTrait;
/**
* {@inheritdoc}
*
* @param Cancel $request
*/
public function execute($request)
{
RequestNotSupportedException::assertSupports($this, $request);
$model = ArrayObject::ensureArrayObject($request->getModel());
$this->gateway->execute($status = new GetHumanStatus($model));
if ($status->isNew()) {
$model['state_override'] = 'canceled';
}
}
/**
* {@inheritdoc}
*/
public function supports($request)
{
return $request instanceof Cancel
&& $request->getModel() instanceof \ArrayAccess;
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action;
use Ekyna\Component\Payum\Payzen\Request\Request;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\GatewayAwareInterface;
use Payum\Core\GatewayAwareTrait;
use Payum\Core\Request\Capture;
use Payum\Core\Request\Sync;
use Payum\Core\Security\GenericTokenFactoryAwareInterface;
use Payum\Core\Security\GenericTokenFactoryAwareTrait;
/**
* Class CaptureAction
* @package Ekyna\Component\Payum\Payzen\Action
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class CaptureAction implements ActionInterface, GatewayAwareInterface, GenericTokenFactoryAwareInterface
{
use GatewayAwareTrait;
use GenericTokenFactoryAwareTrait;
/**
* {@inheritdoc}
*
* @param Capture $request
*/
public function execute($request)
{
RequestNotSupportedException::assertSupports($this, $request);
$model = ArrayObject::ensureArrayObject($request->getModel());
if ($request->getToken()) {
// Done redirections
$targetUrl = $request->getToken()->getTargetUrl();
$doneUrlFields = [
'vads_url_cancel', // Annuler et retourner à la boutique
'vads_url_error', // Erreur de traitement interne
'vads_url_referral', // 02 contacter l'émetteur de la carte
'vads_url_refused', // Refus autre que 02
'vads_url_success', // 00 Success
'vads_url_return', // Retour à la boutique
];
foreach ($doneUrlFields as $field) {
if (false == $model[$field]) {
$model[$field] = $targetUrl;
}
}
// Notify url
if (empty($model['vads_url_check']) && $this->tokenFactory) {
// Custom action
$model['vads_url_check'] = $request->getToken()->getAfterUrl();
}
}
if (false == $model['vads_trans_id']) {
$this->gateway->execute(new Request($model));
}
$this->gateway->execute(new Sync($model));
}
/**
* {@inheritdoc}
*/
public function supports($request)
{
return $request instanceof Capture
&& $request->getModel() instanceof \ArrayAccess;
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Exception\RuntimeException;
use Payum\Core\GatewayAwareInterface;
use Payum\Core\GatewayAwareTrait;
use Payum\Core\Model\PaymentInterface;
use Payum\Core\Request\Convert;
use Payum\Core\Request\GetCurrency;
/**
* Class ConvertPaymentAction
* @package Ekyna\Component\Payum\Payzen\Action
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class ConvertPaymentAction implements ActionInterface, GatewayAwareInterface
{
use GatewayAwareTrait;
/**
* {@inheritDoc}
*
* @param Convert $request
*/
public function execute($request)
{
RequestNotSupportedException::assertSupports($this, $request);
/** @var PaymentInterface $payment */
$payment = $request->getSource();
$model = ArrayObject::ensureArrayObject($payment->getDetails());
if (false == $model['vads_amount']) {
$this->gateway->execute($currency = new GetCurrency($payment->getCurrencyCode()));
if (2 < $currency->exp) {
throw new RuntimeException('Unexpected currency exp.');
}
$divisor = pow(10, 2 - $currency->exp);
$model['vads_currency'] = (string)$currency->numeric;
$model['vads_amount'] = (string)abs($payment->getTotalAmount() / $divisor);
}
if (false == $model['vads_order_id']) {
$model['vads_order_id'] = $payment->getNumber();
}
if (false == $model['vads_cust_id']) {
$model['vads_cust_id'] = $payment->getClientId();
}
if (false == $model['vads_cust_email']) {
$model['vads_cust_email'] = $payment->getClientEmail();
}
$request->setResult((array)$model);
}
/**
* {@inheritDoc}
*/
public function supports($request)
{
return $request instanceof Convert
&& $request->getSource() instanceof PaymentInterface
&& $request->getTo() == 'array';
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\GatewayAwareInterface;
use Payum\Core\GatewayAwareTrait;
use Payum\Core\Request\Notify;
use Payum\Core\Request\Sync;
/**
* Class NotifyAction
* @package Ekyna\Component\Payum\Payzen\Action
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class NotifyAction implements ActionInterface, GatewayAwareInterface
{
use GatewayAwareTrait;
/**
* {@inheritDoc}
*
* @param Notify $request
*/
public function execute($request)
{
RequestNotSupportedException::assertSupports($this, $request);
$details = ArrayObject::ensureArrayObject($request->getModel());
$this->gateway->execute(new Sync($details));
}
/**
* {@inheritDoc}
*/
public function supports($request)
{
return $request instanceof Notify
&& $request->getModel() instanceof \ArrayAccess;
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action;
use Ekyna\Component\Commerce\Bridge\Payum\Request\GetHumanStatus;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\GatewayAwareInterface;
use Payum\Core\GatewayAwareTrait;
use Payum\Core\Request\Refund;
/**
* Class CaptureAction
* @package Ekyna\Component\Payum\Payzen\Action
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class RefundAction implements ActionInterface, GatewayAwareInterface
{
use GatewayAwareTrait;
/**
* {@inheritdoc}
*
* @param Refund $request
*/
public function execute($request)
{
RequestNotSupportedException::assertSupports($this, $request);
$model = ArrayObject::ensureArrayObject($request->getModel());
$this->gateway->execute($status = new GetHumanStatus($model));
if ($status->isCaptured()) {
$model['state_override'] = 'refunded';
}
}
/**
* {@inheritdoc}
*/
public function supports($request)
{
return $request instanceof Refund
&& $request->getModel() instanceof \ArrayAccess;
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\GetStatusInterface;
/**
* Class StatusAction
* @package Ekyna\Component\Payum\Payzen\Action
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class StatusAction implements ActionInterface
{
/**
* {@inheritdoc}
*
* @param GetStatusInterface $request
*/
public function execute($request)
{
RequestNotSupportedException::assertSupports($this, $request);
/** @var GetStatusInterface $request */
$model = ArrayObject::ensureArrayObject($request->getModel());
if (false == $model['vads_trans_id']) {
$request->markNew();
return;
}
if (false != $code = $model['vads_result']) {
switch ($code) {
case "00" : // transaction approuvée ou traitée avec succès
$request->markCaptured();
break;
case "02" : // contacter l’émetteur de carte
$request->markPending(); // TODO is that the good status ?
break;
case "17" : // Annulation client.
$request->markCanceled();
break;
case "03" : // accepteur invalide
case "04" : // conserver la carte
case "05" : // ne pas honorer
case "07" : // conserver la carte, conditions spéciales
case "08" : // approuver après identification
case "12" : // transaction invalide
case "13" : // montant invalide
case "14" : // numéro de porteur invalide
case "30" : // erreur de format
case "31" : // identifiant de l’organisme acquéreur inconnu
case "33" : // date de validité de la carte dépassée
case "34" : // suspicion de fraude
case "41" : // carte perdue
case "43" : // carte volée
case "51" : // provision insuffisante ou crédit dépassé
case "54" : // date de validité de la carte dépassée
case "56" : // carte absente du fichier
case "57" : // transaction non permise à ce porteur
case "58" : // transaction interdite au terminal
case "59" : // suspicion de fraude
case "60" : // l’accepteur de carte doit contacter l’acquéreur
case "61" : // montant de retrait hors limite
case "63" : // règles de sécurité non respectées
case "68" : // réponse non parvenue ou reçue trop tard
case "90" : // arrêt momentané du système
case "91" : // émetteur de cartes inaccessible
case "96" : // mauvais fonctionnement du système
case "94" : // transaction dupliquée
case "97" : // échéance de la temporisation de surveillance globale
case "98" : // serveur indisponible routage réseau demandé à nouveau
case "99" : // incident domaine initiateur
$request->markFailed();
break;
default :
$request->markUnknown();
}
if ($request->isCaptured() && false != $code = $model['state_override']) {
if ($code == 'refunded') {
$request->markRefunded();
}
}
return;
}
if (false != $code = $model['state_override']) {
if ($code == 'canceled') {
$request->markCanceled();
return;
}
}
$request->markNew();
}
/**
* {@inheritdoc}
*/
public function supports($request)
{
return $request instanceof GetStatusInterface
&& $request->getModel() instanceof \ArrayAccess;
}
}
<?php
namespace Ekyna\Component\Payum\Payzen\Action;
use Ekyna\Component\Payum\Payzen\Request\Response;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\GatewayAwareInterface;
use Payum\Core\GatewayAwareTrait;
use Payum\Core\Request\Sync;
/**
* Class SyncAction
* @package Ekyna\Component\Payum\Payzen\Action
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class SyncAction implements ActionInterface, GatewayAwareInterface
{
use GatewayAwareTrait;
/**
* {@inheritdoc}
*
* @param Sync $request
*/
public function execute($request)
{
RequestNotSupportedException::assertSupports($this, $request);
$model = ArrayObject::ensureArrayObject($request->getModel());
$this->gateway->execute(new Response($model));
}
/**
* {@inheritdoc}
*/
public function supports($request)
{
return $request instanceof Sync
&& $request->getModel() instanceof \ArrayAccess;
}
}
<?php /** @noinspection PhpUnusedParameterInspection */
namespace Ekyna\Component\Payum\Payzen\Api;
use Payum\Core\Exception\LogicException;
use Payum\Core\Exception\RuntimeException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Class Api
* @package Ekyna\Component\Payum\Payzen\Api
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class Api
{
/**
* @var OptionsResolver
*/
private $configResolver;
/**
* @var OptionsResolver
*/
private $requestOptionsResolver;
/**
* @var array
*/
private $config;
/**
* Configures the api.
*
* @param array $config
*/
public function setConfig(array $config)
{
$this->config = $this
->getConfigResolver()
->resolve($config);
}
/**
* Returns the next transaction id.
*
* @return string
*/
public function getTransactionId()
{
$path = $this->getDirectoryPath() . 'transaction_id';
// Create file if not exists
if (!file_exists($path)) {
touch($path);
chmod($path, 0600);
}
$date = (new \DateTime())->format('Ymd');
$fileDate = date('Ymd', filemtime($path));
$isDailyFirstAccess = ($date != $fileDate);
// Open file
$handle = fopen($path, 'r+');
if (false === $handle) {
throw new RuntimeException('Failed to open the transaction ID file.');
}
// Lock File
if (!flock($handle, LOCK_EX)) {
throw new RuntimeException('Failed to lock the transaction ID file.');
}
$id = 1;
// If not daily first access, read and increment the id
if (!$isDailyFirstAccess) {
$id = (int)fread($handle, 6);
$id++;
}
// Truncate, write, unlock and close.
fseek($handle, 0);
ftruncate($handle, 0);
fwrite($handle, (string)$id);
fflush($handle);
flock($handle, LOCK_UN);
fclose($handle);
if ($this->config['debug']) {
$id += 89000;
}
return str_pad($id, 6, '0', STR_PAD_LEFT);
}
/**
* Creates the request url.
*
* @param array $data
*
* @return string
*/
public function createRequestUrl(array $data)
{
$this->ensureApiIsConfigured();
$data = $this->createRequestData($data);
$url = $this->getUrl() . '?' .
implode('&', array_map(function ($key, $value) {
return $key . '=' . rawurlencode($value);
}, array_keys($data), $data));
return $url;
}
/**
* Creates the request data.
*
* @param array $data
*
* @return array
*/
public function createRequestData(array $data)
{
$data = $this
->getRequestOptionsResolver()
->resolve(array_replace($data, [
'vads_page_action' => 'PAYMENT',
'vads_version' => 'V2',
]));
$data = array_filter($data, function ($value) {
return null !== $value;
});
$data['vads_site_id'] = $this->config['site_id'];
$data['vads_ctx_mode'] = $this->config['ctx_mode'];
$data['signature'] = $this->generateSignature($data);
return $data;
}
/**
* Checks the response signature.
*
* @param array $data
*
* @return bool
*/
public function checkResponseIntegrity(array $data)
{
if (!isset($data['signature'])) {
return false;
}
return $data['vads_site_id'] === (string)$this->config['site_id']
&& $data['vads_ctx_mode'] === (string)$this->config['ctx_mode']
&& $data['signature'] === $this->generateSignature($data);
}
/**
* Generates the signature.
*
* @param array $data
* @param bool $hashed
*
* @return string
*/
public function generateSignature(array $data, $hashed = true)
{
ksort($data);
$content = "";
foreach ($data as $key => $value) {
if (substr($key, 0, 5) == 'vads_') {
$content .= $value . '+';
}
}
$content .= $this->config['certificate'];
if ($hashed) {
return $this->hash($content);
}
return $content;
}
/**
* Returns the directory path and creates it if not exists.
*
* @return string
*/
private function getDirectoryPath()
{
$path = $this->config['directory'];
// Create directory if not exists
if (!is_dir($path)) {
mkdir($path, 0755, true);
}
return $path . DIRECTORY_SEPARATOR;
}
/**
* Check that the API has been configured.
*
* @throws LogicException
*/
private function ensureApiIsConfigured()
{
if (null === $this->config) {
throw new LogicException('You must first configure the API.');
}
}
/**
* Returns the config option resolver.
*
* @return OptionsResolver
*/
private function getConfigResolver()
{
if (null !== $this->configResolver) {
return $this->configResolver;
}
$resolver = new OptionsResolver();
$resolver
->setRequired([
'site_id',
'certificate',
'ctx_mode',
'directory',
])
->setDefaults([
'endpoint' => null,
'debug' => false,
])
->setAllowedTypes('site_id', 'string')
->setAllowedTypes('certificate', 'string')
->setAllowedValues('ctx_mode', ['TEST', 'PRODUCTION'])
->setAllowedTypes('directory', 'string')
->setAllowedValues('endpoint', $this->getEndPoints())
->setAllowedTypes('debug', 'bool')
->setNormalizer('directory', function (Options $options, $value) {
return rtrim($value, DIRECTORY_SEPARATOR);
});
return $this->configResolver = $resolver;
}
/**
* Returns request options resolver.
*
* @return OptionsResolver
*/
private function getRequestOptionsResolver()
{
if (null !== $this->requestOptionsResolver) {
return $this->requestOptionsResolver;
}
$resolver = new OptionsResolver();
$resolver
->setDefaults([
'vads_action_mode' => 'INTERACTIVE',
'vads_available_languages' => null,
'vads_capture_delay' => null,
'vads_card_info' => null,
'vads_card_options' => null,
'vads_card_number' => null,
'vads_contracts' => function (Options $options) {
/* TODO
Obligatoire si le numéro de contrat commerçant à utiliser n’est pas celui configuré par défaut
sur la plateforme de paiement
*/
return null;
},
'vads_contrib' => null,
'vads_cust_address' => null,
'vads_cust_cell_phone' => null,
'vads_cust_city' => null,
'vads_cust_country' => null,
'vads_cust_email' => function (Options $options) {
/* TODO
Obligatoire si souscription à l'envoi d'e-mail de confirmation de paiement au client
*/
return null;
},
'vads_cust_id' => null,
'vads_cust_name' => null,
'vads_cust_phone' => null,
'vads_cust_title' => null,
'vads_cust_zip' => null,
'vads_cvv' => null,
'vads_expiry_month' => null,
'vads_expiry_year' => null,
'vads_language' => null,
'vads_order_id' => null, // [a-zA-Z0-9-]+
'vads_order_info' => null,
'vads_order_info2' => null,
'vads_order_info3' => null,
'vads_page_action' => 'PAYMENT',
'vads_payment_cards' => null, // Obligatoire si acquisition de la carte par commerçant
'vads_payment_config' => 'SINGLE',
'vads_payment_src' => null, // Obligatoire pour vente à distance
'vads_redirect_error_message' => null,
'vads_redirect_error_timeout' => null,
'vads_redirect_success_message' => null,
'vads_redirect_success_timeout' => null,
'vads_return_get_params' => null,
'vads_return_mode' => function (Options $options) {
/* TODO
Obligatoire si souhait du commerçant de recevoir la réponse à la demande sur l’URL internet
de retour boutique en formulaire GET ou POST (après clic internaute sur bouton retour
boutique).
Ce paramétrage n’impacte pas la transmission, ni les paramètres de transfert, de la réponse
de serveur à serveur (URL serveur commerçant).
*/
return 'POST';
},
'vads_return_post_params' => null,
'vads_ship_to_city' => null,
'vads_ship_to_country' => null,
'vads_ship_to_name' => null,
'vads_ship_to_phone_num' => null,
'vads_ship_to_state' => null,
'vads_ship_to_street' => null,
'vads_ship_to_street2' => null,
'vads_ship_to_zip' => null,
'vads_shop_name' => null,
'vads_shop_url' => null,
'vads_theme_config' => null,
'vads_threeds_cavv' => null, // Obligatoire si 3DS à la charge du client
'vads_threeds_cavvAlgorithm' => null, // Obligatoire si 3DS à la charge du client
'vads_threeds_eci' => null, // Obligatoire si 3DS à la charge du client
'vads_threeds_enrolled' => null, // Obligatoire si 3DS à la charge du client
'vads_threeds_mpi' => null, // Obligatoire si 3DS à la charge du client
'vads_threeds_status' => null, // Obligatoire si 3DS à la charge du client
'vads_threeds_xid' => null, // Obligatoire si 3DS à la charge du client
'vads_validation_mode' => null,
'vads_url_cancel' => null,
'vads_url_check' => null,
'vads_url_error' => null,
'vads_url_referral' => null,
'vads_url_refused' => null,
'vads_url_success' => null,
'vads_url_return' => null, // Obligatoire si acquisition de la carte par commerçant
'vads_user_info' => null,
'vads_version' => 'V2',
])
->setRequired([
'vads_amount',
'vads_currency',
'vads_payment_config',
'vads_trans_date',
'vads_trans_id',
'vads_version',
])
->setAllowedValues('vads_action_mode', ['SILENT', 'INTERACTIVE'])
->setAllowedValues('vads_currency', $this->getCurrencyCodes())
->setAllowedValues('vads_language', $this->getLanguageCodes())
->setAllowedValues('vads_page_action', 'PAYMENT')
->setAllowedValues('vads_payment_cards', $this->getCardsCodes())
->setAllowedValues('vads_payment_config', function ($value) {
if ($value === 'SINGLE') {
return true;
}
// Ex: MULTI:first=5000;count=3;period=30
if (preg_match('~^MULTI:first=\d+;count=\d+;period=\d+$~', $value)) {
return true;
}
// Ex: MULTI_EXT:20120601=5000;20120701=2500;20120808=2500
if (preg_match('MULTI_EXT:\d+=\d+;\d+=\d+;\d+=\d+', $value)) {
return true;
}
return false;
})
->setAllowedValues('vads_payment_src', [null, 'BO', 'MOTO', 'CC', 'OTHER'])
->setAllowedValues('vads_return_mode', [null, 'NONE', 'GET', 'POST'])
->setAllowedValues('vads_validation_mode', [null, '0', '1'])
->setAllowedValues('vads_version', 'V2');
return $this->requestOptionsResolver = $resolver;
}
private function getCurrencyCodes()
{
return [
'36', // Dollar australien
'036', // Dollar australien
'124', // Dollar canadien
'156', // Yuan chinois
'208', // Couronne danoise
'392', // Yen japonais
'578', // Couronne norvégienne
'752', // Couronne suédoise
'756', // Franc suisse
'826', // Livre sterling
'840', // Dollar américain
'953', // Franc pacifique
'978', // Euro
];
}
private function getLanguageCodes()
{
return [
null,
'de', // Allemand
'en', // Anglais
'zh', // Chinois
'es', // Espagnol
'fr', // Français
'it', // Italien
'jp', // Japonais
'pt', // Portugais
'nl', // Néelandais
];
}
private function getCardsCodes()
{
return [
null,
'AMEX', // American Express
'AURORE-MULTI', // Aurore
'BUYSTER', // Buyster
'CB', // CB
'COFINOGA', // Cofinoga
'E-CARTEBLEUE', // E-Carte bleue
'MASTERCARD', // Eurocard / Mastercard
'JCB', // JCB
'MAESTRO', // Maestro
'ONEY', // Oney
'ONEY_SANDBOX', // Oney (sandbox)
'PAYPAL', // Paypal
'PAYPAL_SB', // Paypal (sandbox)
'PAYSAFECARD', // Paysafe card
'VISA', // Visa
];
}
private function getEndPoints()
{
return [null, 'SYSTEMPAY'];
}
private function getUrl()
{
if ($this->config['endpoint'] === 'SYSTEMPAY') {
return 'https://paiement.systempay.fr/vads-payment/';
}
return 'https://secure.payzen.eu/vads-payment/';
}
private function hash(string $content) {
if ($this->config['endpoint'] === 'SYSTEMPAY') {
return sha1($content);
}
return base64_encode(hash_hmac('sha256', $content, $this->config['certificate'], true));
}
}
Copyright (c) 2017 Etienne Dauvergne
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<?php
namespace Ekyna\Component\Payum\Payzen;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\GatewayFactory;
use Payum\Core\GatewayFactoryInterface;
/**
* Class PayzenGatewayFactory
* @package Ekyna\Component\Payum\Payzen
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class PayzenGatewayFactory extends GatewayFactory
{
/**
* Builds a new factory.
*
* @param array $defaultConfig
* @param GatewayFactoryInterface $coreGatewayFactory
*
* @return PayzenGatewayFactory
*/
public static function build(array $defaultConfig, GatewayFactoryInterface $coreGatewayFactory = null)
{
return new static($defaultConfig, $coreGatewayFactory);
}
/**
* @inheritDoc
*/
protected function populateConfig(ArrayObject $config)
{
$config->defaults([
'payum.factory_name' => 'payzen',
'payum.factory_title' => 'Payzen',
'payum.action.capture' => new Action\CaptureAction(),
'payum.action.convert_payment' => new Action\ConvertPaymentAction(),
'payum.action.sync' => new Action\SyncAction(),
'payum.action.cancel' => new Action\CancelAction(),
'payum.action.refund' => new Action\RefundAction(),
'payum.action.status' => new Action\StatusAction(),
'payum.action.notify' => new Action\NotifyAction(),
'payum.action.api.request' => new Action\Api\ApiRequestAction(),
'payum.action.api.response' => new Action\Api\ApiResponseAction(),
]);
if (false == $config['payum.api']) {
$config['payum.default_options'] = [
'site_id' => null,
'certificate' => null,
'ctx_mode' => null,
'directory' => null,
'endpoint' => null,
'debug' => false,
];
$config->defaults($config['payum.default_options']);
$config['payum.required_options'] = ['site_id', 'certificate', 'ctx_mode', 'directory'];
$config['payum.api'] = function (ArrayObject $config) {
$config->validateNotEmpty($config['payum.required_options']);
$payzenConfig = [
'endpoint' => $config['endpoint'],
'site_id' => $config['site_id'],
'certificate' => $config['certificate'],
'ctx_mode' => $config['ctx_mode'],
'directory' => $config['directory'],
'debug' => $config['debug'],
];
$api = new Api\Api();
$api->setConfig($payzenConfig);
return $api;
};
}
}
}
PayumPayzen
===========
PayZen Payum Gateway
## Installation / Configuration
TODO
<?php
namespace Ekyna\Component\Payum\Payzen\Request;
use Payum\Core\Request\Generic;
/**
* Class Request
* @package Ekyna\Component\Payum\Payzen\Request
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class Request extends Generic
{
}
<?php
namespace Ekyna\Component\Payum\Payzen\Request;
use Payum\Core\Request\Generic;
/**
* Class Response
* @package Ekyna\Component\Payum\Payzen\Request
* @author Etienne Dauvergne <contact@ekyna.com>
*/
class Response extends Generic
{
}
{
"name": "ekyna/payum-payzen",
"description": "PayZen Payum gateway",
"type": "component",
"authors": [
{
"name": "Etienne Dauvergne",
"homepage": "http://ekyna.com"
}
],
"keywords": [
"payum",
"payzen"
],
"homepage": "https://github.com/ekyna/PayumPayzen",
"license": [
"MIT"
],
"require": {
"php": "^7.0",
"payum/core": "^1.5",
"php-http/guzzle6-adapter": "^2.0",
"symfony/process": "4.4.*",
"psr/log": "~1.0"
},
"autoload": {
"psr-4": {
"Ekyna\\Component\\Payum\\Payzen\\": ""
}
}
}
<?php
namespace App\Admin;
use App\Entity\User;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Security\Core\Security;
/**
* Administration des flux 'Achat de monnaie'
*
* KOHINOS : Outil de gestion de Monnaie Locale Complémentaire
* @author Damien Moulard <dam.moulard@gmail.com>
*/
class AchatMonnaieAdmin extends AbstractAdmin
{
protected $baseRouteName = 'achat_monnaie';
protected $baseRoutePattern = 'achat_monnaie';
protected $security;
protected $translator;
protected $datagridValues = [
'_sort_order' => 'DESC',
'_sort_by' => 'createdAt',
];
public function setSecurity(Security $security)
{
$this->security = $security;
}
/**
* {@inheritdoc}
*/
protected function configureDatagridFilters(DatagridMapper $datagridMapper): void
{
$datagridMapper->add('type', null, array(
'advanced_filter' => false,
'show_filter' => true,
'field_type' => ChoiceType::class,
'field_options' => array(
'choices' => array('Adhérent' => 'achat_monnaie_adherent', 'Prestataire' => 'achat_monnaie_prestataire'),
'placeholder' => 'Indifférent',
'expanded' => true,
'multiple' => false
)
));
}
/**
* {@inheritdoc}
*/
protected function configureFormFields(FormMapper $formMapper)
{
}
protected function configureRoutes(RouteCollection $collection)
{
$collection->remove('delete');
if ($this->security->getUser() != null && !($this->security->getUser()->isGranted('ROLE_TRESORIER') || $this->security->getUser()->isGranted('ROLE_SUPER_ADMIN') || $this->security->getUser()->isGranted('ROLE_COMPTOIR'))) {
$collection->clearExcept(array('list', 'export'));
}
}
/**
* {@inheritdoc}
*/
protected function configureListFields(ListMapper $listMapper)
{
unset($this->listModes['mosaic']);
$listMapper
->add('createdAt', 'datetime', array('label' => 'Date'))
->add('montant', null, array('label' => 'Montant'))
->add('destinataire', null, array('label' => 'Destinataire'))
->add('operateur', null, array('label' => 'Operateur'))
->add('reference', null, array('label' => 'Reference'))
;
}
}
...@@ -81,7 +81,7 @@ class FluxAdmin extends AbstractAdmin ...@@ -81,7 +81,7 @@ class FluxAdmin extends AbstractAdmin
'show_filter' => true, 'show_filter' => true,
'field_type' => SChoiceType::class, 'field_type' => SChoiceType::class,
'field_options' => array( 'field_options' => array(
'choices' => array('Transactions' => 'transaction', 'Transferts' => 'transfert', 'Cotisations' => 'cotisation'), 'choices' => array('Transactions' => 'transaction', 'Transferts' => 'transfert', 'Cotisations' => 'cotisation', 'Achat de monnaie' => 'achat'),
'placeholder' => 'Indifférent', 'placeholder' => 'Indifférent',
'expanded' => true, 'expanded' => true,
'multiple' => false 'multiple' => false
......
...@@ -15,6 +15,20 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface; ...@@ -15,6 +15,20 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use Payum\Core\Payum;
use Payum\Core\Request\GetHumanStatus;
use Payum\Core\Request\Notify;
use App\Entity\Payment;
use App\Entity\Siege;
use App\Entity\User;
use App\Entity\Adherent;
use App\Entity\Prestataire;
use App\Entity\AchatMonnaieAdherent;
use App\Entity\AchatMonnaiePrestataire;
use App\Entity\CotisationAdherent;
use App\Entity\CotisationPrestataire;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
/** /**
* *
...@@ -43,14 +57,16 @@ class FluxController extends AbstractController ...@@ -43,14 +57,16 @@ class FluxController extends AbstractController
protected $translator; protected $translator;
protected $eventDispatcher; protected $eventDispatcher;
protected $session; protected $session;
protected $payum;
public function __construct(Security $security, EntityManagerInterface $em, TranslatorInterface $translator, EventDispatcherInterface $eventDispatcher, SessionInterface $session) public function __construct(Security $security, EntityManagerInterface $em, TranslatorInterface $translator, EventDispatcherInterface $eventDispatcher, SessionInterface $session, Payum $payum)
{ {
$this->security = $security; $this->security = $security;
$this->em = $em; $this->em = $em;
$this->translator = $translator; $this->translator = $translator;
$this->eventDispatcher = $eventDispatcher; $this->eventDispatcher = $eventDispatcher;
$this->session = $session; $this->session = $session;
$this->payum = $payum;
} }
protected function manageFluxForm(Request $request, Form $form, $compte, $success, $title) protected function manageFluxForm(Request $request, Form $form, $compte, $success, $title)
...@@ -84,4 +100,221 @@ class FluxController extends AbstractController ...@@ -84,4 +100,221 @@ class FluxController extends AbstractController
'title' => $title 'title' => $title
]); ]);
} }
/*
* Crée une instance de Payment et redirige vers la page de paiement
*/
public function preparePaymentAction(Form $form, $type)
{
$flux_data = $form->getData();
// Enregistre les données du Flux en json, pour l'enregistrer une fois le paiement validé
$serializer = $this->container->get('serializer');
$data = $serializer->normalize($flux_data, null,
[AbstractNormalizer::ATTRIBUTES => ['reference',
'moyen',
'montant',
'role',
'expediteur' => ['id'],
'destinataire' => ['id'],
'operateur' => ['id']]]);
$jsondata = $serializer->serialize($data, 'json');
// Prepare CB Payment
$gatewayName = 'payzen';
$storage = $this->payum->getStorage('App\Entity\Payment');
$payment = $storage->create();
$payment->setNumber(uniqid());
$payment->setCurrencyCode('978');
$payment->setTotalAmount($form->get('montant')->getData()*100); // 1.23 EUR
$payment->setDescription($type);
$payment->setClientId($this->getUser()->getId());
$payment->setClientEmail($this->getUser()->getEmail());
$payment->setFluxData($jsondata);
$storage->update($payment);
$captureToken = $this->payum->getTokenFactory()->createCaptureToken(
$gatewayName,
$payment,
'payment_done' // the route to redirect after capture
);
return $this->redirect($captureToken->getTargetUrl());
}
/**
* Fonction de traitement du paiement, à appeler :
* - automatiquement lorsqu'un événement se produit sur le site de Paiement
* - au retour sur le site par l'utilisateur
*
* @Route("/payment/done/", name="payment_done")
*/
public function doneAction(Request $request)
{
try {
$token = $this->payum->getHttpRequestVerifier()->verify($request);
} catch (\Exception $e) {
// Token expiré : retour sur site après paiement
// Get last payment
$payment = $this->em->getRepository(Payment::class)->getUserLastPayment($this->getUser()->getId());
if (!is_null($payment)) {
if ($payment->getStatus() == GetHumanStatus::STATUS_CAPTURED || $payment->getStatus() == GetHumanStatus::STATUS_AUTHORIZED) {
$type = $payment->getDescription();
if (Payment::TYPE_ACHAT_MONNAIE_ADHERENT == $type || Payment::TYPE_ACHAT_MONNAIE_PRESTA == $type) {
$this->addFlash(
'success',
$this->translator->trans('Achat de monnaie locale bien effectué !')
);
} else {
$this->addFlash(
'success',
$this->translator->trans('Cotisation bien reçue. Merci !')
);
}
// Update payment status
$payment->setStatus($payment->getStatus().';done');
$this->em->persist($payment);
$this->em->flush();
} else if ($payment->getStatus() == GetHumanStatus::STATUS_CANCELED ||
$payment->getStatus() == GetHumanStatus::STATUS_EXPIRED ||
$payment->getStatus() == GetHumanStatus::STATUS_FAILED) {
$this->addFlash(
'error',
$this->translator->trans('La transaction a été annulée.')
);
$payment->setStatus($payment->getStatus().';done');
$this->em->persist($payment);
$this->em->flush();
}
}
return $this->redirectToRoute('index');
}
$gateway = $this->payum->getGateway($token->getGatewayName());
// Execute Notify action
$gateway->execute(new Notify($token));
// Execute 'done' action according to payment status
$gateway->execute($status = new GetHumanStatus($token));
// Get payment & update status
$payment = $status->getFirstModel();
$payment->setStatus($status->getValue());
$this->em->persist($payment);
$this->em->flush();
// If payment succesful, persist serialized 'Flux' stored in payment
if ($status->getValue() == GetHumanStatus::STATUS_CAPTURED || $status->getValue() == GetHumanStatus::STATUS_AUTHORIZED) {
$serializer = $this->container->get('serializer');
$flux_array = json_decode($payment->getFluxData(), true);
$type = $payment->getDescription();
if (Payment::TYPE_ACHAT_MONNAIE_ADHERENT == $type) {
$flux = $serializer->deserialize(
$payment->getFluxData(),
AchatMonnaieAdherent::class,
'json',
['disable_type_enforcement' => true]
);
$exp = $this->em->getRepository(Siege::class)->find($flux_array['expediteur']);
$flux->setExpediteur($exp);
$dest = $this->em->getRepository(Adherent::class)->find($flux_array['destinataire']);
$flux->setDestinataire($dest);
} else if (Payment::TYPE_ACHAT_MONNAIE_PRESTA == $type) {
$flux = $serializer->deserialize(
$payment->getFluxData(),
AchatMonnaiePrestataire::class,
'json',
['disable_type_enforcement' => true]
);
$exp = $this->em->getRepository(Siege::class)->find($flux_array['expediteur']);
$flux->setExpediteur($exp);
$dest = $this->em->getRepository(Prestataire::class)->find($flux_array['destinataire']);
$flux->setDestinataire($dest);
} else if (Payment::TYPE_COTISATION_ADHERENT == $type) {
$flux = $serializer->deserialize(
$payment->getFluxData(),
CotisationAdherent::class,
'json',
['disable_type_enforcement' => true]
);
$exp = $this->em->getRepository(Adherent::class)->find($flux_array['expediteur']);
$flux->setExpediteur($exp);
$dest = $this->em->getRepository(Prestataire::class)->find($flux_array['destinataire']);
$flux->setDestinataire($dest);
$flux->setRecu(true);
} else if (Payment::TYPE_COTISATION_PRESTA == $type) {
$flux = $serializer->deserialize(
$payment->getFluxData(),
CotisationPrestataire::class,
'json',
['disable_type_enforcement' => true]
);
$exp = $this->em->getRepository(Prestataire::class)->find($flux_array['expediteur']);
$flux->setExpediteur($exp);
$dest = $this->em->getRepository(Prestataire::class)->find($flux_array['destinataire']);
$flux->setDestinataire($dest);
$flux->setRecu(true);
} else {
return new Response('', Response::HTTP_BAD_REQUEST);
}
$op = $this->em->getRepository(User::class)->find($flux_array['operateur']);
$flux->setOperateur($op);
$this->em->persist($flux);
$this->em->flush();
$this->eventDispatcher->dispatch(
MLCEvents::FLUX,
new FluxEvent($flux)
);
// Add Flash message here in case Gataway doesn't notify
$this->addFlash(
'success',
$this->translator->trans('Achat de monnaie locale bien effectué !')
);
// Invalidate token
$this->payum->getHttpRequestVerifier()->invalidate($token);
} else if ($status->getValue() == GetHumanStatus::STATUS_CANCELED ||
$status->getValue() == GetHumanStatus::STATUS_EXPIRED ||
$status->getValue() == GetHumanStatus::STATUS_FAILED) {
$this->addFlash(
'error',
$this->translator->trans('La transaction a été annulée.')
);
$this->payum->getHttpRequestVerifier()->invalidate($token);
}
return $this->redirectToRoute('index');
}
} }
...@@ -8,6 +8,7 @@ use App\Entity\Geoloc; ...@@ -8,6 +8,7 @@ use App\Entity\Geoloc;
use App\Entity\TransactionAdherentAdherent; use App\Entity\TransactionAdherentAdherent;
use App\Entity\TransactionAdherentPrestataire; use App\Entity\TransactionAdherentPrestataire;
use App\Entity\AchatMonnaieAdherent; use App\Entity\AchatMonnaieAdherent;
use App\Entity\Payment;
use App\Entity\Usergroup; use App\Entity\Usergroup;
use App\Form\Type\AdherentInfosFormType; use App\Form\Type\AdherentInfosFormType;
use App\Form\Type\AdhererFormType; use App\Form\Type\AdhererFormType;
...@@ -104,18 +105,19 @@ class UserAdherentController extends FluxController ...@@ -104,18 +105,19 @@ class UserAdherentController extends FluxController
} }
$entity = new AchatMonnaieAdherent(); $entity = new AchatMonnaieAdherent();
$entity->setReference("Achat Monnaie en CB");
$form = $this->createForm(AchatMonnaieAdherentFormType::class, $entity); $form = $this->createForm(AchatMonnaieAdherentFormType::class, $entity);
$form->handleRequest($request);
//TODO custom form handling -> redirect to payzen or other mean of payment if ($form->isSubmitted() && $form->isValid()) {
return $this->redirectToRoute('index'); return $this->preparePaymentAction(
return $this->manageFluxForm(
$request,
$form, $form,
$this->getUser()->getAdherent()->getCompte(), Payment::TYPE_ACHAT_MONNAIE_ADHERENT
$this->translator->trans('Achat de monnaie locale bien effectuée !'), );
$this->translator->trans('Achat de monnaie locale') }
);
return $this->render('flux/transaction.html.twig', [
'form' => $form->createView(),
'title' => $this->translator->trans('Achat de monnaie locale')
]);
} }
} }
...@@ -5,6 +5,7 @@ namespace App\Controller; ...@@ -5,6 +5,7 @@ namespace App\Controller;
use App\Entity\User; use App\Entity\User;
use App\Entity\CotisationAdherent; use App\Entity\CotisationAdherent;
use App\Entity\CotisationPrestataire; use App\Entity\CotisationPrestataire;
use App\Entity\Payment;
use App\Enum\MoyenEnum; use App\Enum\MoyenEnum;
use App\Form\Type\CotiserFormType; use App\Form\Type\CotiserFormType;
use App\Form\Type\UserInfosFormType; use App\Form\Type\UserInfosFormType;
...@@ -37,10 +38,13 @@ class UserController extends AbstractController ...@@ -37,10 +38,13 @@ class UserController extends AbstractController
public function cotiserAction(Request $request) public function cotiserAction(Request $request)
{ {
$options = []; $options = [];
$payment_type = '';
if ($this->security->getUser()->isGranted('ROLE_ADHERENT')) { if ($this->security->getUser()->isGranted('ROLE_ADHERENT')) {
$options['data_class'] = CotisationAdherent::class; $options['data_class'] = CotisationAdherent::class;
$payment_type = Payment::TYPE_COTISATION_ADHERENT;
} elseif ($this->security->getUser()->isGranted('ROLE_PRESTATAIRE')) { } elseif ($this->security->getUser()->isGranted('ROLE_PRESTATAIRE')) {
$options['data_class'] = CotisationPrestataire::class; $options['data_class'] = CotisationPrestataire::class;
$payment_type = Payment::TYPE_COTISATION_PRESTA;
} }
$form = $this->createForm(CotiserFormType::class, null, $options); $form = $this->createForm(CotiserFormType::class, null, $options);
...@@ -65,7 +69,11 @@ class UserController extends AbstractController ...@@ -65,7 +69,11 @@ class UserController extends AbstractController
); );
return $this->redirectToRoute('index'); return $this->redirectToRoute('index');
} else { } else {
//@TODO : redirect to payment page // Redirect to payment page
return $this->forward('App\Controller\FluxController::preparePaymentAction', [
'form' => $form,
'type' => $payment_type
]);
} }
} else { } else {
$this->addFlash( $this->addFlash(
......
...@@ -9,6 +9,7 @@ use App\Entity\TransactionPrestataireAdherent; ...@@ -9,6 +9,7 @@ use App\Entity\TransactionPrestataireAdherent;
use App\Entity\TransfertPrestataireSiege; use App\Entity\TransfertPrestataireSiege;
use App\Entity\TypePrestataire; use App\Entity\TypePrestataire;
use App\Entity\AchatMonnaiePrestataire; use App\Entity\AchatMonnaiePrestataire;
use App\Entity\Payment;
use App\Form\Type\GroupePrestataireInscriptionFormType; use App\Form\Type\GroupePrestataireInscriptionFormType;
use App\Form\Type\PrestataireInfosFormType; use App\Form\Type\PrestataireInfosFormType;
use App\Form\Type\TransactionPrestataireAdherentFormType; use App\Form\Type\TransactionPrestataireAdherentFormType;
...@@ -135,19 +136,22 @@ class UserPrestataireController extends FluxController ...@@ -135,19 +136,22 @@ class UserPrestataireController extends FluxController
if (empty($this->getUser()) || empty($this->session->get('_prestagere'))) { if (empty($this->getUser()) || empty($this->session->get('_prestagere'))) {
return $this->redirectToRoute('index'); return $this->redirectToRoute('index');
} }
$entity = new AchatMonnaiePrestataire(); $entity = new AchatMonnaiePrestataire();
$form = $this->createForm(AchatMonnaiePrestataireFormType::class, $entity); $form = $this->createForm(AchatMonnaiePrestataireFormType::class, $entity);
$form->handleRequest($request);
///TODO custom form handling -> redirect to payzen or other mean of payment if ($form->isSubmitted() && $form->isValid()) {
return $this->redirectToRoute('index'); return $this->preparePaymentAction(
return $this->manageFluxForm(
$request,
$form, $form,
$this->session->get('_prestagere'), Payment::TYPE_ACHAT_MONNAIE_PRESTA
$this->translator->trans('Achat de monnaie locale bien effectuée !'), );
$this->translator->trans('Achat de monnaie locale') }
);
return $this->render('flux/transaction.html.twig', [
'form' => $form->createView(),
'title' => $this->translator->trans('Achat de monnaie locale')
]);
} }
/** /**
......
...@@ -44,8 +44,8 @@ class Cotisation extends Flux ...@@ -44,8 +44,8 @@ class Cotisation extends Flux
// throw new \Exception("[FLUX] Opération impossible ! Prestataire recevant la monnaie locale non configuré !"); // throw new \Exception("[FLUX] Opération impossible ! Prestataire recevant la monnaie locale non configuré !");
// } // }
// $destinataire = $destinataires[0]; // $destinataire = $destinataires[0];
$compteExp = $this->getExpediteur()->getEcompte() - $this->getMontant();
if ($this->getMoyen() == MoyenEnum::MOYEN_MLC) { if ($this->getMoyen() == MoyenEnum::MOYEN_MLC) {
$compteExp = $this->getExpediteur()->getEcompte() - $this->getMontant();
if ($compteExp < 0) { if ($compteExp < 0) {
throw new \Exception("[FLUX] Opération impossible ! Montant supérieur au solde de monnaie éléctronique !"); throw new \Exception("[FLUX] Opération impossible ! Montant supérieur au solde de monnaie éléctronique !");
} else { } else {
...@@ -55,6 +55,7 @@ class Cotisation extends Flux ...@@ -55,6 +55,7 @@ class Cotisation extends Flux
return [$this->getExpediteur(), $this->getDestinataire()]; return [$this->getExpediteur(), $this->getDestinataire()];
} }
} }
// Pas d'opération si la cotisation se fait par CB
return []; return [];
} }
......
...@@ -13,7 +13,7 @@ trait HasEcompteEntity ...@@ -13,7 +13,7 @@ trait HasEcompteEntity
* Compte de MLC numérique * Compte de MLC numérique
* @var int * @var int
* *
* @ORM\Column(name="ecompte", type="decimal", precision=12, scale=2) * @ORM\Column(name="ecompte", type="decimal", precision=12, scale=2, options={"default" : 0})
* @Groups({"read"}) * @Groups({"read"})
*/ */
private $ecompte = 0; private $ecompte = 0;
......
...@@ -27,6 +27,7 @@ class GlobalParameter ...@@ -27,6 +27,7 @@ class GlobalParameter
const RECONVERSION_PRESTATAIRE = 'RECONVERSION_PRESTATAIRE'; const RECONVERSION_PRESTATAIRE = 'RECONVERSION_PRESTATAIRE';
const MAP_CENTER = 'MAP_CENTER'; const MAP_CENTER = 'MAP_CENTER';
const MAP_ZOOM = 'MAP_ZOOM'; const MAP_ZOOM = 'MAP_ZOOM';
const USE_PAYZEN = 'USE_PAYZEN';
/** /**
* @ORM\Id() * @ORM\Id()
...@@ -92,7 +93,7 @@ class GlobalParameter ...@@ -92,7 +93,7 @@ class GlobalParameter
{ {
return $this->mandatory; return $this->mandatory;
} }
/** /**
* Set mandatory * Set mandatory
* @return $this * @return $this
......
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Payum\Core\Model\Payment as BasePayment;
/**
* @ORM\Entity(repositoryClass="App\Repository\PaymentRepository")
* @ORM\Table(name="payment")
*/
class Payment extends BasePayment
{
const TYPE_ACHAT_MONNAIE_ADHERENT = 'achat_monnaie_adherent';
const TYPE_ACHAT_MONNAIE_PRESTA = 'achat_monnaie_presta';
const TYPE_COTISATION_ADHERENT = 'cotisation_adherent';
const TYPE_COTISATION_PRESTA = 'cotisation_presta';
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*
* @var integer $id
*/
protected $id;
/**
* @var string|null
*
* @ORM\Column(type="string", length=50, nullable=true)
*/
protected $status;
/**
* @var string|null
* JSON array of 'Flux' to persist if payment valid
*
* @ORM\Column(type="text", nullable=true)
*/
protected $flux_data;
/**
* @return string
*/
public function getStatus(): ?string
{
return $this->status;
}
/**
* @param string $status
* @return Payment
*/
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
/**
* @return string
*/
public function getFluxData(): ?string
{
return $this->flux_data;
}
/**
* @param string $flux_data
* @return Payment
*/
public function setFluxData(string $flux_data): self
{
$this->flux_data = $flux_data;
return $this;
}
}
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Payum\Core\Model\Token;
/**
* @ORM\Entity
* @ORM\Table(name="payment_token")
*/
class PaymentToken extends Token
{
}
...@@ -10,7 +10,7 @@ use Doctrine\ORM\Mapping as ORM; ...@@ -10,7 +10,7 @@ use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
/** /**
* @ORM\Entity * @ORM\Entity(repositoryClass="App\Repository\SiegeRepository")
* @ORM\Table(name="siege") * @ORM\Table(name="siege")
*/ */
class Siege class Siege
......
...@@ -23,7 +23,7 @@ class AchatMonnaieAdherentFormType extends AchatMonnaieFormType ...@@ -23,7 +23,7 @@ class AchatMonnaieAdherentFormType extends AchatMonnaieFormType
'em' => $this->em 'em' => $this->em
)) ))
->add('reference', HiddenType::class, array( ->add('reference', HiddenType::class, array(
'data' => 'Achat monnaie en CB' 'data' => 'Achat monnaie en CB Adhérent'
)) ))
->add('save', SubmitType::class, ['label' => "Payer en CB"]) ->add('save', SubmitType::class, ['label' => "Payer en CB"])
; ;
......
...@@ -4,6 +4,7 @@ namespace App\Form\Type; ...@@ -4,6 +4,7 @@ namespace App\Form\Type;
use App\Entity\Prestataire; use App\Entity\Prestataire;
use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
...@@ -22,8 +23,9 @@ class AchatMonnaiePrestataireFormType extends AchatMonnaieFormType ...@@ -22,8 +23,9 @@ class AchatMonnaiePrestataireFormType extends AchatMonnaieFormType
'em' => $this->em 'em' => $this->em
)) ))
->add('reference', HiddenType::class, array( ->add('reference', HiddenType::class, array(
'data' => 'Achat monnaie en CB' 'data' => 'Achat monnaie en CB Prestataire'
)) ))
->add('save', SubmitType::class, ['label' => "Payer en CB"])
; ;
} }
......
...@@ -54,6 +54,8 @@ class CotiserFormType extends AbstractType ...@@ -54,6 +54,8 @@ class CotiserFormType extends AbstractType
$canPayWithMlc = ($this->session->get('_prestagere')->getEcompte() >= $montant); $canPayWithMlc = ($this->session->get('_prestagere')->getEcompte() >= $montant);
} }
$canPayWithCB = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::USE_PAYZEN) === 'true' ? true : false;
$builder $builder
->add('operateur', HiddenType::class, array( ->add('operateur', HiddenType::class, array(
'entity_class' => User::class, 'entity_class' => User::class,
...@@ -94,8 +96,10 @@ class CotiserFormType extends AbstractType ...@@ -94,8 +96,10 @@ class CotiserFormType extends AbstractType
if ($canPayWithMlc) { if ($canPayWithMlc) {
$builder->add('payMLC', SubmitType::class, ['label' => "Payer en eMLC"]); $builder->add('payMLC', SubmitType::class, ['label' => "Payer en eMLC"]);
} }
$builder->add('payCB', SubmitType::class, ['label' => "Payer en CB"]); if ($canPayWithCB) {
$builder->add('payCB', SubmitType::class, ['label' => "Payer en CB"]);
}
if ($this->security->getUser()->isGranted('ROLE_ADHERENT')) { if ($this->security->getUser()->isGranted('ROLE_ADHERENT')) {
$builder $builder
->add('expediteur', HiddenType::class, array( ->add('expediteur', HiddenType::class, array(
......
...@@ -118,6 +118,16 @@ class GlobalConfigurationFormType extends AbstractType ...@@ -118,6 +118,16 @@ class GlobalConfigurationFormType extends AbstractType
], ],
'help' => '' 'help' => ''
)) ))
->add('usepayzen', GlobalParameterType::class, array(
'label' => "Utiliser le paiement par CB avec Payzen :",
'name_param' => GlobalParameter::USE_PAYZEN,
'required' => true,
'_placeholder' => 'false',
'constraints_param' => [
new RegexConstraint(['pattern' => '/^true$|^false$/', 'message' => 'La valeur doit être "true" ou "false"'])
],
'help' => 'Si cette option est activée (true), les utilisateurs pourront cotiser et acheter de la monnaie locale par CB sur l\'application.'
))
; ;
} }
......
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200626122137 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE payment (id INT AUTO_INCREMENT NOT NULL, number VARCHAR(255) DEFAULT NULL, description VARCHAR(255) DEFAULT NULL, client_email VARCHAR(255) DEFAULT NULL, client_id VARCHAR(255) DEFAULT NULL, total_amount INT DEFAULT NULL, currency_code VARCHAR(255) DEFAULT NULL, details LONGTEXT NOT NULL COMMENT \'(DC2Type:json_array)\', status VARCHAR(50) DEFAULT NULL, flux_data LONGTEXT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_general_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE payment_token (hash VARCHAR(255) NOT NULL, details LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', after_url LONGTEXT DEFAULT NULL, target_url LONGTEXT NOT NULL, gateway_name VARCHAR(255) NOT NULL, PRIMARY KEY(hash)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_general_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE adherent CHANGE ecompte ecompte NUMERIC(12, 2) DEFAULT \'0\' NOT NULL');
$this->addSql('ALTER TABLE prestataire CHANGE ecompte ecompte NUMERIC(12, 2) DEFAULT \'0\' NOT NULL');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE payment');
$this->addSql('DROP TABLE payment_token');
$this->addSql('ALTER TABLE adherent CHANGE ecompte ecompte NUMERIC(12, 2) NOT NULL');
$this->addSql('ALTER TABLE prestataire CHANGE ecompte ecompte NUMERIC(12, 2) NOT NULL');
}
}
<?php
namespace App\Repository;
use App\Entity\Payment;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
/**
* @method Siege|null find($id, $lockMode = null, $lockVersion = null)
* @method Siege|null findOneBy(array $criteria, array $orderBy = null)
* @method Siege[] findAll()
* @method Siege[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class PaymentRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Payment::class);
}
/**
* @param int $id User id
*
* @return Payment|null Returns user's last payment
*/
public function getUserLastPayment($id) {
$results = $this->findBy(
array('clientId' => $id),
array('id'=>'DESC'),
1,
0
);
if (empty($results)) {
return null;
} else {
return $results[0];
}
}
}
<?php
namespace App\Repository;
use App\Entity\Siege;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
/**
* @method Siege|null find($id, $lockMode = null, $lockVersion = null)
* @method Siege|null findOneBy(array $criteria, array $orderBy = null)
* @method Siege[] findAll()
* @method Siege[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class SiegeRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Siege::class);
}
}
...@@ -11,6 +11,7 @@ use App\Entity\Prestataire; ...@@ -11,6 +11,7 @@ use App\Entity\Prestataire;
use App\Entity\Rubrique; use App\Entity\Rubrique;
use App\Entity\Siege; use App\Entity\Siege;
use App\Entity\User; use App\Entity\User;
use App\Entity\GlobalParameter;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface; use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
...@@ -61,10 +62,16 @@ class AppExtension extends AbstractExtension ...@@ -61,10 +62,16 @@ class AppExtension extends AbstractExtension
new \Twig_SimpleFunction('getWordpressApiKey', array($this, 'getWordpressApiKey')), new \Twig_SimpleFunction('getWordpressApiKey', array($this, 'getWordpressApiKey')),
new \Twig_SimpleFunction('parameter', function ($name) { new \Twig_SimpleFunction('parameter', function ($name) {
return $this->container->getParameter($name); return $this->container->getParameter($name);
}) }),
new \Twig_SimpleFunction('isPayzenEnabled', array($this, 'isPayzenEnabled'))
]; ];
} }
public function isPayzenEnabled()
{
return $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::USE_PAYZEN) === 'true' ? true : false;
}
public function getFilters() public function getFilters()
{ {
return array( return array(
...@@ -105,7 +112,7 @@ class AppExtension extends AbstractExtension ...@@ -105,7 +112,7 @@ class AppExtension extends AbstractExtension
} }
return $this->em->getRepository(Comptoir::class)->findOneById($this->session->get('_comptoirgere')->getId()); return $this->em->getRepository(Comptoir::class)->findOneById($this->session->get('_comptoirgere')->getId());
} }
public function getCurrentGroupe() public function getCurrentGroupe()
{ {
if (!$this->session->has('_groupegere')) { if (!$this->session->has('_groupegere')) {
...@@ -113,7 +120,7 @@ class AppExtension extends AbstractExtension ...@@ -113,7 +120,7 @@ class AppExtension extends AbstractExtension
} }
return $this->em->getRepository(Groupe::class)->findOneById($this->session->get('_groupegere')->getId()); return $this->em->getRepository(Groupe::class)->findOneById($this->session->get('_groupegere')->getId());
} }
public function getCurrentPrestataire() public function getCurrentPrestataire()
{ {
if (!$this->session->has('_prestagere')) { if (!$this->session->has('_prestagere')) {
......
...@@ -107,6 +107,9 @@ ...@@ -107,6 +107,9 @@
"egulias/email-validator": { "egulias/email-validator": {
"version": "2.1.6" "version": "2.1.6"
}, },
"ekyna/payum-payzen": {
"version": "1.5.x-dev"
},
"exsyst/swagger": { "exsyst/swagger": {
"version": "v0.4.1" "version": "v0.4.1"
}, },
...@@ -248,6 +251,27 @@ ...@@ -248,6 +251,27 @@
"lcobucci/jwt": { "lcobucci/jwt": {
"version": "3.3.1" "version": "3.3.1"
}, },
"league/uri": {
"version": "5.3.0"
},
"league/uri-components": {
"version": "1.8.2"
},
"league/uri-hostname-parser": {
"version": "1.1.1"
},
"league/uri-interfaces": {
"version": "1.1.1"
},
"league/uri-manipulations": {
"version": "1.5.0"
},
"league/uri-parser": {
"version": "1.4.1"
},
"league/uri-schemes": {
"version": "1.2.1"
},
"lexik/jwt-authentication-bundle": { "lexik/jwt-authentication-bundle": {
"version": "2.5", "version": "2.5",
"recipe": { "recipe": {
...@@ -320,6 +344,27 @@ ...@@ -320,6 +344,27 @@
"ocramius/proxy-manager": { "ocramius/proxy-manager": {
"version": "2.1.1" "version": "2.1.1"
}, },
"payum/core": {
"version": "1.6.0"
},
"payum/iso4217": {
"version": "1.0.1"
},
"payum/offline": {
"version": "1.6.0"
},
"payum/payum-bundle": {
"version": "2.4",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "master",
"version": "2.4",
"ref": "72ad834a0f4a99175beddb5e2d049136f4a50a67"
},
"files": [
"config/packages/payum.yaml"
]
},
"php": { "php": {
"version": "7.4" "version": "7.4"
}, },
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
{% if ((app.user and is_granted('ROLE_ADHERENT') and app.user.adherent) or (app.user and is_granted('ROLE_PRESTATAIRE') and app.session.has('_prestagere'))) %} {% if ((app.user and is_granted('ROLE_ADHERENT') and app.user.adherent) or (app.user and is_granted('ROLE_PRESTATAIRE') and app.session.has('_prestagere'))) %}
<a class='btn btn-xs btn-primary' href='{{ path('cotiser') }}'> <a class='btn btn-xs btn-primary' href='{{ path('cotiser') }}'>
{{ 'Cotiser en MLC'|trans }} {{ 'Cotiser'|trans }}
</a> </a>
{% endif %} {% endif %}
{% endblock blockcontent %} {% endblock blockcontent %}
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
{% if flux.type == 'reconversion' %} {% if flux.type == 'reconversion' %}
<td>Demande de reconversion</td> <td>Demande de reconversion</td>
{% else %} {% else %}
<td>{{flux.parenttype|capitalize}} de {{ flux.type|capitalize|replace({'_' : ' à '}) }}</td> <td>{{ flux.type|capitalize|replace({'_' : ' '}) }}</td>
{% endif %} {% endif %}
<td>{{flux.expediteur}}</td> <td>{{flux.expediteur}}</td>
<td>{{flux.destinataire}}</td> <td>{{flux.destinataire}}</td>
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
<div class="btn-group"> <div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" id="dropdownMenuLink"> <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" id="dropdownMenuLink">
<i class="fa fa-share-square-o" aria-hidden="true"></i> <i class="fa fa-share-square-o" aria-hidden="true"></i>
Exporter Exporter
<span class="caret"></span> <span class="caret"></span>
</button> </button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink"> <div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
...@@ -64,4 +64,4 @@ ...@@ -64,4 +64,4 @@
</div> </div>
</div> </div>
{% endblock blockcontent %} {% endblock blockcontent %}
{% endif %} {% endif %}
\ No newline at end of file
...@@ -155,7 +155,9 @@ ...@@ -155,7 +155,9 @@
{% include 'block/cotisations.html.twig' %} {% include 'block/cotisations.html.twig' %}
{% include 'groupepresta/block/inscription.html.twig' %} {% include 'groupepresta/block/inscription.html.twig' %}
{% endif %} {% endif %}
{% include 'presta/block/achat_monnaie.html.twig' %} {% if isPayzenEnabled() %}
{% include 'presta/block/achat_monnaie.html.twig' %}
{% endif %}
{% include 'presta/block/transaction_presta.html.twig' %} {% include 'presta/block/transaction_presta.html.twig' %}
{% include 'presta/block/transaction_adherent.html.twig' %} {% include 'presta/block/transaction_adherent.html.twig' %}
{% if getCurrentPrestataire().mlc == false and getCurrentPrestataire().ecompte > 0 %} {% if getCurrentPrestataire().mlc == false and getCurrentPrestataire().ecompte > 0 %}
...@@ -170,7 +172,9 @@ ...@@ -170,7 +172,9 @@
{% include 'block/userpassword.html.twig' %} {% include 'block/userpassword.html.twig' %}
{% include 'block/cotisations.html.twig' %} {% include 'block/cotisations.html.twig' %}
{% include 'block/transactions.html.twig' %} {% include 'block/transactions.html.twig' %}
{% include 'adherent/block/achat_monnaie.html.twig' %} {% if isPayzenEnabled() %}
{% include 'adherent/block/achat_monnaie.html.twig' %}
{% endif %}
{% include 'adherent/block/transaction_presta.html.twig' %} {% include 'adherent/block/transaction_presta.html.twig' %}
{% include 'adherent/block/transaction_adherent.html.twig' %} {% include 'adherent/block/transaction_adherent.html.twig' %}
......
...@@ -26,8 +26,15 @@ ...@@ -26,8 +26,15 @@
{% else %} {% else %}
<div class='col-12'> <div class='col-12'>
{% endif %} {% endif %}
{% if form.payCB is defined %}
<div class='col-6'>
{{ form_widget(form.payCB) }} {{ form_widget(form.payCB) }}
</div> </div>
<div class='col-6'>
{% else %}
<div class='col-12'>
{% endif %}
</div>
</div> </div>
{{ form_end(form) }} {{ form_end(form) }}
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment