Skip to content

Commit eb77d8e

Browse files
committed
feat: added 3DS support. Additional API methods
1 parent cdc3a6f commit eb77d8e

File tree

6 files changed

+341
-74
lines changed

6 files changed

+341
-74
lines changed

config/betterpay.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
return [
44
'api_key' => env('BETTERPAY_API_KEY'),
55
'merchant_id' => env('BETTERPAY_MERCHANT_ID'),
6-
'api_url' => env('BETTERPAY_API_URL', 'https://www.demo.betterpay.me/merchant/api/'),
76
'callback_url' => env('BETTERPAY_CALLBACK_URL'),
87
'success_url' => env('BETTERPAY_SUCCESS_URL'),
98
'fail_url' => env('BETTERPAY_FAIL_URL'),
9+
'sandbox' => env('BETTERPAY_SANDBOX', false),
10+
'3ds' => env('BETTERPAY_3DS', true),
1011
];

src/Betterpay.php

+94-44
Original file line numberDiff line numberDiff line change
@@ -5,75 +5,125 @@
55
use GuzzleHttp\Client;
66
use Sykez\Betterpay\Exceptions\BetterpayException;
77
use GuzzleHttp\Exception\ClientException;
8-
use Sykez\Betterpay\Hashing;
8+
use Sykez\Betterpay\HashVerification;
9+
use Sykez\Betterpay\Tokenization;
910

1011
class Betterpay
1112
{
13+
use HashVerification, Tokenization;
14+
15+
/**
16+
* API endpoints
17+
* @var string
18+
*/
19+
protected $production_url = 'https://www.betterpay.me/merchant/api/';
20+
protected $sandbox_url = 'https://www.demo.betterpay.me/merchant/api/';
21+
1222
protected $client;
23+
protected $api_url;
1324
protected $api_key;
1425
protected $merchant_id;
1526
protected $callback_url;
1627
protected $success_url;
1728
protected $fail_url;
18-
19-
public function __construct(?string $api_key, ?string $merchant_id, string $api_url, ?string $callback_url, ?string $success_url, ?string $fail_url)
29+
protected $sandbox;
30+
protected $is_3ds;
31+
32+
/**
33+
* __construct
34+
*
35+
* @param mixed $api_key
36+
* @param mixed $merchant_id
37+
* @param mixed $callback_url
38+
* @param mixed $success_url
39+
* @param mixed $fail_url
40+
* @param mixed $sandbox
41+
* @param mixed $is_3ds
42+
* @return void
43+
*/
44+
public function __construct(?string $api_key, ?int $merchant_id, ?string $callback_url, ?string $success_url, ?string $fail_url, bool $sandbox = false, bool $is_3ds = true)
2045
{
21-
if (!$api_key || !$merchant_id || !$api_url || !$callback_url || !$success_url || !$fail_url) {
46+
if (!$api_key || !$merchant_id || !$callback_url || !$success_url || !$fail_url) {
2247
throw BetterpayException::configException();
2348
}
2449

50+
if ($sandbox && $is_3ds) {
51+
throw BetterpayException::sandbox3dsException();
52+
}
53+
2554
$this->api_key = $api_key;
2655
$this->merchant_id = $merchant_id;
27-
$this->api_url = $api_url;
2856
$this->callback_url = $callback_url;
2957
$this->success_url = $success_url;
3058
$this->fail_url = $fail_url;
59+
$this->sandbox = $sandbox;
60+
$this->is_3ds = $is_3ds;
61+
$this->api_url = $this->sandbox ? $this->sandbox_url : $this->production_url;
3162
}
32-
33-
public function createTokenizationUrl(string $reference_id, int $skip_receipt = 0, bool $_3ds = true)
63+
64+
/**
65+
* Set 3D Secure mode. Not supported in sandbox mode.
66+
*
67+
* @param mixed $is_3ds
68+
* @return void
69+
*/
70+
public function set3DS(bool $is_3ds)
3471
{
35-
$hash = Hashing::reference($this->api_key, $this->merchant_id, $reference_id);
36-
$payload = [
37-
'merchant_id' => $this->merchant_id,
38-
'reference_id' => $reference_id,
39-
'callback_url_be' => $this->callback_url,
40-
'callback_url_fe_succ' => $this->success_url,
41-
'callback_url_fe_fail' => $this->fail_url,
42-
'skip_receipt' => $skip_receipt,
43-
'hash' => $hash,
44-
];
45-
46-
$response = $this->http_request('cards/token/v1/' . ($_3ds ? '3ds/' : '') . 'create', $payload);
47-
48-
return $response;
72+
$this->is_3ds = $is_3ds;
4973
}
50-
51-
public function charge(string $token, string $invoice, int $amount, int $sandbox_charge_status = 0)
74+
75+
/**
76+
* Set API URL manually, in case you need to.
77+
*
78+
* @param mixed $api_url
79+
* @return void
80+
*/
81+
public function setApiUrl(string $api_url)
5282
{
53-
$hash = Hashing::tokenizationCharge($this->api_key, $this->merchant_id, $token, $invoice, $amount);
54-
$payload = [
55-
'merchant_id' => $this->merchant_id,
56-
'invoice' => $invoice,
57-
'amount' => $amount,
58-
'sandbox_charge_status' => $sandbox_charge_status,
59-
'hash' => $hash,
60-
];
61-
$response = $this->http_request('cards/token/v1/pay/' . $token, $payload);
62-
return $response;
83+
$this->api_url = $api_url;
6384
}
64-
65-
public function delete_card(string $token)
85+
86+
/**
87+
* Hash (API Key + Merchant ID + ...)
88+
*
89+
* @param mixed $args
90+
* @return string
91+
*/
92+
public function makeHash(string ...$args): string
6693
{
67-
$hash = Hashing::reference($this->api_key, $this->merchant_id, $token);
68-
$payload = [
69-
'merchant_id' => $this->merchant_id,
70-
'hash' => $hash,
71-
];
72-
$response = $this->http_request('cards/token/v1/delete/' . $token, $payload);
73-
return $response;
94+
return md5(implode('|', [$this->api_key, $this->merchant_id, ...$args]));
7495
}
75-
76-
public function http_request(string $url, array $payload)
96+
97+
/**
98+
* Hash2 - reverse of hash() (Merchant ID + API Key + ...)
99+
*
100+
* @param mixed $args
101+
* @return string
102+
*/
103+
public function makeHash2(string ...$args): string
104+
{
105+
return md5(implode('|', [$this->merchant_id, $this->api_key, ...$args]));
106+
}
107+
108+
/**
109+
* Filter payload; remove null or '' array
110+
*
111+
* @param mixed $payload
112+
* @return array
113+
*/
114+
public function filterPayload(array $payload): array
115+
{
116+
return array_filter($payload, fn ($v) => $v !== null && $v !== '');
117+
}
118+
119+
/**
120+
* httpRequest
121+
*
122+
* @param mixed $url
123+
* @param mixed $payload
124+
* @return string
125+
*/
126+
public function httpRequest(string $url, array $payload): array
77127
{
78128
$client = new Client();
79129
try {

src/Exceptions/BetterpayException.php

+35-5
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,32 @@ class BetterpayException extends Exception
1111
private static $error_message = null;
1212

1313
/**
14+
* Configuration exception
15+
*
1416
* @return static
1517
*/
16-
public static function configException()
18+
public static function configException(): static
1719
{
1820
return new static('Missing Betterpay API key, merchant id, API URL, callback URL, success URL, or fail URL.');
1921
}
2022

2123
/**
24+
* Sandbox 3DS exception
25+
*
2226
* @return static
2327
*/
24-
public static function clientException($exception)
28+
public static function sandbox3dsException(): static
29+
{
30+
return new static('Sandbox mode is not supported with 3DS.');
31+
}
32+
33+
/**
34+
* Client exception
35+
*
36+
* @param mixed $exception
37+
* @return static
38+
*/
39+
public static function clientException($exception): static
2540
{
2641
self::$http_code = $exception->getCode();
2742
$response = json_decode($exception->getResponse()->getBody()->getContents(), true);
@@ -36,17 +51,32 @@ public static function clientException($exception)
3651
return new static(self::$error_message);
3752
}
3853

39-
public static function getHttpCode()
54+
/**
55+
* Get http code
56+
*
57+
* @return static
58+
*/
59+
public static function getHttpCode(): static
4060
{
4161
return self::$http_code;
4262
}
4363

44-
public static function getErrorCode()
64+
/**
65+
* Get error code
66+
*
67+
* @return static
68+
*/
69+
public static function getErrorCode(): static
4570
{
4671
return self::$error_code;
4772
}
4873

49-
public static function getErrorMessage()
74+
/**
75+
* Get error message
76+
*
77+
* @return static
78+
*/
79+
public static function getErrorMessage(): static
5080
{
5181
return self::$error_message;
5282
}

src/HashVerification.php

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Sykez\Betterpay;
4+
5+
trait HashVerification
6+
{
7+
/**
8+
* tokenCardVerificationCallback
9+
* - https://www.betterpay.me/docs/?php#mpgs_tokenization6
10+
*
11+
* @param mixed $reference
12+
* @param mixed $status_code
13+
* @param mixed $status_message
14+
* @param mixed $token
15+
* @param mixed $hash
16+
* @return bool
17+
*/
18+
public function tokenCardVerificationCallback(string $reference, string $status_code, string $status_message, string $token, string $hash): bool
19+
{
20+
$_hash = md5($this->api_key . $reference . $status_code . $status_message . $token);
21+
return strcmp($_hash, $hash) !== 0 ? false : true;
22+
}
23+
24+
// https://www.betterpay.me/docs/?php#mpgs_tokenization5
25+
public function reference( string $reference_id)
26+
{
27+
return md5($this->api_key . '|' . urldecode($this->merchant_id) . '|' . urldecode($reference_id));
28+
}
29+
30+
// https://www.betterpay.me/docs/?php#mpgs_tokenization9
31+
public function tokenizationCharge( string $token, string $invoice, int $amount)
32+
{
33+
return md5($this->api_key . '|' . urldecode($this->merchant_id) . '|' . urldecode($token) . '|' . urldecode($invoice) . '|' . urldecode($amount));
34+
}
35+
}

src/Hashing.php

-24
This file was deleted.

0 commit comments

Comments
 (0)