· 7 years ago · Dec 11, 2018, 07:24 AM
1<?php
2
3namespace App\Helpers\Managers;
4
5use App\User;
6use App\Models\Order;
7use App\Models\Payment;
8use GuzzleHttp\Client;
9use GuzzleHttp\Psr7;
10use GuzzleHttp\Exception\RequestException;
11use App\Helpers\Enums\PaymentStatus;
12use App\Helpers\Enums\OrderStatus;
13
14class PaymentManager {
15
16 private $user;
17 private $order;
18
19 public function __construct (User $usr) {
20 $this->user = $usr;
21 }
22
23 public function pay (Order $order) {
24 $this->order = $order;
25 return $this;
26 }
27
28 public function withMidtrans ($payment) {
29 $apiMidtrans = new Client(['base_uri' => env('MIDTRANS_API_URL')]);
30 $snapMidtrans = new Client(['base_uri' => env('MIDTRANS_SNAP_URL')]);
31 $midtransHeaders = [
32 'Accept' => 'application/json',
33 'Content-Type' => 'application/json',
34 'Authorization' => 'Basic ' . base64_encode(env('MIDTRANS_SERVER_KEY') . ':')
35 ];
36 $payment_obj = [
37 "transaction_details"=> [
38 "gross_amount" => $payment['amount'],
39 "order_id"=> $this->order->id.".".$this->order->booking_number
40 ],
41 "customer_details"=> [
42 "email"=> $this->user->email,
43 "first_name"=> $this->user->firstname,
44 "last_name"=> $this->user->lastname,
45 "phone"=> $this->user->phone
46 ]
47 ];
48
49 $midtrans = $snapMidtrans->request('POST', 'transactions', [
50 'headers' => $midtransHeaders,
51 'json' => $payment_obj
52 ]);
53
54 $midtrans = json_decode($midtrans->getBody());
55 $payment = $this->createPayment($payment, $midtrans->token, PaymentStatus::WAITING);
56
57 $this->order->status = OrderStatus::WAITING_PAYMENT;
58 $this->order->save();
59
60 $this->order->histories()->create([
61 'description' => OrderStatus::getString($this->order->status),
62 'status' => $this->order->status
63 ]);
64
65 $payment->histories()->create([
66 'description' => PaymentStatus::getString($payment->status),
67 'status' => $payment->status
68 ]);
69
70 return $payment;
71 }
72
73 public function withWinmarket ($payment) {
74 try {
75 $token = $this->getWinMarketToken();
76 $date = \Carbon\Carbon::now();
77 $name = 'Ticket '. $this->order->booking_number;
78 $user = $this->user;
79 $item = array();
80 $price = 0;
81 $i = 0;
82 $api = env('WINMARKET_API_URL');
83 $privateKey1 = env('WINMARKET_PRIVATE_KEY1');
84 $privateKey2 = env('WINMARKET_PRIVATE_KEY2');
85
86 $item[$i]['name'] = $name;
87 $item[$i]['sku'] = $this->order->booking_number;
88 $item[$i]['qty'] = 1;
89 $item[$i]['unitPrice'] = $payment['amount'];
90 $item[$i]['desc'] = $name;
91 $item[$i]['produkToken'] = '';
92 $item[$i]['totalPrice'] = $payment['amount'];
93 $price = $payment['amount'];
94
95 $json = [
96 'cms'=> 'API_DIRECT',
97 'authKey'=> '',
98 'url_listener'=> url('/api/v1/payment/handling/'.$payment['gateway']),
99 'spi_currency'=> 'IDR',
100 'spi_item'=> $item,
101 'spi_item_description'=> $name,
102 'spi_price'=> $price,
103 'spi_quantity'=> 1,
104 'spi_is_escrow'=> '0',
105 'spi_amount'=> $price,
106 'spi_token'=> $privateKey1.$privateKey2,
107 'spi_merchant_transaction_reff'=> $this->order->booking_order,
108 'spi_item_expedition'=> '0',
109 'spi_billingPhone'=> $user->phone,
110 'spi_billingEmail'=> 'ervan@marlinbooking.id',
111 'spi_billingName'=> $user->firstname,
112 'spi_paymentDate'=> '',
113 'spi_request_key'=> $token
114 ];
115 $message = json_encode($json);
116 $messageEncrypted = $this->encryptData($message, $token);
117 $messageEncrypted = substr($messageEncrypted, 0, 10) . $token . substr($messageEncrypted, 10);
118 $messageEncrypted = trim($messageEncrypted);
119 $url = $api.$payment['gateway']; //URL SPI Speedcash
120
121 $client = new Client([
122 'timeout' => 0,
123 ]);
124 $response = $client->request('POST', $url, [
125 'form_params' => [
126 'orderdata' => $messageEncrypted
127 ]
128 ]);
129 $httpcode = $response->getStatusCode();
130 if (in_array($httpcode, array(200, 201))) {
131 $winmarket = json_decode($response->getBody());
132 $payment = $this->createPayment($payment, $winmarket->payment_code, PaymentStatus::WAITING);
133
134 $this->order->status = OrderStatus::WAITING_PAYMENT;
135 $this->order->save();
136
137 $this->order->histories()->create([
138 'description' => OrderStatus::getString($this->order->status),
139 'status' => $this->order->status
140 ]);
141
142 $payment->histories()->create([
143 'description' => PaymentStatus::getString($payment->status),
144 'status' => $payment->status
145 ]);
146 return $payment;
147 } else {
148 throw new \Exception(json_encode($body), $httpcode);
149 }
150 } catch(RequestException $e) {
151 if ($e->hasResponse()) {
152 throw new \Exception('Failed to make payment with selected gateway', $e->getCode());
153 }
154 throw new \Exception('Failed to make payment with selected gateway.', 500);
155 }
156 }
157
158 public function getWinMarketToken()
159 {
160 $url = env('WINMARKET_TOKEN_URL');
161 $privateKey1 = env('WINMARKET_PRIVATE_KEY1');
162 $privateKey2 = env('WINMARKET_PRIVATE_KEY2');
163
164 $ch = curl_init();
165 curl_setopt($ch, CURLOPT_URL, $url);
166 curl_setopt($ch, CURLOPT_TIMEOUT, 120); //timeout after 30 seconds
167 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);
168 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
169 curl_setopt($ch, CURLOPT_REFERER, "https://marlinbooking.co.id");
170 $headers = array(
171 'Content-Type:application/json',
172 'Authorization: Basic ' . base64_encode($privateKey1 . ":" . $privateKey2)
173 );
174 curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
175 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
176 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
177 // curl_setopt($ch, CURLOPT_SSLVERSION, 3); untuk production aja
178 $result = curl_exec($ch);
179 return $result;
180 }
181
182 public function withLoketCash ($payment) {
183 if ($payment['gateway'] == 'cash') {
184 $token = $this->user->id;
185 } else {
186 $token = $payment['token'];
187 }
188 $payment = $this->createPayment($payment, $token, PaymentStatus::PAID);
189
190 $this->order->status = OrderStatus::COMPLETED;
191 $this->order->save();
192
193 $this->order->histories()->create([
194 'description' => OrderStatus::getString($this->order->status),
195 'status' => $this->order->status
196 ]);
197
198 $payment->histories()->create([
199 'description' => PaymentStatus::getString($payment->status),
200 'status' => $payment->status
201 ]);
202
203 return $payment;
204 }
205
206 public function withStripe($payment) {
207 $amount = intval($payment['amount']);
208
209 $currency = 'idr';
210 $stripe_manager = new StripeManager();
211 $stripe_manager->build();
212 $customer = $stripe_manager->createCustomer($payment['token'], $this->user->email);
213 $charge = $stripe_manager->createCharge($amount, $currency, $customer);
214
215 if(!$charge) {
216 throw new \Exception('Failed to make a payment transaction.', 500);
217 }
218
219 $token = $charge->id;
220 $status = $charge->paid ? PaymentStatus::PAID : PaymentStatus::WAITING;
221
222 if (strtolower($charge->status) == 'succeeded') {
223 $status = PaymentStatus::PAID;
224 $this->order->amount = ($amount / 100);
225 $this->order->status = OrderStatus::COMPLETED;
226 $this->order->save();
227 } else if (strtolower($charge->status) == 'pending') {
228 $status = PaymentStatus::WAITING;
229 $this->order->amount = ($amount / 100);
230 $this->order->status = OrderStatus::PENDING;
231 $this->order->save();
232 } else {
233 $status = PaymentStatus::CANCELED;
234 $this->order->amount = ($amount / 100);
235 $this->order->status = OrderStatus::CANCELED;
236 $this->order->save();
237 }
238
239 $payment['amount'] = intval($payment['amount']) / 100;
240
241 $payment = $this->createPayment($payment, $token, $status);
242
243 $this->order->histories()->create([
244 'description' => OrderStatus::getString($this->order->status),
245 'status' => $this->order->status
246 ]);
247
248 $payment->histories()->create([
249 'description' => PaymentStatus::getString($payment->status),
250 'status' => $payment->status
251 ]);
252
253 return $payment;
254 }
255
256 public function withOvo ($data) {
257 $manager = new OvoManager();
258 $manager->build($data);
259 $response = $manager->beginTransaction($this->order);
260
261 if (!$response) {
262 throw new \Exception('Failed to create transaction');
263 }
264
265 $order_manager = new OrderManager($this->user);
266 $status = PaymentStatus::PAID;
267
268 $token = $response['response']->traceNumber;
269 if (isset($response['response']->traceNumber)) {
270 $token .= '-'.$response['response']->approvalCode;
271 }
272
273 $payment = $this->createPayment($data['payment'], $token, $status);
274
275 $this->order->status = OrderStatus::COMPLETED;
276 $this->order->save();
277
278 $this->order->histories()->create([
279 'description' => OrderStatus::getString($this->order->status),
280 'status' => $this->order->status
281 ]);
282
283 $payment->histories()->create([
284 'description' => PaymentStatus::getString($payment->status),
285 'status' => $payment->status
286 ]);
287
288 return $payment;
289 }
290
291 public function encryptData($message, $key)
292 {
293 $output = false;
294 $encrypt_method = "AES-256-CBC";
295 $secret_key = $key;
296 $secret_iv = $key;
297 // hash
298 $key = hash('sha256', $secret_key);
299 // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
300 $iv = substr(hash('sha256', $secret_iv), 0, 16);
301
302 $output = openssl_encrypt($message, $encrypt_method, $key, 0, $iv);
303 $output = base64_encode($output);
304
305 return $output;
306 }
307
308 public function createPayment($pay, $token, $status) {
309 $payment = new Payment;
310 $payment->order_id = $this->order->id;
311 $payment->amount = $pay['amount'];
312 $payment->token = $token;
313 $payment->status = $status;
314 $payment->type = $pay['type'];
315 $payment->gateway = $pay['gateway'];
316
317 if (!$payment->save()) {
318 throw new \Exception('Failed to create payment');
319 }
320
321 return $payment;
322 }
323
324}