Skip to content
This repository has been archived by the owner on Dec 19, 2019. It is now read-only.

GraphQl-644: [Checkout] Support of "Braintree" payment method #392

Merged
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
93b08f6
Prototype BraintreeGraphQl Payments
pmclain Feb 23, 2019
7f226f6
Merge remote-tracking branch 'origin/2.3-develop' into feature/braint…
naydav Mar 6, 2019
c7fd250
Merge remote-tracking branch 'upstream/2.3-develop' into feature/brai…
pmclain May 17, 2019
a59a919
Braintree CC and Vault Support and Tests
pmclain May 21, 2019
411a559
Merge remote-tracking branch 'upstream/2.3-develop' into feature/brai…
pmclain Jun 15, 2019
a784526
Add braintree mock for testing
pmclain Jun 16, 2019
5f25fdd
fix static test failures
pmclain Jun 18, 2019
4527ea2
Merge remote-tracking branch 'upstream/2.3-develop' into feature/brai…
pmclain Jun 21, 2019
d57d076
Merge remote-tracking branch 'upstream/2.3-develop' into feature/brai…
pmclain Jun 28, 2019
05632a8
Move Method Specific input into PaymentMethodInput
pmclain Jun 28, 2019
3720ec0
Revert error reporting change committed by mistake
pmclain Jul 8, 2019
a6e32e8
Mutation for creating braintree client token
pmclain Jul 9, 2019
c4609cc
Generate nonce from public hash server-side
pmclain Jul 9, 2019
c1eee4f
Merge remote-tracking branch 'upstream/2.3-develop' into feature/brai…
pmclain Jul 14, 2019
4939d9c
Validate additional input is present for associated payment method
pmclain Jul 14, 2019
ba459a1
Merge remote-tracking branch 'upstream/2.3-develop' into feature/brai…
pmclain Jul 23, 2019
fe23996
Add validation for additonal data input
pmclain Jul 24, 2019
2448894
Merge remote-tracking branch 'upstream/2.3-develop' into feature/brai…
pmclain Jul 24, 2019
c552e35
Add parent-compatible typehint to constructor docblock
pmclain Jul 27, 2019
e49df5b
Merge remote-tracking branch 'upstream/2.3-develop' into feature/brai…
pmclain Jul 30, 2019
169ac1b
Get storeId from resolver context
pmclain Jul 30, 2019
f69b080
Add composer deps to module sequence
pmclain Jul 30, 2019
ec719be
Update php reqs in BraintreeGraphQl composer.json
pmclain Jul 30, 2019
d757fb5
Update tests to use @magentoConfigFixture
pmclain Jul 30, 2019
1132a47
Replace static with self
pmclain Jul 31, 2019
6fc0322
Merge remote-tracking branch 'origin/2.3-develop' into feature/braint…
naydav Aug 4, 2019
00002f4
magento/graphql-ce#644: [Checkout] Support of "Braintree" payment method
naydav Aug 4, 2019
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
49 changes: 49 additions & 0 deletions app/code/Magento/BraintreeGraphQl/Model/BraintreeDataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\BraintreeGraphQl\Model;

use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\QuoteGraphQl\Model\Cart\Payment\AdditionalDataProviderInterface;

/**
* Format Braintree input into value expected when setting payment method
*/
class BraintreeDataProvider implements AdditionalDataProviderInterface
{
private const PATH_ADDITIONAL_DATA = 'braintree';

/**
* Format Braintree input into value expected when setting payment method
*
* @param array $args
* @return array
* @throws GraphQlInputException
*/
public function getData(array $args): array
{
if (!isset($args[self::PATH_ADDITIONAL_DATA])) {
throw new GraphQlInputException(
__('Required parameter "braintree" for "payment_method" is missing.')
);
}

if (!isset($args[self::PATH_ADDITIONAL_DATA]['payment_method_nonce'])) {
throw new GraphQlInputException(
__('Required parameter "payment_method_nonce" for "braintree" is missing.')
);
}

if (!isset($args[self::PATH_ADDITIONAL_DATA]['is_active_payment_token_enabler'])) {
throw new GraphQlInputException(
__('Required parameter "is_active_payment_token_enabler" for "braintree" is missing.')
);
}

return $args[self::PATH_ADDITIONAL_DATA];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\BraintreeGraphQl\Model;

use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\QuoteGraphQl\Model\Cart\Payment\AdditionalDataProviderInterface;

/**
* Format Braintree input into value expected when setting payment method
*/
class BraintreeVaultDataProvider implements AdditionalDataProviderInterface
{
private const PATH_ADDITIONAL_DATA = 'braintree_cc_vault';

/**
* Format Braintree input into value expected when setting payment method
*
* @param array $args
* @return array
*/
public function getData(array $args): array
{
if (!isset($args[self::PATH_ADDITIONAL_DATA])) {
throw new GraphQlInputException(
__('Required parameter "braintree_cc_vault" for "payment_method" is missing.')
);
}

if (!isset($args[self::PATH_ADDITIONAL_DATA]['public_hash'])) {
throw new GraphQlInputException(
__('Required parameter "public_hash" for "braintree_cc_vault" is missing.')
);
}

return $args[self::PATH_ADDITIONAL_DATA];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\BraintreeGraphQl\Model\Resolver;

use Magento\Braintree\Gateway\Config\Config;
use Magento\Braintree\Gateway\Request\PaymentDataBuilder;
use Magento\Braintree\Model\Adapter\BraintreeAdapterFactory;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Store\Model\StoreManagerInterface;

/**
* Resolver for generating Braintree client token
*/
class CreateBraintreeClientToken implements ResolverInterface
{
/**
* @var Config
*/
private $config;

/**
* @var BraintreeAdapterFactory
*/
private $adapterFactory;

/**
* @param Config $config
* @param BraintreeAdapterFactory $adapterFactory
*/
public function __construct(
Config $config,
BraintreeAdapterFactory $adapterFactory
) {
$this->config = $config;
$this->adapterFactory = $adapterFactory;
}

/**
* @inheritdoc
*/
public function resolve(
Field $field,
$context,
ResolveInfo $info,
array $value = null,
array $args = null
) {
$storeId = (int)$context->getExtensionAttributes()->getStore()->getId();

if (!$this->config->isActive($storeId)) {
throw new GraphQlInputException(__('The Braintree payment method is not active.'));
}

$params = [];
$merchantAccountId = $this->config->getMerchantAccountId($storeId);
if (!empty($merchantAccountId)) {
$params[PaymentDataBuilder::MERCHANT_ACCOUNT_ID] = $merchantAccountId;
}

return $this->adapterFactory->create($storeId)->generate($params);
}
}
79 changes: 79 additions & 0 deletions app/code/Magento/BraintreeGraphQl/Plugin/SetVaultPaymentNonce.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\BraintreeGraphQl\Plugin;

use Magento\Braintree\Gateway\Command\GetPaymentNonceCommand;
use Magento\Braintree\Model\Ui\ConfigProvider;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Psr\Log\LoggerInterface;

/**
* Plugin creating nonce from Magento Vault Braintree public hash
*/
class SetVaultPaymentNonce
{
/**
* @var GetPaymentNonceCommand
*/
private $command;

/**
* @var LoggerInterface
*/
private $logger;

/**
* @param GetPaymentNonceCommand $command
* @param LoggerInterface $logger
*/
public function __construct(
GetPaymentNonceCommand $command,
LoggerInterface $logger
) {
$this->command = $command;
$this->logger = $logger;
}

/**
* Set Braintree nonce from public hash
*
* @param \Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart $subject
* @param \Magento\Quote\Model\Quote $quote
* @param array $paymentData
* @return array
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function beforeExecute(
\Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart $subject,
\Magento\Quote\Model\Quote $quote,
array $paymentData
): array {
if ($paymentData['code'] !== ConfigProvider::CC_VAULT_CODE
|| !isset($paymentData[ConfigProvider::CC_VAULT_CODE])
|| !isset($paymentData[ConfigProvider::CC_VAULT_CODE]['public_hash'])
) {
return [$quote, $paymentData];
}

$subject = [
'public_hash' => $paymentData[ConfigProvider::CC_VAULT_CODE]['public_hash'],
'customer_id' => $quote->getCustomerId(),
'store_id' => $quote->getStoreId(),
];

try {
$result = $this->command->execute($subject)->get();
$paymentData[ConfigProvider::CC_VAULT_CODE]['payment_method_nonce'] = $result['paymentMethodNonce'];
} catch (\Exception $e) {
$this->logger->critical($e);
throw new GraphQlInputException(__('Sorry, but something went wrong'));
}

return [$quote, $paymentData];
}
}
4 changes: 4 additions & 0 deletions app/code/Magento/BraintreeGraphQl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# BraintreeGraphQl

**BraintreeGraphQl** provides type and resolver for method additional
information.
28 changes: 28 additions & 0 deletions app/code/Magento/BraintreeGraphQl/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "magento/module-braintree-graph-ql",
"description": "N/A",
"type": "magento2-module",
"require": {
"php": "~7.1.3||~7.2.0||~7.3.0",
"magento/framework": "*",
"magento/module-braintree": "*",
"magento/module-store": "*",
"magento/module-quote": "*",
"magento/module-quote-graph-ql": "*"
},
"suggest": {
"magento/module-graph-ql": "*"
},
"license": [
"OSL-3.0",
"AFL-3.0"
],
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Magento\\BraintreeGraphQl\\": ""
}
}
}
20 changes: 20 additions & 0 deletions app/code/Magento/BraintreeGraphQl/etc/graphql/di.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\QuoteGraphQl\Model\Cart\Payment\AdditionalDataProviderPool">
<arguments>
<argument name="dataProviders" xsi:type="array">
<item name="braintree" xsi:type="object">Magento\BraintreeGraphQl\Model\BraintreeDataProvider</item>
<item name="braintree_cc_vault" xsi:type="object">Magento\BraintreeGraphQl\Model\BraintreeVaultDataProvider</item>
</argument>
</arguments>
</type>
<type name="Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart">
<plugin name="braintree_generate_vault_nonce" type="Magento\BraintreeGraphQl\Plugin\SetVaultPaymentNonce" />
</type>
</config>
17 changes: 17 additions & 0 deletions app/code/Magento/BraintreeGraphQl/etc/module.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magento_BraintreeGraphQl">
<sequence>
<module name="Magento_Braintree"/>
<module name="Magento_Quote"/>
<module name="Magento_Store"/>
<module name="Magento_QuoteGraphQl"/>
</sequence>
</module>
</config>
22 changes: 22 additions & 0 deletions app/code/Magento/BraintreeGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright © Magento, Inc. All rights reserved.
# See COPYING.txt for license details.

type Mutation {
createBraintreeClientToken: String! @resolver(class: "\\Magento\\BraintreeGraphQl\\Model\\Resolver\\CreateBraintreeClientToken") @doc(description:"Creates Braintree Client Token for creating client-side nonce.")
}

input PaymentMethodInput {
braintree: BraintreeInput
braintree_cc_vault: BraintreeCcVaultInput
}

input BraintreeInput {
lenaorobei marked this conversation as resolved.
Show resolved Hide resolved
payment_method_nonce: String!
is_active_payment_token_enabler: Boolean!
device_data: String
}

input BraintreeCcVaultInput {
public_hash: String!
device_data: String
}
10 changes: 10 additions & 0 deletions app/code/Magento/BraintreeGraphQl/registration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_BraintreeGraphQl', __DIR__);
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
"magento/module-backend": "*",
"magento/module-backup": "*",
"magento/module-braintree": "*",
"magento/module-braintree-graph-ql": "*",
"magento/module-bundle": "*",
"magento/module-bundle-graph-ql": "*",
"magento/module-bundle-import-export": "*",
Expand Down
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading