Skip to content

Commit

Permalink
Merge pull request #81 from Affirm/ca-release-branch
Browse files Browse the repository at this point in the history
CA Release
  • Loading branch information
taehyunlim authored Aug 22, 2022
2 parents 60500e1 + a436a2e commit 9f8f96a
Show file tree
Hide file tree
Showing 37 changed files with 561 additions and 184 deletions.
4 changes: 3 additions & 1 deletion Block/Promotion/AslowasAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ abstract class AslowasAbstract extends \Magento\Framework\View\Element\Template
*
* @var array
*/
protected $data = ['logo', 'script', 'public_api_key'];
protected $data = ['logo', 'script', 'public_api_key', 'country_code', 'locale'];

/**
* Colors which could be set in "data-affirm-color".
Expand Down Expand Up @@ -208,6 +208,8 @@ public function process()
$config = $configProvider['payment'][ConfigProvider::CODE];
$this->setData('script', $config['script']);
$this->setData('public_api_key', $config['apiKeyPublic']);
$this->setData('country_code', $config['countryCode']);
$this->setData('locale', $config['locale']);
}
// Set max and min options amounts from payment configuration
$this->setData('min_order_total', $this->getPaymentConfigValue('min_order_total'));
Expand Down
2 changes: 2 additions & 0 deletions Block/Promotion/Banners.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ public function getOptions()
if ($config && isset($config['script']) && isset($config['apiKeyPublic'])) {
$options['script'] = $config['script'];
$options['public_api_key'] = $config['apiKeyPublic'];
$options['country_code'] = $config['countryCode'];
$options['locale'] = $config['locale'];
}
}
if ($this->isProductPage()) {
Expand Down
2 changes: 1 addition & 1 deletion Block/Promotion/CartPage/Aslowas.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Aslowas extends AslowasAbstract
*
* @var array
*/
protected $data = ['logo', 'script', 'public_api_key', 'min_order_total', 'max_order_total', 'element_id'];
protected $data = ['logo', 'script', 'public_api_key', 'min_order_total', 'max_order_total', 'element_id', 'country_code', 'locale'];

/**
* Checkout session
Expand Down
2 changes: 2 additions & 0 deletions Block/Promotion/Pixel/Confirm.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ public function getOptions()
if ($config && isset($config['script']) && isset($config['apiKeyPublic'])) {
$options['script'] = $config['script'];
$options['public_api_key'] = $config['apiKeyPublic'];
$options['country_code'] = $config['countryCode'];
$options['locale'] = $config['locale'];
}
}
return $options;
Expand Down
2 changes: 1 addition & 1 deletion Block/Promotion/ProductPage/Aslowas.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Aslowas extends AslowasAbstract
* @var array
*/
protected $data = ['logo', 'script', 'public_api_key', 'min_order_total', 'max_order_total',
'selector', 'currency_rate', 'backorders_options', 'element_id'];
'selector', 'currency_rate', 'backorders_options', 'element_id', 'country_code', 'locale'];

/**
* Validate block before showing on front
Expand Down
5 changes: 5 additions & 0 deletions Gateway/Helper/Util.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ class Util
*/
const IDEMPOTENCY_KEY = "Idempotency-Key";

/**
* Country code
*/
const COUNTRY_CODE = "Country-Code";

/**
* Constructor
*
Expand Down
64 changes: 50 additions & 14 deletions Gateway/Http/AbstractTransferFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@
*/
abstract class AbstractTransferFactory implements TransferFactoryInterface
{
/**
* Constants
*/
const MODE = 'mode';
const SANDBOX = 'sandbox';
const PRODUCTION = 'production';
const COUNTRY_CODE_USA = 'USA';
const COUNTRY_CODE_CAN = 'CAN';
const SUFFIX_CANADA = '_ca';
/**
/**
* Config
*
Expand Down Expand Up @@ -80,18 +92,20 @@ public function __construct(
* Get public API key
*
* @param int $storeId
* @param string $country_code
* @return string
*/
protected function getPublicApiKey($storeId)
protected function getPublicApiKey($storeId, $country_code)
{
$country_suffix = $this->getApiKeyNameByCountry($country_code);
if(!empty($storeId)){
return $this->config->getValue('mode', $storeId) == 'sandbox'
? $this->config->getValue('public_api_key_sandbox', $storeId)
: $this->config->getValue('public_api_key_production', $storeId);
return $this->config->getValue(self::MODE, $storeId) == self::SANDBOX
? $this->config->getValue('public_api_key_sandbox' . $country_suffix, $storeId)
: $this->config->getValue('public_api_key_production' . $country_suffix, $storeId);
} else {
return $this->config->getValue('mode') == 'sandbox'
? $this->config->getValue('public_api_key_sandbox')
: $this->config->getValue('public_api_key_production');
return $this->config->getValue('mode') == self::SANDBOX
? $this->config->getValue('public_api_key_sandbox' . $country_suffix)
: $this->config->getValue('public_api_key_production' . $country_suffix);
}

}
Expand All @@ -100,18 +114,20 @@ protected function getPublicApiKey($storeId)
* Get private API key
*
* @param int $storeId
* @param string $country_code
* @return string
*/
protected function getPrivateApiKey($storeId)
protected function getPrivateApiKey($storeId, $country_code)
{
$country_suffix = $this->getApiKeyNameByCountry($country_code);
if(!empty($storeId)){
return $this->config->getValue('mode', $storeId) == 'sandbox'
? $this->config->getValue('private_api_key_sandbox', $storeId)
: $this->config->getValue('private_api_key_production', $storeId);
return $this->config->getValue('mode', $storeId) == self::SANDBOX
? $this->config->getValue('private_api_key_sandbox' . $country_suffix, $storeId)
: $this->config->getValue('private_api_key_production' . $country_suffix, $storeId);
} else {
return $this->config->getValue('mode') == 'sandbox'
? $this->config->getValue('private_api_key_sandbox')
: $this->config->getValue('private_api_key_production');
return $this->config->getValue('mode') == self::SANDBOX
? $this->config->getValue('private_api_key_sandbox' . $country_suffix)
: $this->config->getValue('private_api_key_production' . $country_suffix);
}
}

Expand All @@ -124,4 +140,24 @@ protected function getStoreId()
{
return $this->_storeManager->getStore()->getId();
}

/**
* Map country code to API key config suffix name
*
* @param string $country_code
* @return string
*/
protected function getApiKeyNameByCountry($country_code)
{
$_suffix = '';
$countryCodeToSuffix = array(
self::COUNTRY_CODE_CAN => self::SUFFIX_CANADA,
self::COUNTRY_CODE_USA => '',
);

if (isset($country_code)) {
$_suffix = $countryCodeToSuffix[$country_code] ?: '';
}
return $_suffix;
}
}
5 changes: 3 additions & 2 deletions Gateway/Http/Client/ClientService.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,17 @@ public function placeRequest(TransferInterface $transferObject)
$client = $this->httpClientFactory->create();
$client->setUri($requestUri);
$client->setAuth($transferObject->getAuthUsername(), $transferObject->getAuthPassword());
$headers = $transferObject->getHeaders();
if (strpos($transferObject->getUri(), $this->action::API_TRANSACTIONS_PATH) !== false) {
$idempotencyKey = $this->util->generateIdempotencyKey();
$client->setHeaders([Util::IDEMPOTENCY_KEY => $idempotencyKey]);
$headers[Util::IDEMPOTENCY_KEY] = $idempotencyKey;
}
$client->setHeaders($headers);
if (!empty($transferObject->getBody())) {
$data = $transferObject->getBody();
$data = json_encode($data, JSON_UNESCAPED_SLASHES);
$client->setRawData($data, 'application/json');
}

$response = $client->request($transferObject->getMethod());
$rawResponse = $response->getRawBody();
$response = $this->converter->convert($rawResponse);
Expand Down
10 changes: 7 additions & 3 deletions Gateway/Http/TransferFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ public function create(array $request)
$method = isset($request['method']) ? $request['method'] : ClientService::POST;
// Admin actions will include store id in the request
$storeId = isset($request['storeId']) ? $request['storeId'] : $this->getStoreId();
$country_code = $request['country_code'] ?: 'USA';
return $this->transferBuilder
->setMethod($method)
->setHeaders(['Content-Type' => 'application/json'])
->setHeaders([
'Content-Type' => 'application/json',
'Country-Code' => $country_code
])
->setBody($request['body'])
->setAuthUsername($this->getPublicApiKey($storeId))
->setAuthPassword($this->getPrivateApiKey($storeId))
->setAuthUsername($this->getPublicApiKey($storeId, $country_code))
->setAuthPassword($this->getPrivateApiKey($storeId, $country_code))
->setUri($this->getApiUrl($request['path'], $storeId))
->build();
}
Expand Down
2 changes: 2 additions & 0 deletions Gateway/Request/AbstractDataBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ abstract class AbstractDataBuilder implements BuilderInterface
const CHECKOUT_TOKEN = 'checkout_token';
const TRANSACTION_ID = 'transaction_id';
const CHARGE_ID = 'charge_id';
const COUNTRY_CODE = 'country_code';
const DEFAULT_COUNTRY_CODE = 'USA';
/**#@-*/

/**
Expand Down
4 changes: 3 additions & 1 deletion Gateway/Request/AuthorizationRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ public function build(array $buildSubject)
$paymentDataObject = $buildSubject['payment'];
$payment = $paymentDataObject->getPayment();
$token = $payment->getAdditionalInformation(self::CHECKOUT_TOKEN);
$countryCode = $payment->getAdditionalInformation(self::COUNTRY_CODE) ?: self::DEFAULT_COUNTRY_CODE;
return [
'body' => [
self::TRANSACTION_ID => $token
],
'path' => ''
'path' => '',
'country_code' => $countryCode
];
}
}
6 changes: 4 additions & 2 deletions Gateway/Request/CaptureRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ public function build(array $buildSubject)
$payment = $paymentDataObject->getPayment();
$transactionId = $payment->getAdditionalInformation(self::TRANSACTION_ID) ?:
$payment->getAdditionalInformation(self::CHARGE_ID);
$countryCode = $payment->getAdditionalInformation(self::COUNTRY_CODE) ?: self::DEFAULT_COUNTRY_CODE;
$order = $payment->getOrder();
$storeId = isset($order) ? $order->getStoreId() : $this->_storeManager->getStore()->getId();
if (!$storeId) {
$storeId = null;
}
if ($this->affirmPaymentConfig->getPartialCapture()) {
if ($this->affirmPaymentConfig->getPartialCapture($countryCode)) {
$_amount = $buildSubject['amount'] ? Util::formatToCents($buildSubject['amount']) : null;
$_body = [
'amount' => $_amount
Expand All @@ -62,7 +63,8 @@ public function build(array $buildSubject)
return [
'path' => "{$transactionId}/capture",
'storeId' => $storeId,
'body' => $_body
'body' => $_body,
'country_code' => $countryCode,
];
}
}
4 changes: 3 additions & 1 deletion Gateway/Request/PreAuthorizationRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@ public function build(array $buildSubject)
$paymentDataObject = $buildSubject['payment'];
$payment = $paymentDataObject->getPayment();
$token = $payment->getAdditionalInformation(self::CHECKOUT_TOKEN);
$countryCode = $payment->getAdditionalInformation(self::COUNTRY_CODE) ?: self::DEFAULT_COUNTRY_CODE;
return [
'body' => '',
'path' => $token,
'method' => self::GET
'method' => self::GET,
'country_code' => $countryCode
];
}
}
7 changes: 5 additions & 2 deletions Gateway/Request/RefundRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public function build(array $buildSubject)
$payment = $paymentDataObject->getPayment();
$transactionId = $payment->getAdditionalInformation(self::TRANSACTION_ID) ?:
$payment->getAdditionalInformation(self::CHARGE_ID);
$amountInCents = Util::formatToCents($buildSubject['amount']);
$countryCode = $payment->getAdditionalInformation(self::COUNTRY_CODE) ?: self::DEFAULT_COUNTRY_CODE;
$creditMemoAmount = $payment->getCreditmemo()->getGrandTotal();
$amountInCents = Util::formatToCents($creditMemoAmount);
$order = $payment->getOrder();
if($order) {
$storeId = $order->getStoreId();
Expand All @@ -59,7 +61,8 @@ public function build(array $buildSubject)
'amount' => $amountInCents
],
'path' => "{$transactionId}/refund",
'storeId' => $storeId
'storeId' => $storeId,
'country_code' => $countryCode,
];
}
}
4 changes: 3 additions & 1 deletion Gateway/Request/VoidRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function build(array $buildSubject)
$payment = $paymentDataObject->getPayment();
$transactionId = $payment->getAdditionalInformation(self::TRANSACTION_ID) ?:
$payment->getAdditionalInformation(self::CHARGE_ID);
$countryCode = $payment->getAdditionalInformation(self::COUNTRY_CODE) ?: self::DEFAULT_COUNTRY_CODE;
$order = $payment->getOrder();
if($order) {
$storeId = $order->getStoreId();
Expand All @@ -55,7 +56,8 @@ public function build(array $buildSubject)
return [
'body' => [],
'path' => "{$transactionId}/void",
'storeId' => $storeId
'storeId' => $storeId,
'country_code' => $countryCode,
];
}
}
26 changes: 24 additions & 2 deletions Gateway/Validator/Client/PaymentActionsValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,34 @@
class PaymentActionsValidator extends AbstractResponseValidator
{
/**
* @inheritdoc
* Validate response
*
* @param array $validationSubject
* @return \Magento\Payment\Gateway\Validator\ResultInterface
*/
public function validate(array $validationSubject)
{
$response = SubjectReader::readResponse($validationSubject);
$amount = SubjectReader::readAmount($validationSubject);
$amount = '';

if ( (isset($response['checkout_status']) && $response['checkout_status'] == 'confirmed')
|| (isset($response['status']) && $response['status'] == 'authorized')
|| (isset($response['type']) && $response['type'] == 'capture'))
{
// Pre-Auth/Auth/Capture uses amount_ordered from payment
$_payment = $validationSubject['payment']->getPayment();
$payment_data = $_payment->getData();
$amount = $payment_data['amount_ordered'];
} elseif ( (isset($response['type']) && $response['type'] == 'refund') ) {
// Refund (including partial) uses grand_total from creditmemo (credit memo invoice)
$_payment = $validationSubject['payment']->getPayment();
$_creditMemo = $_payment->getData()['creditmemo'];
$amount = $_creditMemo->getGrandTotal();
} else {
// Partial capture (US only) uses validationSubject
$amount = SubjectReader::readAmount($validationSubject);
}

$amountInCents = Util::formatToCents($amount);

$errorMessages = [];
Expand Down
15 changes: 9 additions & 6 deletions Helper/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@
class Payment
{
/**
* Country code for address validation
* Region (country) code for address validation
*/
const VALIDATE_COUNTRY = 'US';
const VALID_REGIONS = array('US', 'CA');
const DEFAULT_REGION = 'US';

/**
* Affirm payment facade
Expand Down Expand Up @@ -311,7 +312,7 @@ public function getConfigurableProductBackordersOptions(Product $product = null)
public function validateVirtual()
{
if ($this->quote->getIsVirtual() && !$this->quote->getCustomerIsGuest()) {
$countryId = self::VALIDATE_COUNTRY;
$countryId = self::DEFAULT_REGION;
// get customer addresses list
$addresses = $this->quote->getCustomer()->getAddresses();
// get default shipping address for the customer
Expand All @@ -321,12 +322,14 @@ public function validateVirtual()
foreach ($addresses as $address) {
if ($address->getId() == $defaultShipping) {
$countryId = $address->getCountryId();
if (in_array($countryId, self::VALID_REGIONS)) {
return true;
} else {
return false;
}
break;
}
}
if ($countryId != self::VALIDATE_COUNTRY) {
return false;
}
}
}
return true;
Expand Down
Loading

0 comments on commit 9f8f96a

Please sign in to comment.