Fixes #90: Direct Checkout now an option BitPay magento plugin

This commit is contained in:
Alex Leitner 2015-07-08 13:39:12 -04:00 committed by System Administrator
parent a25d5320ba
commit 14fb6302c0
12 changed files with 201 additions and 76 deletions

View File

@ -23,6 +23,24 @@ class Bitpay_Core_Block_Iframe extends Mage_Checkout_Block_Onepage_Payment
*/
public function getIframeUrl()
{
if (!($quote = Mage::getSingleton('checkout/session')->getQuote())
or !($payment = $quote->getPayment())
or !($paymentMethod = $payment->getMethod())
or ($paymentMethod !== 'bitpay')
or (Mage::getStoreConfig('payment/bitpay/fullscreen')))
{
return 'notbitpay';
}
\Mage::helper('bitpay')->registerAutoloader();
// fullscreen disabled?
if (Mage::getStoreConfig('payment/bitpay/fullscreen'))
{
return 'disabled';
}
if (\Mage::getModel('bitpay/ipn')->getQuotePaid($this->getQuote()->getId())) {
return 'paid'; // quote's already paid, so don't show the iframe
}
@ -30,60 +48,23 @@ class Bitpay_Core_Block_Iframe extends Mage_Checkout_Block_Onepage_Payment
/*** @var Bitpay_Core_Model_PaymentMethod ***/
$method = $this->getQuote()->getPayment()->getMethodInstance();
$amount = $this->getQuote()->getGrandTotal();
if (false === isset($method) || true === empty($method)) {
\Mage::helper('bitpay')->debugData('[ERROR] In Bitpay_Core_Block_Iframe::getIframeUrl(): Could not obtain an instance of the payment method.');
throw new \Exception('In Bitpay_Core_Block_Iframe::getIframeUrl(): Could not obtain an instance of the payment method.');
}
$options = array_merge(
array(
'currency' => $this->getQuote()->getQuoteCurrencyCode(),
'fullNotifications' => 'true',
'notificationURL' => \Mage::getUrl('bitpay/ipn'),
'redirectURL' => \Mage::getUrl('checkout/onepage/success'),
'transactionSpeed' => \Mage::getStoreConfig('payment/bitpay/speed'),
),
$method->extractAddress($this->getQuote()->getShippingAddress())
);
$bitcoinMethod = \Mage::getModel('bitpay/method_bitcoin');
if (false === isset($options) || true === empty($options)) {
\Mage::helper('bitpay')->debugData('[ERROR] In Bitpay_Core_Block_Iframe::getIframeUrl(): Could not merge the options array.');
throw new \Exception('In Bitpay_Core_Block_Iframe::getIframeUrl(): Could not merge the options array.');
} else {
\Mage::helper('bitpay')->debugData($options);
}
// Mage doesn't round the total until saving and it can have more precision
// at this point which would be bad for later comparing records w/ bitpay.
// So round here to match what the price will be saved as:
$price = round($this->getQuote()->getGrandTotal(), 4);
if (false === isset($price) || true === empty($price)) {
\Mage::helper('bitpay')->debugData('[ERROR] In Bitpay_Core_Block_Iframe::getIframeUrl(): Could not get the new rounded price.');
throw new \Exception('In Bitpay_Core_Block_Iframe::getIframeUrl(): Could not get the new rounded price.');
}
//serialize info about the quote to detect changes
$hash = $method->getQuoteHash($this->getQuote()->getId());
if (false === isset($hash) || true === empty($hash)) {
\Mage::helper('bitpay')->debugData('[ERROR] In Bitpay_Core_Block_Iframe::getIframeUrl(): Could not get the quote hash.');
throw new \Exception('In Bitpay_Core_Block_Iframe::getIframeUrl(): Could not merge the quote hash.');
}
\Mage::helper('bitpay')->registerAutoloader();
//$invoice = bpCreateInvoice($quoteId, $price, array('quoteId' => $quoteId, 'quoteHash' => $hash), $options);
$invoice = array('url' => 'https://test.bitpay.com/invoice?id=5NxFkXcJbCSivtQRJa4kHP');
if (array_key_exists('error', $invoice)) {
\Mage::helper('bitpay')->debugData(array('Error creating bitpay invoice', $invoice['error'],));
try {
$bitcoinMethod->authorize($payment, $amount, true);
} catch (\Exception $e) {
\Mage::helper('bitpay')->debugData('[ERROR] In Bitpay_Core_Block_Iframe::getIframeUrl(): failed with the message: ' . $e->getMessage());
\Mage::throwException("Error creating BitPay invoice. Please try again or use another payment option.");
return false;
}
//return $invoice['url'].'&view=iframe';
return false;
return $bitcoinMethod->getOrderPlaceRedirectUrl();
}
}

View File

@ -57,17 +57,17 @@ class Bitpay_Core_Model_Invoice extends Mage_Core_Model_Abstract
* @param Mage_Sales_Model_Order $order
* @return Bitpay_Core_Model_Invoice
*/
public function prepateWithOrder($order)
public function prepareWithOrder($order)
{
if (false === isset($order) || true === empty($order)) {
\Mage::helper('bitpay')->debugData('[ERROR] In Bitpay_Core_Model_Invoice::prepateWithOrder(): Missing or empty $order parameter.');
throw new \Exception('In Bitpay_Core_Model_Invoice::prepateWithOrder(): Missing or empty $order parameter.');
}
$this->addData(
array(
'quote_id' => $order->getQuoteId(),
'increment_id' => $order->getIncrementId(),
'quote_id' => $order['quote_id'],
'increment_id' => $order['increment_id'],
)
);

View File

@ -12,6 +12,53 @@ class Bitpay_Core_Model_Ipn extends Mage_Core_Model_Abstract
*/
protected function _construct()
{
parent::_construct();
$this->_init('bitpay/ipn');
}
/**
* @param string $quoteId
* @param array $statuses
*
* @return boolean
*/
function GetStatusReceived($quoteId, $statuses)
{
if (!$quoteId)
{
return false;
}
$quote = Mage::getModel('sales/quote')->load($quoteId, 'entity_id');
if (!$quote)
{
Mage::log('quote not found', Zend_Log::WARN, 'bitpay.log');
return false;
}
$collection = $this->getCollection();
foreach ($collection as $i)
{
if ($quoteId == json_decode($i->pos_data, true)['quoteId']) {
if (in_array($i->status, $statuses)) {
return true;
}
}
}
return false;
}
/**
* @param string $quoteId
*
* @return boolean
*/
function GetQuotePaid($quoteId)
{
return $this->GetStatusReceived($quoteId, array('paid', 'confirmed', 'complete'));
}
}

View File

@ -35,8 +35,24 @@ class Bitpay_Core_Model_Method_Bitcoin extends Mage_Payment_Model_Method_Abstrac
* @param float $amount
* @return Bitpay_Core_Model_PaymentMethod
*/
public function authorize(Varien_Object $payment, $amount)
public function authorize(Varien_Object $payment, $amount, $iframe = false)
{
// Check if coming from iframe or submit button
if ((!Mage::getStoreConfig('payment/bitpay/fullscreen') && $iframe === false)
|| (Mage::getStoreConfig('payment/bitpay/fullscreen') && $iframe === true)) {
$quoteId = $payment->getOrder()->getQuoteId();
$ipn = Mage::getModel('bitpay/ipn');
if (!$ipn->GetQuotePaid($quoteId))
{
// This is the error that is displayed to the customer during checkout.
Mage::throwException("Order not paid for. Please pay first and then Place your Order.");
Mage::log('Order not paid for. Please pay first and then Place Your Order.', Zend_Log::CRIT, Mage::helper('bitpay')->getLogFile());
}
return $this;
}
if (false === isset($payment) || false === isset($amount) || true === empty($payment) || true === empty($amount)) {
$this->debugData('[ERROR] In Bitpay_Core_Model_Method_Bitcoin::authorize(): missing payment or amount parameters.');
throw new \Exception('In Bitpay_Core_Model_Method_Bitcoin::authorize(): missing payment or amount parameters.');
@ -61,7 +77,7 @@ class Bitpay_Core_Model_Method_Bitcoin extends Mage_Payment_Model_Method_Abstrac
\Mage::throwException('In Bitpay_Core_Model_Method_Bitcoin::authorize(): Could not authorize transaction.');
}
self::$_redirectUrl = $bitpayInvoice->getUrl();
self::$_redirectUrl = (Mage::getStoreConfig('payment/bitpay/fullscreen')) ? $bitpayInvoice->getUrl(): $bitpayInvoice->getUrl().'&view=iframe';
$this->debugData(
array(
@ -70,10 +86,13 @@ class Bitpay_Core_Model_Method_Bitcoin extends Mage_Payment_Model_Method_Abstrac
)
);
$quote = Mage::getSingleton('checkout/session')->getQuote();
$order = \Mage::getModel('sales/order')->load($quote->getId(), 'quote_id');
// Save BitPay Invoice in database for reference
$mirrorInvoice = \Mage::getModel('bitpay/invoice')
->prepareWithBitpayInvoice($bitpayInvoice)
->prepateWithOrder($payment->getOrder())
->prepareWithOrder(array('increment_id' => $order->getIncrementId(), 'quote_id'=> $quote->getId()))
->save();
$this->debugData('[INFO] Leaving Bitpay_Core_Model_Method_Bitcoin::authorize(): invoice id ' . $bitpayInvoice->getId());
@ -200,6 +219,7 @@ class Bitpay_Core_Model_Method_Bitcoin extends Mage_Payment_Model_Method_Abstrac
$this->debugData('[INFO] In Bitpay_Core_Model_Method_Bitcoin::getOrderPlaceRedirectUrl(): $_redirectUrl is ' . self::$_redirectUrl);
return self::$_redirectUrl;
}
/**
@ -247,12 +267,22 @@ class Bitpay_Core_Model_Method_Bitcoin extends Mage_Payment_Model_Method_Abstrac
$this->debugData('[INFO] In Bitpay_Core_Model_Method_Bitcoin::prepareInvoice(): entered function with good invoice, payment and amount parameters.');
}
$invoice->setOrderId($payment->getOrder()->getIncrementId());
$invoice->setPosData(json_encode(array('id' => $payment->getOrder()->getIncrementId())));
$quote = Mage::getSingleton('checkout/session')->getQuote();
$order = \Mage::getModel('sales/order')->load($quote->getId(), 'quote_id');
$invoice = $this->addCurrencyInfo($invoice, $payment->getOrder());
if (Mage::getStoreConfig('payment/bitpay/fullscreen')) {
$invoice->setOrderId($order->getIncrementId());
$invoice->setPosData(json_encode(array('orderId' => $order->getIncrementId())));
} else {
$invoice->setOrderId($quote->getId());
$invoice->setPosData(json_encode(array('quoteId' => $quote->getId())));
$convertQuote = Mage::getSingleton('sales/convert_quote');
$order = $convertQuote->toOrder($quote);
}
$invoice = $this->addCurrencyInfo($invoice, $order);
$invoice = $this->addPriceInfo($invoice, $amount);
$invoice = $this->addBuyerInfo($invoice, $payment->getOrder());
$invoice = $this->addBuyerInfo($invoice, $order);
return $invoice;
}
@ -280,10 +310,17 @@ class Bitpay_Core_Model_Method_Bitcoin extends Mage_Payment_Model_Method_Abstrac
throw new \Exception('In Bitpay_Core_Model_Method_Bitcoin::addBuyerInfo(): could not construct new BitPay buyer object.');
}
$buyer->setFirstName($order->getCustomerFirstname());
$buyer->setLastName($order->getCustomerLastname());
$address = $order->getBillingAddress();
if (Mage::getStoreConfig('payment/bitpay/fullscreen')) {
$address = $order->getBillingAddress();
} else {
$quote = Mage::getSingleton('checkout/session')->getQuote();
$address = $quote->getBillingAddress();
}
if (!empty($address->getStreet1())) {
$buyer->setAddress(

View File

@ -0,0 +1,44 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2011-2014 BitPay, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
class Bitpay_Core_Model_Resource_Ipn_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
{
/**
*/
protected function _construct()
{
parent::_construct();
$this->_init('bitpay/ipn');
}
public function delete()
{
foreach ($this->getItems() as $item) {
$item->delete();
}
}
}

View File

@ -14,21 +14,16 @@ class Bitpay_Core_IndexController extends Mage_Core_Controller_Front_Action
*/
public function indexAction()
{
$paid = false;
$params = $this->getRequest()->getParams();
if (true === isset($params['paid'])) {
\Mage::helper('bitpay')->registerAutoloader();
\Mage::helper('bitpay')->debugData($params);
} else {
\Mage::helper('bitpay')->debugData('[ERROR] In Bitpay_Core_IndexController::indexAction(), Could not get parameters from HTTP request.');
}
$params = $this->getRequest()->getParams();
$quoteId = $params['quote'];
\Mage::helper('bitpay')->registerAutoloader();
\Mage::helper('bitpay')->debugData($params);
$paid = Mage::getModel('bitpay/ipn')->GetQuotePaid($quoteId);
$this->loadLayout();
$this->getResponse()->setHeader('Content-type', 'application/json');
// ?
$this->getResponse()->setBody(json_encode(array('paid' => $paid)));
}
}

View File

@ -69,7 +69,13 @@ class Bitpay_Core_IpnController extends Mage_Core_Controller_Front_Action
)
)->save();
$order = \Mage::getModel('sales/order')->loadByIncrementId($ipn->posData->id);
// Order isn't being created for iframe...
if (isset($ipn->posData->orderId)) {
$order = \Mage::getModel('sales/order')->loadByIncrementId($ipn->posData->orderId);
} else {
$order = \Mage::getModel('sales/order')->load($ipn->posData->quoteId, 'quote_id');
}
if (false === isset($order) || true === empty($order->getId())) {
\Mage::helper('bitpay')->debugData('[ERROR] In Bitpay_Core_IpnController::indexAction(), Invalid Bitpay IPN received.');

View File

@ -118,6 +118,7 @@
<notification_url>bitpay/ipn</notification_url>
<redirect_url>checkout/onepage/success</redirect_url>
<speed>medium</speed>
<fullscreen>0</fullscreen>
<invoice_new>new</invoice_new>
<invoice_paid>processing</invoice_paid>
<invoice_confirmed>processing</invoice_confirmed>

View File

@ -98,6 +98,15 @@
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</redirect_url>
<fullscreen translate="label">
<label>Redirect Checkout</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_yesno</source_model>
<sort_order>2</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</fullscreen>
<speed translate="label">
<label>Transaction Speed</label>
<frontend_type>select</frontend_type>

View File

@ -6,4 +6,9 @@
*/
-->
<layout>
<checkout_onepage_review>
<reference name="checkout.onepage.review.info.items.after">
<block name="iframe" type="bitpay/iframe"/>
</reference>
</checkout_onepage_review>
</layout>

View File

@ -9,8 +9,9 @@
*/
$_code = $this->getMethodCode();
echo '<ul class="form-list" id="payment_form_' . $_code . '" style="display:none;">' .
'<li>You will be transfered to <a href="https://bitpay.com" target="_blank">BitPay</a> to complete your purchase when using this payment method.</li>' .
'</ul>';
if (Mage::getStoreConfig('payment/bitpay/fullscreen')) {
echo '<ul class="form-list" id="payment_form_' . $_code . '" style="display:none;">' .
'<li>You will be transfered to <a href="https://bitpay.com" target="_blank">BitPay</a> to complete your purchase when using this payment method.</li>' .
'</ul>';
}
?>

View File

@ -37,14 +37,13 @@ new PeriodicalExecuter(function() {
asynchronous: true,
evalScripts: true,
onComplete: function(request, json) {
data = request.responseText.evalJSON();
var data = request.responseText.evalJSON();
if (data.paid) {
buttons = $$("button.btn-checkout");
buttons.each(function(btn) { btn.click(); })
review.save();
}
}
}
)
);
}, 5);
//]]>
</script>