AuthorizeDotNetPayment::executeURL()   B
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 19
nc 3
nop 1
1
<?php
0 ignored issues
show
Coding Style introduced by
File has mixed line endings; this may cause incorrect results
Loading history...
2
3
/**
4
 * This class provides an e-commerce payment gateway to the Authorize.net DPM method
5
 * (note that there also seems to be SIM and AIM)
6
 *
7
 * @author nicolaas[at]sunnysideup.co.nz
8
 * visit https://developer.authorize.net/ and sign up for account to start testing
9
 * @see:
10
 * https://developer.authorize.net/guides/DPM/wwhelp/wwhimpl/js/html/wwhelp.htm
11
 * https://developer.authorize.net/tools/responsecode99/
12
 * http://www.authorize.net/support/merchant/wwhelp/wwhimpl/js/html/wwhelp.htm
13
 * https://developer.authorize.net/tools/responsecode97/
14
 * https://developer.authorize.net/tools/
15
 *
16
 */
17
18
class AuthorizeDotNetPayment extends EcommercePayment
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
19
{
20
21
    /**
22
     * Standard SS variable
23
     * @var Array
24
     **/
25
    private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
26
        'ValuesSubmitted' => 'Text',
27
        'Hash' => 'Varchar(255)',
28
        'ValuesReceived' => 'Text'
29
    );
30
31
    /**
32
     * must be set - check for live vs test values
33
     * @var String
34
     **/
35
    private static $api_login_id = 'YOUR_API_LOGIN_ID';
0 ignored issues
show
Unused Code introduced by
The property $api_login_id is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
36
37
    /**
38
     * must be set - check for live vs test values
39
     * @var String
40
     **/
41
    private static $transaction_key = 'YOUR_TRANSACTION_KEY';
0 ignored issues
show
Unused Code introduced by
The property $transaction_key is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
42
43
    /**
44
     * Not sure if this is needed....
45
     * @var String
46
     **/
47
    private static $md5_setting = '';
0 ignored issues
show
Unused Code introduced by
The property $md5_setting is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
48
49
    /**
50
     * we are not using any special variables here
51
     * @var String
52
     **/
53
    private static $show_form_type = 'PAYMENT_FORM';
0 ignored issues
show
Unused Code introduced by
The property $show_form_type is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
54
55
    /**
56
     * Test URL that form is submitted to
57
     * @var String
58
     **/
59
    private static $debug_url = 'https://developer.authorize.net/tools/paramdump/index.php';
60
61
    /**
62
     * Test URL that form is submitted to
63
     * @var String
64
     **/
65
    private static $test_url = 'https://test.authorize.net/gateway/transact.dll';
66
67
    /**
68
     * Test URL that form is submitted to
69
     * @var String
70
     **/
71
    private static $live_url = 'https://secure.authorize.net/gateway/transact.dll';
72
73
74
    /**
75
     * Link to information about privacy
76
     * @var String
77
     **/
78
    private static $privacy_link = '';
0 ignored issues
show
Unused Code introduced by
The property $privacy_link is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
79
80
81
    /**
82
     * Link to Authorize.net logo
83
     * @var String
84
     **/
85
    private static $logo_link = '';
0 ignored issues
show
Unused Code introduced by
The property $logo_link is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
86
87
    /**
88
     *
89
     * @param Int $timeStamp
90
     * @param String $amount - needs to be formatted at 11.00 (two digits)
91
     *
92
     * @return String
93
     */
94
    public static function create_fingerprint($myID, $timeStamp, $amount)
95
    {
96
        $string = Config::inst()->get("AuthorizeDotNetPayment", "api_login_id") . "^" . $myID . "^" . $timeStamp . "^" . $amount . "^";
97
        $key = Config::inst()->get("AuthorizeDotNetPayment", "transaction_key");
98
        $fingerprint = hash_hmac("md5", $string, $key);
99
        //debug::log($string."---".$key."---".$fingerprint);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
100
        return $fingerprint;
101
    }
102
103
    /**
104
     *
105
     * @var boolean
106
     */
107
    protected $debug = false;
108
109
    public function getCMSFields()
110
    {
111
        $fields = parent::getCMSFields();
112
        $fields->replaceField("DebugMessage", new ReadonlyField("DebugMessage", "Debug info"));
113
        return $fields;
114
    }
115
116
    /**
117
     * fields for the final step of the checkout out process...
118
     * @return FieldList
119
     */
120
    public function getPaymentFormFields()
121
    {
122
        $logoLink = $this->Config()->get("logo_link");
123
        $logo = "";
124
        if ($logoLink) {
125
            $logo = '<img src="' . $logoLink . '" alt="Credit card payments powered by Authorize.Net"/>';
126
        }
127
        $privacyLink = $this->Config()->get("privacy_link");
128
        $privacy = "";
129
        if ($privacyLink) {
130
            if ($logo) {
131
                $privacy = '<a href="' . $privacyLink . '" target="_blank" title="Read AuthorizeDotNet\'s privacy policy">' . $logo . '</a>';
132
            } else {
133
                $privacy = '<a href="' . $privacyLink . '" target="_blank" title="Read AuthorizeDotNet\'s privacy policy">Powered by Authorize . net</a>';
134
            }
135
        }
136
        $fields = new FieldList(
137
            new LiteralField('AuthorizeDotNetInfo', $privacy)
138
        );
139
        return $fields;
140
    }
141
142
    public function getPaymentFormRequirements()
143
    {
144
        return array();
145
    }
146
147
    public function processPayment($data, $form)
148
    {
149
        $amount = 0;
150
        $member = null;
151
        $billingAddress = null;
152
        $shippingAddress = null;
153
        $order = $this->Order();
0 ignored issues
show
Documentation Bug introduced by
The method Order does not exist on object<AuthorizeDotNetPayment>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
154
        if ($order) {
155
            $billingAddress = $order->BillingAddress();
156
            $shippingAddress = $order->ShippingAddress();
157
            $orderID = $order->ID;
0 ignored issues
show
Unused Code introduced by
$orderID is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
158
            $amount = number_format($this->getAmountValue(), 2, '.', '');
159
            $currency = $this->getAmountCurrency();
0 ignored issues
show
Unused Code introduced by
$currency is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
160
            if ($member = $order->Member()) {
161
                $email = $member->Email;
0 ignored issues
show
Unused Code introduced by
$email is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
162
            }
163
        }
164
        $this->write();
165
        $timeStamp = time();
166
        $fingerprint = self::create_fingerprint($this->ID, $timeStamp, $amount);
167
        $this->Hash = $fingerprint;
0 ignored issues
show
Documentation introduced by
The property Hash does not exist on object<AuthorizeDotNetPayment>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
168
        $this->write();
169
        //start creating object and end with
170
        $obj = new stdClass();
171
        $obj->fields = array();
172
        $obj->label = _t("AuthorizeDotNet.PAYNOW", "Pay now");
173
        $obj->fingerprint = $fingerprint;
174
        //IMPORTANT!
175
        $obj->fields["x_invoice_num"] = $this->ID;
176
        //all the other stuff...
177
        $obj->fields["x_login"] = $this->Config()->get("api_login_id");
178
        $obj->fields["x_amount"] = $amount;
179
        //$obj->fields["x_currency_code"] = $currency;
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
180
        $obj->fields["x_fp_sequence"] = $this->ID;
181
        $obj->fields["x_fp_timestamp"] = $timeStamp;
182
        $obj->fields["x_fp_hash"] = $fingerprint;
183
        $obj->fields["x_test_request"] = ($this->isLiveMode() ? "false" : "true");
184
        $obj->fields["x_show_form"] = $this->Config()->get("show_form_type");
185
        $obj->fields["x_recurring_billing"] = "false";
186
        $obj->fields["x_description"] =  $order->Title();
187
        $obj->fields["x_first_name"] = $billingAddress->FirstName;
188
        $obj->fields["x_last_name"] = $billingAddress->Surname;
189
        $obj->fields["x_company"] = "";
190
        $obj->fields["x_address"] = $billingAddress->Address." ".$billingAddress->Address2;
191
        $obj->fields["x_city"] = $billingAddress->City;
192
        $region =  EcommerceRegion::get()->byID($billingAddress->RegionID);
193
        if ($region) {
194
            $obj->fields["x_state"] = $region->Code;
195
        }
196
        $obj->fields["x_zip"] = $billingAddress->PostalCode;
197
        $obj->fields["x_country"] = $billingAddress->Country;
198
        $obj->fields["x_phone"] = $billingAddress->Phone;
199
        $obj->fields["x_fax"] = "";
200
        $obj->fields["x_email"] = $member->Email;
201
        $obj->fields["x_cust_id"] = $member->ID;
202
        $obj->fields["x_ship_to_first_name"] = $shippingAddress->ShippingFirstName;
203
        $obj->fields["x_ship_to_last_name"] = $shippingAddress->ShippingSurname;
204
        $obj->fields["x_ship_to_company"] = "";
205
        $obj->fields["x_ship_to_address"] = $shippingAddress->ShippingAddress." ".$shippingAddress->ShippingAddress2;
206
        $obj->fields["x_ship_to_city"] = $shippingAddress->ShippingCity;
207
        $region =  EcommerceRegion::get()->byID($shippingAddress->ShippingRegionID);
208
        if ($region) {
209
            $obj->fields["x_ship_to_state"] = $region->Code;
210
        }
211
        $obj->fields["x_ship_to_zip"] = $shippingAddress->ShippingPostalCode;
212
        $obj->fields["x_ship_to_country"] = $shippingAddress->ShippingCountry;
213
        $obj->fields["x_receipt_link_method"] = "POST";
214
        $obj->fields["x_receipt_link_text"] = _t("AuthorizeDotNet.FINALISE", "Finalise now");
215
        $obj->fields["x_receipt_link_url"] = AuthorizeDotNetPxPayPayment_Handler::complete_link($timeStamp, true);
216
217
        $this->ValuesSubmitted = serialize($obj);
0 ignored issues
show
Documentation introduced by
The property ValuesSubmitted does not exist on object<AuthorizeDotNetPayment>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
218
        $this->write();
219
        return $this->executeURL($obj);
220
    }
221
222
223
    /**
224
     * executes payment: redirects to Authorize.net
225
     *
226
     * @param Object $obj
227
     *
228
     */
229
    protected function executeURL($obj)
230
    {
231
        Requirements::clear();
232
        Requirements::javascript(THIRDPARTY_DIR."/jquery/jquery.js");
233
        $page = new Page();
234
        if ($obj->fingerprint) {
235
            $page->Title = 'Redirection to Authorize.Net...';
236
            $logoLink = $this->Config()->get("logo_link");
237
            $page->Logo = "";
238
            if ($logoLink) {
239
                $page->Logo = '<img src="' . $logoLink . '" alt="Payments powered by Authorize.Net" />';
240
            }
241
            $page->Form = $this->AuthorizeDotNetForm($obj);
242
            $controller = new ContentController($page);
243
            //Requirements::block(THIRDPARTY_DIR."/jquery/jquery.js");
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
244
            //Requirements::javascript(Director::protocol()."ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js");
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
245
            return EcommercePayment_Processing::create($controller->renderWith('PaymentProcessingPage'));
246
        } else {
247
            $page->Title = 'Sorry, Authorize.Net can not be contacted at the moment ...';
248
            $page->Logo = '';
249
            $page->Form = 'Sorry, an error has occurred in contacting the Payment Processing Provider (Authorize.Net), please try again in a few minutes or contact the website provider...';
250
            $controller = new ContentController($page);
251
            //Requirements::block(THIRDPARTY_DIR."/jquery/jquery.js");
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
252
            //Requirements::javascript(Director::protocol()."ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js");
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
253
            return EcommercePayment_Failure::create($controller->renderWith('PaymentProcessingPage'));
254
        }
255
    }
256
257
    /**
258
     * turns an object into HTML.
259
     *
260
     * @param Object $obj
261
     *
262
     * @return String (html)
263
     */
264
    protected function AuthorizeDotNetForm($obj)
265
    {
266
        $obj->ActionURL = $this->isLiveMode() ? self::$live_url : self::$test_url;
267
        if ($this->debug) {
268
            $obj->ActionURL = self::$debug_url;
269
        }
270
        $html = '
271
			<form id="PaymentFormAuthorizeDotNet" method="post" action="'.$obj->ActionURL.'">';
272
        foreach ($obj->fields as $field => $value) {
273
            $html .= '
274
				<input type="hidden" name="'.$field.'" value="'.Convert::raw2att($value).'" />';
275
        }
276
        if ($this->debug) {
277
            $obj->fields["transaction_key"] = $this->Config()->get("transaction_key");
278
            foreach ($obj->fields as $field => $value) {
279
                $html .= '
280
					'.$field.' = '.$value.'<br />';
281
            }
282
        }
283
        $html .='
284
				<input type="submit" value="'.$obj->label.'" />
285
			</form>
286
			<script type="text/javascript">
287
				jQuery(document).ready(function() {
288
					if(!jQuery.browser.msie) {
289
						//jQuery("#PaymentFormAuthorizeDotNet").submit();
290
					}
291
				});
292
			</script>';
293
        return $html;
294
    }
295
296
    protected function isLiveMode()
297
    {
298
        return Director::isLive();
299
    }
300
}
301
302
class AuthorizeDotNetPxPayPayment_Handler extends Controller
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
303
{
304
    private static $response_approved = 1;
305
    private static $response_declined = 2;
0 ignored issues
show
Unused Code introduced by
The property $response_declined is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
306
    private static $response_error = 3;
0 ignored issues
show
Unused Code introduced by
The property $response_error is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
307
    private static $response_held = 4;
308
309
    private static $allowed_actions = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $allowed_actions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
310
        "paid"
311
    );
312
313
    /**
314
     * make sure that this value is the same as the one set in the route
315
     * yml config file!
316
     *
317
     * @var String
318
     *
319
     */
320
    private static $url_segment = 'authorizedotnetpxpaypayment';
0 ignored issues
show
Unused Code introduced by
The property $url_segment is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
321
322
    /**
323
     * returns relative or absolute link to payment handler
324
     * @param Boolean $absolute
325
     * @return String
0 ignored issues
show
Documentation introduced by
Should the return type not be false|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
326
     */
327
    public static function complete_link($timeStamp, $absolute = false)
328
    {
329
        $link = Config::inst()->get("AuthorizeDotNetPxPayPayment_Handler", "url_segment") . '/paid/'.$timeStamp."/";
330
        if ($absolute) {
331
            $link = Director::AbsoluteURL($link);
332
        }
333
        return $link;
334
    }
335
336
    /**
337
     * confirm payment...
338
     * @param HTTP_Request (SS_HTTPRequest)
339
     */
340
    public function paid($request)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
Coding Style introduced by
paid uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
paid uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
341
    {
342
        $timeStamp = $request->param("ID");
343
        if ($timeStamp) {
344
            //find payment
345
            $payment = AuthorizeDotNetPayment::get()->byID(intval($_POST["x_invoice_num"]));
346
            if ($payment) {
347
                $payment->ValuesReceived = Convert::raw2sql(serialize($_POST));
348
                //already completed?
349
                if ($payment->Status != "Incomplete") {
350
                    return $payment->redirectToOrder();
351
                }
352
                //get amount ...
353
                if (isset($_REQUEST["x_amount"])) {
354
                    $amount = $_REQUEST["x_amount"];
355
                } else {
356
                    $amount = "0.00";
357
                }
358
                //check if it is authorize.net response
359
                $checkHash = AuthorizeDotNetPayment::create_fingerprint($payment->ID, trim($timeStamp), $amount);
360
                if ($payment->Hash == $checkHash) {
361
                    $payment->Hash = "";
362
                    //now we know it is legit, lets see the response...
363
                    $responseCode = $_POST["x_response_code"];
364
                    if ($responseCode == self::$response_approved) {
365
                        $payment->Status = 'Success';
366
                    } elseif ($responseCode == self::$response_held) {
367
                        $payment->Status = 'Pending';
368
                    } else {
369
                        $payment->Status = 'Failure';
370
                    }
371
                } else {
372
                    $payment->Status = 'Failure';
373
                }
374
                $payment->write();
375
                return $payment->redirectToOrder();
376
            } else {
377
                USER_ERROR("PAYMENT COULD NOT BE FOUND ", E_USER_WARNING);
378
            }
379
        } else {
380
            USER_ERROR("URL IS MISSING TIMESTAMP OF TRANSACTION", E_USER_WARNING);
381
        }
382
    }
383
}
384