Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ACP-3507 APIs to enable projects embed payment elements to frontends based on Glue API #15

Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
2563323
ACP-2601 Added new endpoints for differetn payment options for fronte…
stereomon Jul 31, 2024
435629e
ACP-3507 Added confirmPreOrderPayment
stereomon Aug 1, 2024
ec8e888
ACP-3507 Allowing implementations without AppPreOrderPaymentPlatformP…
stereomon Aug 1, 2024
bccb237
ACP-3507 Added handling of multiple payment methods.
stereomon Aug 2, 2024
5d3726e
ACP-3507 Updated API.
stereomon Aug 2, 2024
3ed322b
ACP-3507 Added another test case, removed redirect data for the hoste…
stereomon Aug 6, 2024
840a2c9
ACP-3507 Updated PaymentMethod Add and Delete messages.
stereomon Aug 6, 2024
fbaea6e
ACP-3507 Updated Payment Method handling
stereomon Aug 7, 2024
c01c524
ACP-3507 Updated PaymentMethod message handling, added new UpdatePaym…
stereomon Aug 7, 2024
cf964ac
ACP-3507 Updated PaymentMethod handling
stereomon Aug 7, 2024
8e1c9c2
ACP-3507 Fixed some SprykerCV issues.
stereomon Aug 8, 2024
1ac6aea
ACP-3507 Updated column size for tenant_identifier.
stereomon Aug 12, 2024
a76633a
Merge branch 'main' of github.com:spryker/app-payment into feature/ac…
stereomon Aug 13, 2024
25acb38
ACP-3507 Fixed CI
stereomon Aug 13, 2024
f255ff2
ACP-3507 Added idempotency to payment initialize request.
stereomon Aug 19, 2024
0942f54
ACP-3507 Process unprocessed webhook requests after the order pre-ord…
stereomon Aug 21, 2024
690c1a2
ACP-3507 CR fixes.
stereomon Aug 22, 2024
8e173b1
ACP-3507 Added default files.
stereomon Aug 22, 2024
c98642b
ACP-3507 Fixed PHPStan issues.
stereomon Aug 22, 2024
5c4cc31
ACP-3507 Updated open API schema
stereomon Aug 22, 2024
7f4353b
ACP-3507 Updated renamed plugin occurrences.
stereomon Aug 26, 2024
34d441a
ACP-3507 Updated schema, update quote in confirm-pre-order payment.
stereomon Aug 26, 2024
9486412
Merge branch 'feature/acp-3507-investigate-how-the-apis-to-enable-pro…
stereomon Aug 26, 2024
f4afc7f
ACP-3507 Merged with master
stereomon Sep 10, 2024
91b5dad
ACP3507 Fixed tests.
stereomon Sep 10, 2024
71eeff6
ACP-3636 Updated docs
stereomon Sep 16, 2024
6d13279
ACP-3507 Separated interfaces.
stereomon Sep 17, 2024
6b515a7
ACP-3507 Updated composer.lock.
stereomon Sep 17, 2024
6dc64c0
ACP-3507 Fixes after CR.
stereomon Sep 18, 2024
ec1a684
ACP-3507 CR changes.
stereomon Sep 18, 2024
b703516
ACP-3507 CR fixes
stereomon Sep 18, 2024
243441e
ACP-3507 Updated specifications, docs, applied CR fixes.
stereomon Sep 19, 2024
459c516
ACP-3507 Renamed paymentServiceProviderData to preOrderPaymentData
stereomon Sep 19, 2024
3ff5d95
ACP-3507 Updated AppKernel
stereomon Sep 19, 2024
4939a83
ACP-3507 Fixed missed renamings.
stereomon Sep 19, 2024
3ad7218
ACP-3507 Fixed pre order payment status change
stereomon Sep 23, 2024
37bbdef
ACP-3507 Added pre-order-cancellation endpoint.
stereomon Sep 24, 2024
1752d33
Fixed text, typos
matweew Sep 24, 2024
0abc048
ACP-3507 CamelCased response.
stereomon Sep 24, 2024
83e1741
Merge branch 'feature/acp-3507-investigate-how-the-apis-to-enable-pro…
stereomon Sep 24, 2024
bd64796
ACP-3507 Fixed wrong API definition.
stereomon Sep 25, 2024
426e868
ACP-3507 Use full configuration of payment method for comparison.
stereomon Sep 26, 2024
7dd267e
ACP-3507 Updated batch in README.md
stereomon Sep 26, 2024
a2495b3
Batch update, will be reverted
stereomon Sep 26, 2024
c0a07d0
Batch update
stereomon Sep 26, 2024
0f939dd
ACP-3507 Updated composer.json versions.
stereomon Sep 26, 2024
bc092d8
ACP-3507 Updated README.md
stereomon Sep 30, 2024
a143f33
Merge branch 'feature/acp-3507-investigate-how-the-apis-to-enable-pro…
stereomon Sep 30, 2024
e57516e
ACP-3507 Updated AsyncAPI version.
stereomon Sep 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ src/Generated/
/src/Orm/Zed/
tests/_data/app_payment_db
/data/cache
/data/DE/logs/ZED/propel.log

# tools
.phpstorm.meta.php
Expand Down
149 changes: 145 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ This plugin provides the routes for the AppPaymentBackendApi module.
###### Routes provided

- /private/initialize-payment - Used from the Tenant side to initialize a payment.

- /private/confirm-pre-order-payment - Used from the Tenant side to confirm pre-order payment after the order was persisted.

### AppKernel
- \Spryker\Glue\AppPaymentBackendApi\Plugin\AppKernel\PaymentConfigurationValidatorPlugin
- \Spryker\Zed\AppPayment\Communication\Plugin\AppKernel\ConfigurePaymentMethodsConfigurationAfterSavePlugin
- \Spryker\Zed\AppPayment\Communication\Plugin\AppKernel\DeleteTenantPaymentsConfigurationAfterDeletePlugin
- \Spryker\Zed\AppPayment\Communication\Plugin\AppKernel\SendAddPaymentMethodMessageConfigurationAfterSavePlugin
- \Spryker\Zed\AppPayment\Communication\Plugin\AppKernel\SendDeletePaymentMethodMessageConfigurationAfterDeletePlugin
- \Spryker\Zed\AppPayment\Communication\Plugin\AppKernel\SendDeletePaymentMethodMessagesConfigurationAfterDeletePlugin

### AppWebhook
- \Spryker\Zed\AppPayment\Communication\Plugin\AppWebhook\PaymentWebhookHandlerPlugin
Expand All @@ -70,7 +70,44 @@ This plugin provides the routes for the AppPaymentBackendApi module.
### MessageBrokerAws
- \Spryker\Zed\AppPayment\Communication\Plugin\MessageBrokerAws\ConsumerIdHttpChannelMessageReceiverRequestExpanderPlugin

### Configure the MessageBroker
## Extensions

- \Spryker\Zed\AppPayment\Dependency\Plugin\AppPaymentPlatformMarketplacePluginInterface
- \Spryker\Zed\AppPayment\Dependency\Plugin\AppPaymentPlatformPaymentMethodsPluginInterface
- \Spryker\Zed\AppPayment\Dependency\Plugin\AppPaymentPlatformPaymentPagePluginInterface
- \Spryker\Zed\AppPayment\Dependency\Plugin\AppPaymentPlatformPluginInterface
- \Spryker\Zed\AppPayment\Dependency\Plugin\AppPaymentPlatformPreOrderPluginInterface
- \Spryker\Zed\AppPayment\Dependency\Plugin\PaymentTransmissionsRequestExtenderPluginInterface

### AppPaymentPlatformMarketplacePluginInterface

You can implement this plugin when your PSP App supports Marketplace capabilities.

### AppPaymentPlatformPaymentMethodsPluginInterface

This plugin must be implemented to provide the payment methods that the PSP App supports.

### AppPaymentPlatformPaymentPagePluginInterface

This plugin can be implemented to provide a payment page that the PSP App supports. This is only needed when using the redirect flows after the order was created.

### AppPaymentPlatformPluginInterface

This is the root plugin which must be implemented to provide the PSP App capabilities from the project level.

### AppPaymentPlatformPreOrderPluginInterface

This plugin can be implemented to provide the pre-order capabilities that the PSP App supports.

When using the pre-order payment flow, the InitializePayment API endpoint is used before the order gets persisted and it returns the needed data for an headless approach to add the payment page on project side. Usually, this is done via a provided JavaScript that is send to the frontend in the InitializePayment API call response.

On project side the customer than makes the Payment via the provided JavaScripts and the payment page provided by the PSP provider. After the order is persistzed on the project side a call to the ConfirmPreOrderPayment API endpoint is made to confirm the payment and connect it with the orderReference.

### PaymentTransmissionsRequestExtenderPluginInterface

This plugin can be implemented to extend the request data that is send to the PSP App when doing payouts to Merchants. This is usually only needed when the PSP App supports Marketplace capabilities.

## Configure the MessageBroker

Add this to your project configuration:

Expand All @@ -89,8 +126,10 @@ $config[MessageBrokerAwsConstants::MESSAGE_TO_CHANNEL_MAP] = [
CapturePaymentTransfer::class => 'payment-commands',
RefundPaymentTransfer::class => 'payment-commands',
AddPaymentMethodTransfer::class => 'payment-method-commands',
UpdatePaymentMethodTransfer::class => 'payment-method-commands',
DeletePaymentMethodTransfer::class => 'payment-method-commands',
PaymentCreatedTransfer::class => 'payment-events',
PaymentUpdatedTransfer::class => 'payment-events',
// App event
AppConfigUpdatedTransfer::class => 'app-events',
];
Expand All @@ -112,3 +151,105 @@ $config[MessageBrokerAwsConstants::CHANNEL_TO_RECEIVER_TRANSPORT_MAP] = [
'payment-commands' => MessageBrokerAwsConfig::SQS_TRANSPORT,
];
```

### Configure Payment Methods

Each PSP implementation has different Payment Methods available. Through the `\Spryker\Zed\AppPayment\Dependency\Plugin\AppPaymentPlatformPaymentMethodsPluginInterface` you can provide the available Payment Methods.

Each Payment Method can also have different configuration details.

Add the plugin interface to your implementation and you can configure the payment methods.

#### Payment Method default configuration

This package adds endpoints to be used from the SCOS side to each of the configured Payment Methods. The default configuration for each Payment Method is:

- The base URL - This is the URL that the SCOS side will use to call the PSP App.
- Endpoints - The endpoints that the SCOS side will call on the PSP App.
- `authorization` - The endpoint to initialize a Payment, `/private/initialize-payment`
- `pre-order-confirmation` - The endpint to confirm a PreOrder payment, `/private/confirm-pre-order-payment`
- `pre-order-cancellation` - The endpint to cancel a PreOrder payment, `/private/cancel-pre-order-payment`
- `transfer` - The endpoint to transfer money to a Merchant, `/private/transfers`

These are used on the SCOS side by their names. F.e. when the SCOS side wants to initialize a payment it will call the `authorization` endpoint on the PSP App.

#### Payment Service Provider with only one Payment Method

A simple example for a PSP with only one Payment Method could look like this:

```
public function configurePaymentMethods(PaymentMethodConfigurationRequestTransfer $paymentMethodConfigurationRequestTransfer): PaymentMethodConfigurationResponseTransfer
{
$paymentMethodConfigurationResponseTransfer = new PaymentMethodConfigurationResponseTransfer();

$checkoutConfigurationTransfer = new CheckoutConfigurationTransfer();
$checkoutConfigurationTransfer->setStrategy('embedded');
$checkoutConfigurationTransfer->setScripts([
...
]);

$paymentMethodAppConfigurationTransfer = new PaymentMethodAppConfigurationTransfer();
$paymentMethodAppConfigurationTransfer
->setCheckoutConfiguration($checkoutConfigurationTransfer);

$paymentMethodTransfer = new PaymentMethodTransfer();
$paymentMethodTransfer
->setName('Foo')
->setProviderName('Bar')
->setPaymentMethodAppConfiguration($paymentMethodAppConfigurationTransfer);

$paymentMethodConfigurationResponseTransfer->addPaymentMethod($paymentMethodTransfer);

return $paymentMethodConfigurationResponseTransfer;
}
```

Here we configure exactly one payment method. The payment method is named "Foo" and the provider is named "Bar". The Payment method also has a configuration that will be persisted on the SCOS side.

The strategy is set to "embedded" which means that the payment page will be embedded in the SCOS checkout. The scripts are the scripts that are needed to embed and run the payment page in the SCOS checkout.

This code runs when the PSP App gets configured. After this method call the so configured methods will be persisted on the App sides database, enriched with default configurations, and via the AddPaymentMethod message sent to the SCOS side.

When the App gets reconfigured and a different number of Payment Methods are configured, the DeletePaymentMethod message will be sent to the SCOS side and the previously configured Payment Methods for the current Tenant will be deleted from the database.

When the PaymentMethod configuration has changed the UpdatePaymentMethod message will be sent to the SCOS side.

#### Payment Service Provider with multiple Payment Methods

In case you have multiple payment methods, you can add multiple PaymentMethodTransfer objects to the PaymentMethodConfigurationResponseTransfer object. For this, you can get the AppConfigTransfer from the PaymentMethodConfigurationRequestTransfer. An example could look like this:

```
public function configurePaymentMethods(PaymentMethodConfigurationRequestTransfer $paymentMethodConfigurationRequestTransfer): PaymentMethodConfigurationResponseTransfer
{
$appConfigTransfer = $paymentMethodConfigurationRequestTransfer->getAppConfig();

// Contains ['bar'] which was the only one selected through the configuration page
$configuredPaymentMethods = $appConfigTransfer->getPaymentMethods();

// These are all methods you can provide which are configurable through the AppStore Catalogs App configuration page
$availablePaymentMethods = [
'foo',
'bar',
'baz',
];

$paymentMethodConfigurationResponseTransfer = new PaymentMethodConfigurationResponseTransfer();

foreeach ($availablePaymentMethods as $paymentMethodName) {
if (!isset($configuredPaymentMethods[$paymentMethodName])) {
continue;
}

$paymentMethodTransfer = new PaymentMethodTransfer();
$paymentMethodTransfer
->setName($paymentMethodName)
->setProviderName('PaymentProviderName');

$paymentMethodConfigurationResponseTransfer->addPaymentMethod($paymentMethodTransfer);
}

return $paymentMethodConfigurationResponseTransfer;
}
```

In thie example you would get one PaymentMethod added to SCOS via the AddPaymentMethod message. The PaymentMethod is named "bar" and the provider is named "PaymentProviderName".
27 changes: 13 additions & 14 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@
"description": "AppPayment module",
"license": "proprietary",
"require": {
"php": ">=8.1",
"php": ">=8.2",
"spryker/app-kernel": "^2.0.0",
"spryker/app-webhook": "dev-feature/acp-3507/acp-3746-persist-webhooks-and-allow-to-run-them-later as 1.1.0",
"spryker/event-dispatcher": "^1.6.0",
"spryker/glue-application-extension": "^1.0.0",
"spryker/glue-backend-api-application": "^1.7.0",
"spryker/glue-json-api-convention": "^1.3.0",
"spryker/kernel": "^3.30.0",
"spryker/log": "^3.0.0",
"spryker/message-broker": "^1.11.0",
"spryker/router": "^1.19.0",
"spryker/symfony": "^3.0.0",
"spryker/transfer": "^3.33.0"
"spryker/transfer": "^3.33.0",
"spryker/translator": "^1.13.0"
},
"require-dev": {
"spryker/app-webhook": "^1.0.0",
"codeception/codeception": "^5.0",
"codeception/module-asserts": "^3.0.0",
"codeception/module-cli": "^2.0.0",
Expand All @@ -22,27 +28,20 @@
"codeception/module-rest": "^3.0.0",
"codeception/module-webdriver": "^3.0.0",
"codeception/phpunit-wrapper": "^9.0.0",
"galbar/jsonpath": "^3.0",
"galbar/jsonpath": "^3.0.0",
"infection/codeception-adapter": "^0.4.3",
"infection/infection": "^0.29.6",
"phpstan/phpdoc-parser": "1.25.0",
"phpstan/phpstan": "1.10.66",
"rector/rector": "^0.19.0",
"spryker-sdk/async-api": "dev-master as 0.3.1",
"spryker/app-kernel": "^1.0.0",
"spryker/code-sniffer": "*",
"spryker/container": "*",
"spryker/development": "^3.34.0",
"spryker/event-dispatcher": "^1.6",
"spryker/glue-backend-api-application": "*",
"spryker/glue-json-api-convention": "^1.3",
"spryker/http": "^1.11",
"spryker/http": "^1.11.0",
"spryker/message-broker-aws": "*",
"spryker/propel": "*",
"spryker/router": "^1.19",
"spryker/testify": "*",
"spryker/testify-async-api": "*",
"spryker/translator": "^1.13"
"spryker/testify-async-api": "*"
},
"autoload": {
"psr-4": {
Expand All @@ -66,7 +65,7 @@
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"setup": "tests/bin/console app-payment:setup && tests/bin/console transfer:generate && tests/bin/console transfer:databuilder:generate && tests/bin/console dev:ide-auto-completion:zed:generate && tests/bin/console dev:ide-auto-completion:glue:generate && tests/bin/console propel:install && vendor/bin/codecept build",
"setup": "tests/bin/console app-payment:setup && tests/bin/console transfer:generate && tests/bin/console transfer:databuilder:generate && tests/bin/console dev:ide-auto-completion:zed:generate && tests/bin/console dev:ide-auto-completion:glue:generate && tests/bin/console dev:ide-auto-completion:glue-backend:generate && tests/bin/console propel:install && vendor/bin/codecept build",
"cs-check": "phpcs -p src/ tests/",
"cs-fix": "phpcbf -p src/ tests/",
"stan": "phpstan analyze src/Spryker/ --memory-limit=1G",
Expand Down
4 changes: 4 additions & 0 deletions config/Shared/config_default.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

use Generated\Shared\Transfer\AddPaymentMethodTransfer;
use Generated\Shared\Transfer\UpdatePaymentMethodTransfer;
use Generated\Shared\Transfer\AppConfigUpdatedTransfer;
use Generated\Shared\Transfer\CancelPaymentTransfer;
use Generated\Shared\Transfer\CapturePaymentTransfer;
Expand All @@ -18,6 +19,7 @@
use Generated\Shared\Transfer\PaymentCreatedTransfer;
use Generated\Shared\Transfer\PaymentRefundedTransfer;
use Generated\Shared\Transfer\PaymentRefundFailedTransfer;
use Generated\Shared\Transfer\PaymentUpdatedTransfer;
use Generated\Shared\Transfer\RefundPaymentTransfer;
use Ramsey\Uuid\Uuid;
use Spryker\Shared\AppKernel\AppKernelConstants;
Expand Down Expand Up @@ -149,8 +151,10 @@
CapturePaymentTransfer::class => 'payment-commands',
RefundPaymentTransfer::class => 'payment-commands',
AddPaymentMethodTransfer::class => 'payment-method-commands',
UpdatePaymentMethodTransfer::class => 'payment-method-commands',
DeletePaymentMethodTransfer::class => 'payment-method-commands',
PaymentCreatedTransfer::class => 'payment-events',
PaymentUpdatedTransfer::class => 'payment-events',
// App event
AppConfigUpdatedTransfer::class => 'app-events',
];
Expand Down
5 changes: 5 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,9 @@
<exclude name="SlevomatCodingStandard.Classes.DisallowConstructorPropertyPromotion.DisallowedConstructorPropertyPromotion"/>
</rule>

<!-- PHP 8.0 we will allow the null safe operator -->
<rule ref="SlevomatCodingStandard.ControlStructures.DisallowNullSafeObjectOperator">
<exclude name="SlevomatCodingStandard.ControlStructures.DisallowNullSafeObjectOperator"/>
</rule>

</ruleset>
4 changes: 0 additions & 4 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,3 @@ parameters:
level: 8
ignoreErrors:
- '#Call to an undefined method Spryker\\Shared\\Kernel\\Transfer\\AbstractTransfer::getMessageAttributesOrFail\(\)#'
- '#Call to method appPayment\(\) on an unknown class Generated\\GlueBackend\\Ide\\AutoCompletion.#'
- '#Call to an undefined method Spryker\\Zed\\AppPayment\\Dependency\\Plugin\\AppPaymentPlatformPluginInterface::transferPayments\(\).#'
- '#Method Spryker\\Zed\\AppPayment\\Business\\Payment\\AppConfig\\AppConfigLoader::loadAppConfig\(\) should return Generated\\Shared\\Transfer\\AppConfigTransfer but returns Spryker\\Shared\\Kernel\\Transfer\\TransferInterface.#'
- '#Method Spryker\\Zed\\AppKernel\\Business\\AppKernelFacadeInterface::getConfig\(\) invoked with 2 parameters, 1 required.#'
2 changes: 2 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@
__DIR__ . '/src/Spryker/Glue/AppPaymentBackendApi/Dependency/Facade/AppPaymentBackendApiToAppPaymentFacadeBridge.php',
__DIR__ . '/src/Spryker/Zed/AppPayment/Dependency/Facade/AppPaymentToAppKernelFacadeBridge.php',
__DIR__ . '/src/Spryker/Zed/AppPayment/Dependency/Facade/AppPaymentToMessageBrokerFacadeBridge.php',
__DIR__ . '/src/Spryker/Zed/AppPayment/Dependency/Facade/AppPaymentToAppWebhookFacadeBridge.php',
__DIR__ . '/src/Spryker/Zed/AppPayment/Dependency/Service/AppPaymentToUtilEncodingServiceBridge.php',
],
AddParamTypeFromPropertyTypeRector::class => [
__DIR__ . '/src/Spryker/Glue/AppPaymentBackendApi/Dependency/Facade/AppPaymentBackendApiToAppPaymentFacadeBridge.php',
__DIR__ . '/src/Spryker/Zed/AppPayment/Dependency/Facade/AppPaymentToAppKernelFacadeBridge.php',
__DIR__ . '/src/Spryker/Zed/AppPayment/Dependency/Facade/AppPaymentToMessageBrokerFacadeBridge.php',
__DIR__ . '/src/Spryker/Zed/AppPayment/Dependency/Facade/AppPaymentToAppWebhookFacadeBridge.php',
__DIR__ . '/src/Spryker/Zed/AppPayment/Dependency/Service/AppPaymentToUtilEncodingServiceBridge.php',
],
]);
Expand Down
Loading
Loading