globalpayments / php-sdk

GNU General Public License v2.0
49 stars 66 forks source link

Amount cannot be null for this transaction type #88

Closed izamzam2020 closed 3 years ago

izamzam2020 commented 3 years ago

Hi,

I'm trying to resolve the following error (below) but the support on the phone and email are next to useless and take over a month to respond which isn't good enough!

My previous issue was fixed by a user on here so hopefully they can help me again.

GlobalPayments\Api\Entities\Exceptions\BuilderException: amount cannot be null for this transaction type

I have printed out the amount and even harded coded the amount to match the amount in the api example but the error persists.

This error only happens when the is enrolled check returns "N", everything else works perfectly.

I'm using Version 2.3.3 installed via composer and using 3D secure method 1 API on PHP

Open to any suggestions as support dont respond.

Thanks Ian

MSmedal commented 3 years ago

Are you able to share your code/usage that generates this error?

izamzam2020 commented 3 years ago

Are you able to share your code/usage that generates this error?

Hi,

Thank you for your reply, the section that generates the error is when the code checks is enrolled is "N"

I have included the code block beforehand so you can see that as well.

`// Configure client & request settings $config = new GpEcomConfig(); $config->merchantId = "***"; $config->accountId = ""; $config->orderId = $orderid; $config->sharedSecret = ( ENVIRONMENT != "production") ? "" : "**"; $config->serviceUrl = ( ENVIRONMENT != "production") ? "https://api.sandbox.realexpayments.com/epage-remote.cgi" : "https://api.realexpayments.com/epage-remote.cgi"; $config->secure3dVersion = Secure3dVersion::ONE; ServicesContainer::configureService($config);

    // Add the cardholder data
    $card = new CreditCardData();
    $card->number = $cardnumber;
    $card->expMonth = $data['cexpiremonth'];
    $card->expYear = $data['ex_year'];
    $card->cvn = $ccv2;
    $card->cardHolderName = $cardname;

    // Check for enrollment
    try {
       $threeDSecureData = Secure3dService::checkEnrollment($card)
          ->withAmount($amount)
          ->withOrderId($orderid) // sets the order ID
          ->withCurrency("GBP")
          ->execute('default',Secure3dVersion::ONE);

    } catch (ApiException $e) {

        // TODO: add your error handling here
        $error_msg = "Sorry, we have encountered an error while trying to process your order, please contact customer support. --- " . $e;
        //set flash data &  redirect
        self::CI()->session->set_flashdata("user_msg_error",$error_msg);        
        header("Location: {$redirect_url}");
    }

    //We have an object back from GI
    if (isset($threeDSecureData)) 
    {

       //get the enrolled status N,Y or blank (dont processs blank)
       $enrolled = $threeDSecureData->enrolled; // true or false

        // if the card is enrolled for 3D Secure 1
        if ($enrolled) 
        {

          // Data necessary to redirect the customer to the Issuer ACS page
          $acsUrl = $threeDSecureData->issuerAcsUrl;
          $pareq = $threeDSecureData->payerAuthenticationRequest;

          // The Merchant Data object contains the necessary transaction data to persist for the
          // Verify Signature step, including the Order ID, amount and currency
          $md = $threeDSecureData->getMerchantData();
          $md->add('fee_id',$package_details->ID);
          $mdString = $md->toString();

          // We need to persist the MD object so add to the userdata for use with the verify method
          self::CI()->session->set_userdata("MD_OBJ",$md);

          if($enrolled == "N")
          {

            //we only run the check if the card is vias or master card
            $exemptions = array("VISA","MASTERCARD");
            if( in_array( strtoupper($cardtype), $exemptions))
            {

                // As the card isn't enrolled we have to set the ECI, this is only for VISA and MASTERCARD
                $eci = ( strtoupper($cardtype) == "VISA" ) ? 6 : 1;
                $xid =  $threeDSecureData->eci;
                $threeDSecureData->xid = $xid;
                $threeDSecureData->eci = $eci;

                // Add the 3D Secure 1 data and Merchant Data to the card
                $card->threeDSecure = $threeDSecureData;

                try {
                   // Create the authorization with 3D Secure information
                   $response = $card->charge()
                                    ->execute();

                } catch (ApiException $e) {

                    echo "<br />" . $e . "<br />";

                    // handle the error
                    $error_msg = "Sorry, we have encountered an error while trying to process your order, please contact customer support. --- " . $e;
                    //set flash data &  redirect
                    self::CI()->session->set_flashdata("user_msg_error",$error_msg);        
                    //header("Location: {$redirect_url}");;
                }
            }
         }
    }
}

`

Thanks Ian

MSmedal commented 3 years ago

Hi Ian,

Change this bit:

// Create the authorization with 3D Secure information
 $response = $card->charge()
                  ->execute();

... to this:

// Create the authorization with 3D Secure information
$response = $card->charge(12.34) // some amount
    ->withCurrency('GBP')
    ->execute();

... and your code should work.

Those transaction details aren't set in threeDSecureData when checkEnrollment returns a not-enrolled response. I need to do a bit more checking to figure out if this is intended behavior on our part or not, but the above minor change should work regardless.

izamzam2020 commented 3 years ago

Hi Ian,

Change this bit:

// Create the authorization with 3D Secure information
 $response = $card->charge()
                  ->execute();

... to this:

// Create the authorization with 3D Secure information
$response = $card->charge(12.34) // some amount
    ->withCurrency('GBP')
    ->execute();

... and your code should work.

Those transaction details aren't set in threeDSecureData when checkEnrollment returns a not-enrolled response. I need to do a bit more checking to figure out if this is intended behavior on our part or not, but the above minor change should work regardless.

Thanks for the fast reply.

Your changes worked and I can now put through not enrolled payments without error.

I was confused as to why this was happening as the documentation on the website doesn't say you need those lines of code above.

Thanks Again Ian

MSmedal commented 3 years ago

No problem!