phppaypalpaypal-adaptive-payments

Paypal Adaptive Payments


I want to make payment to two receivers i.e. buyer buys goods for 100, receiver 1 gets 90 and receiver 2 gets 10. I am using chained payment method. I am getting 100 in receiver 1's account which is ok but I am not able to get receiver 2's payment. Receiver's account id are set but not given here. What I am doing wrong? Thanks

<?php
require_once('../includes/config.php');
require_once('../includes/paypal.class.php');

$PayPalConfig = array(
                      'Sandbox' => $sandbox,
                      'DeveloperAccountEmail' => $developer_account_email,
                      'ApplicationID' => $application_id,
                      'DeviceID' => $device_id,
                      'IPAddress' => $_SERVER['REMOTE_ADDR'],
                      'APIUsername' => $api_username,
                      'APIPassword' => $api_password,
                      'APISignature' => $api_signature,
                      'APISubject' => $api_subject
                    );

$PayPal = new PayPal_Adaptive($PayPalConfig);

$PayRequestFields = array(
                        'ActionType' => 'PAY_PRIMARY',                              
                        'CancelURL' => $domain.'cancel.php',                        
                        'CurrencyCode' => 'USD',                                
                        'FeesPayer' => 'EACHRECEIVER',                                  
                        'IPNNotificationURL' => '',                         
                        'Memo' => '',                                       
                        'Pin' => '',                                        
                        'PreapprovalKey' => '',                              
                        'ReturnURL' => $domain.'return.php',                                    
                        'ReverseAllParallelPaymentsOnError' => '',          
                        'SenderEmail' => '',                                
                        'TrackingID' => ''                                  
                        );

$ClientDetailsFields = array(
                        'CustomerID' => '',                                 
                        'CustomerType' => '',                               
                        'GeoLocation' => '',                                
                        'Model' => '',                                      
                        'PartnerName' => ''                                 
                        );

$FundingTypes = array('ECHECK', 'BALANCE', 'CREDITCARD');                   

$Receivers = array();
$Receiver = array(
                'Amount' => '100.00',                                           
                'Email' => 'receiver1accountid',                                                
                'InvoiceID' => '',                                          
                'PaymentType' => 'GOODS',                                       
                'PaymentSubType' => '',                                     
                'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => ''), 
                'Primary' => 'true'                                             
                );
array_push($Receivers,$Receiver);

$Receiver = array(
                'Amount' => '10.00',                                            
                'Email' => 'receiver2accountid',                                                
                'InvoiceID' => '',                                          
                'PaymentType' => 'GOODS',                                       
                'PaymentSubType' => '',                                     
                'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => ''), 
                'Primary' => 'false'                                                
                );
array_push($Receivers,$Receiver);

$SenderIdentifierFields = array(
                                'UseCredentials' => ''                      
                                );

$AccountIdentifierFields = array(
                                'Email' => '',                              
                                'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => '')                               
                                );

$PayPalRequestData = array(
                    'PayRequestFields' => $PayRequestFields, 
                    'ClientDetailsFields' => $ClientDetailsFields, 
                    'FundingTypes' => $FundingTypes, 
                    'Receivers' => $Receivers, 
                    'SenderIdentifierFields' => $SenderIdentifierFields, 
                    'AccountIdentifierFields' => $AccountIdentifierFields
                    );


$PayPalResult = $PayPal->Pay($PayPalRequestData);

if(!$PayPalResult)
    {
        $errors = array('Errors'=>$PayPalResult['Errors']);

echo '<pre />';
print_r($errors);
exit();
    }
    else
    {

        header('Location: '.$PayPalResult['RedirectURL']);


$ExecutePaymentFields = array(
                            'PayKey' => $PayPalResult['PayKey'],                                
                            'FundingPlanID' => ''                           
                            );

$PayPalRequestData = array('ExecutePaymentFields' => $ExecutePaymentFields);


$PayPalResult = $PayPal->ExecutePayment($PayPalRequestData);
if(!$PayPalResult)
    {
        $errors = array('Errors'=>$PayPalResult['Errors']);

echo '<pre />';
print_r($errors);
exit();
    }
    else
    {

echo '<pre />';
print_r($PayPalResult);
}
}

?>

Solution

  • Your problem is the use of PAY_PRIMARY instead of just PAY. Per PayPal's documentation...

    For chained payments only, specify this value to delay payments to the secondary receivers; only the payment to the primary receiver is processed.

    Do you really need to delay it, or are you just after the split in general? It looks like you're attempting to trigger them both at the same time, so there's really no need for the delay.

    In your case you can simply set the primary and secondary receiver like you have, and then call Pay with an ActionType of PAY instead of PAY_PRIMARY. This will still split it as a chained payment (where the buyer only sees the primary receiver during checkout) but the secondary receiver will get their payment at the same time like you're expecting.

    I've adjusted your code to do what you want based on my understanding...

    <?php
    require_once('../includes/config.php');
    require_once('../includes/paypal.class.php');
    
    $PayPalConfig = array(
                          'Sandbox' => $sandbox,
                          'DeveloperAccountEmail' => $developer_account_email,
                          'ApplicationID' => $application_id,
                          'DeviceID' => $device_id,
                          'IPAddress' => $_SERVER['REMOTE_ADDR'],
                          'APIUsername' => $api_username,
                          'APIPassword' => $api_password,
                          'APISignature' => $api_signature,
                          'APISubject' => $api_subject
                        );
    
    $PayPal = new PayPal_Adaptive($PayPalConfig);
    
    $PayRequestFields = array(
                            'ActionType' => 'PAY',                              
                            'CancelURL' => $domain.'cancel.php',                        
                            'CurrencyCode' => 'USD',                                
                            'FeesPayer' => 'EACHRECEIVER',                                  
                            'IPNNotificationURL' => '',                         
                            'Memo' => '',                                       
                            'Pin' => '',                                        
                            'PreapprovalKey' => '',                              
                            'ReturnURL' => $domain.'return.php',                                    
                            'ReverseAllParallelPaymentsOnError' => '',          
                            'SenderEmail' => '',                                
                            'TrackingID' => ''                                  
                            );
    
    $ClientDetailsFields = array(
                            'CustomerID' => '',                                 
                            'CustomerType' => '',                               
                            'GeoLocation' => '',                                
                            'Model' => '',                                      
                            'PartnerName' => ''                                 
                            );
    
    $FundingTypes = array('ECHECK', 'BALANCE', 'CREDITCARD');                   
    
    $Receivers = array();
    $Receiver = array(
                    'Amount' => '100.00',                                           
                    'Email' => 'receiver1accountid',                                                
                    'InvoiceID' => '',                                          
                    'PaymentType' => 'GOODS',                                       
                    'PaymentSubType' => '',                                     
                    'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => ''), 
                    'Primary' => 'true'                                             
                    );
    array_push($Receivers,$Receiver);
    
    $Receiver = array(
                    'Amount' => '10.00',                                            
                    'Email' => 'receiver2accountid',                                                
                    'InvoiceID' => '',                                          
                    'PaymentType' => 'GOODS',                                       
                    'PaymentSubType' => '',                                     
                    'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => ''), 
                    'Primary' => 'false'                                                
                    );
    array_push($Receivers,$Receiver);
    
    $SenderIdentifierFields = array(
                                    'UseCredentials' => ''                      
                                    );
    
    $AccountIdentifierFields = array(
                                    'Email' => '',                              
                                    'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => '')                               
                                    );
    
    $PayPalRequestData = array(
                        'PayRequestFields' => $PayRequestFields, 
                        'ClientDetailsFields' => $ClientDetailsFields, 
                        'FundingTypes' => $FundingTypes, 
                        'Receivers' => $Receivers, 
                        'SenderIdentifierFields' => $SenderIdentifierFields, 
                        'AccountIdentifierFields' => $AccountIdentifierFields
                        );
    
    
    $PayPalResult = $PayPal->Pay($PayPalRequestData);
    
    if($PayPal->APICallSuccessful($PayPalResult['Ack']))
    {
        // Redirect to PayPal so user can complete payment.
        header('Location: '.$PayPalResult['RedirectURL']);
    }
    else
    {
        // Error    
        echo '<pre />';
        print_r($PayPalResult['Errors']);
        exit();
    }
    ?>
    

    Again, you don't need to worry about using ExecutePayment in this case. It will simply redirect the user to PayPal where they complete payment, and upon doing so they'll be returned to your RedirectURL like are now, but the secondary payment will trigger at the same time.

    If you really do want to delay the secondary payment for some reason (most people end up waiting a day/week/etc before triggering the secondary payment) then let me know and I can help you with that.

    Another tip: if you're using the most recent version of my library there is a new function included, PayWithOptions, that will allow you to include SetPaymentOptions() in the mix so you can provide more details about the payment without setting up additional calls on your own. I'd recommend using this. Everything would be setup the same, but then it comes with some additional parameters you can set which can be useful for different projects.