Skip to content

Commit

Permalink
Merge pull request #5 from aune-io/feature/vault_source
Browse files Browse the repository at this point in the history
Feature/vault source
  • Loading branch information
renatocason authored Oct 3, 2018
2 parents 50d5429 + 9017f57 commit 364564f
Show file tree
Hide file tree
Showing 41 changed files with 1,361 additions and 137 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ install:
- composer create-project --repository=https://repo.magento.com magento/marketplace-eqp marketplace-eqp

script:
- php marketplace-eqp/vendor/bin/phpcs Block/ Gateway/ Model/ Observer/ Test/ view/ --standard=MEQP2 --severity=10
- php vendor/bin/phpmd Block/,Gateway/,Model/,Observer/,Test/,view/ text cleancode,codesize,controversial,design,naming,unusedcode --ignore-violations-on-exit
- php marketplace-eqp/vendor/bin/phpcs Block/ Gateway/ Model/ Observer/ Setup/ Test/ view/ --standard=MEQP2 --severity=10
- php vendor/bin/phpmd Block/,Gateway/,Model/,Observer/,Setup/,Test/,view/ text cleancode,codesize,controversial,design,naming,unusedcode --ignore-violations-on-exit
- php vendor/phpunit/phpunit/phpunit --coverage-clover Test/Unit/logs/clover.xml Test

after_script:
Expand Down
3 changes: 3 additions & 0 deletions Block/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use Magento\Payment\Block\Form\Cc;

/**
* @codeCoverageIgnore
*/
class Form extends Cc
{

Expand Down
5 changes: 3 additions & 2 deletions Block/Info.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

use Magento\Payment\Block\ConfigurableInfo;

/**
* @codeCoverageIgnore
*/
class Info extends ConfigurableInfo
{
/**
* Returns label
*
* @codeCoverageIgnore
*
* @param string $field
* @return \Magento\Framework\Phrase
*/
Expand Down
10 changes: 6 additions & 4 deletions Gateway/Command/CaptureStrategyCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Aune\Stripe\Gateway\Command;

use Stripe\Charge;

use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\SearchCriteriaBuilder;
Expand All @@ -17,6 +15,10 @@

use Aune\Stripe\Gateway\Helper\SubjectReader;

/**
* @SuppressWarnings(PHPMD.StaticAccess)
* @SuppressWarnings(PHPMD.LongVariable)
*/
class CaptureStrategyCommand implements CommandInterface
{
/**
Expand Down Expand Up @@ -134,10 +136,10 @@ private function getCommand(OrderPaymentInterface $payment)
*/
private function isExpiredAuthorization(OrderPaymentInterface $payment)
{
$ts = $this->dateTime->timestamp();
$currentTs = $this->dateTime->timestamp();
$txTs = $this->dateTime->timestamp($payment->getOrder()->getCreatedAt());

return $ts - $txTs > self::AUTHORIZATION_TTL;
return $currentTs - $txTs > self::AUTHORIZATION_TTL;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion Gateway/Config/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function getSdkUrl()
*
* @return bool
*/
public function getStoreCustomer()
public function isStoreCustomerEnabled()
{
return (bool) $this->getValue(self::KEY_STORE_CUSTOMER);
}
Expand Down
4 changes: 2 additions & 2 deletions Gateway/Helper/AmountProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class AmountProvider
*
* @var array
*/
protected $zeroDecimalCurrencies = [
private $zeroDecimal = [
'BIF',
'XAF',
'XPF',
Expand Down Expand Up @@ -41,7 +41,7 @@ class AmountProvider
*/
public function convert($amount, $currency)
{
$multiplier = in_array($currency, $this->zeroDecimalCurrencies) ? 1 : 100;
$multiplier = in_array($currency, $this->zeroDecimal) ? 1 : 100;

return (int)($multiplier * $amount);
}
Expand Down
3 changes: 3 additions & 0 deletions Gateway/Helper/SubjectReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
use Magento\Vault\Api\Data\PaymentTokenInterface;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;

/**
* @SuppressWarnings(PHPMD.StaticAccess)
*/
class SubjectReader
{
/**
Expand Down
66 changes: 66 additions & 0 deletions Gateway/Helper/TokenProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Aune\Stripe\Gateway\Helper;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Aune\Stripe\Model\Adapter\StripeAdapter;

class TokenProvider
{
const ATTRIBUTE_CODE = 'stripe_id';
const TOKEN_TYPE_CUSTOMER = 'customer';
const TOKEN_TYPE_SOURCE = 'source';

/**
* @var CustomerRepositoryInterface
*/
private $customerRepository;

/**
* @var StripeAdapter
*/
private $stripeAdapter;

/**
* @param CustomerRepositoryInterface $customerRepository
* @param StripeAdapter $stripeAdapter
*/
public function __construct(
CustomerRepositoryInterface $customerRepository,
StripeAdapter $stripeAdapter
) {
$this->customerRepository = $customerRepository;
$this->stripeAdapter = $stripeAdapter;
}

/**
* Returns the Stripe customer id given the Magento customer id
*/
public function getCustomerStripeId(int $magentoCustomerId)
{
$stripeCustomerId = null;

try {
$customer = $this->customerRepository->getById($magentoCustomerId);
$attribute = $customer->getCustomAttribute(self::ATTRIBUTE_CODE);
if ($attribute instanceof \Magento\Framework\Api\AttributeValue) {
$stripeCustomerId = $attribute->getValue();
}
} catch (NoSuchEntityException $ex) { }

return $stripeCustomerId;
}

/**
* Saves the Stripe customer id against a Magento customer
*/
public function setCustomerStripeId(int $magentoCustomerId, string $stripeCustomerId)
{
try {
$customer = $this->customerRepository->getById($magentoCustomerId);
$customer->setCustomAttribute(self::ATTRIBUTE_CODE, $stripeCustomerId);
$this->customerRepository->save($customer);
} catch (NoSuchEntityException $ex) { }
}
}
31 changes: 28 additions & 3 deletions Gateway/Request/CustomerDataBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

use Aune\Stripe\Gateway\Config\Config;
use Aune\Stripe\Gateway\Helper\SubjectReader;
use Aune\Stripe\Gateway\Helper\TokenProvider;
use Aune\Stripe\Observer\DataAssignObserver;

class CustomerDataBuilder implements BuilderInterface
{
const CUSTOMER = 'customer';
const SOURCE = 'source';

/**
* @var Config
Expand All @@ -23,16 +25,24 @@ class CustomerDataBuilder implements BuilderInterface
*/
private $subjectReader;

/**
* @var TokenProvider
*/
private $tokenProvider;

/**
* @param Config $config
* @param SubjectReader $subjectReader
* @param TokenProvider $tokenProvider
*/
public function __construct(
Config $config,
SubjectReader $subjectReader
SubjectReader $subjectReader,
TokenProvider $tokenProvider
) {
$this->config = $config;
$this->subjectReader = $subjectReader;
$this->tokenProvider = $tokenProvider;
}

/**
Expand All @@ -43,12 +53,27 @@ public function build(array $buildSubject)
$paymentDO = $this->subjectReader->readPayment($buildSubject);
$payment = $paymentDO->getPayment();

// Check if a vaulted payment method is being used
$extensionAttributes = $payment->getExtensionAttributes();
$paymentToken = $extensionAttributes->getVaultPaymentToken();

// Handle customer token (extension version < 2.1.0)
$details = json_decode($paymentToken->getTokenDetails(), true);
if (empty($details['tokenType']) || $details['tokenType'] != TokenProvider::TOKEN_TYPE_SOURCE) {
return [
self::CUSTOMER => $paymentToken->getGatewayToken(),
];
}

// Fetch Stripe customer id and use vaulted token
$stripeCustomerId = $this->tokenProvider->getCustomerStripeId(
$paymentToken->getCustomerId()
);

return [
self::CUSTOMER => $paymentToken->getGatewayToken(),
self::CUSTOMER => $stripeCustomerId,
self::SOURCE => $paymentToken->getGatewayToken(),
];


}
}
1 change: 0 additions & 1 deletion Gateway/Request/PaymentDataBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public function __construct(
public function build(array $buildSubject)
{
$paymentDO = $this->subjectReader->readPayment($buildSubject);
$payment = $paymentDO->getPayment();
$order = $paymentDO->getOrder();

// Prepare payload
Expand Down
79 changes: 61 additions & 18 deletions Gateway/Request/SourceDataBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@

use Stripe\Customer;

use Magento\Payment\Gateway\Data\OrderAdapterInterface;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Payment\Model\InfoInterface as PaymentInfoInterface;
use Magento\Vault\Model\Ui\VaultConfigProvider;

use Aune\Stripe\Gateway\Config\Config;
use Aune\Stripe\Gateway\Helper\SubjectReader;
use Aune\Stripe\Gateway\Helper\TokenProvider;
use Aune\Stripe\Model\Adapter\StripeAdapter;
use Aune\Stripe\Observer\DataAssignObserver;

Expand All @@ -26,20 +30,28 @@ class SourceDataBuilder implements BuilderInterface
* @var SubjectReader
*/
private $subjectReader;

/**
* @var TokenProvider
*/
private $tokenProvider;

/**
* @param Config $config
* @param SubjectReader $subjectReader
* @param StripeAdapter $stripeAdapter
* @param TokenProvider $tokenProvider
*/
public function __construct(
Config $config,
SubjectReader $subjectReader,
StripeAdapter $stripeAdapter
StripeAdapter $stripeAdapter,
TokenProvider $tokenProvider
) {
$this->config = $config;
$this->subjectReader = $subjectReader;
$this->stripeAdapter = $stripeAdapter;
$this->tokenProvider = $tokenProvider;
}

/**
Expand All @@ -49,40 +61,71 @@ public function build(array $buildSubject)
{
$paymentDO = $this->subjectReader->readPayment($buildSubject);
$payment = $paymentDO->getPayment();
$orderAdapter = $paymentDO->getOrder();

$sourceId = $payment->getAdditionalInformation(DataAssignObserver::SOURCE);

// Store the customer if module is configured to do so or if customer is vaulting the card
$shouldStore = $this->config->getStoreCustomer() ||
$payment->getAdditionalInformation(VaultConfigProvider::IS_ACTIVE_CODE);

if ($shouldStore) {
$customerId = $this->getStripeCustomerId(
$paymentDO->getOrder(),
$sourceId
);
return [
self::CUSTOMER => $customerId,
];
} else {
// If vaulting is enabled, assign the customer id
if ($this->canVaultCustomer($orderAdapter, $payment)) {

// Attach new source to customer
$stripeCustomer = $this->getStripeCustomer($orderAdapter);

$this->stripeAdapter->customerAttachSource($stripeCustomer, $sourceId);

return [
self::SOURCE => $sourceId,
self::CUSTOMER => $stripeCustomer->id,
];
}

// Otherwise assign the payment source
return [
self::SOURCE => $sourceId,
];
}

/**
* Check if the customer can be vaulted for the given order
*/
private function canVaultCustomer(
OrderAdapterInterface $order,
PaymentInfoInterface $payment
) {
if (is_null($order->getCustomerId())) {
return false;
}

return $this->config->isStoreCustomerEnabled() ||
$payment->getAdditionalInformation(VaultConfigProvider::IS_ACTIVE_CODE);
}

/**
* Create Stripe customer and return its id
* Get Stripe customer if it exists, otherwise create a new one and assign
* it to the Magento customer
*/
protected function getStripeCustomerId($orderAdapter, $sourceId)
private function getStripeCustomer(OrderAdapterInterface $orderAdapter)
{
// Check if the customer already has a stripe id
$customerId = $orderAdapter->getCustomerId();

$stripeId = $this->tokenProvider->getCustomerStripeId($customerId);
if ($stripeId) {
return $this->stripeAdapter->customerRetrieve($stripeId);
}

$addressAdapter = $orderAdapter->getBillingAddress();
$stripeCustomer = $this->stripeAdapter->customerCreate([
'email' => $addressAdapter->getEmail(),
'description' => $addressAdapter->getFirstname() . ' ' . $addressAdapter->getLastname(),
'source' => $sourceId,
]);

return $stripeCustomer->id;
// Assign the customer Stripe id to the Magento customer
$this->tokenProvider->setCustomerStripeId(
$customerId,
$stripeCustomer->id
);

return $stripeCustomer;
}
}
Loading

0 comments on commit 364564f

Please sign in to comment.