Test Failed
Push — master ( 35163f...e607ec )
by Martin
05:29
created

Mollie   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 48
c 1
b 0
f 0
dl 0
loc 138
rs 10
wmc 18

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
C updatePayment() 0 63 14
A getPaymentUrl() 0 35 3
1
<?php
2
3
namespace App\PaymentProvider;
4
5
use App\Purchase;
6
use App\Exceptions\PaymentProviderException;
7
use App\Mail\TicketsPaid;
8
use Illuminate\Support\Facades\Log;
9
use Illuminate\Support\Facades\Mail;
10
use Mollie\Api\MollieApiClient;
11
12
/**
13
 * Class to process requests to Mollie
14
 * 
15
 * Find docs @ https://github.com/mollie/mollie-api-php
16
 */
17
class Mollie
18
{
19
    /**
20
     * API-Object; initialized by constructor
21
     */
22
    protected $apiClient;
23
24
    /**
25
     * 
26
     * @param string $configKey Configuration key for this exact project
27
     * @return void
28
     */
29
    public function __construct($configKey)
30
    {
31
        $this->apiClient = new MollieApiClient();
32
        $this->apiClient->setApiKey($configKey);
33
    }
34
35
    /**
36
     * Generates for a given Purchase a payment request at Mollie and
37
     * returns a payment url where the customer can pay the purchase
38
     * 
39
     * For more details on the payment-create-process take a look at
40
     * https://github.com/mollie/mollie-api-php/blob/master/examples/payments/create-payment.php
41
     * 
42
     * @param Purchase $purchase the customer's purchase
43
     * @return string PaymentUrl to Mollie for the given purchase
44
     */
45
    public function getPaymentUrl(Purchase $purchase)
46
    {
47
        // Format the purchase's total to have 2 decimals being seperated by a dot and without
48
        // a thousand-seperator. Format = 123456.78
49
        $amountFormatted = number_format($purchase->total(), 2, '.', '');
50
51
        $firstEvent = $purchase->events()->pop();
52
53
        try {
54
            $payment = $this->apiClient->payments->create([
55
                'amount' => [
56
                    'currency' => 'EUR',
57
                    'value'    => $amountFormatted
58
                ],
59
                'description' => $firstEvent->project->name . ' | ' . $firstEvent->second_name,
60
                'redirectUrl' => route('ticket.purchase', $purchase),
61
                'webhookUrl'  => route('ts.payment.mollie.webhook'),
62
                'metadata' => [
63
                    'purchase_id' => $purchase->id
64
                ]
65
            ]);
66
            
67
            // Store the payment-reference from Mollie to the associated purchase
68
            $purchase->payment_id = $payment->id;
69
            $purchase->save();
70
71
        } catch( \Mollie\Api\Exceptions\ApiException $e ) {
72
            throw new PaymentProviderException( $e );
73
        }
74
75
        // Set a reference to the customer, depending if a user object exists
76
        $customerReference = $purchase->customer ? $purchase->customer->id : $purchase->customer_name;
77
        Log::info('[Purchase#' . $purchase->id . '] Created Payment#' . $payment->id . ' @Mollie and sending customer#' . $customerReference . ' to payment provider');
78
        
79
        return $payment->getCheckoutUrl();
80
    }
81
82
    /**
83
     * This function gets called by the mollie webhook
84
     * 
85
     * For more details on the payment-create-process take a look at
86
     * https://github.com/mollie/mollie-api-php/blob/master/examples/payments/webhook.php
87
     * 
88
     * @param string $paymentId 
89
     * @return void 
90
     * @throws PaymentProviderException 
91
     */
92
    public function updatePayment(string $paymentId)
93
    {
94
        try {
95
            // Retrieve the payment's current state and its associated purchase
96
            $payment = $this->apiClient->payments->get($paymentId);
97
            $purchaseId = $payment->metadata->purchase_id;
98
            $purchase = Purchase::find($purchaseId);
99
100
            if( !$purchase ) {
101
                throw new PaymentProviderException('Payment-Id "' . $paymentId . '" has no matching purchase!');
102
            }
103
104
            if( $payment->isPaid() && !$payment->hasRefunds() && !$payment->hasChargebacks() ) {
105
                /*
106
                * The payment is paid and isn't refunded or charged back.
107
                */
108
                // Only send an email with the tickets on the change of state to "paid"
109
                if($purchase->state != 'paid') {
110
                    Log::info('[Purchase#' . $purchase->id . '] Sending Ticket-Mail.');
111
                    Mail::to($purchase->customer)->send(new TicketsPaid($purchase));
112
                }
113
            } elseif( $payment->isOpen() ) {
114
                /*
115
                * The payment is open.
116
                */
117
            } elseif( $payment->isPending() ) {
118
                /*
119
                * The payment is pending.
120
                */
121
            } elseif( $payment->isFailed() ) {
122
                /*
123
                * The payment has failed.
124
                */
125
                $purchase->deleteWithAllData();
126
            } elseif( $payment->isExpired() ) {
127
                /*
128
                * The payment is expired.
129
                */
130
                $purchase->deleteWithAllData();
131
            } elseif( $payment->isCanceled() ) {
132
                /*
133
                * The payment has been canceled.
134
                */
135
                $purchase->deleteWithAllData();
136
            } elseif( $payment->hasRefunds() ) {
137
                /*
138
                * The payment has been (partially) refunded.
139
                * The status of the payment is still "paid"
140
                */
141
            } elseif( $payment->hasChargebacks() ) {
142
                /*
143
                * The payment has been (partially) charged back.
144
                * The status of the payment is still "paid"
145
                */
146
            }
147
148
            // Update the purchase's state
149
            $purchase->state = $payment->status;
150
            $purchase->state_updated = new \DateTime();
151
            $purchase->save();
152
153
        } catch (\Mollie\Api\Exceptions\ApiException $e) {
154
            throw new PaymentProviderException( $e );
155
        }
156
    }
157
158
}
159