Skip to content

Commit

Permalink
Authorize and capture separately (#7)
Browse files Browse the repository at this point in the history
* wip

* add PHP 8.1 to test suite

* use setTransactionReference instead of setPaymentReference for CaptureRequest

* update license

* update readme and add comments

* add badges

* update readme

* improve tests
  • Loading branch information
aozisik authored Jan 4, 2023
1 parent 1073540 commit ec61271
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 12 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
- "7.3"
- "7.4"
- "8.0"
- "8.1"
operating-system:
- "ubuntu-latest"

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2021 Swiftmade OÜ
Copyright 2023 Swiftmade OÜ

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:

Expand Down
88 changes: 77 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
# Omnipay - EveryPay Gateway
[![Latest Version on Packagist](https://img.shields.io/packagist/v/swiftmade/omnipay-everypay.svg?style=flat-square)](https://packagist.org/packages/swiftmade/omnipay-everypay)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
[![Total Downloads](https://img.shields.io/packagist/dt/swiftmade/omnipay-everypay.svg?style=flat-square)](https://packagist.org/packages/swiftmade/omnipay-everypay)

_Disclaimer: This package is **not** an official package by EveryPay AS nor by omnipay._
# PHP EveryPay Client (for Omnipay)

[EveryPay](https://every-pay.com/) is an Estonian payment provider, currently working with LHV and SEB banks.
Use this package to integrate EveryPay into your PHP application using [Omnipay](http://omnipay.thephpleague.com).

The package currently supports a limited set of essential features in EveryPay v4:
EveryPay is a payment gateway currently used by:

- LHV
- SEB
- Swedbank

The package supports the following payment types:

- One-off payments
- Requesting card tokens
- One-click / CIT (Customer initiated Transactions) Payments
- One-click / CIT (Customer Initiated Transactions) Payments
- MIT (Merchant Initiated Transactions) Payments

## Usage

Require the package using composer:
Install the package using composer

> composer require swiftmade/omnipay-everypay
```bash
composer require swiftmade/omnipay-everypay
```

### Initialize the gateway

Expand All @@ -39,7 +50,7 @@ $purchase = $gateway
->setTransactionId($orderId) // unique order id for this purchase
->setReturnUrl($customerUrl) // the url to redirect if the payment fails or gets cancelled
->setClientIp($_SERVER['REMOTE_ADDR']) // optional, helps fraud detection
->setEmail(''); // optional, helps fraud detection
->setEmail(''); // optional, helps fraud detection

// Use this, if you want to make the payment using a previously stored card token
// Only applicable for MIT and CIT payment types.
Expand Down Expand Up @@ -81,7 +92,7 @@ if ($response->isSuccessful()) {
} else if($response->isRedirect()) {
// 3DS Confirmation needed!
// Redirect the user to 3DS Page.
return $response->redirect();
return $response->redirect();
} else {
// Something went wrong!
// Check $response->getMessage();
Expand All @@ -97,8 +108,8 @@ You need to validate whether the payment went through.
// Here, pass the payment array that we previously stored when creating the payment
$response = $gateway->completePurchase()
// These values are passed back to you by EveryPay
->setTransactionId($_GET['payment_reference'])
->setTransactionReference($_GET['order_reference'])
->setTransactionId($_GET['order_reference'])
->setTransactionReference($_GET['payment_reference'])
->send();

if (!$response->isSuccessful()) {
Expand All @@ -115,3 +126,58 @@ if ($card = $response->getCardToken()) {
}
```

### Authorize & Capture Later

In EveryPay, when the payment will be captured is configured at the account level. If you want to authorize a payment without capturing it, then you need a Merchant Account configured accordingly.

To authorize a payment, simply substitue `purchase` and `completePurchase` methods with `authorize` and `completeAuthorize`. Then call `capture` to capture the funds.

```php
// Here, pass the payment array that we previously stored when creating the payment
$gateway->authorize([
'amount' => $amount,
'paymentType' => PaymentType::CIT,
])
->setCardReference('previously stored card token')
// Set all the other parameters. See previous examples ...
->send();

// Redirect the user to 3DS confirmation as necessary.

// When EveryPay redirects the user back, do this...
// This won't capture the payment yet, but makes sure the authorization is successful.
$authorizeResponse = $gateway->completeAuthorize()
->setTransactionId($_GET['order_reference'])
->setTransactionReference($_GET['payment_reference'])
->send();

// Hold on to this.. You'll use this reference to capture the payment.
$paymentReference = $authorizeResponse->getTransactionReference();

// When you're ready to capture, call:
$response = $gateway->capture([
'amount' => $amount, // You can capture partially, or the whole amount.
'transactionReference' => $paymentReference,
])->send();

if ($response->isSuccessful()) {
// Payment captured!
} else {
// Something went wrong!
// Check $response->getMessage();
}
```

---

### Security

If you discover any security related issues, please email hello@swiftmade.co instead of using the issue tracker.

### Disclaimer

This package is **not** an official package by EveryPay AS nor by Omnipay.

### License

The MIT License (MIT). Please see [License File](LICENSE) for more information.
16 changes: 16 additions & 0 deletions src/Gateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Omnipay\Common\AbstractGateway;
use Omnipay\EveryPay\Enums\PaymentType;
use Omnipay\EveryPay\Support\SignedData;
use Omnipay\EveryPay\Messages\CaptureRequest;
use Omnipay\EveryPay\Messages\CitPaymentRequest;
use Omnipay\EveryPay\Messages\MitPaymentRequest;
use Omnipay\EveryPay\Messages\OneOffPaymentRequest;
Expand Down Expand Up @@ -53,4 +54,19 @@ public function completePurchase(array $options = [])
{
return $this->createRequest(CompletePurchaseRequest::class, $options);
}

public function authorize(array $options = [])
{
return $this->purchase($options);
}

public function completeAuthorize(array $options = [])
{
return $this->completePurchase($options);
}

public function capture($options = [])
{
return $this->createRequest(CaptureRequest::class, $options);
}
}
50 changes: 50 additions & 0 deletions src/Messages/CaptureRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Omnipay\EveryPay\Messages;

use Omnipay\Common\Exception\InvalidResponseException;

class CaptureRequest extends AbstractRequest
{
public function getData()
{
$this->validate(
'amount',
'transactionReference'
);

$baseData = $this->getBaseData();

return array_merge($baseData, [
'amount' => $this->getAmount(),
'payment_reference' => $this->getTransactionReference(),
]);
}

public function sendData($data): PurchaseResponse
{
try {
$payment = $this->httpRequest(
'POST',
$this->getEndpoint() . '/payments/capture',
$this->getHeaders(),
$data
);

return $this->response = new PurchaseResponse(
$this,
$payment
);
} catch (InvalidResponseException $e) {
return $this->response = new PurchaseResponse(
$this,
[
'error' => [
'message' => $e->getMessage(),
'code' => $e->getCode(),
],
]
);
}
}
}
6 changes: 6 additions & 0 deletions src/Messages/PurchaseResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,17 @@ public function isCancelled(): bool
return $this->getPaymentState() === PaymentState::ABANDONED;
}

/**
* This is usually he ID of the payment record in your database.
*/
public function getTransactionId()
{
return $this->data['order_reference'] ?? null;
}

/**
* This is the Payment Gateway’s reference to the transaction
*/
public function getTransactionReference()
{
return $this->data['payment_reference'] ?? null;
Expand Down
47 changes: 47 additions & 0 deletions tests/RequestsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

use Omnipay\Tests\TestCase;
use Omnipay\EveryPay\Gateway;
use Omnipay\EveryPay\Enums\PaymentType;
use Omnipay\EveryPay\Messages\CaptureRequest;
use Omnipay\EveryPay\Messages\CitPaymentRequest;
use Omnipay\EveryPay\Messages\MitPaymentRequest;
use Omnipay\EveryPay\Messages\OneOffPaymentRequest;
use Omnipay\EveryPay\Messages\CompletePurchaseRequest;

class RequestsTest extends TestCase
{
public function testPurchaseRequest()
{
$gateway = new Gateway();

$this->assertInstanceOf(OneOffPaymentRequest::class, $gateway->purchase());

$this->assertInstanceOf(OneOffPaymentRequest::class, $gateway->purchase([
'paymentType' => PaymentType::ONE_OFF,
]));

$this->assertInstanceOf(CitPaymentRequest::class, $gateway->purchase([
'paymentType' => PaymentType::CIT,
]));

$this->assertInstanceOf(MitPaymentRequest::class, $gateway->purchase([
'paymentType' => PaymentType::MIT,
]));
}

public function testCompletePurchaseRequest()
{
$gateway = new Gateway();

$this->assertInstanceOf(CompletePurchaseRequest::class, $gateway->completePurchase());
$this->assertInstanceOf(CompletePurchaseRequest::class, $gateway->completeAuthorize());
}

public function testCaptureRequest()
{
$gateway = new Gateway();

$this->assertInstanceOf(CaptureRequest::class, $gateway->capture());
}
}

0 comments on commit ec61271

Please sign in to comment.