0

I am working with PayPal NVP to create a subscription-based service, where I will be accepting payments via PayPal and the type of payment is going to be Recurring Payments.

This is my signup.php page:

//SetExpressCheckout
$sec_data = array(
    'USER'                           => PAYPAL_API_USERNAME,
    'PWD'                            => PAYPAL_API_PASSWORD,
    'SIGNATURE'                      => PAYPAL_API_SIGNATURE,
    'VERSION'                        => "95.0",
    'METHOD'                         => "SetExpressCheckout",
    'PAYMENTREQUEST_0_AMT'           => $total_amt,
    'RETURNURL'                      => "<url_structure>",
    'CANCELURL'                      => "<url_structure>",
    'NOSHIPPING'                     => "1",
    'SOLUTIONTYPE'                   => "Sole",
    'LOGOIMG'                        => "<url_structure>",
    'BRANDNAME'                      => "My Website",
    'PAYMENTREQUEST_0_CURRENCYCODE'  => "USD",
    'PAYMENTREQUEST_0_ITEMAMT'       => $current_plan_price,
    'PAYMENTREQUEST_0_PAYMENTACTION' => "Sale",
    'L_PAYMENTREQUEST_0_AMT0'        => $current_plan_price,
    'L_BILLINGTYPE0'                 => "RecurringPayments",
    'L_BILLINGAGREEMENTDESCRIPTION0' => "You'll be billed USD ".$total_amt.".",
    'PAYMENTREQUEST_0_DESC'          => "You'll be billed USD ".$total_amt.".",
    'PAYMENTREQUEST_0_CUSTOM'        => "Thank you for your payment!",
    'PAYMENTREQUEST_0_INVNUM'        => "INV-".$invoice_num,
    'NOTETOBUYER'                    => $current_plan_name,
    'PAYMENTREQUEST_0_PAYMENTREASON' => "None",
    'EMAIL'                          => $email,
    'LANDINGPAGE'                    => "Billing",
    'PAYMENTREQUEST_0_TAXAMT'        => $tax_amt,
    'L_PAYMENTTYPE0'                 => "InstantOnly"
);

//GetExpressCheckoutDetails
$get_ec_data = array(
    'USER'      => PAYPAL_API_USERNAME,
    'PWD'       => PAYPAL_API_PASSWORD,
    'SIGNATURE' => PAYPAL_API_SIGNATURE,
    'TOKEN'     => $ec_token,
    'METHOD'    => "GetExpressCheckoutDetails",
    'VERSION'   => "95.0"
);

//DoExpressCheckoutPayment
$decp_data = array(
    'USER'                          => PAYPAL_API_USERNAME,
    'PWD'                           => PAYPAL_API_PASSWORD,
    'SIGNATURE'                     => PAYPAL_API_SIGNATURE,
    'METHOD'                        => "DoExpressCheckoutPayment",
    'TOKEN'                         => $ec_token,
    'PAYERID'                       => $ec_response['PAYERID'],
    'PAYMENTREQUEST_0_AMT'          => $total_amt,
    'PAYMENTREQUEST_0_CURRENCYCODE' => "USD",
    'PAYMENTREQUEST_0_ITEMAMT'      => $total_amt,
    'VERSION'                       => "95.0"
);

//CreateRecurringPaymentsProfile
$crpp_array = array(
    'USER'               => PAYPAL_API_USERNAME,
    'PWD'                => PAYPAL_API_PASSWORD,
    'SIGNATURE'          => PAYPAL_API_SIGNATURE,
    'VERSION'            => "95.0",
    'METHOD'             => "CreateRecurringPaymentsProfile",
    'TOKEN'              => $ec_token,
    'PROFILESTARTDATE'   => $last_payment_date,
    'DESC'               => "You'll be billed USD ".$total_amt.".",
    'BILLINGPERIOD'      => "Month",
    'BILLINGFREQUENCY'   => "12",
    'TOTALBILLINGCYCLES' => '0',
    'AMT'                => $total_amt,
    'CURRENCYCODE'       => "USD",
    'EMAIL'              => $get_cx_data['cx_email'],
    'STREET'             => "Bedford Ave",
    'CITY'               => "Brooklyn",
    'STATE'              => "New York",
    'COUNTRYCODE'        => "US",
    'ZIP'                => "11211"
);

//GetRecurringPaymentsProfileDetails
$grppd_array = array(
    'USER'      => PAYPAL_API_USERNAME,
    'PWD'       => PAYPAL_API_PASSWORD,
    'SIGNATURE' => PAYPAL_API_SIGNATURE,
    'VERSION'   => "95.0",
    'METHOD'    => 'GetRecurringPaymentsProfileDetails',
    'PROFILEID' => $get_crpp_response['PROFILEID']
);

And I am sending the nvp data to PayPal like this:

toPayPal($nvp_data, "https://api-3t." .(PAYPAL_MODE == 'TEST' ? 'sandbox.paypal' : 'paypal'). ".com/nvp");

Now the issue is that everything seems to be working on Sandbox but when it comes to Live, the Recurring Account is not being created on my main PayPal account.

Is there anything that I am missing? Also, do I need to install NVP SDK or something, I have no idea about it.

Also, in the sandbox, when I am running print_r() on the response of GetRecurringPaymentsProfileDetails the PROFILESTARTDATE and NEXTPAYMENTDATE are the same. Is that the issue?

Here are the PayPal functions that I am using on my paypal-functions.php page:

function toPayPal($inputArray, $PayPalURL) {
        $nvp_post_data_str   = '';

        foreach($inputArray as $key => $value) {
            $nvp_post_data_str .= $key.'='.urlencode($value).'&';
        }

        $nvp_post_data_str = substr($nvp_post_data_str, 0, strlen($nvp_post_data_str) - 1);
        $ch = curl_init();
        
        curl_setopt($ch, CURLOPT_URL, $PayPalURL);
        curl_setopt($ch, CURLOPT_VERBOSE, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $nvp_post_data_str);
        $httpResponse = curl_exec($ch);
        
        //$httpResponse;
        
        $httpResponse = explode('&', $httpResponse);
        
        for($i = 0; $i < count($httpResponse); $i++) {
            $temp_array = explode('=', $httpResponse[$i]);
            $httpResponseArray[$temp_array[0]] = urldecode($temp_array[1]);
        }
        
        return $httpResponseArray;
    }

Am I missing out on any curl code on the paypal-functions.php page or something?

Any help would be greatly appreciated

I tried reading the PayPal NVP documentation as well and whatever I coded is based on that. I am not sure why everything is working on Sandbox and not on Live mode.

On Sandbox, when I am running print_r() on the response of CreateRecurringPaymentsProfile method, I am getting these values:

[PROFILEID] => I-SXK4UUEV0M0J
[PROFILESTATUS] => ActiveProfile
[ACK] => Success

and I am able to capture the profileid in my database as well.

However, when I am switching to Live mode, the same code is able to create a recurring profile on my PayPal business account. Also, in my database, the profileid column in not being populated.

Thank you!

imsh1vaay
  • 21
  • 6
  • Why are you using the legacy/deprecated NVP API? It is very old. See the current subscriptions documentation, https://developer.paypal.com/docs/subscriptions/ . You can generate a button in the account interface, for sandbox https://www.sandbox.paypal.com/billing/plans – Preston PHX Apr 13 '23 at 22:29
  • I have an admin panel designed which I want to give to the user after a successful signup. I want to be able to get the user's data that I have been collecting on the `signup.php` page and basically give a customized admin panel based on that data. I hope this makes sense. – imsh1vaay Apr 13 '23 at 22:39
  • The end goal makes sense enough, but using the NVP API for subscriptions in 2023 does not make sense – Preston PHX Apr 13 '23 at 22:43
  • I know, but this is how I am "supposed" to make it work. Can you please help me in this case? – imsh1vaay Apr 13 '23 at 23:40
  • Seems like a waste of time, but at the least you'll need to log and show the example request+response that's failing (in live) in your question – Preston PHX Apr 13 '23 at 23:55
  • Is there any other way of doing it, keeping my requirements constant? PayPal subscription offers hassle-free integration, however, I am not quite sure if that's going to serve my purpose. I am open to suggestions. – imsh1vaay Apr 14 '23 at 18:39
  • The Subscriptons REST API is newer and better than the classic recurring payments profile NVP API in every way, and generating a working Subscriptions plan/button (via the account interface) is far simpler. Integrate a webhook listener for each client-id and subscribe it to the event `PAYMENT.SALE.COMPLETED` afterward. Use `custom_id` if you need to send any additional metadata at createSubscription time, such as which user it is for. – Preston PHX Apr 14 '23 at 20:15
  • Sounds a bit complicated, but will give it a try. Thanks! – imsh1vaay Apr 17 '23 at 18:52

0 Answers0