Skip to content

Instantly share code, notes, and snippets.

@bummzack
Created March 17, 2016 10:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bummzack/7fe04392e552ed1473ac to your computer and use it in GitHub Desktop.
Save bummzack/7fe04392e552ed1473ac to your computer and use it in GitHub Desktop.
<?php
/**
* Fix an issue with Omnipay 2.0 and the shop system.
* The shop assumes that all gateways support the "purchase" method, but that isn't the case.
*/
class FixedPurchaseService extends PurchaseService
{
/**
* Attempt to make a payment.
*
* @param array $data returnUrl/cancelUrl + customer creditcard and billing/shipping details.
* Some keys (e.g. "amount") are overwritten with data from the associated {@link $payment}.
* If this array is constructed from user data (e.g. a form submission), please take care
* to whitelist accepted fields, in order to ensure sensitive gateway parameters like "freeShipping" can't be set.
* If using {@link Form->getData()}, only fields which exist in the form are returned,
* effectively whitelisting against arbitrary user input.
* @return ResponseInterface omnipay's response class, specific to the chosen gateway.
*/
public function purchase($data = array())
{
if ($this->payment->Status !== "Created") {
return null; //could be handled better? send payment response?
}
if (!$this->payment->isInDB()) {
$this->payment->write();
}
//update success/fail urls
$this->update($data);
//set the client IP address, if not already set
if (!isset($data['clientIp'])) {
$data['clientIp'] = Controller::curr()->getRequest()->getIP();
}
$gatewaydata = array_merge($data, array(
'card' => $this->getCreditCard($data),
'amount' => (float)$this->payment->MoneyAmount,
'currency' => $this->payment->MoneyCurrency,
//set all gateway return/cancel/notify urls to PaymentGatewayController endpoint
'returnUrl' => $this->getEndpointURL("complete", $this->payment->Identifier),
'cancelUrl' => $this->getEndpointURL("cancel", $this->payment->Identifier),
'notifyUrl' => $this->getEndpointURL("notify", $this->payment->Identifier)
));
if (!isset($gatewaydata['transactionId'])) {
$gatewaydata['transactionId'] = $this->payment->Identifier;
}
//--- BEGIN FIX
$gateway = $this->oGateway();
if($gateway->supportsPurchase()){
$request = $gateway->purchase($gatewaydata);
} else {
$request = $gateway->authorize($gatewaydata);
}
//--- END FIX
$message = $this->createMessage('PurchaseRequest', $request);
$message->SuccessURL = $this->returnurl;
$message->FailureURL = $this->cancelurl;
$message->write();
$gatewayresponse = $this->createGatewayResponse();
try {
$response = $this->response = $request->send();
$gatewayresponse->setOmnipayResponse($response);
//update payment model
if (GatewayInfo::is_manual($this->payment->Gateway)) {
//initiate manual payment
$this->createMessage('AuthorizedResponse', $response);
$this->payment->Status = 'Authorized';
$this->payment->write();
$gatewayresponse->setMessage("Manual payment authorised");
} elseif ($response->isSuccessful()) {
//successful payment
$this->createMessage('PurchasedResponse', $response);
$this->payment->Status = 'Captured';
$gatewayresponse->setMessage("Payment successful");
$this->payment->write();
$this->payment->extend('onCaptured', $gatewayresponse);
} elseif ($response->isRedirect()) {
// redirect to off-site payment gateway
$this->createMessage('PurchaseRedirectResponse', $response);
$this->payment->Status = 'Authorized';
$this->payment->write();
$gatewayresponse->setMessage("Redirecting to gateway");
} else {
//handle error
$this->createMessage('PurchaseError', $response);
$gatewayresponse->setMessage(
"Error (" . $response->getCode() . "): " . $response->getMessage()
);
}
} catch (Omnipay\Common\Exception\OmnipayException $e) {
$this->createMessage('PurchaseError', $e);
$gatewayresponse->setMessage($e->getMessage());
}
$gatewayresponse->setRedirectURL($this->getRedirectURL());
return $gatewayresponse;
}
/**
* Finalise this payment, after off-site external processing.
* This is ususally only called by PaymentGatewayController.
* @return PaymentResponse encapsulated response info
*/
public function completePurchase($data = array())
{
$gatewayresponse = $this->createGatewayResponse();
//set the client IP address, if not already set
if (!isset($data['clientIp'])) {
$data['clientIp'] = Controller::curr()->getRequest()->getIP();
}
$gatewaydata = array_merge($data, array(
'amount' => (float)$this->payment->MoneyAmount,
'currency' => $this->payment->MoneyCurrency
));
$this->payment->extend('onBeforeCompletePurchase', $gatewaydata);
//--- BEGIN FIX
$gateway = $this->oGateway();
if($gateway->supportsPurchase()){
$request = $gateway->completePurchase($gatewaydata);
} else {
$request = $gateway->completeAuthorize($gatewaydata);
}
//--- END FIX
$this->createMessage('CompletePurchaseRequest', $request);
$response = null;
try {
$response = $this->response = $request->send();
$gatewayresponse->setOmnipayResponse($response);
if ($response->isSuccessful()) {
$this->createMessage('PurchasedResponse', $response);
$this->payment->Status = 'Captured';
$this->payment->write();
$this->payment->extend('onCaptured', $gatewayresponse);
} else {
$this->createMessage('CompletePurchaseError', $response);
}
} catch (Omnipay\Common\Exception\OmnipayException $e) {
$this->createMessage("CompletePurchaseError", $e);
}
return $gatewayresponse;
}
}
---
Name: omnipay-fixes
After: shop
---
#---- Temporary workaround for https://github.com/burnbright/silverstripe-omnipay/issues/3
Injector:
PurchaseService:
class: 'FixedPurchaseService'
#---- End Temporary workaround
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment