diff --git a/app/code/Magento/Authorizenet/Model/Authorizenet.php b/app/code/Magento/Authorizenet/Model/Authorizenet.php
index b35e4f4c39911df89d553ef98ad77eba768ccf3c..4ad08d89cc495556bd4b5b794417fb7185817d92 100644
--- a/app/code/Magento/Authorizenet/Model/Authorizenet.php
+++ b/app/code/Magento/Authorizenet/Model/Authorizenet.php
@@ -6,6 +6,7 @@
 namespace Magento\Authorizenet\Model;
 
 use Magento\Authorizenet\Model\TransactionService;
+use Magento\Framework\HTTP\ZendClientFactory;
 
 /**
  * @SuppressWarnings(PHPMD.TooManyFields)
@@ -97,6 +98,11 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc
      */
     protected $_debugReplacePrivateDataKeys = ['merchantAuthentication', 'x_login'];
 
+    /**
+     * @var \Magento\Framework\HTTP\ZendClientFactory
+     */
+    protected $httpClientFactory;
+
     /**
      * @param \Magento\Framework\Model\Context $context
      * @param \Magento\Framework\Registry $registry
@@ -111,6 +117,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc
      * @param \Magento\Authorizenet\Model\Request\Factory $requestFactory
      * @param \Magento\Authorizenet\Model\Response\Factory $responseFactory
      * @param \Magento\Authorizenet\Model\TransactionService $transactionService
+     * @param \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory
      * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
      * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
      * @param array $data
@@ -130,6 +137,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc
         \Magento\Authorizenet\Model\Request\Factory $requestFactory,
         \Magento\Authorizenet\Model\Response\Factory $responseFactory,
         TransactionService $transactionService,
+        ZendClientFactory $httpClientFactory,
         \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
         array $data = []
@@ -138,6 +146,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc
         $this->requestFactory = $requestFactory;
         $this->responseFactory = $responseFactory;
         $this->transactionService = $transactionService;
+        $this->httpClientFactory = $httpClientFactory;
 
         parent::__construct(
             $context,
@@ -370,7 +379,8 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc
     protected function postRequest(\Magento\Authorizenet\Model\Request $request)
     {
         $result = $this->responseFactory->create();
-        $client = new \Magento\Framework\HTTP\ZendClient();
+        /** @var \Magento\Framework\HTTP\ZendClient $client */
+        $client = $this->httpClientFactory->create();
         $url = $this->getConfigData('cgi_url') ?: self::CGI_URL;
         $debugData = ['url' => $url, 'request' => $request->getData()];
         $client->setUri($url);
diff --git a/app/code/Magento/Authorizenet/Model/Directpost.php b/app/code/Magento/Authorizenet/Model/Directpost.php
index bbfcd0f7d6e128fb7d0e5d0740223ef42282c469..68fd630f21f4593740fed6288e3821b87677d7db 100644
--- a/app/code/Magento/Authorizenet/Model/Directpost.php
+++ b/app/code/Magento/Authorizenet/Model/Directpost.php
@@ -6,6 +6,7 @@
 namespace Magento\Authorizenet\Model;
 
 use Magento\Authorizenet\Model\TransactionService;
+use Magento\Framework\HTTP\ZendClientFactory;
 use Magento\Payment\Model\Method\ConfigInterface;
 use Magento\Payment\Model\Method\TransparentInterface;
 use Magento\Sales\Model\Order\Email\Sender\OrderSender;
@@ -132,6 +133,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
      * @param Directpost\Request\Factory $requestFactory
      * @param Directpost\Response\Factory $responseFactory
      * @param \Magento\Authorizenet\Model\TransactionService $transactionService
+     * @param \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory
      * @param \Magento\Sales\Model\OrderFactory $orderFactory
      * @param \Magento\Store\Model\StoreManagerInterface $storeManager
      * @param \Magento\Quote\Model\QuoteRepository $quoteRepository
@@ -156,6 +158,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
         \Magento\Authorizenet\Model\Directpost\Request\Factory $requestFactory,
         \Magento\Authorizenet\Model\Directpost\Response\Factory $responseFactory,
         TransactionService $transactionService,
+        ZendClientFactory $httpClientFactory,
         \Magento\Sales\Model\OrderFactory $orderFactory,
         \Magento\Store\Model\StoreManagerInterface $storeManager,
         \Magento\Quote\Model\QuoteRepository $quoteRepository,
@@ -187,6 +190,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
             $requestFactory,
             $responseFactory,
             $transactionService,
+            $httpClientFactory,
             $resource,
             $resourceCollection,
             $data
@@ -404,9 +408,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra
                     if ($result->getXTransId() != $payment->getParentTransactionId()) {
                         $payment->setTransactionId($result->getXTransId());
                     }
-                    $shouldCloseCaptureTransaction = $payment->getOrder()->canCreditmemo() ? 0 : 1;
-                    $payment->setIsTransactionClosed(1)
-                        ->setShouldCloseParentTransaction($shouldCloseCaptureTransaction)
+                    $payment->setIsTransactionClosed(true)
                         ->setTransactionAdditionalInfo(self::REAL_TRANSACTION_ID_KEY, $result->getXTransId());
                     return $this;
                 }
diff --git a/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php b/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php
index 3247ed2cb9329f86e0efda4e07aeae938515f05b..f2203f2fbe1f2bcd7cefa5e2fbf9a8955b1fc24a 100644
--- a/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php
+++ b/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php
@@ -9,6 +9,9 @@ use Magento\Framework\Simplexml\Element;
 use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
 use Magento\Authorizenet\Model\Directpost;
 use Magento\Authorizenet\Model\TransactionService;
+use Magento\Authorizenet\Model\Request;
+use Magento\Authorizenet\Model\Directpost\Request\Factory;
+use Magento\Sales\Model\Order;
 use Magento\Sales\Model\Order\Payment\Transaction\Repository as TransactionRepository;
 
 /**
@@ -16,6 +19,10 @@ use Magento\Sales\Model\Order\Payment\Transaction\Repository as TransactionRepos
  */
 class DirectpostTest extends \PHPUnit_Framework_TestCase
 {
+    const TOTAL_AMOUNT = 100.02;
+    const INVOICE_NUM = '00000001';
+    const TRANSACTION_ID = '41a23x34fd124';
+
     /**
      * @var \Magento\Authorizenet\Model\Directpost
      */
@@ -56,6 +63,16 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase
      */
     protected $transactionServiceMock;
 
+    /**
+     * @var \Magento\Framework\HTTP\ZendClient|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $httpClientMock;
+
+    /**
+     * @var \Magento\Authorizenet\Model\Directpost\Request\Factory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $requestFactory;
+
     protected function setUp()
     {
         $this->scopeConfigMock = $this->getMockBuilder('Magento\Framework\App\Config\ScopeConfigInterface')
@@ -64,7 +81,8 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->setMethods([
                 'getOrder', 'getId', 'setAdditionalInformation', 'getAdditionalInformation',
-                'setIsTransactionDenied', 'setIsTransactionClosed'
+                'setIsTransactionDenied', 'setIsTransactionClosed', 'decrypt', 'getCcLast4',
+                'getParentTransactionId', 'getPoNumber'
             ])
             ->getMock();
         $this->dataHelperMock = $this->getMockBuilder('Magento\Authorizenet\Helper\Data')
@@ -85,15 +103,20 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase
             ->setMethods(['getTransactionDetails'])
             ->getMock();
 
+        $this->requestFactory = $this->getRequestFactoryMock();
+        $httpClientFactoryMock = $this->getHttpClientFactoryMock();
+
         $helper = new ObjectManagerHelper($this);
         $this->directpost = $helper->getObject(
             'Magento\Authorizenet\Model\Directpost',
             [
                 'scopeConfig' => $this->scopeConfigMock,
                 'dataHelper' => $this->dataHelperMock,
+                'requestFactory' => $this->requestFactory,
                 'responseFactory' => $this->responseFactoryMock,
                 'transactionRepository' => $this->transactionRepositoryMock,
-                'transactionService' => $this->transactionServiceMock
+                'transactionService' => $this->transactionServiceMock,
+                'httpClientFactory' => $httpClientFactoryMock
             ]
         );
     }
@@ -376,7 +399,7 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @covers \Magento\Authorizenet\Model\Directpost::fetchTransactionInfo
+     * @covers       \Magento\Authorizenet\Model\Directpost::fetchTransactionInfo
      *
      * @param $transactionId
      * @param $resultStatus
@@ -440,6 +463,72 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase
         $this->directpost->fetchTransactionInfo($this->paymentMock, $transactionId);
     }
 
+    /**
+     * @covers \Magento\Authorizenet\Model\Directpost::refund()
+     * @return void
+     */
+    public function testSuccessRefund()
+    {
+        $card = 1111;
+
+        $this->paymentMock->expects(static::exactly(2))
+            ->method('getCcLast4')
+            ->willReturn($card);
+        $this->paymentMock->expects(static::once())
+            ->method('decrypt')
+            ->willReturn($card);
+        $this->paymentMock->expects(static::exactly(3))
+            ->method('getParentTransactionId')
+            ->willReturn(self::TRANSACTION_ID . '-capture');
+        $this->paymentMock->expects(static::once())
+            ->method('getPoNumber')
+            ->willReturn(self::INVOICE_NUM);
+        $this->paymentMock->expects(static::once())
+            ->method('setIsTransactionClosed')
+            ->with(true)
+            ->willReturnSelf();
+
+        $orderMock = $this->getOrderMock();
+
+        $this->paymentMock->expects(static::exactly(2))
+            ->method('getOrder')
+            ->willReturn($orderMock);
+
+        $transactionMock = $this->getMockBuilder(Order\Payment\Transaction::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getAdditionalInformation'])
+            ->getMock();
+        $transactionMock->expects(static::once())
+            ->method('getAdditionalInformation')
+            ->with(Directpost::REAL_TRANSACTION_ID_KEY)
+            ->willReturn(self::TRANSACTION_ID);
+
+        $this->transactionRepositoryMock->expects(static::once())
+            ->method('getByTransactionId')
+            ->willReturn($transactionMock);
+
+        $response = $this->getRefundResponseBody(
+            Directpost::RESPONSE_CODE_APPROVED,
+            Directpost::RESPONSE_REASON_CODE_APPROVED,
+            'Successful'
+        );
+        $this->httpClientMock->expects(static::once())
+            ->method('getBody')
+            ->willReturn($response);
+
+        $this->responseMock->expects(static::once())
+            ->method('getXResponseCode')
+            ->willReturn(Directpost::RESPONSE_CODE_APPROVED);
+        $this->responseMock->expects(static::once())
+            ->method('getXResponseReasonCode')
+            ->willReturn(Directpost::RESPONSE_REASON_CODE_APPROVED);
+
+        $this->dataHelperMock->expects(static::never())
+            ->method('wrapGatewayError');
+
+        $this->directpost->refund($this->paymentMock, self::TOTAL_AMOUNT);
+    }
+
     /**
      * Get data for tests
      * @return array
@@ -468,14 +557,48 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase
         $this->responseMock = $this->getMockBuilder('Magento\Authorizenet\Model\Directpost\Response')
             ->setMethods(
                 [
-                    'setData', 'isValidHash', 'getXTransId',
-                    'getXResponseCode', 'getXResponseReasonText',
-                    'getXAmount'
+                    'isValidHash',
+                    'getXTransId', 'getXResponseCode', 'getXResponseReasonCode', 'getXResponseReasonText', 'getXAmount',
+                    'setXResponseCode', 'setXResponseReasonCode', 'setXAvsCode', 'setXResponseReasonText',
+                    'setXTransId', 'setXInvoiceNum', 'setXAmount', 'setXMethod', 'setXType', 'setData',
+                    'setXAccountNumber',
+                    '__wakeup'
                 ]
             )
             ->disableOriginalConstructor()
             ->getMock();
 
+        $this->responseMock->expects(static::any())
+            ->method('setXResponseCode')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setXResponseReasonCode')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setXResponseReasonText')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setXAvsCode')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setXTransId')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setXInvoiceNum')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setXAmount')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setXMethod')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setXType')
+            ->willReturnSelf();
+        $this->responseMock->expects(static::any())
+            ->method('setData')
+            ->willReturnSelf();
+
         $this->responseFactoryMock->expects($this->any())
             ->method('create')
             ->willReturn($this->responseMock);
@@ -530,4 +653,105 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase
         libxml_use_internal_errors(false);
         return $document;
     }
+
+    /**
+     * Get mock for authorize.net request factory
+     * @return \PHPUnit_Framework_MockObject_MockBuilder
+     */
+    private function getRequestFactoryMock()
+    {
+        $requestFactory = $this->getMockBuilder(Factory::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $request = $this->getMockBuilder(Request::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['__wakeup'])
+            ->getMock();
+        $requestFactory->expects(static::any())
+            ->method('create')
+            ->willReturn($request);
+        return $requestFactory;
+    }
+
+    /**
+     * Get mock for order
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getOrderMock()
+    {
+        $orderMock = $this->getMockBuilder(Order::class)
+            ->disableOriginalConstructor()
+            ->setMethods([
+                'getId', 'getIncrementId', 'getStoreId', 'getBillingAddress', 'getShippingAddress',
+                'getBaseCurrencyCode', 'getBaseTaxAmount', '__wakeup'
+            ])
+            ->getMock();
+
+        $orderMock->expects(static::once())
+            ->method('getId')
+            ->willReturn(1);
+
+        $orderMock->expects(static::exactly(2))
+            ->method('getIncrementId')
+            ->willReturn(self::INVOICE_NUM);
+
+        $orderMock->expects(static::once())
+            ->method('getStoreId')
+            ->willReturn(1);
+
+        $orderMock->expects(static::once())
+            ->method('getBaseCurrencyCode')
+            ->willReturn('USD');
+        return $orderMock;
+    }
+
+    /**
+     * Create and return mock for http client factory
+     * @return \PHPUnit_Framework_MockObject_MockObject
+     */
+    private function getHttpClientFactoryMock()
+    {
+        $this->httpClientMock = $this->getMockBuilder(\Magento\Framework\HTTP\ZendClient::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['request', 'getBody', '__wakeup'])
+            ->getMock();
+
+        $this->httpClientMock->expects(static::any())
+            ->method('request')
+            ->willReturnSelf();
+
+        $httpClientFactoryMock = $this->getMockBuilder(\Magento\Framework\HTTP\ZendClientFactory::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $httpClientFactoryMock->expects(static::any())
+            ->method('create')
+            ->willReturn($this->httpClientMock);
+        return $httpClientFactoryMock;
+    }
+
+    /**
+     * Get mocked response for refund transaction
+     * @param $code
+     * @param $reasonCode
+     * @param $reasonText
+     * @return string
+     */
+    private function getRefundResponseBody($code, $reasonCode, $reasonText)
+    {
+        $result = array_fill(0, 50, '');
+        $result[0] = $code; // XResponseCode
+        $result[2] = $reasonCode; // XResponseReasonCode
+        $result[3] = $reasonText; // XResponseReasonText
+        $result[6] = self::TRANSACTION_ID; // XTransId
+        $result[7] = self::INVOICE_NUM; // XInvoiceNum
+        $result[9] = self::TOTAL_AMOUNT; // XAmount
+        $result[10] = Directpost::REQUEST_METHOD_CC; // XMethod
+        $result[11] = Directpost::REQUEST_TYPE_CREDIT; // XType
+        $result[37] = md5(self::TRANSACTION_ID); // x_MD5_Hash
+        $result[50] = '48329483921'; // setXAccountNumber
+        return implode(Directpost::RESPONSE_DELIM_CHAR, $result);
+    }
 }
diff --git a/app/code/Magento/Braintree/Model/PaymentMethod.php b/app/code/Magento/Braintree/Model/PaymentMethod.php
index 45171956e87bcf8832723f7b7dffeb90ea5f1f79..7b045d5dcde6eb43b1b1cf37419728a7594fe0aa 100644
--- a/app/code/Magento/Braintree/Model/PaymentMethod.php
+++ b/app/code/Magento/Braintree/Model/PaymentMethod.php
@@ -657,7 +657,6 @@ class PaymentMethod extends \Magento\Payment\Model\Method\Cc
                 : $this->braintreeTransaction->refund($transactionId, $amount);
             $this->_debug($this->_convertObjToArray($result));
             if ($result->success) {
-                $payment->setTransactionId($transactionId . '-' . Transaction::TYPE_REFUND);
                 $payment->setIsTransactionClosed(true);
             } else {
                 throw new LocalizedException($this->errorHelper->parseBraintreeError($result));
diff --git a/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php b/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php
index e20af765062e3b3b0713c5732d5b67f8f3c279f3..9e90e201f6b85d8062be2784947c7bef3ada301c 100644
--- a/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php
+++ b/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php
@@ -2379,7 +2379,6 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase
 
         $this->model->refund($paymentObject, $amount);
         $this->assertEquals(1, $paymentObject->getIsTransactionClosed());
-        $this->assertEquals($refundTransactionId . '-' .Transaction::TYPE_REFUND, $paymentObject->getTransactionId());
     }
 
     /**
diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php
index 6efc7e7cca4ed1735aeeaaacc8deee09aaf18eb1..894c0792a99e4ab689f5c40aed6b0d29c0d334a5 100644
--- a/app/code/Magento/Paypal/Model/Payflowpro.php
+++ b/app/code/Magento/Paypal/Model/Payflowpro.php
@@ -500,8 +500,7 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc implements GatewayInte
         $this->processErrors($response);
 
         if ($response->getResultCode() == self::RESPONSE_CODE_APPROVED) {
-            $payment->setTransactionId($response->getPnref())->setIsTransactionClosed(1);
-            $payment->setShouldCloseParentTransaction(!$payment->getCreditmemo()->getInvoice()->canRefund());
+            $payment->setTransactionId($response->getPnref())->setIsTransactionClosed(true);
         }
         return $this;
     }
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/PayflowproTest.php b/app/code/Magento/Paypal/Test/Unit/Model/PayflowproTest.php
index 215680852225b7b3ed5b4507a223fda725b821b5..c6250a24903ee0e71b30669e762a44c00a3eb06c 100644
--- a/app/code/Magento/Paypal/Test/Unit/Model/PayflowproTest.php
+++ b/app/code/Magento/Paypal/Test/Unit/Model/PayflowproTest.php
@@ -175,7 +175,6 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase
         $this->payflowpro->fetchTransactionInfo($payment, 'AD49G8N825');
     }
 
-
     /**
      * @param $response
      * @dataProvider setTransStatusDataProvider
@@ -323,6 +322,22 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase
         ];
     }
 
+    /**
+     * @covers \Magento\Paypal\Model\Payflowpro::refund()
+     */
+    public function testRefund()
+    {
+        /** @var \Magento\Sales\Model\Order\Payment $paymentMock */
+        $paymentMock = $this->getPaymentMock();
+
+        $response = $this->execGatewayRequest();
+
+        $amount = 213.04;
+        $this->payflowpro->refund($paymentMock, $amount);
+        static::assertEquals($response['pnref'], $paymentMock->getTransactionId());
+        static::assertTrue($paymentMock->getIsTransactionClosed());
+    }
+
     /**
      * Create mock object for store model
      * @return void
@@ -399,16 +414,16 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase
             'year' => 18,
             'cvv' => 123
         ];
-        $paymentMock->expects(static::once())
+        $paymentMock->expects(static::any())
             ->method('getCcNumber')
             ->willReturn($cardData['number']);
-        $paymentMock->expects(static::once())
+        $paymentMock->expects(static::any())
             ->method('getCcExpMonth')
             ->willReturn($cardData['month']);
-        $paymentMock->expects(static::once())
+        $paymentMock->expects(static::any())
             ->method('getCcExpYear')
             ->willReturn($cardData['year']);
-        $paymentMock->expects(static::once())
+        $paymentMock->expects(static::any())
             ->method('getCcCid')
             ->willReturn($cardData['cvv']);
         return $paymentMock;
diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php
index 690bde68d5c575ece27f56d68165d1ccf31bc7d5..885838781eecfe282ba6c1889c9dcfb6b932b6ec 100644
--- a/app/code/Magento/Sales/Model/Order/Payment.php
+++ b/app/code/Magento/Sales/Model/Order/Payment.php
@@ -139,7 +139,8 @@ class Payment extends Info implements OrderPaymentInterface
         \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
         \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
         array $data = []
-    ) {
+    )
+    {
         $this->priceCurrency = $priceCurrency;
         $this->creditmemoFactory = $creditmemoFactory;
         $this->transactionRepository = $transactionRepository;
@@ -629,7 +630,7 @@ class Payment extends Info implements OrderPaymentInterface
                     $this->getOrder()->getId()
                 );
                 if ($captureTxn) {
-                    $this->setParentTransactionId($captureTxn->getTxnId());
+                    $this->setTransactionIdsForRefund($captureTxn);
                 }
                 $this->setShouldCloseParentTransaction(true);
                 // TODO: implement multiple refunds per capture
@@ -638,10 +639,7 @@ class Payment extends Info implements OrderPaymentInterface
                         $this->getOrder()->getStoreId()
                     );
                     $this->setRefundTransactionId($invoice->getTransactionId());
-                    $gateway->refund(
-                        $this,
-                        $baseAmountToRefund
-                    );
+                    $gateway->refund($this, $baseAmountToRefund);
 
                     $creditmemo->setTransactionId($this->getLastTransId());
                 } catch (\Magento\Framework\Exception\LocalizedException $e) {
@@ -2414,5 +2412,24 @@ class Payment extends Info implements OrderPaymentInterface
         return (bool)$this->getData('should_close_parent_transaction');
     }
 
+    /**
+     * Set payment parent transaction id and current transaction id if it not set
+     * @param Transaction $transaction
+     * @return void
+     */
+    private function setTransactionIdsForRefund(Transaction $transaction)
+    {
+        if (!$this->getTransactionId()) {
+            $this->setTransactionId(
+                $this->transactionManager->generateTransactionId(
+                    $this,
+                    Transaction::TYPE_REFUND,
+                    $transaction
+                )
+            );
+        }
+        $this->setParentTransactionId($transaction->getTxnId());
+    }
+
     //@codeCoverageIgnoreEnd
 }
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php
index 29757fc570f2380410376d09d3ca137062ffad9d..e9b65325df8831bfebcf4e91f033e5f297133888 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php
@@ -17,6 +17,8 @@ use Magento\Sales\Model\Order\Payment\Transaction;
  */
 class PaymentTest extends \PHPUnit_Framework_TestCase
 {
+    const TRANSACTION_ID = 'ewr34fM49V0';
+
     private $mockContext;
     /**
      * @var Payment
@@ -166,6 +168,7 @@ class PaymentTest extends \PHPUnit_Framework_TestCase
                     'order',
                     'isInitializeNeeded',
                     'initialize',
+                    'refund'
                 ]
             )
             ->getMock();
@@ -258,7 +261,10 @@ class PaymentTest extends \PHPUnit_Framework_TestCase
                 'register',
                 'addComment',
                 'save',
-                'getGrandTotal'
+                'getGrandTotal',
+                'getBaseGrandTotal',
+                'getDoTransaction',
+                'getInvoice'
             ],
             [],
             '',
@@ -268,7 +274,7 @@ class PaymentTest extends \PHPUnit_Framework_TestCase
         $this->payment = $this->initPayment();
         $this->payment->setMethod('any');
         $this->payment->setOrder($this->orderMock);
-        $this->transactionId = 100;
+        $this->transactionId = self::TRANSACTION_ID;
     }
 
     protected function tearDown()
@@ -825,13 +831,13 @@ class PaymentTest extends \PHPUnit_Framework_TestCase
      */
     protected function mockInvoice($transactionId, $countCall = 1)
     {
-        $this->invoiceMock->expects($this->once())
+        $this->invoiceMock->expects(static::any())
             ->method('getTransactionId')
             ->willReturn($transactionId);
-        $this->invoiceMock->expects($this->once())
+        $this->invoiceMock->expects(static::any())
             ->method('load')
             ->with($transactionId);
-        $this->invoiceMock->expects($this->once())
+        $this->invoiceMock->expects(static::any())
             ->method('getId')
             ->willReturn($transactionId);
         $this->orderMock->expects($this->exactly($countCall))
@@ -1314,7 +1320,8 @@ class PaymentTest extends \PHPUnit_Framework_TestCase
      */
     public function testRegisterRefundNotification()
     {
-        $message = 'Registered notification about refunded amount of . Transaction ID: "100-refund"';
+        $message = 'Registered notification about refunded amount of . Transaction ID: "' .
+            self::TRANSACTION_ID . '-refund"';
         $amount = 50;
         $grandTotalCreditMemo = 50;
         $invoiceBaseGrandTotal = 50;
@@ -1429,6 +1436,73 @@ class PaymentTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($canRefund, $this->payment->canRefund());
     }
 
+    /**
+     * @covers \Magento\Sales\Model\Order\Payment::refund()
+     */
+    public function testRefund()
+    {
+        $amount = 204.04;
+        $this->creditMemoMock->expects(static::once())
+            ->method('getBaseGrandTotal')
+            ->willReturn($amount);
+        $this->creditMemoMock->expects(static::once())
+            ->method('getGrandTotal')
+            ->willReturn($amount);
+        $this->creditMemoMock->expects(static::once())
+            ->method('getDoTransaction')
+            ->willReturn(true);
+
+        $this->paymentMethodMock->expects(static::once())
+            ->method('canRefund')
+            ->willReturn(true);
+
+        $this->mockInvoice(self::TRANSACTION_ID, 0);
+        $this->creditMemoMock->expects(static::once())
+            ->method('getInvoice')
+            ->willReturn($this->invoiceMock);
+
+        $captureTranId = self::TRANSACTION_ID . '-' . Transaction::TYPE_CAPTURE;
+        $captureTransaction = $this->getMockBuilder(Transaction::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['getTxnId'])
+            ->getMock();
+
+        $refundTranId = $captureTranId . '-' . Transaction::TYPE_REFUND;
+        $this->transactionManagerMock->expects(static::once())
+            ->method('generateTransactionId')
+            ->willReturn($refundTranId);
+        $captureTransaction->expects(static::once())
+            ->method('getTxnId')
+            ->willReturn($captureTranId);
+        $this->transactionRepositoryMock->expects(static::once())
+            ->method('getByTransactionId')
+            ->willReturn($captureTransaction);
+
+        $this->paymentMethodMock->expects(static::once())
+            ->method('refund')
+            ->with($this->payment, $amount);
+
+        $isOnline = true;
+        $this->getTransactionBuilderMock([], $isOnline, Transaction::TYPE_REFUND, $refundTranId);
+
+        $this->currencyMock->expects(static::once())
+            ->method('formatTxt')
+            ->willReturn($amount);
+        $this->orderMock->expects(static::once())
+            ->method('getBaseCurrency')
+            ->willReturn($this->currencyMock);
+
+        $status = 'status';
+        $message = 'We refunded ' . $amount . ' online. Transaction ID: "' . $refundTranId . '"';
+        $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $status);
+        $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, $message);
+
+        static::assertSame($this->payment, $this->payment->refund($this->creditMemoMock));
+        static::assertEquals($amount, $this->payment->getData('amount_refunded'));
+        static::assertEquals($amount, $this->payment->getData('base_amount_refunded_online'));
+        static::assertEquals($amount, $this->payment->getData('base_amount_refunded'));
+    }
+
     public function boolProvider()
     {
         return [