use Omnipay\Omnipay;
use Omnipay\CreditCard;
$gateway = OmniPay::create('SagePay\Direct');
$gateway->setVendor('your-vendor-code');
$gateway->setTestMode(true); // For test account
// The minimal card details to save to the gateway.
// The CVV is optional. However it can be supplied later when
// transactions are being initiated, though that is not advised
// as the CVV will need to go through your site to be added to
// the transaction.
$card = new CreditCard([
'firstName' => 'Joe',
'lastName' => 'Bloggs',
'number' => '4929000000006',
'expiryMonth' => '12',
'expiryYear' => '2020',
'cvv' => '123',
]);
// Send the request.
$request = $gateway->createCard([
'currency' => 'GBP',
'card' => $card,
]);
$response = $request->send();
// There will be no need for any redirect (e.g. 3D Secure), since the
// card is not being authorized at this point.
if ($response->isSuccessful()) {
$cardReference = $response->getCardReference();
// or if you prefer to treat it as a single-use token:
$token = $response->getToken();
}
use Omnipay\Omnipay;
$gateway = OmniPay::create('SagePay\Server');
$gateway->setVendor('your-vendor-code');
$gateway->setTestMode(true); // For a test account
// Use the billing name and address for the shipping name and address too.
$gateway->setBillingForShipping(true);
// or
$response = $gateway->authorize([
'billingForShipping' => true,
...
]);
// Create a unique transaction ID to track this transaction.
$transactionId = {create a unique transaction id};
// Custom surcharges can be added here.
// You must construct the XML string; there is no XML builder in this driver
// at this time. Length is very limited, so keep it compact.
$surchargeXml = '<surcharges>'
. '<surcharge>'
. '<paymentType>VISA</paymentType>'
. '<percentage>5.20</percentage>'
. '</surcharge>'
. '</surcharges>';
// Send the authorize request.
// Some optional parameters are shown commented out.
$response = $gateway->authorize([
'amount' => '9.99',
'currency' => 'GBP',
'card' => $card,
'notifyUrl' => 'http://example.com/your/notify.php',
'transactionId' => $transactionId,
'description' => 'Mandatory description',
// 'items' => $items,
// 'cardReference' => '{4E50F334-9D42-9946-2B0B-ED70B2421D48}',
// 'surchargeXml' => $surchargeXml,
// 'token' => $token,
// 'cardReference' => $cardReference,
// 'useAuthenticate' => true,
])->send();
If `useAuthenticate` is set, then the `authorize` will use the `AUTHENTICATE`/`AUTHORISE`
method of reserving the transaction details.
If `useAuthenticate` is not set (the default) then the `DEFERRED`/`RELEASE`
method of reserving the transaction details will be used.
The same method must be used when capturing the transaction.
// Create storage for this transaction now, indexed by the transaction ID.
// We will need to access it in the notification handler.
// The reference given by `$response->getTransactionReference()` must be stored.
// Now decide what to do next, based on the response.
if ($response->isSuccessful()) {
// The transaction is complete and successful and no further action is needed.
// This may happen if a cardReference has been supplied, having captured
// the card reference with a CVV and using it for the first time. The CVV will
// only be kept by the gateway for this first authorization. This also assumes
// 3D Secure is turned off.
} elseif ($response->isRedirect()) {
// Redirect to offsite payment gateway to capture the users credit card
// details.
// If a cardReference was provided, then only the CVV will be asked for.
// 3D Secure will be performed here too, if enabled.
// Once the user is redirected to the gateway, the results will be POSTed
// to the [notification handler](#sage-pay-server-notification-handler).
// The handler will then inform the gateway where to finally return the user
// to on the merchant site.
$response->redirect();
} else {
// Something went wrong; get the message.
// The error may be a simple validation error on the address details.
// Catch those and allow the user to correct the details and submit again.
// This is a particular pain point of Sage Pay Server.
$reason = $response->getMessage();
}
// The transaction ID is used to store the result in the notify callback.
// Create storage for this transaction now, indexed by the transaction ID.
$transactionId = {create a unique transaction id};
$request = $gateway->createCard([
'currency' => 'GBP',
'notifyUrl' => {notify callback URL},
'transactionId' => $transactionId,
'iframe' => true, // TRUE if the offsite form is to go into an iframe
]);
$response = $request->send();
if ($response->isSuccessful()) {
// Should never happen for Sage Pay Server, since the user will always
// be asked to go off-site to enter their credit card details.
} elseif ($response->isRedirect()) {
// Redirect to offsite payment gateway to capture the users credit card
// details. Note that no address details are needed, nor are they captured.
// Here add the $response->getTransactionReference() to the stored transaction,
// as the notification handler will need it for checking the signature of the
// notification it receives.
$response->redirect();
} else {
$reason = $response->getMessage();
}
// The Server response will be a redirect to the Sage Pay CC form.
// This is a Sage Pay Server Purchase request.
$transactionId = {create a unique transaction id};
$items = [
[
'name' => 'My Product Name',
'description' => 'My Product Description',
'quantity' => 1,
'price' => 9.99,
]
];
$response = $gateway->purchase([
'amount' => 9.99,
'currency' => 'GBP',
// Just the name and address, NOT CC details.
'card' => $card,
// The route to your application's notification handler.
'notifyUrl' => 'https://example.com/notify',
'transactionId' => $transactionId,
'description' => 'test',
'items' => $items,
])->send();
// Before redirecting, save `$response->getSecurityKey()` in the database,
// retrievable by `$transactionId`.
if ($response->isRedirect()) {
// Go to Sage Pay to enter CC details.
// While your user is there, the notification handler will be called
// to accept the result and provide the final URL for the user.
$response->redirect();
}
$gateway = Omnipay\Omnipay::create('SagePay_Server');
$gateway->setVendor('your-vendor-name');
$gateway->setTestMode(true); // To access your test account.
$notifyRequest = $gateway->acceptNotification();
// Use this transaction ID to look up the `$securityKey` you saved:
$transactionId = $notifyRequest->getTransactionId();
$transaction = customFetchMyTransaction($transactionId); // Local storage
$securityKey = $transaction->getSecurityKey(); // From your local storage
// Alternatively, if you did not save the `securityKey` as a distinct field,
// then use the `transactionReference` you saved.
// The `transactionReference` for this driver will be a compound JSON string
// with the `securityKey` as an integral part of it, so the driver can use it
// directly.
$transactionReference = $transaction->getTransactionReference(); // From your local storage
$notifyRequest->setSecurityKey($securityKey);
// or
$notifyRequest->setTransactionReference($transactionReference);
if (! $notifyRequest->isValid()) {
// Respond to Sage Pay indicating we are not accepting anything about this message.
// You might want to log `$request->getData()` first, for later analysis.
$notifyRequest->invalid($nextUrl, 'Signature not valid - goodbye');
}
$notifyRequest->error($nextUrl, 'This transaction does not exist on the system');
// All raw data - just log it for later analysis:
$notifyRequest->getData();
// Save the final transactionReference against the transaction in the database. It will
// be needed if you want to capture the payment (for an authorize) or void or refund or
// repeat the payment later.
$finalTransactionReference = $notifyRequest->getTransactionReference();
// The payment or authorization result:
// Result is $notifyRequest::STATUS_COMPLETED, $notifyRequest::STATUS_PENDING
// or $notifyRequest::STATUS_FAILED
$notifyRequest->getTransactionStatus();
// If you want more detail, look at the raw data. An error message may be found in:
$notifyRequest->getMessage();
// The transaction may be the result of a `createCard()` request.
// The cardReference can be found like this:
if ($notifyRequest->getTxType() === $notifyRequest::TXTYPE_TOKEN) {
$cardReference = $notifyRequest->getCardReference();
}
// Now let Sage Pay know you have accepted and saved the result:
$notifyRequest->confirm($nextUrl);
$gateway->setExitOnResponse(true);
// or
$notifyRequest->setExitOnResponse(true);
$response = $gateway->authorize([
...all the normal details...
//
'returnUrl' => 'https://example.com/success',
'failureUrl' => 'https://example.com/failure',
]);
// The result will be read and decrypted from the return URL (or failure URL)
// query parameters.
// You MUST provide the original expected transactionId, which is validated
// against the transactionId provided in the server request.
// This prevents different payments getting mixed up.
$completeRequest = $gateway->completeAuthorize(['transactionId' => $originalTransactionId]);
$result = $completeRequest->send();
$result->isSuccessful();
$result->getTransactionReference();
// etc.
// repeatAuthorize() or repeatPurchase()
$repeatRequest = $gateway->repeatAuthorize([
'transactionReference' => $originalTransactionReference,
// or
'securityKey' => $originalSecurityKey,
'txAuthNo' => $originalTxAuthNo,
'vpsTxId' => $originalVPSTxId(),
'relatedTransactionId' => $originalTransactionId,
//
'amount' => '99.99',
'transactionId' => $newTransactionId.'C',
'currency' => 'GBP',
'description' => 'Buy it again, Sam',
]);
$repeatResponse = $repeatRequest->send();
// Treat $repeatResponse like any new authorization or purchase response.
$captureRequest = $gateway->capture([
// authenticate is not set
'useAuthenticate' => false,
// Provide either the original transactionReference:
'transactionReference' => $deferredTransactionReference,
// Or the individual items:
'securityKey' => $savedSecurityKey(),
'txAuthNo' => $savedTxAuthNo(),
'vpsTxId' => $savedVPSTxId(),
'relatedTransactionId' => $savedTransactionId,
// Up to the original amount, one chance only.
'amount' => '99.99',
]);
$captureRequest = $gateway->capture([
// authenticate is set
'useAuthenticate' => true,
// Provide either the original transactionReference:
'transactionReference' => $deferredTransactionReference,
// Or the individual items:
'securityKey' => $savedSecurityKey(),
'txAuthNo' => $savedTxAuthNo(),
'vpsTxId' => $savedVPSTxId(),
'relatedTransactionId' => $savedTransactionId,
// Up to 115% of the original amount, in as many chunks as you like.
'amount' => '9.99',
// The capture becomes a transaction in its own right.
'transactionId' => $newTransactionId,
'currency' => 'GBP',
'description' => 'Take staged payment number 1',
]);
$captureResponse = $captureRequest->send();
if ($captureResponse->isSuccessful()) {
// The capture was successful.
// There will never be a redirect here.
}
use Omnipay\Omnipay;
use Omnipay\CreditCard;
$gateway = OmniPay::create('SagePay\Direct');
// or
$gateway = OmniPay::create('SagePay\Server');
$gateway->setVendor('your-vendor-code');
$gateway->setTestMode(true); // For test account
// Send the request.
$request = $gateway->deleteCard([
'cardReference' => $cardReference,
]);
$response = $request->send();
// There will be no need for any redirect (e.g. 3D Secure), since no
// authorization is being done.
if ($response->isSuccessful()) {
$message = $response->getMessage();
// "2017 : Token removed successfully."
}