cancel
Showing results for 
Search instead for 
Did you mean: 

Basic CIM questions

I've been reading some of the other posts here on the forum regarding CIM but still have some questions:

 

1) Am I correct in thinking that I should have only one CustomerProfile for each for each of my customers?  Does the authorize.net system prevent me from using a single merchantCustomerID more than once?  There was a post on here that referred to a duplicate profile error returned by the authorize.net API but I have seen no information to tell me under what circumstances that would occur.

 

2) Is a credit card or bank account number required when creating a CustomerProfile? The CIM documentation neglects to explicitly specify if this information is required, optional, or conditional.

 

3) Is it possible to look up an authorize.net customer profile using merchantCustomerId?  Looking at GetCustomerProfile, this does not appear to the case.

 

4) While I find the PDF documentation for CIM linked here to be pretty useful, it is pretty narrowly focused on the inputs and outputs of the API.  Is there a more general source of documentation to show the ins and outs of CIM -- perhaps an overview or tutorial-based documentation?

 

5) What is the difference between SOAP and XML guides?  If I'm using the PHP code provided by authorize.net, do I even care?  From what I can tell, there is no way for me to specify whether I use SOAP or XML.

 

6) Where does one specify the web service location when setting up one's PHP code?  The documentation refers to Production, Test, and WSDL variants without describing why one would choose one or the other.  Additionally, all urls contain 'soap' in them, suggesting they might be inappropriate for an XML implementation.

 

7) In some of the AIM code examples, I see definition of such constants as AUTHORIZENET_API_LOGIN_ID,  AUTHORIZENET_TRANSACTION_KEY, and AUTHORIZENET_SANDBOX.  Is defining these in one's own code the proper approach to configuring the authorize.net PHP code?  Are there other such constants?  Where is this configuration documented?  

sneakyimp
Contributor
19 REPLIES 19

1) Depends on how you set up your system. If you have users on your site and associate a customer ID with each user as you create it, then obviously you don't have to worry about duplicate profiles unless the user signs up more than once. If you don't have user profiles, then you might have more than one customer profile per person depending on what info they put in. Shouldn't matter much from a payment perspective, however, since each instance of the person will work equally well so long as the billing info is good. Look in the pdf documentation for the words "Duplicate Profile Verification" and you'll get a list of fields that determine dupes.

 

2) No. You can create a profile with very little info - either an email, merchant customer ID, or description. Billing profiles can be assigned separately.

 

3) Not as far as I know. You should associate lookup values with profile ID's in your own database.

 

4) If you're using PHP, you can get a fairly good overview by looking at the CIM.markdown file in the doc folder of the SDK. Note that this is for regular CIM - if using hosted CIM to avoid PCI requirements, you'll need to look in the documentation to find out how to do that, or try to reverse-engineer the demo application.

 

5) No idea. I use the XML guide.

 

6) If you're using the PHP API, the URL's are set in the AuthorizeNetCim.php file in the lib folder. No need to mess with them, however, since the API chooses where to send the transaction depending on whether you set sandbox mode or not. I always set it at the class level, something like this (for a developer / sandbox account):

 

$request = new AuthorizeNetCIM;
$request->setSandbox(true);

 Always use your account in live mode, incidently - test mode isn't as good at simulating things.

 

7) It's generally bad practice (in my opinion) to set those in the overall config. I always use a fresh, totally unconfigured SDK, and set things at the transaction level. To add to the above:

 

$request = new AuthorizeNetCIM(
    'login_id', 'transaction_key');
$request->setSandbox(true);

// or...

$request = new AuthorizeNetCIM(
    $GLOBALS['_login_id'], $GLOBALS['_transaction_key']);
$request->setSandbox(true);

// Where the globals are set in some master settings file for your site, separate from the SDK.

 The best illustration of all the options is in the AIM.markdown file in your doc folder. It shows all the variants.

TJPride
Expert

OK thanks so much for the response!  For some reason I was not notified. 

 

I have made some progress.  The markdown files are somewhat useful (and I've been reading some of the source) but I still wonder how certain things work.  There are a few test cases I expect to deal with.  NOTE that I am using CIM exclusively here via the PHP API:

 

1) A customer has no existing customer profile or payment profiles at authorize.net.

In this situation, I look at my records for a given user and there are *NO* id's stored for any customer profiles or payment profiles at authorize.net.  I therefore need to create them both.  I assume in this case that I can more or less construct a AuthorizeNetCustomer object with nested AuthorizeNetPaymentProfile (assigned like so: $customerProfile->paymentProfiles[] = $paymentProfile;) as detailed in the markdown file and then call the api thusly:

$request = new AuthorizeNetCIM(MY_API_LOGIN, MY_API_TRANSACTION_KEY);
$request->setSandbox(MY_SANDBOX_VALUE);
$request->setLogFile(MY_LOG_LOCATION);

$response = $request->createCustomerProfile($customerProfile);

 

Q1: What methods of the $response object are valid for this particular request?  I see two different methods defined in the $response class for both getting a customer profile id and for getting a payment profile id:

            $response->getPaymentProfileId();
            $response->getCustomerPaymentProfileIds();
            $response->getCustomerProfileId();
            $response->getCustomerProfileIds();

 

2) Scenario 2 is where I have previously stored an authorizenet customer profile id in my system so I am guessing it's safe to assume this profile exists on the authorize.net system.  I am guessing that I must take care in my code to use the different request createCustomerPaymentProfile and supply the customer profile id I had stored before.  More questions come to mind

Q2: What would happen if I assembled a createCustomerProfile call just like I did in scenario 1.  Would it cause an error?  Or is authorize.net's gateway smart enough to know that I just want to attach a new payment profile to the existing customer profile? 

Q3: Are there any circumstances under which authorize.net may have dropped a customer profile such that when I attempt createCustomerPaymentProfile there is an error?  How would I know this had happened?  The markdown documents don't show any error-handling examples.

Q4: Suppose a customer opted not to use an existing payment profile but instead wanted to enter a new card number but they mistakenly re-entered a cc number for which a payment profile already exists.  Will that cause an error?  Will the system permit an identical record? 

I'm also wondering a couple of other things:

 

* Can one re-use a $request object after performing some other function?  E.g.:

// build $customerProfile object here

$response = $request->createCustomerProfile($customerProfile);

// build $transaction object here and re-use $reqest object

$response = $request->createCustomerProfileTransaction("AuthCapture", $transaction);

 

Does that work or must we create a new $request object?

 

* The examples I've seen in the markdown files don't show any error checking for profile and payment profile and transaction requests.  Given that we're making a request via ssl across a network, it seems obvious that failure is a possibility for a variety of reasons.  Where might I find some examples of best practices here?  Do these functions throw exceptions when they fail?  Is there an error condition we can check for after they complete to make sure they were successful? What about response codes for createCustomerProfileTransactionRequest?  Does one use the same techniques shown in the AIM markdown?

 

$response = $request->createCustomerProfileTransaction("AuthCapture", $transaction);
$response->response_code;
$response->response_subcode;
$response->response_reason_code;
$response->transaction_id;

Probably these:

$response->getCustomerProfileId();

$response->getCustomerPaymentProfileIds();

 

You could theoretically create the profile with more than one payment profile. There will, however, only ever be one customer profile in the response.

 

If you try to create a profile for a customer who already has a profile, you get CIM error E00039 and the duplicate profile ID is returned. Just use that. Figuring out what to do with the duplicate profile is a more complicated issue, since there will already be a payment entry and it may not be the same as the one the customer entered the second time.

 

Creating a profile can fail, just like any operation. Check for errors, proceed accordingly. Your best bet is to trigger some errors on purpose and do a print_r of the $response so you can see what you get back.

 

If you don't want to deal with the hassle of managing payment or shipping profiles, just implement hosted CIM for those. Essentially, you'd use iframe popups hosted by Authorize.net, then update your page once the user is done using them and use getCustomerProfile to populate pulldowns with masked card numbers and so on so the user can choose which payment profile to pay with.

 

Overall, your best strategy is probably to call things and print_r($response). That'll make most things fairly obvious.

Thanks yet again for your helpful response.

 

Unfortunately, I have been using print_r to see the response and I see that an AuthorizeNetCIM_Response is what comes back and this object has 3 member variables:

* xml - SimpleXMLElement object

* response - a lengthy string that appears to contain the raw xml of the response

* xpath_xml - another, separate SimpleXMLElement object.

 

I'd prefer, if possible, to use the PHP code provided by authorize.net to parse these objects and extract the data I need rather than attempting some misguided effort at parsing XML myself or trying to navigate these objects. I'm shocked that not one of the markdown documents in the 'doc' folder for CIM's PHP library even bothers to mention the word 'error'. 

 

I see that this call:

            $response = $request->createCustomerProfile($customerProfile);

returns a response object where I can do the following:

 

echo $response->getResultCode()

* returns 'Ok' for successful attempt.

* returns 'Error' for unsuccessful attempt?

I find it surprising that the possible results of this function are not documented in the PHP source.  One must go to the raw API document to find it. Having looked at the PHP source, the functions $response->isOK() and $response->isError() just check $response->getResultCode() to see if it is Ok or Error, respectively.

 

$response->getCustomerProfileId();

* returns the authorize.net ID for the newly created profile as a string rather than a numeric value.

* populated on error?? not specified.

 

$response->getCustomerPaymentProfileIds();

* although the name implies an array or collection of some kind, this also seems to return a single string containing the authorize.net id for a customer payment profile

* returns ??? if more than one profile is created?

 

I've also tried to take the customer payment profile and create a transaction with it using more or less the same code in the markdown example:

        $transaction = new AuthorizeNetTransaction;
        $transaction->amount = MY_ANNUAL_SUBSCRIPTION_COST;
        $transaction->customerProfileId = $authorizenet_customer_profile_id;
        $transaction->customerPaymentProfileId = $authorizenet_payment_profile_id;
   
        $lineItem              = new AuthorizeNetLineItem;
        //$lineItem->itemId      = "4";
        $lineItem->name        = "Annual Subscription to example.com";
        $lineItem->description = "An annual subscription to allow enhanced activities on example.com";
        $lineItem->quantity    = "1";
        $lineItem->unitPrice   = MY_ANNUAL_SUBSCRIPTION_COST;

        $transaction->lineItems[] = $lineItem;

    
        $response = $request->createCustomerProfileTransaction("AuthCapture", $transaction);
        print_r($response);

The result is an another triple-xml object that appears to have an error:

[code] => E00003
[text] => The element 'lineItems' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has invalid child element 'name' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'. List of possible elements expected: 'itemId' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.

 

I don't understand why 'name' would cause a problem because it is explicitly mentioned in the api documentation and also used in the markdown examples.

 

Also, itemId is specified in the markdown examples but the documentation doesn't say what this is for -- is it a product id on my system?  Is it only meaningful in the context of one transaction?

 

Any answers would be much appreciated.  I'm making progress but have been dramatically slowed down by the ad-hoc nature of the documentation.

The xml part of the response may be -named- xml, but should actually be nested arrays representing the xml after it's been parsed. I generally use that myself. Go ahead and do a print_r of your response, then view source on your page (so it nests properly) and copy and paste it here.

 

The profile ID obviously won't be populated unless one is created. I imagine you'll get an array back from getCustomerPaymentProfileIds() if there's more than one - just check the field type.

 

Item ID is just whatever internal product code you decide to supply. Authorize.net doesn't care what it is. The specific error you're getting is a bug having to do with the fields being out of order, probably because itemId is expected but not being included. Finding the specific line of code that causes that might be a bit difficult, though.

Thank you so much.

 

OK I think I'm starting to feel somewhat comfortable with the idea of handling these transaction responses. 

 

I'm moving on to actually completing transactions.  My primary consideration is that I'd like to store details about each transaction on my system, but I am unsure what the nature of the responses are.  For instance, there's a whole comprehensive list of properties defined in the class AuthorizeNetResponse but I have no idea what the data format of these items is or how I might define my database table to accommodate these data values.  For example, what's the maximum length required for response_reason_text?  The response to a createCustomerProfileTransaction call is apparently an object of type AuthorizeNetAIM_Response and I've checked the AIM documentation but this document doesn't seem to describe any data types or values for the response elements.  Is there somewhere I can find out the data types/sizes for elements of a AuthorizeNetAIM_Response object (which inherits from AuthorizeNetResponse?

 

Also, how consistent can I expect the responses to be in data format?  I see that the constructor function for  AuthorizeNetAIM_Response accepts a $custom_fields parameter.  I reckon that if I want a comprehensive archive of all my transaction responses, I'll need to just log a text file as the responses may have extra data depending on circumstances?

Ah!  I see the docs do record information about how lengthy these fields are.  My mistake.

 

Still wondering how consistent gateway responses might be.

The CIM XML documentation should give you a pretty good idea of what's coming back. See the Responses -> CIM Responses section and also the Response Codes section.

http://www.authorize.net/support/CIM_XML_guide.pdf

 

Personally, for logging purposes I just log print_r() output to a text file or to a TEXT field in my MySQL database (up to 65536 characters, variable-length). That way I don't really need to worry about what format the response is in.