Archive

Posts Tagged ‘Credit Card Processing’

Simple Credit Card Processing using VB.NET and AUTHORIZE.NET

August 24, 2011 Leave a comment

Today I built a custom credit card payment processor for a website I’m building. The site I’m using didn’t need a full featured cart and store, and it was custom enough that we decided to build our own processor using the Authorize.Net API. I found a great walk through by Keith Fimreite at Enkode showing how to do this using a simple form and C#. I’m a VB.NET guy and also wanted to move all of the code into some classes so that I could easily re-use it elsewhere. The final result is below, followed by an example subroutine that might connect it to an ASP.NET form.

Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Collections
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports System.Net
Imports System.Net.Mail

Namespace C2IT.PaymentProcessors

    Public Class AuthorizeDotNet

        Public Class MerchantInfo
            Public AuthNetVersion As String = "3.1" 'Contains CCV support
            Public MerchantEmail As String = ""
            Public AuthNetLoginId As String = "" 'Set AuthNetLoginId here (or in the calling routine)
            Public AuthNetTransKey As String = "" ' Get this from your authorize.net merchant interface (set it here or in the calling routine)
        End Class

        Public Class Output
            Public AuthorizationCode As String
            Public TransactionId As String
            Public HasError As Boolean
            Public ErrorMessage As String
        End Class

        Public Class OrderInfo
            Public FirstName As String
            Public LastName As String
            Public Phone As String
            Public Address As String
            Public City As String
            Public State As String
            Public ZipCode As String
            Public Email As String
            Public Country As String
            Public Amount As Double
            Public Description As String
            Public IPNumber As String
            Public CreditCardNumber As String
            Public ExpireDate As String
            Public SecurityCode As String

        End Class

        Public Shared Function ProcessPayment(ByVal Merchant As MerchantInfo, ByVal Order As OrderInfo) As Output
            Dim rv As New Output

            Dim webClientRequest As New WebClient()
            Dim InputObject As New System.Collections.Specialized.NameValueCollection(30)
            Dim ReturnObject As New System.Collections.Specialized.NameValueCollection(30)

            Dim ReturnBytes As Byte()
            Dim ReturnValues As String()

            InputObject.Add("x_version", Merchant.AuthNetVersion)
            InputObject.Add("x_delim_data", "True")
            InputObject.Add("x_login", Merchant.AuthNetLoginId)
            InputObject.Add("x_tran_key", Merchant.AuthNetTransKey)
            InputObject.Add("x_relay_response", "False")

            'Set this to false to go live
            InputObject.Add("x_test_request", "True")

            InputObject.Add("x_delim_char", ",")
            InputObject.Add("x_encap_char", "|")

            'Billing Address
            InputObject.Add("x_first_name", Order.FirstName)
            InputObject.Add("x_last_name", Order.LastName)
            InputObject.Add("x_phone", Order.Phone)
            InputObject.Add("x_address", Order.Address)
            InputObject.Add("x_city", Order.City)
            InputObject.Add("x_state", Order.State)
            InputObject.Add("x_zip", Order.ZipCode)
            InputObject.Add("x_email", Order.Email)
            InputObject.Add("x_email_customer", "TRUE")                     'Emails Customer
            InputObject.Add("x_merchant_email", Merchant.MerchantEmail)  'Emails Merchant
            InputObject.Add("x_country", Order.Country)
            InputObject.Add("x_customer_ip", Order.IPNumber)

            'Amount
            InputObject.Add("x_description", Order.Description + ": " + String.Format("{0:c2}", Order.Amount)) 'Description of Purchase

            'Card Details
            InputObject.Add("x_card_num", Order.CreditCardNumber)
            InputObject.Add("x_exp_date", Order.ExpireDate) 'MM/DD
            InputObject.Add("x_card_code", Order.SecurityCode)

            InputObject.Add("x_method", "CC")
            InputObject.Add("x_type", "AUTH_CAPTURE")
            InputObject.Add("x_amount", String.Format("{0:c2}", Order.Amount))

            'Currency setting. Check the guide for other supported currencies
            InputObject.Add("x_currency_code", "USD")

            Try
                'Actual Server
                'Set above Testmode=off to go live
                webClientRequest.BaseAddress = "https://secure.authorize.net/gateway/transact.dll"

                ReturnBytes = webClientRequest.UploadValues(webClientRequest.BaseAddress, "POST", InputObject)
                ReturnValues = System.Text.Encoding.ASCII.GetString(ReturnBytes).Split(",".ToCharArray())

                If ReturnValues(0).Trim(Char.Parse("|")) = "1" Then
                    rv.AuthorizationCode = ReturnValues(4).Trim(Char.Parse("|"))
                    rv.TransactionId = ReturnValues(6).Trim(Char.Parse("|"))
                    Return rv
                Else
                    'Error!
                    rv.HasError = True
                    rv.ErrorMessage = ReturnValues(3).Trim(Char.Parse("|")) + " (" + ReturnValues(2).Trim(Char.Parse("|")) + ")"
                    If ReturnValues(2).Trim(Char.Parse("|")) = "44" Then
                        rv.ErrorMessage += "Credit Card Code Verification (CCV) returned the following error: "
                        Select Case ReturnValues(38).Trim(Char.Parse("|"))
                            Case Is = "N"
                                rv.ErrorMessage += " Card Code does not match."
                            Case Is = "P"
                                rv.ErrorMessage += " Card Code was not processed."
                            Case Is = "S"
                                rv.ErrorMessage = " Card Code should be on card but was not indicated."
                            Case Is = "U"
                                rv.ErrorMessage = " Issuer was not certified for Card Code."
                        End Select
                    End If
                    If ReturnValues(2).Trim(Char.Parse("|")) = "45" Then
                        rv.ErrorMessage += "<br/>n"

                        'AVS transaction decline
                        rv.ErrorMessage += "Address Verification System (AVS) returned the following error:"

                        Select Case ReturnValues(5).Trim(Char.Parse("|"))
                            Case Is = "A"
                                rv.ErrorMessage += " the zip code entered does not match the billing address."
                            Case Is = "B"
                                rv.ErrorMessage += " no information was provided for the AVS check."
                            Case Is = "E"
                                rv.ErrorMessage += " a general error occurred in the AVS system."
                            Case Is = "G"
                                rv.ErrorMessage += " the credit card was issued by a non-US bank."
                            Case Is = "N"
                                rv.ErrorMessage += " neither the entered street address nor zip code matches the billing address."
                            Case Is = "P"
                                rv.ErrorMessage += " AVS is not applicable for this transaction."
                            Case Is = "R"
                                rv.ErrorMessage += " please retry the transaction; the AVS system was unavailable or timed out."
                            Case Is = "S"
                                rv.ErrorMessage += " the AVS service is not supported by your credit card issuer."
                            Case Is = "U"
                                rv.ErrorMessage += " address information is unavailable for the credit card."
                            Case Is = "W"
                                rv.ErrorMessage += " the 9 digit zip code matches, but the street address does not."
                            Case Is = "Z"
                                rv.ErrorMessage += " the zip code matches, but the address does not."
                        End Select
                    End If
                End If
            Catch ex As Exception
                rv.HasError = True
                rv.ErrorMessage = ex.Message
            End Try

            Return rv

        End Function

    End Class
End Namespace

Since this operates as a class within a .VB file (place it inside your APP_CODE folder), you can call it through a subroutine from anywhere within your application, like so:

Private Sub ProcessPayment()
        Dim MerchantInfo As New AuthorizeDotNet.MerchantInfo
        Dim OrderInfo As New AuthorizeDotNet.OrderInfo
        Dim Results As New AuthorizeDotNet.Output

        With MerchantInfo
            .AuthNetVersion = "3.1"
            .MerchantEmail = "info@c2itconsulting.net"
            .AuthNetLoginId = "XXXXXXXXXX"
            .AuthNetTransKey = "XXXXXXXXXXXXXX"
        End With

        With OrderInfo
            .FirstName = Me.txtContactFirstName.Text
            .LastName = Me.txtContactLastName.Text
            .Phone = Me.txtPhone.Text
            .Address = Me.txtAddress1.Text
            .City = txtCity.Text
            .State = txtState.Text
            .ZipCode = txtZipCode.Text
            .Email = txtEmail.Text
            .Country = "US"
            .Amount = txtAmount.Text
            .Description = txtDescription.Text
            .CreditCardNumber = txtCreditCardNumber.Text
            .ExpireDate = txtExpireDate.Text
            .IPNumber = Request.UserHostAddress
            .SecurityCode = txtSecurityCode.Text
        End With

        Results = AuthorizeDotNet.ProcessPayment(MerchantInfo, OrderInfo)
        If Results.HasError = True Then
            Response.Write(Results.ErrorMessage)
        Else
            Response.Write(Now.ToString & ": SUCCESS!<br/>Auth:" & Results.AuthorizationCode & "<BR/>ID:" & Results.TransactionId)
        End If

    End Sub

That’s really all there is to it. This works for me so far, and while there are still a number of blanks I may fill in (shipping info, taxes, etc.) this does what I need: hit someone’s credit card.

Be sure your site is encrypted using a good certificate provider (SSL / HTTPS), and if you’d like help implementing something like this, let me know!