AuthorizeNet / sample-code-php

This repository contains working code samples which demonstrate php integration with the Authorize.Net API
MIT License
175 stars 197 forks source link

'Get Customer Profile' doesn't return payment profiles #124

Closed RobotPorcupine closed 5 years ago

RobotPorcupine commented 5 years ago

When following the portion of the sample code from get-customer-profile.php related to retrieving a customer profile, the payment profiles are not returned. In the sample code

$paymentProfilesSelected = $profileSelected->getPaymentProfiles();

returns an array with a number of empty elements equal to the number of payment profiles present, but none of the payment profile is there.

var_dump($paymentProfilesSelected);

outputs

array(1) { [0]=> array(0) { } }

for a profile with one payment profile. So the next line of sample code

echo "Profile Has " . count($paymentProfilesSelected). " Payment Profiles" . "\n";

technically works, but is pretty useless.

I am trying to retrieve all payment profile information for a user with more than one payment profile, but can't find a way to do that via this code package. I do understand that you can retrieve individual payment profiles via AnetAPI\GetCustomerPaymentProfileRequest() but that requires storing the payment profile ids on my side, which just seems silly to have to do, especially when I can see that the API is returning the info I need via the "Try It" function on the documentation page for Get Customer Profile. https://developer.authorize.net/api/reference/index.html#customer-profiles-get-customer-profile

gnongsie commented 5 years ago

Hi @RobotPorcupine , I tried the same use case you described, with a profile having 1 payment profile and with another having multiple payment profiles. In both cases, I cannot reproduce the issue you mention.

I also tried both print_r as well as var_dump, and in both cases, I can see all the payment profile information.

Is it possible to share the code you are using to make this request and to parse the response? You can hide all sensitive information.

RobotPorcupine commented 5 years ago

code `<?php

namespace APIv2; use net\authorize\api\contract\v1 as AnetAPI; use net\authorize\api\controller as AnetController; define("AUTHORIZENET_LOG_FILE", "phplog");

class AuthorizeNet {

    static $LoginId = 'mystuff';
static $TransactionKey = 'mything';

    public static function GetCustomerProfile(\Logger &$log, $id) {
    $log->add("Fetch a customer profile from Authorize.net for user $id.");

    $merchantAuthentication = new AnetAPI\MerchantAuthenticationType();
    $merchantAuthentication->setName(static::$LoginId);
    $merchantAuthentication->setTransactionKey(static::$TransactionKey);

    // Retrieve an existing customer profile along with all the associated payment profiles and shipping addresses
    $request = new AnetAPI\GetCustomerProfileRequest();
    $request->setMerchantAuthentication($merchantAuthentication);
    $request->setMerchantCustomerId($id);
    $request->setUnmaskExpirationDate(true);
    $controller = new AnetController\GetCustomerProfileController($request);
    $response = $controller->executeWithApiResponse( \net\authorize\api\constants\ANetEnvironment::SANDBOX);
    if (($response != null) && ($response->getMessages()->getResultCode() == "Ok") ) {
        $profile = array();
        $profileSelected = $response->getProfile();
        $profile['id'] = $id;
        $profile['cust_id'] = $profileSelected->getCustomerProfileId();
        $profile['email_address'] = $profileSelected->getEmail();
        $profile['description'] = $profileSelected->getDescription();
        $profile['payment_profiles'] = $profileSelected->getPaymentProfiles();
        return $profile;
    }
    else {
        $errorMessages = $response->getMessages()->getMessage();
        $log->add($errorMessages[0]->getText(), 2);
        return false;
    }
}

}`

composer.json { "require": { "php": ">=5.6", "ext-curl": "*", "authorizenet/authorizenet": ">=1.9.3" } }

In the code above $profile['payment_profiles'] is what returns the empty array I described, but I also ran it without alteration to the sample code and got the same result.

gnongsie commented 5 years ago

So I made a few changes here in order to be able to test your code, but I was able to see the correct response coming in.

Can you add this line at the beginning of your code, after the namespace?

require 'vendor/autoload.php';

Please check again and get back to us, if the issue is not resolved.

RobotPorcupine commented 5 years ago

It was already loaded outside that file, but I did as you requested with the same result. I'm stumped. Obviously the SDK is installed because it's returning other data, and composer should ensure that all files are present. I did an update which updated the Authorize package from 1.9.6 to 1.9.7, and that also had no effect. Running PHP v7.2.8.

It would seem that the data is being fetched properly since the array knows how many payment profiles there are, but that the array is somehow not being populated properly.

RobotPorcupine commented 5 years ago

I found the source of my issue. All of the data is there, however, all of the members returned by getProfile are private with their own accessor method, which means that I have to individually drill down into all 30 members of the returned object in order to get the all the data for this object.

Sorry for wasting your time. I just expected a get function to return usable data; this is a very inefficient method for accessing customer data in my opinion, though I do understand the rationale behind the design decision.