Parsian::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Parsian;
4
5
use Shetabit\Multipay\Abstracts\Driver;
6
use Shetabit\Multipay\Contracts\ReceiptInterface;
7
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
8
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
9
use Shetabit\Multipay\Invoice;
10
use Shetabit\Multipay\Receipt;
11
use Shetabit\Multipay\RedirectionForm;
12
use Shetabit\Multipay\Request;
13
14
class Parsian extends Driver
15
{
16
    /**
17
     * Invoice
18
     *
19
     * @var Invoice
20
     */
21
    protected $invoice;
22
23
    /**
24
     * Driver settings
25
     *
26
     * @var object
27
     */
28
    protected $settings;
29
30
    /**
31
     * Parsian constructor.
32
     * Construct the class with the relevant settings.
33
     *
34
     * @param Invoice $invoice
35
     * @param $settings
36
     */
37
    public function __construct(Invoice $invoice, $settings)
38
    {
39
        $this->invoice($invoice);
40
        $this->settings = (object) $settings;
41
    }
42
43
    /**
44
     * Purchase Invoice.
45
     *
46
     * @return string
47
     *
48
     * @throws PurchaseFailedException
49
     * @throws \SoapFault
50
     */
51
    public function purchase()
52
    {
53
        $soap = new \SoapClient($this->settings->apiPurchaseUrl);
54
        $response = $soap->SalePaymentRequest(
55
            ['requestData' => $this->preparePurchaseData()]
56
        );
57
58
        // no response from bank
59
        if (empty($response->SalePaymentRequestResult)) {
60
            throw new PurchaseFailedException('bank gateway not response');
61
        }
62
63
        $result = $response->SalePaymentRequestResult;
64
65
        if (isset($result->Status) && $result->Status == 0 && !empty($result->Token)) {
66
            $this->invoice->transactionId($result->Token);
67
        } else {
68
            // an error has happened
69
            throw new PurchaseFailedException($result->Message);
70
        }
71
72
        // return the transaction's id
73
        return $this->invoice->getTransactionId();
74
    }
75
76
    /**
77
     * Pay the Invoice
78
     *
79
     * @return RedirectionForm
80
     */
81
    public function pay() : RedirectionForm
82
    {
83
        $payUrl = sprintf(
84
            '%s?Token=%s',
85
            $this->settings->apiPaymentUrl,
86
            $this->invoice->getTransactionId()
87
        );
88
89
        return $this->redirectWithForm(
90
            $payUrl,
91
            ['Token' => $this->invoice->getTransactionId()],
92
            'GET'
93
        );
94
    }
95
96
    /**
97
     * Verify payment
98
     *
99
     * @return ReceiptInterface
100
     *
101
     * @throws InvalidPaymentException
102
     * @throws \SoapFault
103
     */
104
    public function verify() : ReceiptInterface
105
    {
106
        $status = Request::input('status');
107
        $token = $this->invoice->getTransactionId() ?? Request::input('Token');
108
109
        if (empty($token)) {
110
            throw new InvalidPaymentException('تراکنش توسط کاربر کنسل شده است.', (int)$status);
111
        }
112
113
        $data = $this->prepareVerificationData();
114
        $soap = new \SoapClient($this->settings->apiVerificationUrl);
115
116
        $response = $soap->ConfirmPayment(['requestData' => $data]);
117
        if (empty($response->ConfirmPaymentResult)) {
118
            throw new InvalidPaymentException('از سمت بانک پاسخی دریافت نشد.');
119
        }
120
        $result = $response->ConfirmPaymentResult;
121
122
        $hasWrongStatus = (!isset($result->Status) || $result->Status != 0);
123
        $hasWrongRRN = (!isset($result->RRN) || $result->RRN <= 0);
124
        if ($hasWrongStatus || $hasWrongRRN) {
125
            $message = 'خطا از سمت بانک با کد '.$result->Status.' رخ داده است.';
126
            throw new InvalidPaymentException($message, (int)$result->Status);
127
        }
128
129
        return $this->createReceipt($result->RRN);
130
    }
131
132
    /**
133
     * Generate the payment's receipt
134
     *
135
     * @param $referenceId
136
     *
137
     * @return Receipt
138
     */
139
    protected function createReceipt($referenceId)
140
    {
141
        $receipt = new Receipt('parsian', $referenceId);
142
143
        return $receipt;
144
    }
145
146
    /**
147
     * Prepare data for payment verification
148
     *
149
     * @return array
150
     */
151
    protected function prepareVerificationData()
152
    {
153
        $transactionId = $this->invoice->getTransactionId() ?? Request::input('Token');
154
155
        return [
156
            'LoginAccount' => $this->settings->merchantId,
157
            'Token'        => $transactionId,
158
        ];
159
    }
160
161
    /**
162
     * Prepare data for purchasing invoice
163
     *
164
     * @return array
165
     */
166
    protected function preparePurchaseData()
167
    {
168
        // The bank suggests that an English description is better
169
        if (empty($description = $this->invoice->getDetail('description'))) {
170
            $description = $this->settings->description;
171
        }
172
173
        $phone = $this->invoice->getDetail('phone')
174
            ?? $this->invoice->getDetail('cellphone')
175
            ?? $this->invoice->getDetail('mobile');
176
177
178
        return [
179
            'LoginAccount'   => $this->settings->merchantId,
180
            'Amount'         => $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1), // convert to rial
181
            'OrderId'        => crc32($this->invoice->getUuid()),
182
            'CallBackUrl'    => $this->settings->callbackUrl,
183
            'Originator'     => $phone,
184
            'AdditionalData' => $description,
185
        ];
186
    }
187
}
188