Skip to content

[API] Add Payment request#15502

Closed
Prometee wants to merge 72 commits intoSylius:payment-requestfrom
Prometee:payment-request
Closed

[API] Add Payment request#15502
Prometee wants to merge 72 commits intoSylius:payment-requestfrom
Prometee:payment-request

Conversation

@Prometee
Copy link
Copy Markdown
Contributor

@Prometee Prometee commented Nov 6, 2023

Q A
Branch? 1.13
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Related tickets
License MIT

First PR to handle payments via requests.
Sylius - Payment Request

@Prometee Prometee requested a review from a team as a code owner November 6, 2023 19:19
@github-actions
Copy link
Copy Markdown

github-actions bot commented Nov 6, 2023

Bunnyshell Preview Environment deleted

Available commands:

  • /bns:deploy to redeploy the environment

@Prometee Prometee force-pushed the payment-request branch 2 times, most recently from ec4f275 to 487ba19 Compare November 7, 2023 10:59
@probot-autolabeler probot-autolabeler bot added the API APIs related issues and PRs. label Nov 17, 2023
@Prometee Prometee force-pushed the payment-request branch 2 times, most recently from 5d54f31 to cd679fc Compare November 23, 2023 19:08
@Prometee Prometee force-pushed the payment-request branch 3 times, most recently from 162906d to f2c46d1 Compare February 1, 2024 19:11
@Prometee Prometee requested a review from a team as a code owner February 2, 2024 16:26
@Prometee Prometee force-pushed the payment-request branch 2 times, most recently from 4a52858 to 2de795b Compare February 2, 2024 19:03
@probot-autolabeler probot-autolabeler bot added the Maintenance CI configurations, READMEs, releases, etc. label Feb 3, 2024
@Prometee Prometee force-pushed the payment-request branch 3 times, most recently from f054ae6 to 77e2207 Compare February 3, 2024 17:19
@Prometee Prometee mentioned this pull request Feb 6, 2024
5 tasks
@Prometee Prometee force-pushed the payment-request branch 2 times, most recently from 3e9e391 to 5d8c23b Compare February 7, 2024 14:43
Copy link
Copy Markdown
Contributor

@NoResponseMate NoResponseMate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The graph is not necessarily true since you can technically immediately finalize the payment via the create request endpoint.
Now the question is whether we should allow that or force using the post endpoint for initializing/validating/handshake only. It'd then require using the payments API at least twice but might be easier to manage, at least the responsibilities of each would be clearer. Food for thought.

Comment on lines +45 to +50
$stateMachine = $this->stateMachineFactory->get($payment, PaymentTransitions::GRAPH);
if ($paymentRequest->getResponseData()['paid']) {
$stateMachine->apply(PaymentTransitions::TRANSITION_COMPLETE);
} else {
$stateMachine->apply(PaymentTransitions::TRANSITION_PROCESS);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that we need to manually trigger a transition cascade to payment is annoying, but I don't really have any good idea ATM how to abstract it out, or if it's even possible given the multiple request types.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but keep in mind that this is required only for non Payum gateways, Payum is doing this transition too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you've wrote, makes me think about a way to setup a state machine on the payment request which can cascade status to the payment.

I can imagine it clearly for this Offline gateway: transition from new|processing to completed (if the type === "capture|authorize"), cascade state to completed on the related payment.

WDTY?

Copy link
Copy Markdown
Contributor

@NoResponseMate NoResponseMate Feb 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main problem I see with that is you'd need a matrix of paymentRequest state machines for every factory and paymentRequest type within, which might get messy fast.
Let's say we have 3 factories, each having 4 steps per payment (4 different types of requests), I'd assume you'd need 12 state machines to process the payment's state correctly since each factory can change the state of payment differently per type.
Having to set it manually is maybe annoying, but at least the person implementing it can be sure what state will be the result and there is no internal magic that can be potentially buggy.

@Prometee Prometee force-pushed the payment-request branch 3 times, most recently from be9dc0a to a3fa5a7 Compare February 22, 2024 22:31
@Prometee Prometee self-assigned this Feb 23, 2024
@Prometee Prometee changed the title [WIP] [API] Add Payment request [API] Add Payment request Feb 28, 2024
Copy link
Copy Markdown
Member

@diimpp diimpp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes is due PaymentRequest/Payum/Checker/PayumRequirementsChecker, looks like this system needs to be refactored. (#15502 (comment))

Prometee and others added 8 commits February 28, 2024 20:06
Co-authored-by: Dmitri Perunov <diimpp@gmail.com>
Co-authored-by: Dmitri Perunov <diimpp@gmail.com>
Co-authored-by: Dmitri Perunov <diimpp@gmail.com>
@Prometee
Copy link
Copy Markdown
Contributor Author

Request changes is due PaymentRequest/Payum/Checker/PayumRequirementsChecker, looks like this system needs to be refactored. (#15502 (comment))

I refactored it, thank you very much for your review @diimpp !

count: 1
path: src/Sylius/Bundle/ApiBundle/CommandHandler/Checkout/UpdateCartHandler.php

-
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general it would be good to apply rule that we can only remove from the baseline, not add to it. We can either fix it (preferable option) or write ignore for some type of problem

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally agree, I only add what other existing rules were doing like the one for the repositories for example, the rest are needed exclusion for mixed data.

$response = $this->client->show(Resources::ORDERS, $this->sharedStorage->get('cart_token'));
Assert::same($this->client->getLastResponse()->getStatusCode(), 200);

// If the payment is canceled we won't be able to retrieve it because only new one are retrievable
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we eventaully change it and just return cancelled payments as well. Or allow to fetch them with filtration

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the payment state of the Order is canceled then it's a final state (sylius_order_payment graph):
sylius_order_payment

We don't need to retrieve payment when the order itself is canceled.

Having a way to get access to all payments related to an order can be something that developers will want, but the current behaviour is fine IMHO.

) {
}

public function check(PaymentRequestHashAwareInterface $command): PaymentRequestInterface
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced about naming of this service. It should check something, but it mostly asserts and provides request from command

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, since it mainly retrieve a PaymentRequest it can be named "Provider".
@lchrusciel What about PaymentRequestProvider and divide the actual method to 2 methods : provideFromCommand and provideFromHash ?


public function add(PaymentRequestInterface $paymentRequest): void
{
$this->paymentRequestRepository->add($paymentRequest);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logic will persist new object and commit transaction. Do we really want to do it at this stage? Shouldn't we rather just persist it and depend on flushing around command bus?

All in all, maybe this logic should be based more on commands?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To some extend logic in this class could be simplify to one function, where we will always persist() on object manager

Copy link
Copy Markdown
Contributor Author

@Prometee Prometee Feb 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading the code of promotion catalog, I see how to solve this.
Lets just make the same as here : https://github.com/Sylius/Sylius/blob/1.13/src/Sylius/Bundle/ApiBundle/CommandHandler/Catalog/AddProductReviewHandler.php#L68
And then I will add an event subscriber like this one dispatching the commands :
https://github.com/Sylius/Sylius/blob/1.13/src/Sylius/Bundle/ApiBundle/EventSubscriber/CatalogPromotionEventSubscriber.php#L47


$command = $this->paymentRequestCommandProvider->provide($paymentRequest);

$this->commandBus->dispatch($command);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should dispatch command after flushing the transaction as we are processing it on async queue

Copy link
Copy Markdown
Contributor Author

@Prometee Prometee Feb 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved by comment above

use Sylius\Component\Payment\Repository\PaymentRequestRepositoryInterface;
use Symfony\Component\Messenger\MessageBusInterface;

final class PaymentRequestCommandDispatcher implements PaymentRequestCommandDispatcherInterface
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to rethink this class name. Maybe some saver or something like that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catalog promotion called this kind of class "Announcer" WDYT ?

}

$paymentRequest->setResponseData($responseData);
$paymentRequest->setState(PaymentRequestInterface::STATE_COMPLETED);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe therefore we should change function to somethin like $paymentRequest->complete()?

use Sylius\Component\Payment\Model\PaymentRequestInterface;
use Sylius\Component\Payment\PaymentTransitions;

final class AfterCaptureProcessor implements AfterCaptureProcessorInterface
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the main idea behind splitting capture into normal and after? If I see correctly, we always trigger both of them

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I wanted to split those two but it's not required.

@NoResponseMate NoResponseMate changed the base branch from 1.13 to payment-request March 1, 2024 14:46
@NoResponseMate NoResponseMate deleted the branch Sylius:payment-request March 1, 2024 15:25
@NoResponseMate
Copy link
Copy Markdown
Contributor

Before someone asks why was it closed.
I have no idea.
Github has outages at the moment and it might be related to that, I'll try to reopen it when it stabilizes.
On the off chance it won't be possible, we'll go with a new PR and link this one in the description.

@Prometee Prometee mentioned this pull request Mar 4, 2024
TheMilek added a commit that referenced this pull request Mar 5, 2024
This PR was merged into the payment-request branch.

Discussion
----------

| Q               | A                                                            |
|-----------------|--------------------------------------------------------------|
| Branch?         | payment-request                 |
| Bug fix?        | no                                                       |
| New feature?    | yes                                                       |
| BC breaks?      | no                                                       |
| Deprecations?   | no |
| Related tickets |        #15502               |
| License         | MIT                                                          |


Commits
-------
  Add Payment request model
  Add API resource
  Add first step of a PAYUM Capture request
  Finalise Payum POC and 1st try with no Payum using Offline payment method
  Rename data to payload
  Rename input/output data to requestPayload/responseData
  Move Payum stuff to PayumBundle
  Move services from ApiBundle to PaymentBundle
  Move services from ApiBundle to PayumBundle
  Update field in migration
  Add validation on adding payment request
  Behat api scenario for PayPal
  Attempt to get a real object instead of proxy one
  Pay with PayPal via authorize working
  Refactor some repeated processes and fix ECS
  3/5 behat tests ok
  Behat ecs fix
  @paying_for_order&&@api fully working
  Fix PHPStan real issue and regenrate baseline for the rest
  Fix service definition and use state machine absctraction
  Move Payum related integrations to a dedicated folder
  Fix composer require checker missing new usages
  Regenerate baseline for PHP8.2 and Sf 6.4
  Fix baseline
  Add missing deps
  Fix old ignore
  Use Sylius abstract doctrine migration to allow PostgreSQL
  Create migration for PostgreSQL
  Add missing messenger buses
  Refactor to use CoreBundle instead of SyliusPay(um|ment)Bundle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API APIs related issues and PRs. Maintenance CI configurations, READMEs, releases, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants