-
Notifications
You must be signed in to change notification settings - Fork 0
/
Yoco.php
179 lines (153 loc) · 5.54 KB
/
Yoco.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<?php
namespace App\Classes;
use App\Classes\Config\Config;
/**
* Yoco Class
*
* This class provides functionality for integrating with the Yoco payment gateway.
* It allows you to create and manage checkouts, add line items, and perform API requests.
*
* @package App\Classes
*/
class Yoco
{
private $id; // not always needed
private $failureUrl; // yoco sends the customer there on failure
private $redirectUrl; // yoco sends this to you to send the customer to
private $successUrl; // yoco sends the customer there on success
private $cancelUrl; // yoco sends the customer there when they cancel
private $amount; // cents
private $currency; / ZAR
private $metadata = []; // undocumented, but it's an array map of info you can send them, unsure where they display it.
private $totalDiscount; // display purposes only
/**
* Array of line items for the checkout.
*
* This property holds an array of line items that provide additional details
* for the items purchased during the checkout process. Each line item should
* be an associative array with the following structure:
*
* [
* "displayName" => "Product Name",
* "description" => "Product Description",
* "quantity" => 1, // Quantity of the product
* "pricingDetails" => [
* "price" => 100, // Price of the product in cents
* ],
* ]
*
* @var array
*/
private $lineItems = [];
private $totalTaxAmount; // display purposes only
private $subtotalAmount; // not always needed
private $yocoConfig; // my config for this payment gateway
public function __construct()
{
$this->id = bin2hex(random_bytes(5));
$this->currency = 'ZAR';
$this->totalDiscount = 0;
$this->yocoConfig = Config::get('payment_gateway')['yoco'];
}
public function setUrls($successUrl, $cancelUrl, $failureUrl = '')
{
$this->successUrl = $successUrl;
$this->cancelUrl = $cancelUrl;
$this->failureUrl = $failureUrl;
}
public function addItem($item)
{
if ($this->validateInvoiceLineItem($item)) {
$this->lineItems[] = $item;
return true; // Item added successfully
} else {
return false; // Validation failed
}
}
private function validateInvoiceLineItem($item)
{
// Define the required fields and their types
$requiredFields = [
"displayName" => "string",
"description" => "string",
"quantity" => "integer",
"pricingDetails" => "array"
];
// Check if all required fields are present and have the correct type
foreach ($requiredFields as $field => $type) {
if (!array_key_exists($field, $item) || gettype($item[$field]) !== $type) {
return false;
}
}
// Check the pricingDetails structure if it's an array
if (isset($item["pricingDetails"]) && !is_array($item["pricingDetails"])) {
return false;
}
return true; // All validation checks passed
}
public function getItems() {
if(empty($this->lineItems)) {
return 'No items has been added yet, please add items first.';
}
return $this->lineItems;
}
public function checkout($amount, $note = '', $additionalNote = '', $transactionId = '')
{
// Construct checkout data
$this->amount = $amount;
$this->totalTaxAmount = $this->amount - ($this->amount) / 1.15; // show the tax separately - 99 - (99/(1.15)) = R12.91 VAT
if (!$this->lineItems) {
echo 'No items have been added yet, please add items first.';
return false;
}
$data = array(
"amount" => $this->amount,
"totalTaxAmount" => $this->totalTaxAmount,
"currency" => $this->currency,
"totalDiscount" => $this->totalDiscount,
"successUrl" => $this->successUrl,
"cancelUrl" => $this->cancelUrl,
"failureUrl" => $this->failureUrl,
"metadata" => array(
"billNote" => $note, // optional
"additionalNote" => $additionalNote, // optional
"transactionId" => $transactionId, // optional
),
"lineItems" => $this->getItems()
);
// Perform the API request
$response = $this->sendCheckoutRequest($data);
if ($response === false) {
return false; // Failed to perform API request
}
return $response;
}
private function sendCheckoutRequest($data)
{
$payload = json_encode($data);
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://payments.yoco.com/api/checkouts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer ".$this->yocoConfig['xxxx_api_key'],
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
$err = "cURL Error #:" . $err;
return false;
} else {
return $response;
}
}
}