-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18 from academe/dpm_support
DPM support for Authorize.Net
- Loading branch information
Showing
20 changed files
with
933 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
namespace Omnipay\AuthorizeNet; | ||
|
||
/** | ||
* Authorize.Net DPM (Direct Post Method) Class | ||
*/ | ||
class DPMGateway extends SIMGateway | ||
{ | ||
public function getName() | ||
{ | ||
return 'Authorize.Net DPM'; | ||
} | ||
|
||
/** | ||
* Helper to generate the authorize direct-post form. | ||
*/ | ||
public function authorize(array $parameters = array()) | ||
{ | ||
return $this->createRequest('\Omnipay\AuthorizeNet\Message\DPMAuthorizeRequest', $parameters); | ||
} | ||
|
||
/** | ||
* Get, validate, interpret and respond to the Authorize.Net callback. | ||
*/ | ||
public function completeAuthorize(array $parameters = array()) | ||
{ | ||
return $this->createRequest('\Omnipay\AuthorizeNet\Message\DPMCompleteRequest', $parameters); | ||
} | ||
|
||
/** | ||
* Helper to generate the purchase direct-post form. | ||
*/ | ||
public function purchase(array $parameters = array()) | ||
{ | ||
return $this->createRequest('\Omnipay\AuthorizeNet\Message\DPMPurchaseRequest', $parameters); | ||
} | ||
|
||
/** | ||
* Get, validate, interpret and respond to the Authorize.Net callback. | ||
*/ | ||
public function completePurchase(array $parameters = array()) | ||
{ | ||
return $this->createRequest('\Omnipay\AuthorizeNet\Message\DPMCompleteRequest', $parameters); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
namespace Omnipay\AuthorizeNet\Message; | ||
|
||
/** | ||
* Authorize.Net DPM Authorize Request. | ||
* Takes the data that will be used to create the direct-post form. | ||
*/ | ||
class DPMAuthorizeRequest extends SIMAuthorizeRequest | ||
{ | ||
protected $action = 'AUTH_ONLY'; | ||
|
||
public function getData() | ||
{ | ||
$data = parent::getData(); | ||
|
||
// If x_show_form is set, then the form will be displayed on the Authorize.Net | ||
// gateway, in a similar way to the SIM gateway. The DPM documentation does NOT | ||
// make this clear at all. | ||
// Since x_show_form is set in the SIM gateway, make sure we unset it here. | ||
|
||
unset($data['x_show_form']); | ||
|
||
// Must be set for DPM. | ||
// This directs all errors to the relay response. | ||
|
||
$data['x_relay_always'] = 'TRUE'; | ||
|
||
// The card details are optional. | ||
// They will most likely only be used for development and testing. | ||
// The card fields are still needed in the direct-post form regardless. | ||
|
||
if ($this->getCard()) { | ||
$data['x_card_num'] = $this->getCard()->getNumber(); | ||
|
||
// Workaround for https://github.com/thephpleague/omnipay-common/issues/29 | ||
$expiry_date = $this->getCard()->getExpiryDate('my'); | ||
$data['x_exp_date'] = ($expiry_date === '1299' ? '' : $expiry_date); | ||
|
||
$data['x_card_code'] = $this->getCard()->getCvv(); | ||
} else { | ||
$data['x_card_num'] = ''; | ||
$data['x_exp_date'] = ''; | ||
$data['x_card_code'] = ''; | ||
} | ||
|
||
return $data; | ||
} | ||
|
||
|
||
/** | ||
* Given the DPM data, we want to turn it into a form for the user to submit to Authorize.net | ||
* The form may have most of the fields hidden, or may allow the user to change some details - | ||
* that depends on the use-case. | ||
* So this method will provide us with an object used to build the form. | ||
*/ | ||
public function sendData($data) | ||
{ | ||
return $this->response = new DPMResponse($this, $data, $this->getEndpoint()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?php | ||
|
||
namespace Omnipay\AuthorizeNet\Message; | ||
|
||
use Omnipay\Common\Exception\InvalidRequestException; | ||
|
||
/** | ||
* Authorize.Net DPM Complete Authorize Request | ||
*/ | ||
class DPMCompleteRequest extends SIMCompleteAuthorizeRequest | ||
{ | ||
public function getData() | ||
{ | ||
// The hash sent in the callback from the Authorize.Net gateway. | ||
$hash_posted = strtolower($this->httpRequest->request->get('x_MD5_Hash')); | ||
|
||
// The transaction reference generated by the Authorize.Net gateway and sent in the callback. | ||
$posted_transaction_reference = $this->httpRequest->request->get('x_trans_id'); | ||
|
||
// The amount that the callback has authorized. | ||
$posted_amount = $this->httpRequest->request->get('x_amount'); | ||
|
||
// Calculate the hash locally, using the shared "hash secret" and login ID. | ||
$hash_calculated = $this->getDpmHash($posted_transaction_reference, $posted_amount); | ||
|
||
if ($hash_posted !== $hash_calculated) { | ||
// If the hash is incorrect, then we can't trust the source nor anything sent. | ||
// Throwing exceptions here is probably a bad idea. We are trying to get the data, | ||
// and if it is invalid, then we need to be able to log that data for analysis. | ||
// Except we can't, baceuse the exception means we can't get to the data. | ||
// For now, this is consistent with other OmniPay gateway drivers. | ||
|
||
throw new InvalidRequestException('Incorrect hash'); | ||
} | ||
|
||
// The hashes have passed, but the amount should also be validated against the | ||
// amount in the stored and retrieved transaction. If the application has the | ||
// ability to retrieve the transaction (using the transaction_id sent as a custom | ||
// form field, or perhaps in an otherwise unused field such as x_invoice_id. | ||
|
||
$amount = $this->getAmount(); | ||
|
||
if (isset($amount) && $amount != $posted_amount) { | ||
// The amounts don't match. Someone may have been playing with the | ||
// transaction references. | ||
|
||
throw new InvalidRequestException('Incorrect amount'); | ||
} | ||
|
||
return $this->httpRequest->request->all(); | ||
} | ||
|
||
/** | ||
* This hash confirms the ransaction has come from the Authorize.Net gateway. | ||
* It confirms the sender knows ther shared hash secret and that the amount and | ||
* transaction reference has not been changed in transit. | ||
*/ | ||
public function getDpmHash($transaction_reference, $amount) | ||
{ | ||
$key = $this->getHashSecret() | ||
. $this->getApiLoginId() | ||
. $transaction_reference | ||
. $amount; | ||
|
||
return md5($key); | ||
} | ||
|
||
public function sendData($data) | ||
{ | ||
return $this->response = new DPMCompleteResponse($this, $data); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
|
||
namespace Omnipay\AuthorizeNet\Message; | ||
|
||
use Omnipay\Common\Message\AbstractResponse; | ||
use Omnipay\Common\Message\RedirectResponseInterface; | ||
|
||
/** | ||
* Authorize.Net DPM Complete Authorize Response | ||
* This is the result of handling the callback. | ||
* The result will always be a HTML redirect snippet. This gets | ||
* returned to the gateway, displayed in the user's browser, and a | ||
* redirect is performed using JavaScript and meta refresh (for backup). | ||
* We may want to return to the success page, the failed page or the retry | ||
* page (so the user can correct the form to try again). | ||
*/ | ||
class DPMCompleteResponse extends SIMCompleteAuthorizeResponse implements RedirectResponseInterface | ||
{ | ||
const RESPONSE_CODE_APPROVED = '1'; | ||
const RESPONSE_CODE_DECLINED = '2'; | ||
const RESPONSE_CODE_ERROR = '3'; | ||
const RESPONSE_CODE_REVIEW = '4'; | ||
|
||
public function isSuccessful() | ||
{ | ||
return isset($this->data['x_response_code']) | ||
&& static::RESPONSE_CODE_APPROVED === $this->data['x_response_code']; | ||
} | ||
|
||
/** | ||
* If there is an error in the form, then the user should be able to go back | ||
* to the form and give it another shot. | ||
*/ | ||
public function isError() | ||
{ | ||
return isset($this->data['x_response_code']) | ||
&& static::RESPONSE_CODE_ERROR === $this->data['x_response_code']; | ||
} | ||
|
||
/** | ||
* We are in the callback, and we MUST return a HTML fragment to do a redirect. | ||
* All headers we may return are discarded by the gateway, so we cannot use | ||
* the "Location:" header. | ||
*/ | ||
public function isRedirect() | ||
{ | ||
return true; | ||
} | ||
|
||
/** | ||
* We set POST because the default redirect mechanism in Omnipay Common only | ||
* generates a HTML snippet for POST and not for the GET method. | ||
* The redirect method is actually "HTML", where a HTML page is supplied | ||
* to do a redirect using any method it likes. | ||
*/ | ||
public function getRedirectMethod() | ||
{ | ||
return 'POST'; | ||
} | ||
|
||
/** | ||
* We probably do not require any redirect data, if the incomplete transaction | ||
* is still in the user's session and we can inspect the results from the saved | ||
* transaction in the database. We cannot send the result through the redirect | ||
* unless it is hashed so the authorisation result cannot be faked. | ||
*/ | ||
public function getRedirectData() | ||
{ | ||
return array(); | ||
} | ||
|
||
/** | ||
* The cancel URL is never handled here - that is a direct link from the gateway. | ||
*/ | ||
public function getRedirectUrl() | ||
{ | ||
// Leave it for the applicatino to decide where to sent the user. | ||
return; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
namespace Omnipay\AuthorizeNet\Message; | ||
|
||
/** | ||
* Authorize.Net DPM Purchase Request (aka "Authorize and Capture") | ||
*/ | ||
class DPMPurchaseRequest extends DPMAuthorizeRequest | ||
{ | ||
protected $action = 'AUTH_CAPTURE'; | ||
} |
Oops, something went wrong.