Transaction Matching
Implement a Currency Exchanger to USD, amounts are converted to USD when Request currency is different from Payment currency.
use MerchantOP\Services\ExchangerContract;
class Exchanger implements ExchangerContract
{
protected $rates = [
'EUR' => 1.21,
'GBP' => 1.37,
];
public function __construct()
{
$this->rates = $this->getFreshRates();
}
public function exchangeToUSD($currency, $amount)
{
return $this->rates[$currency] * $amount;
}
protected function getFreshRates()
{
//
}
}
Capture request parameters:
use MerchantOP\Models\ProvisionRequest;
$request = ProvisionRequest::capture();
Preliminary filter available transactions by card number and transaction date:
$transactionDate = $request->authorizationDate ?: $request->settlementDate;
$transactions = Transactions::where('card_bin', $request->cardBin)
->where('card_last4', $request->cardLast4)
->where('transaction_timestamp', '>=', $request->authorizationDate->add(DateInterval::createFromDateString('-3 days')))
->where('transaction_timestamp', '<=', $request->authorizationDate->add(DateInterval::createFromDateString('+3 days')));
Transform raw filtered entities to Payment objects:
$payments = $transactions->map(function ($transactions) {
$payment = new Payment;
$payment->authDate = $transaction->transaction_timestamp;
$payment->cardBin = $transaction->card_bin;
$payment->cardLast4 = $transaction->card_last4;
$payment->total = $transaction->amount;
$payment->currency = $transaction->currency;
$payment->authDescriptor = $transaction->descriptor;
$payment->arn = $transaction->arn;
$payment->orderId = $transaction->order_id;
return $payment;
});
Match Payments to requested parameters:
use MerchantOP\OrderPullingManager;
$matched = OrderPullingManager::matcher(new Exchanger)->match($payments, $request);
Matching steps (the process stops on the step where only a single payment is matched):
- Exact Match by ARN, Order ID, Gateway ID, if both available in Request and Payment.
- Match by Card Number, Transaction Date (+- 2 days), Amount (exchanged to USD; on exchange, a difference of 5 USD is accepted)
- Match by Descriptor (65% similarity; removed numbers, whitespaces)
- Match by exact payment date
Check matched payments:
if (!$matched) {
abort(404); # Not found
} elseif ($matched === true) {
abort(300); # Multiple choices
} else {
$response = new ProvisionResponse;
$response->payments[] = $matched;
// build response...
echo $response->toJson();
}