Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bubach/ed86611c634b401e5d66392cf32c2f6e to your computer and use it in GitHub Desktop.
Save bubach/ed86611c634b401e5d66392cf32c2f6e to your computer and use it in GitHub Desktop.
Small module enabling refunds on Magento 1.x Paypal standard payments
<?xml version="1.0"?>
<config>
<modules>
<Namespace_Modulename>
<version>0.0.1</version>
<depends>
<!-- <MageCoders_PaypalMulticurrency /> -->
<Mage_Paypal />
<!-- <AW_Storecredit /> -->
</depends>
</Namespace_Modulename>
</modules>
<global>
<models>
<modulename>
<class>Namespace_Modulename_Model</class>
</modulename>
</models>
</global>
<adminhtml>
<events>
<sales_order_payment_refund>
<observers>
<modulename>
<type>singleton</type>
<class>Namespace_Modulename_Model_Model_Observer</class>
<method>creditMemo</method>
</modulename>
</observers>
</sales_order_payment_refund>
</events>
</adminhtml>
<!-- Left out config for module setting 'modulename/active', ACL and other crap. -->
</config>
<?php
/**
* app/code/local/Namespace/Modulename/Model/Namespace_Modulename_Model_Observer.php
*/
class Namespace_Modulename_Model_Model_Observer
{
/**
* Observer for paypal standard payments refund
*
* @param Varien_Event_Observer $observer
* @throws Mage_Core_Exception
*/
public function creditMemo(Varien_Event_Observer $observer)
{
$payment = $observer->getEvent()->getPayment();
$paymentCode = $payment->getMethod();
$storeId = $payment->getOrder()->getStoreId();
// check if we should handle paypal refunds
if (Mage::getStoreConfigFlag('modulename/paypal/active', storeId)) {
if ($paymentCode == "paypal_standard") {
$creditmemo = $observer->getEvent()->getCreditmemo();
// instantiate our model directly instead of keeping rewrite in config (why not)
$paypal = Mage::getModel('modulename/paypal');
//$paypal = Mage::getModel('paypal/pro');
if ($paypal && method_exists($paypal, 'tryRefund')) {
$ares = $paypal->tryRefund($payment, $creditmemo->getGrandTotal());
if ($ares[0] == 0) {
Mage::getSingleton('adminhtml/session')->addSuccess($ares[1]);
} elseif ($ares[0] > 1) {
throw new Mage_Core_Exception($ares[1]);
} elseif ($ares[0] < 0) {
throw new Mage_Core_Exception($ares[1]);
}
$payment
->getOrder()
->addStatusToHistory($payment
->getOrder()
->getStatus(), $ares[1]);
}
}
}
}
/**
* Observer for paypal standard payments cancel order
*
* @param Varien_Event_Observer $observer
* @throws Mage_Core_Exception
*/
public function orderCancel(Varien_Event_Observer $observer)
{
$payment = $observer->getEvent()->getPayment();
$paymentCode = $payment->getMethod();
$storeId = $payment->getOrder()->getStoreId();
// check if we should handle paypal refunds
if (Mage::getStoreConfigFlag('paymentaddon/paypal/active', $storeId)) {
if ($paymentCode == "paypal_standard") {
// if payment is pending, then we have no money to return
$order = $payment->getOrder();
if ($order && $order->getState() == 'pending_payment') {
return;
}
// instantiate our model directly instead of keeping rewrite in config (why not)
$paypal = Mage::getModel('paymentaddon/paypal');
//$paypal = Mage::getModel('paypal/pro');
if ($paypal && method_exists($paypal, 'tryCancel')) {
$ares = $paypal->tryCancel($payment);
if ($ares[0] == 0) {
if ($ares[1] != "") {
Mage::getSingleton('adminhtml/session')->addSuccess($ares[1]);
}
} elseif ($ares[0] > 1) {
throw new Mage_Core_Exception($ares[1]);
} elseif ($ares[0] < 0) {
throw new Mage_Core_Exception($ares[1]);
}
$payment
->getOrder()
->addStatusToHistory($payment
->getOrder()
->getStatus(), $ares[1]);
}
}
}
}
}
<?php
/**
* app/code/local/Namespace/Modulename/Model/Namespace_Modulename_Model_Paypal.php
*/
class Namespace_Modulename_Model_Paypal extends Mage_Paypal_Model_Standard
{
protected $_canRefund = true;
protected $_canRefundInvoicePartial = true;
protected $_canVoid = true;
/**
* https://developer.paypal.com/webapps/developer/docs/classic/api/merchant/RefundTransaction_API_Operation_NVP/
*/
public function tryRefund(Varien_Object $payment, $amount)
{
$transactionId = $payment->getLastTransId();
if ($transactionId) {
$order = $payment->getOrder();
$storeId = $order->getStoreId();
$refundType = "Partial";
$invoiceFee = $payment->getMethodInstance()->getInfoInstance()->getAdditionalInformation('invoice_fee');
$remaining = $order->getTotalInvoiced() - ($order->getTotalOfflineRefunded() + $order->getTotalOnlineRefunded()) - $invoiceFee;
if (abs($remaining - $amount) < 0.00001) {
$refundType = "Full";
}
$currencyCode = $order->getBaseCurrencyCode();
$invoiceId = $order->getIncrementId();
$params = array(
"METHOD" => "RefundTransaction",
"VERSION" => "72.0",
"TRANSACTIONID" => $transactionId,
"INVOICEID" => $invoiceId,
"REFUNDTYPE" => $refundType,
"AMT" => $amount,
"CURRENCYCODE" => $currencyCode,
"USER" => Mage::getStoreConfig('paypal/wpp/api_username', $storeId),
"PWD" => Mage::getStoreConfig('paypal/wpp/api_password', $storeId),
"SIGNATURE" => Mage::getStoreConfig('paypal/wpp/api_signature', $storeId)
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api-3t.paypal.com/nvp");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
$response = curl_exec($ch);
if (curl_errno($ch)) {
curl_close($ch);
throw new Mage_Core_Exception('Impossible to issue a refund transaction because of cURL error.');
} else {
curl_close($ch);
$responseArray = array();
parse_str($response, $responseArray); // Break the NVP string to an array
if ($responseArray['ACK'] == "Success") {
return array(0, "Paypal refunded successfully");
} else {
return array(-1, "Paypal refund failed!");
}
}
} else {
Mage::throwException(Mage::helper('paypal')->__('Impossible to issue a refund transaction because the capture transaction does not exist.'));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment