Passed
Push — master ( 56fbd8...c5e685 )
by Brian
04:51
created

GetPaid_Authorize_Net_Gateway::get_line_items()   B

Complexity

Conditions 9
Paths 65

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 21
c 1
b 0
f 0
dl 0
loc 35
rs 8.0555
cc 9
nc 65
nop 1
1
<?php
2
/**
3
 * Authorize.net payment gateway
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * Authorize.net Payment Gateway class.
11
 *
12
 */
13
class GetPaid_Authorize_Net_Gateway extends GetPaid_Authorize_Net_Legacy_Gateway {
14
15
    /**
16
	 * Payment method id.
17
	 *
18
	 * @var string
19
	 */
20
    public $id = 'authorizenet';
21
22
    /**
23
	 * An array of features that this gateway supports.
24
	 *
25
	 * @var array
26
	 */
27
    protected $supports = array( 'subscription', 'sandbox', 'tokens' );
28
29
    /**
30
	 * Payment method order.
31
	 *
32
	 * @var int
33
	 */
34
    public $order = 4;
35
36
    /**
37
	 * Endpoint for requests from Authorize.net.
38
	 *
39
	 * @var string
40
	 */
41
	protected $notify_url;
42
43
	/**
44
	 * Endpoint for requests to Authorize.net.
45
	 *
46
	 * @var string
47
	 */
48
    protected $endpoint;
49
50
    /**
51
	 * Currencies this gateway is allowed for.
52
	 *
53
	 * @var array
54
	 */
55
	public $currencies = array( 'USD', 'CAD', 'GBP', 'DKK', 'NOK', 'PLN', 'SEK', 'AUD', 'EUR', 'NZD' );
56
57
    /**
58
	 * URL to view a transaction.
59
	 *
60
	 * @var string
61
	 */
62
    public $view_transaction_url = 'https://{sandbox}authorize.net/ui/themes/sandbox/Transaction/TransactionReceipt.aspx?transid=%s';
63
64
    /**
65
	 * Class constructor.
66
	 */
67
	public function __construct() {
68
69
        $this->title                = __( 'Credit Card / Debit Card', 'invoicing' );
70
        $this->method_title         = __( 'Authorize.Net', 'invoicing' );
71
        $this->notify_url           = wpinv_get_ipn_url( $this->id );
72
73
        add_filter( 'getpaid_daily_maintenance_should_expire_subscription', array( $this, 'maybe_renew_subscription' ), 10, 2 );
74
        add_filter( 'wpinv_gateway_description', array( $this, 'sandbox_notice' ), 10, 2 );
75
        parent::__construct();
76
    }
77
78
    /**
79
	 * Displays the payment method select field.
80
	 *
81
	 * @param int $invoice_id 0 or invoice id.
82
	 * @param GetPaid_Payment_Form $form Current payment form.
83
	 */
84
    public function payment_fields( $invoice_id, $form ) {
85
86
        // Let the user select a payment method.
87
        echo $this->saved_payment_methods();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->saved_payment_methods() targeting GetPaid_Payment_Gateway::saved_payment_methods() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
88
89
        // Show the credit card entry form.
90
        echo $this->new_payment_method_entry( $this->get_cc_form( true ) );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->new_payment_metho...his->get_cc_form(true)) targeting GetPaid_Payment_Gateway:..._payment_method_entry() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
91
    }
92
93
    /**
94
	 * Creates a customer profile.
95
	 *
96
	 *
97
	 * @param WPInv_Invoice $invoice Invoice.
98
     * @param array $submission_data Posted checkout fields.
99
     * @param bool $save Whether or not to save the payment as a token.
100
     * @link https://developer.authorize.net/api/reference/index.html#customer-profiles-create-customer-profile
101
	 * @return string|WP_Error Payment profile id.
102
	 */
103
	public function create_customer_profile( $invoice, $submission_data, $save = true ) {
104
105
        // Remove non-digits from the number
106
        $submission_data['authorizenet']['cc_number'] = preg_replace('/\D/', '', $submission_data['authorizenet']['cc_number'] );
107
108
        // Generate args.
109
        $args = array(
110
            'createCustomerProfileRequest' => array(
111
                'merchantAuthentication'   => $this->get_auth_params(),
112
                'profile'                  => array(
113
                    'merchantCustomerId'   => getpaid_limit_length( $invoice->get_user_id(), 20 ),
114
                    'description'          => getpaid_limit_length( $invoice->get_full_name(), 255 ),
115
                    'email'                => getpaid_limit_length( $invoice->get_email(), 255 ),
116
                    'paymentProfiles'      => array(
117
                        'customerType'     => 'individual',
118
119
                        // Billing information.
120
                        'billTo'           => array(
121
                            'firstName'    => getpaid_limit_length( $invoice->get_first_name(), 50 ),
122
                            'lastName'     => getpaid_limit_length( $invoice->get_last_name(), 50 ),
123
                            'address'      => getpaid_limit_length( $invoice->get_last_name(), 60 ),
124
                            'city'         => getpaid_limit_length( $invoice->get_city(), 40 ),
125
                            'state'        => getpaid_limit_length( $invoice->get_state(), 40 ),
126
                            'zip'          => getpaid_limit_length( $invoice->get_zip(), 20 ),
127
                            'country'      => getpaid_limit_length( $invoice->get_country(), 60 ),
128
                        ),
129
130
                        // Payment information.
131
                        'payment'          => $this->get_payment_information( $submission_data['authorizenet'] ),
132
                    )
133
                ),
134
                'validationMode'           => $this->is_sandbox( $invoice ) ? 'testMode' : 'liveMode',
135
            )
136
        );
137
138
        $response = $this->post( apply_filters( 'getpaid_authorizenet_customer_profile_args', $args, $invoice ), $invoice );
139
140
        if ( is_wp_error( $response ) ) {
141
            return $response;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response also could return the type stdClass which is incompatible with the documented return type WP_Error|string.
Loading history...
142
        }
143
144
        update_user_meta( $invoice->get_user_id(), $this->get_customer_profile_meta_name( $invoice ), $response->customerProfileId );
0 ignored issues
show
Bug introduced by
The property customerProfileId does not seem to exist on WP_Error.
Loading history...
145
146
        // Save the payment token.
147
        if ( $save ) {
148
            $this->save_token(
149
                array(
150
                    'id'      => $response->customerPaymentProfileIdList[0],
0 ignored issues
show
Bug introduced by
The property customerPaymentProfileIdList does not seem to exist on WP_Error.
Loading history...
151
                    'name'    => getpaid_get_card_name( $submission_data['authorizenet']['cc_number'] ) . '&middot;&middot;&middot;&middot;' . substr( $submission_data['authorizenet']['cc_number'], -4 ),
152
                    'default' => true,
153
                    'type'    => $this->is_sandbox( $invoice ) ? 'sandbox' : 'live',
154
                )
155
            );
156
        }
157
158
        // Add a note about the validation response.
159
        $invoice->add_note(
160
            sprintf( __( 'Created Authorize.NET customer profile: %s', 'invoicing' ), $response->validationDirectResponseList[0] ),
0 ignored issues
show
Bug introduced by
The property validationDirectResponseList does not seem to exist on WP_Error.
Loading history...
161
            false,
162
            false,
163
            true
164
        );
165
166
        return $response->customerPaymentProfileIdList[0];
167
    }
168
169
    /**
170
	 * Retrieves a customer profile.
171
	 *
172
	 *
173
	 * @param string $profile_id profile id.
174
	 * @return string|WP_Error Profile id.
175
     * @link https://developer.authorize.net/api/reference/index.html#customer-profiles-get-customer-profile
176
	 */
177
	public function get_customer_profile( $profile_id ) {
178
179
        // Generate args.
180
        $args = array(
181
            'getCustomerProfileRequest'  => array(
182
                'merchantAuthentication' => $this->get_auth_params(),
183
                'customerProfileId'      => $profile_id,
184
            )
185
        );
186
187
        return $this->post( $args, false );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->post($args, false) also could return the type stdClass which is incompatible with the documented return type WP_Error|string.
Loading history...
Bug introduced by
false of type false is incompatible with the type WPInv_Invoice expected by parameter $invoice of GetPaid_Authorize_Net_Legacy_Gateway::post(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

187
        return $this->post( $args, /** @scrutinizer ignore-type */ false );
Loading history...
188
189
    }
190
191
    /**
192
	 * Creates a customer profile.
193
	 *
194
	 *
195
     * @param string $profile_id profile id.
196
	 * @param WPInv_Invoice $invoice Invoice.
197
     * @param array $submission_data Posted checkout fields.
198
     * @param bool $save Whether or not to save the payment as a token.
199
     * @link https://developer.authorize.net/api/reference/index.html#customer-profiles-create-customer-profile
200
	 * @return string|WP_Error Profile id.
201
	 */
202
	public function create_customer_payment_profile( $customer_profile, $invoice, $submission_data, $save ) {
203
204
        // Remove non-digits from the number
205
        $submission_data['authorizenet']['cc_number'] = preg_replace('/\D/', '', $submission_data['authorizenet']['cc_number'] );
206
207
        // Generate args.
208
        $args = array(
209
            'createCustomerPaymentProfileRequest' => array(
210
                'merchantAuthentication'   => $this->get_auth_params(),
211
                'customerProfileId'        => $customer_profile,
212
                'paymentProfile'           => array(
213
214
                    // Billing information.
215
                    'billTo'           => array(
216
                        'firstName'    => getpaid_limit_length( $invoice->get_first_name(), 50 ),
217
                        'lastName'     => getpaid_limit_length( $invoice->get_last_name(), 50 ),
218
                        'address'      => getpaid_limit_length( $invoice->get_last_name(), 60 ),
219
                        'city'         => getpaid_limit_length( $invoice->get_city(), 40 ),
220
                        'state'        => getpaid_limit_length( $invoice->get_state(), 40 ),
221
                        'zip'          => getpaid_limit_length( $invoice->get_zip(), 20 ),
222
                        'country'      => getpaid_limit_length( $invoice->get_country(), 60 ),
223
                    ),
224
225
                    // Payment information.
226
                    'payment'          => $this->get_payment_information( $submission_data['authorizenet'] )
227
                ),
228
                'validationMode'       => $this->is_sandbox( $invoice ) ? 'testMode' : 'liveMode',
229
            )
230
        );
231
232
        $response = $this->post( apply_filters( 'getpaid_authorizenet_create_customer_payment_profile_args', $args, $invoice ), $invoice );
233
234
        if ( is_wp_error( $response ) ) {
235
            return $response;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response also could return the type stdClass which is incompatible with the documented return type WP_Error|string.
Loading history...
236
        }
237
238
        // Save the payment token.
239
        if ( $save ) {
240
            $this->save_token(
241
                array(
242
                    'id'      => $response->customerPaymentProfileId,
0 ignored issues
show
Bug introduced by
The property customerPaymentProfileId does not seem to exist on WP_Error.
Loading history...
243
                    'name'    => getpaid_get_card_name( $submission_data['authorizenet']['cc_number'] ) . ' &middot;&middot;&middot;&middot; ' . substr( $submission_data['authorizenet']['cc_number'], -4 ),
244
                    'default' => true
245
                )
246
            );
247
        }
248
249
        // Add a note about the validation response.
250
        $invoice->add_note(
251
            sprintf( __( 'Saved Authorize.NET payment profile: %s', 'invoicing' ), $response->validationDirectResponse ),
0 ignored issues
show
Bug introduced by
The property validationDirectResponse does not seem to exist on WP_Error.
Loading history...
252
            false,
253
            false,
254
            true
255
        );
256
257
258
        return $response->customerPaymentProfileId;
259
    }
260
261
    /**
262
	 * Retrieves a customer payment profile.
263
	 *
264
	 *
265
	 * @param string $customer_profile_id customer profile id.
266
     * @param string $payment_profile_id payment profile id.
267
	 * @return string|WP_Error Profile id.
268
     * @link https://developer.authorize.net/api/reference/index.html#customer-profiles-get-customer-payment-profile
269
	 */
270
	public function get_customer_payment_profile( $customer_profile_id, $payment_profile_id ) {
271
272
        // Generate args.
273
        $args = array(
274
            'getCustomerPaymentProfileRequest' => array(
275
                'merchantAuthentication'       => $this->get_auth_params(),
276
                'customerProfileId'            => $customer_profile_id,
277
                'customerPaymentProfileId'     => $payment_profile_id,
278
            )
279
        );
280
281
        return $this->post( $args, false );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->post($args, false) also could return the type stdClass which is incompatible with the documented return type WP_Error|string.
Loading history...
Bug introduced by
false of type false is incompatible with the type WPInv_Invoice expected by parameter $invoice of GetPaid_Authorize_Net_Legacy_Gateway::post(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

281
        return $this->post( $args, /** @scrutinizer ignore-type */ false );
Loading history...
282
283
    }
284
285
    /**
286
	 * Charges a customer payment profile.
287
	 *
288
     * @param string $customer_profile_id customer profile id.
289
     * @param string $payment_profile_id payment profile id.
290
	 * @param WPInv_Invoice $invoice Invoice.
291
     * @link https://developer.authorize.net/api/reference/index.html#payment-transactions-charge-a-customer-profile
292
	 * @return WP_Error|object
293
	 */
294
	public function charge_customer_payment_profile( $customer_profile_id, $payment_profile_id, $invoice ) {
295
296
        // Generate args.
297
        $args = array(
298
299
            'createTransactionRequest'         => array(
300
301
                'merchantAuthentication'       => $this->get_auth_params(),
302
                'refId'                        => $invoice->get_id(),
303
                'transactionRequest'           => array(
304
                    'transactionType'          => 'authCaptureTransaction',
305
                    'amount'                   => $invoice->get_total(),
306
                    'currencyCode'             => $invoice->get_currency(),
307
                    'profile'                  => array(
308
                        'customerProfileId'    => $customer_profile_id,
309
                        'paymentProfile'       => array(
310
                            'paymentProfileId' => $payment_profile_id,
311
                        )
312
                    ),
313
                    'order'                    => array(
314
                        'invoiceNumber'        => getpaid_limit_length( $invoice->get_number(), 20 ),
315
                    ),
316
                    'lineItems'                => array( 'lineItem' => $this->get_line_items( $invoice ) ),
317
                    'tax'                      => array(
318
                        'amount'               => $invoice->get_total_tax(),
319
                        'name'                 => getpaid_tax()->get_vat_name(),
320
                    ),
321
                    'poNumber'                 => getpaid_limit_length( $invoice->get_number(), 25 ),
322
                    'customer'                 => array(
323
                        'id'                   => getpaid_limit_length( $invoice->get_user_id(), 25 ),
324
                        'email'                => getpaid_limit_length( $invoice->get_email(), 25 ),
325
                    ),
326
                    'customerIP'               => $invoice->get_ip(),
327
                )
328
            )
329
        );
330
331
        if ( 0 == $invoice->get_total_tax() ) {
332
            unset( $args['createTransactionRequest']['transactionRequest']['tax'] );
333
        }
334
335
        return $this->post( apply_filters( 'getpaid_authorizenet_charge_customer_payment_profile_args', $args, $invoice ), $invoice );
336
337
    }
338
339
    /**
340
	 * Processes a customer charge.
341
	 *
342
     * @param stdClass $result Api response.
343
	 * @param WPInv_Invoice $invoice Invoice.
344
	 */
345
	public function process_charge_response( $result, $invoice ) {
346
347
        wpinv_clear_errors();
348
		$response_code = (int) $result->transactionResponse->responseCode;
349
350
		// Succeeded.
351
		if ( 1 == $response_code || 4 == $response_code ) {
352
353
			// Maybe set a transaction id.
354
			if ( ! empty( $result->transactionResponse->transId ) ) {
355
				$invoice->set_transaction_id( $result->transactionResponse->transId );
356
			}
357
358
			$invoice->add_note( sprintf( __( 'Authentication code: %s (%s).', 'invoicing' ), $result->transactionResponse->authCode, $result->transactionResponse->accountNumber ), false, false, true );
359
360
			if ( 1 == $response_code ) {
361
				return $invoice->mark_paid();
362
			}
363
364
			$invoice->set_status( 'wpi-onhold' );
365
        	$invoice->add_note(
366
                sprintf(
367
                    __( 'Held for review: %s', 'invoicing' ),
368
                    $result->transactionResponse->messages->message[0]->description
369
                )
370
			);
371
372
			return $invoice->save();
373
374
		}
375
376
        wpinv_set_error( 'card_declined', __( 'Credit card declined.', 'invoicing' ) );
377
378
        if ( ! empty( $result->transactionResponse->errors ) ) {
379
            $errors = (object) $result->transactionResponse->errors;
380
            wpinv_set_error( $errors->error[0]->errorCode, esc_html( $errors->error[0]->errorText ) );
381
        }
382
383
    }
384
385
    /**
386
	 * Returns payment information.
387
	 *
388
	 *
389
	 * @param array $card Card details.
390
	 * @return array
391
	 */
392
	public function get_payment_information( $card ) {
393
        return array(
394
395
            'creditCard'         => array (
396
                'cardNumber'     => $card['cc_number'],
397
                'expirationDate' => $card['cc_expire_year'] . '-' . $card['cc_expire_month'],
398
                'cardCode'       => $card['cc_cvv2'],
399
            )
400
401
        );
402
    }
403
404
    /**
405
	 * Returns the customer profile meta name.
406
	 *
407
	 *
408
	 * @param WPInv_Invoice $invoice Invoice.
409
	 * @return string
410
	 */
411
	public function get_customer_profile_meta_name( $invoice ) {
412
        return $this->is_sandbox( $invoice ) ? 'getpaid_authorizenet_sandbox_customer_profile_id' : 'getpaid_authorizenet_customer_profile_id';
413
    }
414
415
    /**
416
	 * Validates the submitted data.
417
	 *
418
	 *
419
	 * @param array $submission_data Posted checkout fields.
420
     * @param WPInv_Invoice $invoice
421
	 * @return WP_Error|string The payment profile id
422
	 */
423
	public function validate_submission_data( $submission_data, $invoice ) {
424
425
        // Validate authentication details.
426
        $auth = $this->get_auth_params();
427
428
        if ( empty( $auth['name'] ) || empty( $auth['transactionKey'] ) ) {
429
            return new WP_Error( 'invalid_settings', __( 'Please set-up your login id and transaction key before using this gateway.', 'invoicing') );
430
        }
431
432
        // Validate the payment method.
433
        if ( empty( $submission_data['getpaid-authorizenet-payment-method'] ) ) {
434
            return new WP_Error( 'invalid_payment_method', __( 'Please select a different payment method or add a new card.', 'invoicing') );
435
        }
436
437
        // Are we adding a new payment method?
438
        if ( 'new' != $submission_data['getpaid-authorizenet-payment-method'] ) {
439
            return $submission_data['getpaid-authorizenet-payment-method'];
440
        }
441
442
        // Retrieve the customer profile id.
443
        $profile_id = get_user_meta( $invoice->get_user_id(), $this->get_customer_profile_meta_name( $invoice ), true );
444
445
        // Create payment method.
446
        if ( empty( $profile_id ) ) {
447
            return $this->create_customer_profile( $invoice, $submission_data, ! empty( $submission_data['getpaid-authorizenet-new-payment-method'] ) );
448
        }
449
450
        return $this->create_customer_payment_profile( $profile_id, $invoice, $submission_data, ! empty( $submission_data['getpaid-authorizenet-new-payment-method'] ) );
451
452
    }
453
454
    /**
455
	 * Returns invoice line items.
456
	 *
457
	 *
458
	 * @param WPInv_Invoice $invoice Invoice.
459
	 * @return array
460
	 */
461
	public function get_line_items( $invoice ) {
462
        $items = array();
463
464
        foreach ( $invoice->get_items() as $item ) {
465
466
            $amount  = $invoice->is_renewal() ? $item->get_price() : $item->get_initial_price();
467
            $items[] = array(
468
                'itemId'      => getpaid_limit_length( $item->get_id(), 31 ),
469
                'name'        => getpaid_limit_length( $item->get_raw_name(), 31 ),
470
                'description' => getpaid_limit_length( $item->get_description(), 255 ),
471
                'quantity'    => (string) $invoice->get_template() == 'amount' ? 1 : $item->get_quantity(),
472
                'unitPrice'   => (float) $amount,
473
                'taxable'     => wpinv_use_taxes() && $invoice->is_taxable() && 'tax-exempt' != $item->get_vat_rule(),
474
            );
475
476
        }
477
478
        foreach ( $invoice->get_fees() as $fee_name => $fee ) {
479
480
            $amount  = $invoice->is_renewal() ? $fee['recurring_fee'] : $fee['initial_fee'];
481
482
            if ( $amount > 0 ) {
483
                $items[] = array(
484
                    'itemId'      => getpaid_limit_length( $fee_name, 31 ),
485
                    'name'        => getpaid_limit_length( $fee_name, 31 ),
486
                    'description' => getpaid_limit_length( $fee_name, 255 ),
487
                    'quantity'    => '1',
488
                    'unitPrice'   => (float) $amount,
489
                    'taxable'     => false,
490
                );
491
            }
492
493
        }
494
495
        return $items;
496
    }
497
498
    /**
499
	 * Process Payment.
500
	 *
501
	 *
502
	 * @param WPInv_Invoice $invoice Invoice.
503
	 * @param array $submission_data Posted checkout fields.
504
	 * @param GetPaid_Payment_Form_Submission $submission Checkout submission.
505
	 * @return array
506
	 */
507
	public function process_payment( $invoice, $submission_data, $submission ) {
508
509
        // Validate the submitted data.
510
        $payment_profile_id = $this->validate_submission_data( $submission_data, $invoice );
511
512
        // Do we have an error?
513
        if ( is_wp_error( $payment_profile_id ) ) {
514
            wpinv_set_error( $payment_profile_id->get_error_code(), $payment_profile_id->get_error_message() );
515
            wpinv_send_back_to_checkout();
516
        }
517
518
        // Save the payment method to the order.
519
        update_post_meta( $invoice->get_id(), 'getpaid_authorizenet_profile_id', $payment_profile_id );
520
521
        // Check if this is a subscription or not.
522
        $subscription = getpaid_get_invoice_subscription( $invoice );
523
        if ( ! empty( $subscription ) ) {
524
            $this->process_subscription( $invoice, $subscription );
0 ignored issues
show
Bug introduced by
It seems like $subscription can also be of type boolean; however, parameter $subscription of GetPaid_Authorize_Net_Ga...:process_subscription() does only seem to accept WPInv_Subscription, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

524
            $this->process_subscription( $invoice, /** @scrutinizer ignore-type */ $subscription );
Loading history...
525
        }
526
527
        // If it is free, send to the success page.
528
        if ( ! $invoice->needs_payment() ) {
529
            $invoice->mark_paid();
530
            wpinv_send_to_success_page( array( 'invoice_key' => $invoice->get_key() ) );
531
        }
532
533
        // Charge the payment profile.
534
        $this->process_initial_payment( $invoice );
535
536
        wpinv_send_to_success_page( array( 'invoice_key' => $invoice->get_key() ) );
537
538
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
539
540
	}
541
	
542
	/**
543
	 * Processes the initial payment.
544
	 *
545
     * @param WPInv_Invoice $invoice Invoice.
546
	 */
547
	protected function process_initial_payment( $invoice ) {
548
549
		$payment_profile_id = get_post_meta( $invoice->get_id(), 'getpaid_authorizenet_profile_id', true );
550
        $customer_profile   = get_user_meta( $invoice->get_user_id(), $this->get_customer_profile_meta_name( $invoice ), true );
551
		$result             = $this->charge_customer_payment_profile( $customer_profile, $payment_profile_id, $invoice );
0 ignored issues
show
Bug introduced by
It seems like $payment_profile_id can also be of type false; however, parameter $payment_profile_id of GetPaid_Authorize_Net_Ga...tomer_payment_profile() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

551
		$result             = $this->charge_customer_payment_profile( $customer_profile, /** @scrutinizer ignore-type */ $payment_profile_id, $invoice );
Loading history...
Bug introduced by
It seems like $customer_profile can also be of type false; however, parameter $customer_profile_id of GetPaid_Authorize_Net_Ga...tomer_payment_profile() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

551
		$result             = $this->charge_customer_payment_profile( /** @scrutinizer ignore-type */ $customer_profile, $payment_profile_id, $invoice );
Loading history...
552
553
		// Do we have an error?
554
		if ( is_wp_error( $result ) ) {
555
			wpinv_set_error( $result->get_error_code(), $result->get_error_message() );
556
			wpinv_send_back_to_checkout();
557
		}
558
559
		// Process the response.
560
		$this->process_charge_response( $result, $invoice );
0 ignored issues
show
Bug introduced by
$result of type WP_Error is incompatible with the type stdClass expected by parameter $result of GetPaid_Authorize_Net_Ga...ocess_charge_response(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

560
		$this->process_charge_response( /** @scrutinizer ignore-type */ $result, $invoice );
Loading history...
561
562
		if ( wpinv_get_errors() ) {
563
			wpinv_send_back_to_checkout();
564
		}
565
566
	}
567
568
    /**
569
	 * Processes recurring payments.
570
	 *
571
     * @param WPInv_Invoice $invoice Invoice.
572
     * @param WPInv_Subscription $subscription Subscription.
573
	 */
574
	public function process_subscription( $invoice, $subscription ) {
575
576
        // Check if there is an initial amount to charge.
577
        if ( (float) $invoice->get_total() > 0 ) {
578
			$this->process_initial_payment( $invoice );
579
        }
580
581
        // Activate the subscription.
582
        $duration = strtotime( $subscription->get_expiration() ) - strtotime( $subscription->get_date_created() );
583
        $expiry   = date( 'Y-m-d H:i:s', ( current_time( 'timestamp' ) + $duration ) );
584
585
		$subscription->set_next_renewal_date( $expiry );
586
		$subscription->set_date_created( current_time( 'mysql' ) );
587
		$subscription->set_profile_id( $invoice->generate_key() );
588
		$subscription->activate();
589
590
		// Redirect to the success page.
591
        wpinv_send_to_success_page( array( 'invoice_key' => $invoice->get_key() ) );
592
593
    }
594
595
	/**
596
	 * (Maybe) renews an authorize.net subscription profile.
597
	 *
598
	 *
599
	 * @param bool $should_expire
600
     * @param WPInv_Subscription $subscription
601
	 */
602
	public function maybe_renew_subscription( $should_expire, $subscription ) {
603
604
        // Ensure its our subscription && it's active.
605
        if ( $this->id != $subscription->get_gateway() || ! $subscription->has_status( 'active trialling' ) ) {
606
            return $should_expire;
607
        }
608
609
        // If this is the last renewal, complete the subscription.
610
        if ( $subscription->is_last_renewal() ) {
611
            $subscription->complete();
612
            return false;
613
        }
614
615
        $this->renew_subscription( $subscription );
616
617
        return false;
618
619
	}
620
621
    /**
622
	 * Renews a subscription.
623
	 *
624
     * @param WPInv_Subscription $subscription
625
	 */
626
	public function renew_subscription( $subscription ) {
627
628
		// Generate the renewal invoice.
629
		$new_invoice = $subscription->create_payment();
630
		$old_invoice = $subscription->get_parent_payment();
631
632
        if ( empty( $new_invoice ) ) {
633
            $old_invoice->add_note( __( 'Error generating a renewal invoice.', 'invoicing' ), false, false, false );
634
            $subscription->failing();
635
            return;
636
        }
637
638
        // Charge the payment method.
639
		$payment_profile_id = get_post_meta( $old_invoice->get_id(), 'getpaid_authorizenet_profile_id', true );
640
		$customer_profile   = get_user_meta( $old_invoice->get_user_id(), $this->get_customer_profile_meta_name( $old_invoice ), true );
641
		$result             = $this->charge_customer_payment_profile( $customer_profile, $payment_profile_id, $new_invoice );
0 ignored issues
show
Bug introduced by
It seems like $payment_profile_id can also be of type false; however, parameter $payment_profile_id of GetPaid_Authorize_Net_Ga...tomer_payment_profile() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

641
		$result             = $this->charge_customer_payment_profile( $customer_profile, /** @scrutinizer ignore-type */ $payment_profile_id, $new_invoice );
Loading history...
Bug introduced by
It seems like $customer_profile can also be of type false; however, parameter $customer_profile_id of GetPaid_Authorize_Net_Ga...tomer_payment_profile() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

641
		$result             = $this->charge_customer_payment_profile( /** @scrutinizer ignore-type */ $customer_profile, $payment_profile_id, $new_invoice );
Loading history...
642
643
		// Do we have an error?
644
		if ( is_wp_error( $result ) ) {
645
646
			$old_invoice->add_note(
647
				sprintf( __( 'Error renewing subscription : ( %s ).', 'invoicing' ), $result->get_error_message() ),
648
				true,
649
				false,
650
				true
651
			);
652
			$subscription->failing();
653
			return;
654
655
		}
656
657
		// Process the response.
658
		$this->process_charge_response( $result, $new_invoice );
0 ignored issues
show
Bug introduced by
$result of type WP_Error is incompatible with the type stdClass expected by parameter $result of GetPaid_Authorize_Net_Ga...ocess_charge_response(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

658
		$this->process_charge_response( /** @scrutinizer ignore-type */ $result, $new_invoice );
Loading history...
659
660
		if ( wpinv_get_errors() ) {
661
662
			$old_invoice->add_note(
663
				sprintf( __( 'Error renewing subscription : ( %s ).', 'invoicing' ), getpaid_get_errors_html() ),
664
				true,
665
				false,
666
				true
667
			);
668
			$subscription->failing();
669
			return;
670
671
        }
672
673
        $subscription->add_payment( array(), $new_invoice );
674
        $subscription->renew();
675
    }
676
677
    /**
678
     * Displays a notice on the checkout page if sandbox is enabled.
679
     */
680
    public function sandbox_notice( $description, $gateway ) {
681
682
        if ( $this->id == $gateway && wpinv_is_test_mode( $this->id ) ) {
683
            $description .= '<br>&nbsp;<br>' . sprintf(
684
                __( 'SANDBOX ENABLED. You can use sandbox testing details only. See the %sAuthorize.NET Sandbox Testing Guide%s for more details.', 'invoicing' ),
685
                '<a href="https://developer.authorize.net/hello_world/testing_guide.html">',
686
                '</a>'
687
            );
688
        }
689
        return $description;
690
691
    }
692
693
    /**
694
	 * Filters the gateway settings.
695
	 *
696
	 * @param array $admin_settings
697
	 */
698
	public function admin_settings( $admin_settings ) {
699
700
        $currencies = sprintf(
701
            __( 'Supported Currencies: %s', 'invoicing' ),
702
            implode( ', ', $this->currencies )
703
        );
704
705
        $admin_settings['authorizenet_active']['desc'] .= " ($currencies)";
706
        $admin_settings['authorizenet_desc']['std']     = __( 'Pay securely using your credit or debit card.', 'invoicing' );
707
708
        $admin_settings['authorizenet_login_id'] = array(
709
            'type' => 'text',
710
            'id'   => 'authorizenet_login_id',
711
            'name' => __( 'API Login ID', 'invoicing' ),
712
            'desc' => '<a href="https://support.authorize.net/s/article/How-do-I-obtain-my-API-Login-ID-and-Transaction-Key"><em>' . __( 'How do I obtain my API Login ID and Transaction Key?', 'invoicing' ) . '</em></a>',
713
        );
714
715
        $admin_settings['authorizenet_transaction_key'] = array(
716
            'type' => 'text',
717
            'id'   => 'authorizenet_transaction_key',
718
            'name' => __( 'Transaction Key', 'invoicing' ),
719
        );
720
721
        $admin_settings['authorizenet_signature_key'] = array(
722
            'type' => 'text',
723
            'id'   => 'authorizenet_signature_key',
724
            'name' => __( 'Signature Key', 'invoicing' ),
725
            'desc' => '<a href="https://support.authorize.net/s/article/What-is-a-Signature-Key"><em>' . __( 'Learn more.', 'invoicing' ) . '</em></a>',
726
        );
727
728
        $admin_settings['authorizenet_ipn_url'] = array(
729
            'type'     => 'ipn_url',
730
            'id'       => 'authorizenet_ipn_url',
731
            'name'     => __( 'Webhook URL', 'invoicing' ),
732
            'std'      => $this->notify_url,
733
            'desc'     => __( 'Create a new webhook using this URL as the endpoint URL and set it to receive all payment events.', 'invoicing' ) . ' <a href="https://support.authorize.net/s/article/How-do-I-add-edit-Webhook-notification-end-points"><em>' . __( 'Learn more.', 'invoicing' ) . '</em></a>',
734
            'custom'   => 'authorizenet',
735
            'readonly' => true,
736
        );
737
738
		return $admin_settings;
739
	}
740
741
}
742