From 275880af7ea3d18121762145de1f5e98bb04671b Mon Sep 17 00:00:00 2001
From: "Nek (Maxime Veber)" <nek.dev@gmail.com>
Date: Tue, 26 May 2020 17:20:00 +0200
Subject: [PATCH] doc: add some doc about online refund

Problem
-------

There is no documentation for actual refund.

Solution
--------

Add some.
---
 README.md              | 23 ++++++------
 docs/online-payment.md | 83 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+), 12 deletions(-)
 create mode 100644 docs/online-payment.md

diff --git a/README.md b/README.md
index af14df25..80cd8864 100644
--- a/README.md
+++ b/README.md
@@ -97,21 +97,20 @@ Configuration of all elements mentioned above can be found and customized in `co
 
 ## Payment requirements
 
-By default to refund your order, you need to have at least one available payment method configured with `offline` gateway.
+By default, to refund your order, you need to have at least one available payment method configured with `offline` gateway.
 In case your custom refund logic allows a different type of gateway (for example `stripe`), you should modify the specific parameter,
 as shown below:
 
-   ```xml
-        <parameters>
-            <parameter key="sylius_refund.supported_gateways" type="collection">
-                <parameter>offline</parameter>
-                <parameter>stripe</parameter>
-            </parameter>
-        </parameters>
-   ```
-
-Online refund logic should be implemented if you need it.
-As the first try for the possible customization, you can check out `Sylius\RefundPlugin\Event\UnitsRefunded` event.
+```xml
+    <parameters>
+        <parameter key="sylius_refund.supported_gateways" type="collection">
+            <parameter>offline</parameter>
+            <parameter>stripe</parameter>
+        </parameter>
+    </parameters>
+```
+
+Learn more in our [dedicated documentation](docs/online-payment.md).
 
 ## Security issues
 
diff --git a/docs/online-payment.md b/docs/online-payment.md
new file mode 100644
index 00000000..ff4e136d
--- /dev/null
+++ b/docs/online-payment.md
@@ -0,0 +1,83 @@
+Online Payment
+==============
+
+If you configured online payment, you probably want as well online refunds. The best way to do the following tasks:
+
+## Add payment methods to the related parameter (examples bellow in XML and YAML)
+
+```yaml
+# services.yaml
+parameters:
+    sylius_refund.supported_gateways:
+        - offline
+        - stripe
+```
+
+```xml
+<!-- services.xml -->
+    <parameters>
+        <parameter key="sylius_refund.supported_gateways" type="collection">
+            <parameter>offline</parameter>
+            <parameter>stripe</parameter>
+        </parameter>
+    </parameters>
+```
+
+## Create your custom handler
+
+Here is an example that binds the refund plugin to payum.
+
+```php
+class RefundPaymentGeneratedHandler
+{
+    private ObjectManager $objectManager;
+    private Payum $payum;
+    private FactoryInterface $stateMachineFactory;
+
+    public function __construct(ObjectManager $objectManager, Payum $payum, FactoryInterface $stateMachineFactory)
+    {
+        $this->objectManager = $objectManager;
+        $this->payum = $payum;
+        $this->stateMachineFactory = $stateMachineFactory;
+    }
+
+    public function __invoke(RefundPaymentGenerated $message): void
+    {
+        $orderRepository = $this->objectManager->getRepository(Order::class);
+        $paymentMethodRepository = $this->objectManager->getRepository(PaymentMethod::class);
+
+        $order = $orderRepository->findOneByNumber($message->orderNumber());
+        $payment = $order->getLastPayment();
+
+        // Notice: the payment method is not obviously the same as the one of the order payment
+        $paymentMethod = $paymentMethodRepository->find($message->paymentMethodId());
+        $gatewayName = $paymentMethod->getCode();
+
+        // Call payum to refund
+        $stripe = $this->payum->getGateway($gatewayName);
+        $reply = $stripe->execute(new Refund([
+            'amount' => $message->amount(),
+            // You may want to add many other information here depending on your refund implementation
+        ]));
+
+        $refundPaymentRepository = $this->objectManager->getRepository(RefundPayment::class);
+        $refundPayment = $refundPaymentRepository->find($message->id());
+
+        // use the state machine of sylius to mark the refund done!
+        $stateMachine = $this->stateMachineFactory->get($refundPayment, RefundPaymentTransitions::GRAPH);
+        $stateMachine->apply(RefundPaymentTransitions::TRANSITION_COMPLETE);
+
+        $this->objectManager->flush();
+    }
+}
+```
+
+Be careful, you need to register this handler against the correct bus, which is the specific event bus of this
+plugin:
+
+```yaml
+# services.yaml
+services:
+    App\MessageHandler\RefundPaymentGeneratedHandler:
+        tags: [{ name: messenger.message_handler, bus: sylius_refund_plugin.event_bus }]
+```