Handling Authorize.Net Silent Post with PHP

Handling Authorize.Net Silent Post submissions with PHP, or any language for that matter, is easy. It’s really no different then receiving a form submission. You just need to know to expect. I took care of that in my All About Authorize.Net’s Silent Post article.

But still, some people need it spelled out for them. This code snippet takes a response and determines the status of it (i.e. approved, declined, expired card, or error):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
< ?php
// Get the subscription ID if it is available. 
// Otherwise $subscription_id will be set to zero.
$subscription_id = (int) $_POST['x_subscription_id'];
 
// Check to see if we got a valid subscription ID.
// If so, do something with it.
if ($subscription_id)
{
    // Get the response code. 1 is success, 2 is decline, 3 is error
    $response_code = (int) $_POST['x_response_code'];
 
    // Get the reason code. 8 is expired card.
    $reason_code = (int) $_POST['x_response_reason_code'];
 
    if ($response_code == 1)
    {
        // Approved!
 
        // Some useful fields might include:
        // $authorization_code = $_POST['x_auth_code'];
        // $avs_verify_result  = $_POST['x_avs_code'];
        // $transaction_id     = $_POST['x_trans_id'];
        // $customer_id        = $_POST['x_cust_id'];
    }
    else if ($response_code == 2)
    {
        // Declined
    }
    else if ($response_code == 3 && $reason_code == 8)
    {
        // An expired card
    }
    else 
    {
        // Other error
    }
}
?>

What you do once you determine the status of a POST response is up to you. Typically updating a database with the result of the transaction is done although the majority of the time this is only done with recurring subscription payments as immediate payments should be logged immediately as opposed to waiting for a Silent Post request.

Related Posts:

19 thoughts on “Handling Authorize.Net Silent Post with PHP

  1. Very good blog! Keep it up. I’m newbie in the software field. And I’m learning new improvements in the software field. Now we have decided to use Authorize.net’s ARB for a new project. And I’m very happy reading this blog. It gave me most of the information that I need for integrating Authorize.net’s ARB service in our new website project. But still I’m in a confusion. I tried creating an ARB subscription. And I know I can process further transactions on that subscription using the subscriptionid which I can store in db in a field corresponding to a customer record. And I’m aware of the silent post feature. But ,as I’m using a test account, I don’t have silent post feature enabled. Anyway I’m planning to have an actual account. But I’m very much confused of where to provide an interface in website, where the customer can come and pay their next subscriptions. Please give me suggestions. I’ll be very thankful to you. And I’m sure you can provide me this information.

    Thanks in advance,
    Greeshma

  2. Great post, your ‘All About Authorize.Net’s Silent Post’ really helped me out too. I have one question though. In your sample code above you list $response_code == 3 && $reason_code == 8 as an expired card. I’m a little confused because I read in your other post that expired cards don’t get handled by the silent post at all.

    “However, if a credit card on file within an ARB subscription has expired a transaction will not process thus you will not receive a Silent Post response, as you only receive Silent Post responses to transactions that process through your account. In order to be notified about expired credit cards, you can enable the ARB email notifications from within the account control panel. ”

    I’m about to write some code to suspend a user’s account if their payment is no good, and I’m wondering if I can do it all through the silent post, or if I need to store the exp-date and make my own scheduled task to parse through them and suspend accounts with expired accounts.

    Any help would be greatly appreciated.

    Thanks,
    Brian

  3. If a credit card is expired when ARB goes to process it it won’t be run at all. ARB knows the card is expired and simply aborts the transaction since the card is obviously no good anymore. However, a credit card may be in the ARB system with an incorrect expiration date, in which case those cards will be processed and will come back as declined.

    So in your case you will want to make a note of a user’s expiration date so you can notify them it is time to update their credit card before it actually does expire and then automatically suspend their account when it is past the expiration date. That will handle the vast majority of your expired card issues. Silent post will only catch the odd ones that have incorrect expiration dates.

  4. Thanks so much for the clarification. That really helps. I’ve got it setup now just like you described. Thanks for the speedy response.

  5. Hi John,

    Thanks for the wonderful posts on authorize.net.
    My question : Is there a way I can authenticate Authorize.net on my silent POST page. Is there a way I can know that the being made to my page is really coming from authorize.net and that its not a hack or a bogus call?

    All help is very much appreciated and Thanks for the help in advance!

  6. You can calculate the MD5 yourself and make sure it matches what is presented to you in Silent Post. The SIM sample code will show you how that is done.

  7. If you mean the URL you define in the Authorize.Net control panel, then yes, that’s how you would do it. Just keep in mind Silent Post works for all APIs, not just ARB.

  8. Pingback: All About Authorize.Net’s Silent Post « Harshil's Blog

  9. Hello John,

    I’ve been reading you articles regarding authorize.net and i found it very easy and helpful.

    Today i was working on the authorize.net’s silent post; and i’m facing problem in updating my database with silent post url response.

    Following is the code i’m using; please let me know what mistakes i’ve done.

    $subscription_id = (int) $_REQUEST['x_subscription_id'];

    // Check to see if we got a valid subscription ID.
    // If so, do something with it.
    if ($subscription_id)
    {
    // Get the response code. 1 is success, 2 is decline, 3 is error
    $response_code = (int) $_REQUEST['x_response_code'];

    // Get the reason code. 8 is expired card.
    $reason_code = (int) $_REQUEST['x_response_reason_code'];
    $sql = “Select user_id from user_invoices where SubscriptionId='”.$_REQUEST['x_subscription_id'].”‘”;
    $subDetail = mysql_fetch_array(mysql_query( $sql ));
    $userid = (isset($subDetail['user_id']))?$subDetail['user_id']:$_REQUEST['x_subscription_id'] ;
    if ($response_code == 1)
    {
    // Approved!

    // Some useful fields might include:
    // $authorization_code = $_POST['x_auth_code'];
    // $avs_verify_result = $_POST['x_avs_code'];
    // $transaction_id = $_POST['x_trans_id'];
    // $customer_id = $_POST['x_cust_id'];
    $result = ‘approved';
    $data = $_REQUEST;
    }
    else if ($response_code == 2)
    {
    // Declined
    $result = ‘Decline';
    $data = $_REQUEST;
    }
    else if ($response_code == 3 && $reason_code == 8)
    {
    // An expired card
    $result = ‘Card Expired';
    $data = $_REQUEST;
    }
    else
    {
    // Other error
    $result = ‘Other Error';
    $data = $_REQUEST;
    }
    $update = ‘insert into user_invoices set
    `user_id` = “‘.$userid.'”,
    `transaction_id`= “‘.$_REQUEST['x_trans_id'].'”,
    `amount_payed` = “‘.$_REQUEST['x_amount'].'”,
    `payment_status` = “‘.$result.'”,
    `payed_on` = “‘.date(‘Y-m-d’).'”,
    `method` = “‘.$_REQUEST['x_method'].'”,
    `SubscriptionId`= “‘.$_REQUEST['x_subscription_id'].'”‘;
    mysql_query($update);

    $f = fopen(‘silentpost.txt’, ‘a’);

    fwrite($f, ‘new-request: ‘);
    fwrite($f, date(‘Y-m-d H:i’));
    fwrite($f, ‘ ‘ . $_SERVER['REQUEST_METHOD']. “\n\n”);
    fwrite($f, ‘ ‘ . $_SERVER['QUERY_STRING']. “\n\n”);
    fwrite($f, ‘ ‘ . $_SERVER['REQUEST_URI']. “\n\n”);
    fwrite($f, ‘ ‘ . print_r($_REQUEST) . “\n\n”);
    fwrite($f, ‘ ‘ .$update . “\n\n”);
    fwrite($f, ‘ ‘ . print_r($data) . “\n\n”);
    fclose($f);
    //fwrite($f, print_r(http_get_request_headers(),1));
    //fwrite($f, print_r($_REQUEST,1));
    }

    Thanks in Advance

  10. Jhon just a question. I’m integrated with Authorize with Checkout Express. If a transaction finihses but the status remains on pending. Is Silent Post Going to pot to my server when this transaction changes hgis status to Completed or denied?? thanks

  11. Hello ,
    Thanks for your nice blog. I have some doubt can you clarify me please ? The silent post url section (notify ) part i got all values except subscription id . how to get subscription id ? i am using recurring payment .. The next recurring payment i will get from silent post url at that time i need subscription id ? how to get please explain ? i already put $subscription_id = (int) _POST['x_subscription_id']; But the value is zero(0)..Help me please

  12. Instead of hard-coding the response codes, you can use the constants defined in AuthorizeNetResponse. Also, a switch statement seems more appropriate than a sequence of ifs.


    switch ($response_code) {
    case AuthorizeNetResponse::APPROVED:
    /* ... */
    break;

    case AuthorizeNetResponse::DECLINED:
    /* ... */
    break;

    case AuthorizeNetResponse::ERROR:
    switch ($reason_code) {
    case 8: # expired card
    /* ... */
    break;
    }
    break;

    case AuthorizeNetResponse::HELD:
    /* ... */
    break;

    default: # Illegal response code. Shouldn't happen, but just in case...
    /* ... */
    break;
    }

  13. how do you check/verify the silent post is authentic, instead of a forged one by random person?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>