Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create Encrypted PayNow button "on the fly" for Third-party customers, using Paypal NVP API?

I need to create Encrypted "PayNow" paypal buttons on the fly for a website.
I read all the documentation I can find on the paypal website.
I understood that I need to use the BMCreateButton ButtonManager NVP API.
But I've been unable to find any information, nor any reasonably simple and documented sample code, about HOW I'm supposed to call these API.

Do I need to put my parameter in a form and post it on some kind of server?
Do I need to put all the parameter on an url, call this url, ad use the result?
How do I authenticate to this service?
I'm going to create encrypted paynow button for different paypal business account.

Can someone show me some VB.Net or C# code that actually call this BMCreateButton NVP API?
So that I can see:

  • how to do the call
  • how to authenticate to the service
  • how to format/use the parameters of the API call
  • how to get the results

Various link to useful resource
- Thanks to this answer I've been able to find some useful sample code here and there about how to call Paypal API.
- Here is more usefull information about how paypal NVP API works.
- Here an interesting website that generate API Call URL for the BMCreateButton API
- Here you can find instruction for obtaining "Third Party" API credentials. (thanks to this answer)
- Some more useful information here about Paypal API integration
- Here you can find the current and latest version number of the Paypal API

Update 1
Now I've created some code that actually do something, but it give me an error. This code actually create an encrypted paynow button using the BMCreateButton API. It seem to works, but when I click the paynow button, it show all the payment parameters, but also show the error "There was a problem with the decryption of your secure order. Please contact your merchant."

Here is the code:

Public Shared Sub PaypalTest3web()

    Dim NVP As New Dictionary(Of String, String)

    Dim strUsername As String = "aso_1273063882_biz_api3.megatesto.it"
    Dim strPassword As String = "1273063582"
    Dim strSignature As String = "A22sd7623RGUsduDHDSFU57N7dfhfS23DUYVhdf85du8S6FJ6D5bfoh5"

    Dim strNVPSandboxServer As String = "https://api-3t.sandbox.paypal.com/nvp"


    NVP.Add("USER", strUsername)
    NVP.Add("PWD", strPassword)
    NVP.Add("SIGNATURE", strSignature)


    Dim bvCount As Integer
    bvCount = 0

    NVP.Add("METHOD", "BMCreateButton")
    NVP.Add("VERSION", "85.0")

    NVP.Add("BUTTONCODE", "ENCRYPTED")    ''CLEARTEXT / ENCRYPTED
    NVP.Add("BUTTONTYPE", "BUYNOW")
    NVP.Add("BUTTONSUBTYPE", "PRODUCTS")  ''Optional: PRODUCTS / SERVICES

    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "business=D64TG758HIWj2") ''Merchant ID

    'bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "cmd=_s-xclick")  ''DONT SPECIFY the cmd parameter, if specifien it will generate an error on the decription of the "secure order", I don't know why...
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "lc=IT")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "button_subtype=PRODUCTS")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "item_name=Test_product")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "item_number=123456")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "amount=12.00")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "currency_code=EUR")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "quantity=1")

    ''build the parameter string
    Dim paramBuilder As New StringBuilder
    For Each kv As KeyValuePair(Of String, String) In NVP
        Dim st As String
        st = kv.Key & "=" & HttpUtility.UrlEncode(kv.Value) & "&"
        paramBuilder.Append(st)
    Next

    Dim param As String
    param = paramBuilder.ToString
    param = param.Substring(0, param.Length - 1) 'remove the last '&'

    'Create web request and web response objects, make sure you using the correct server (sandbox/live)
    Dim wrWebRequest As HttpWebRequest = DirectCast(WebRequest.Create(strNVPSandboxServer), HttpWebRequest)
    wrWebRequest.Method = "POST"

    Dim requestWriter As New StreamWriter(wrWebRequest.GetRequestStream())
    requestWriter.Write(param)
    requestWriter.Close()

    '' Get the response.
    Dim responseReader As StreamReader
    responseReader = New StreamReader(wrWebRequest.GetResponse().GetResponseStream())

    ''and read the response
    Dim responseData As String
    responseData = responseReader.ReadToEnd()
    responseReader.Close()

    ''url-decode the results
    Dim result As String
    result = HttpUtility.UrlDecode(responseData)

    Dim formattedResult As String

    formattedResult = "Request on " & strNVPSandboxServer & vbCrLf &
                     HttpUtility.UrlDecode(param.Replace("&", vbCrLf & "  ")) & vbCrLf & vbCrLf &
                     "Result:" & vbCrLf & result & vbCrLf & vbCrLf &
                     "--------------------------------------" & vbCrLf



    ''show the results
    Trace.WriteLine(result)
    MessageBox.Show(result)
End Sub

Here is the HTML Response

<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----
">
<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_buynow_LG.gif" border="0" name="submit" alt="PayPal - Il sistema di pagamento online più facile e sicuro!">
<img alt="" border="0" src="https://www.sandbox.paypal.com/it_IT/i/scr/pixel.gif" width="1" height="1">
</form>

And here is the error I get after clicking on this encrypted pay-now button

enter image description here

As you can see, all the parameters (item name, price, item_id...) are correct. But I'm unable to understand why I'm getting this error.

If you want to try this code you should substitute your API user/password/signature. The generated PayNow button only works when you are logged in your paypal sandbox account.

Do you have any idea about how to solve this error?

Note: after solving this issue, I'll need to understand how to create encrypted button for a third paypal business account (we will need to create encrypted button for paypal accounts of our customers). Using our API credentials, customer merchant code, and having our API credential configured up in our customers paypal account isn't enought... It say that merchant code is not valid. Probably I'm missing something...

Update 2
It seem that I've found how to solve the aforementioned error: simply remove the "cmd=_s-xclick / _xclick" parameters. If the "cmd" is not specified, the paynow button doesn't seem to generate any error. More testing is needed... anyway I've commented the code line in the code example.

Now, back to business. Let's do some testing, and then find the proper way to create paynow button for third party paypal accounts.

like image 808
Max Avatar asked Mar 30 '12 09:03

Max


1 Answers

Ok, finally I got it! :-)

My objective is to create Encrypted PayNow buttons "on the fly" for some of our customers. Here is a brief explanation of how PayPal API works with Third-party access.

  • Create a Paypal Sandbox account (here)
  • In this sandbox account, create 2 new business account
    you should hook these business account to a credit card. This will mark these account as "verified", unless it won't work
    • The first account (account A) will represent our company
    • The second account (account B) will represent one of our customers
  • log in account A, and request the API credentials (instructions here)
  • log in account B, and grant API permission to account A (instruction here check the paragraph "Third-party authentication: Grant your cart the appropriate API authentication permissions")
  • grab the Api credentials of account A, and put them in your source code
  • grab Merchant ID and merchant Email of account B and put them in your source code
  • run the code
  • grab the returned html, put it on a web page, and test it, it should works
    (you need to be logged on your paypal sandbox account, or the generated button wont works)

Why this simple and concise knowledge is timewastingly scattered among a countless number of PayPal help pages, PayPal PDF manuals, and third party blog post, is beyond my understanding :-) Anyway...

Here is the working code in VB.Net

Public Shared Sub PaypalThirdPartyPayNowButtonTest()
    Dim bvCount As Integer = 0  ''L_BUTTONVAR counter
    Dim NVP As New Dictionary(Of String, String)  ''Api Name-Value-Pair parameters

    ''define paypal SANDBOX server
    Dim paypalApiServerUrl As String = "https://api-3t.sandbox.paypal.com/nvp"

    ''define Api credentials of YOUR business paypal account 
    Dim yourApiUsername As String = "aso_1273063882_biz_api3.megatesto.it"
    Dim yourApiPassword As String = "1273063582"
    Dim yourApiSignature As String = "A22sd7623RGUsduDHDSFU57N7dfhfS23DUYVhdf85du8S6FJ6D5bfoh5"

    ''define Your CUSTOMER identification data
    Dim customerEmailID As String = "[email protected]"
    Dim customerMerchantID As String = "3S4EF7BI96YHS"


    ''use YOUR identification data
    NVP.Add("USER", yourApiUsername)
    NVP.Add("PWD", yourApiPassword)
    NVP.Add("SIGNATURE", yourApiSignature)

    ''use your CUSTOMER identification data
    NVP.Add("SUBJECT", customerEmailID)
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "business=" & customerMerchantID) ''Merchant ID


    ''Api method name and version
    NVP.Add("METHOD", "BMCreateButton")
    NVP.Add("VERSION", "85.0")

    ''method specific parameters
    NVP.Add("BUTTONCODE", "ENCRYPTED")
    NVP.Add("BUTTONTYPE", "BUYNOW")
    NVP.Add("BUTTONSUBTYPE", "PRODUCTS")

    ''Buynow button specific parameters
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "lc=IT")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "button_subtype=PRODUCTS")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "item_name=Test_product")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "item_number=123456")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "amount=12.00")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "currency_code=EUR")
    bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "quantity=1")
    ''bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "cmd=_s-xclick")  'DONT' specify the cmd parameter, if you specify it, it wont work, paypal will give you an error

    ''build the parameter string
    Dim paramBuilder As New StringBuilder
    For Each kv As KeyValuePair(Of String, String) In NVP
        Dim st As String
        st = kv.Key & "=" & HttpUtility.UrlEncode(kv.Value) & "&"
        paramBuilder.Append(st)
    Next

    Dim param As String
    param = paramBuilder.ToString
    param = param.Substring(0, param.Length - 1) ''remove the last '&'


    ''Create web request and web response objects, make sure you using the correct server (sandbox/live)
    Dim wrWebRequest As HttpWebRequest = DirectCast(WebRequest.Create(paypalApiServerUrl), HttpWebRequest)
    wrWebRequest.Method = "POST"


    Dim requestWriter As New StreamWriter(wrWebRequest.GetRequestStream())
    requestWriter.Write(param)
    requestWriter.Close()

    '' Get the responseReader
    Dim responseReader As StreamReader
    responseReader = New StreamReader(wrWebRequest.GetResponse().GetResponseStream())

    ''read the response
    Dim responseData As String
    responseData = responseReader.ReadToEnd()
    responseReader.Close()


    ''url-decode the results
    Dim result As String
    result = HttpUtility.UrlDecode(responseData)

    Dim formattedResult As String

    formattedResult = "Request on " & paypalApiServerUrl & vbCrLf &
                     HttpUtility.UrlDecode(param.Replace("&", vbCrLf & "  ")) & vbCrLf & vbCrLf &
                     "Result:" & vbCrLf & HttpUtility.UrlDecode(responseData.Replace("&", vbCrLf & "  ")) & vbCrLf & vbCrLf &
                     "--------------------------------------" & vbCrLf

    ''show the results
    Trace.WriteLine(formattedResult)
    MessageBox.Show(formattedResult)
End Sub

And here is the same code in C#

public static void PaypalThirdPartyPayNowButtonTest()
{
    int bvCount = 0; //L_BUTTONVAR counter
    Dictionary<string, string> NVP = new Dictionary<string, string>(); //Api Name-Value-Pair parameters

    //paypal SANDBOX server
    string paypalApiServerUrl = "https://api-3t.sandbox.paypal.com/nvp";

    //Api credentials of YOUR business paypal account 
    string yourApiUsername = "aso_1273063882_biz_api3.megatesto.it";
    string yourApiPassword = "1273063582";
    string yourApiSignature = "A22sd7623RGUsduDHDSFU57N7dfhfS23DUYVhdf85du8S6FJ6D5bfoh5";

    //Your CUSTOMER identification data
    string customerEmailID = "[email protected]";
    string customerMerchantID = "3S4EF7BI96YHS";

    //use YOUR identification data
    NVP.Add("USER", yourApiUsername);
    NVP.Add("PWD", yourApiPassword);
    NVP.Add("SIGNATURE", yourApiSignature);

    //use your CUSTOMER identification data
    NVP.Add("SUBJECT", customerEmailID);
    bvCount++; NVP.Add("L_BUTTONVAR" + bvCount.ToString() , "business=" + customerMerchantID);

    //Api method name and version
    NVP.Add("METHOD", "BMCreateButton");
    NVP.Add("VERSION", "85.0");

    //method specific parameters
    NVP.Add("BUTTONCODE", "ENCRYPTED");
    NVP.Add("BUTTONTYPE", "BUYNOW");
    NVP.Add("BUTTONSUBTYPE", "PRODUCTS");

    //Buynow button specific parameters
    bvCount++; NVP.Add("L_BUTTONVAR" + bvCount.ToString() , "lc=IT");
    bvCount++; NVP.Add("L_BUTTONVAR" + bvCount.ToString() , "button_subtype=PRODUCTS");
    bvCount++; NVP.Add("L_BUTTONVAR" + bvCount.ToString() , "item_name=Test_product");
    bvCount++; NVP.Add("L_BUTTONVAR" + bvCount.ToString() , "item_number=123456");
    bvCount++; NVP.Add("L_BUTTONVAR" + bvCount.ToString() , "amount=12.00");
    bvCount++; NVP.Add("L_BUTTONVAR" + bvCount.ToString() , "currency_code=EUR");
    bvCount++; NVP.Add("L_BUTTONVAR" + bvCount.ToString() , "quantity=1");
    //bvCount = bvCount + 1 : NVP.Add("L_BUTTONVAR" & bvCount, "cmd=_s-xclick")  //DON'T specify the cmd parameter, if you specify it, it wont work, paypal will give you an error


    //build the parameter string
    StringBuilder paramBuilder = new StringBuilder();
    foreach (KeyValuePair<string, string> kv in NVP)
    {
        string st = kv.Key + "=" + System.Web.HttpUtility.UrlEncode(kv.Value) + "&";
        paramBuilder.Append(st);
    }

    string param = paramBuilder.ToString();
    param = param.Substring(0, param.Length - 1); //remove the last '&'


    //Create web request and web response objects, make sure you using the correct server (sandbox/live)
    System.Net.HttpWebRequest wrWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(paypalApiServerUrl);
    wrWebRequest.Method = "POST";

    System.IO.StreamWriter requestWriter = new System.IO.StreamWriter(wrWebRequest.GetRequestStream());
    requestWriter.Write(param);
    requestWriter.Close();


    //Get the responseReader
    System.IO.StreamReader responseReader = new System.IO.StreamReader(wrWebRequest.GetResponse().GetResponseStream());
    string responseData = responseReader.ReadToEnd();
    responseReader.Close();

    //url-decode the results
    string result = System.Web.HttpUtility.UrlDecode(responseData);

    string formattedResult = "Request on " + paypalApiServerUrl + "\r\n" + System.Web.HttpUtility.UrlDecode(param.Replace("&", "\r\n  ")) + "\r\n\r\nResult:\r\n" + System.Web.HttpUtility.UrlDecode(responseData.Replace("&", "\r\n  ")) + "\r\n\r\n--------------------------------------\r\n";

    //show the results
    System.Diagnostics.Trace.WriteLine(formattedResult);
    System.Windows.Forms.MessageBox.Show(formattedResult);
}

I wish everyone a happy PayPal integration :-)

Update (for PHP coder)
@Style is asking for a working PHP example... I don't know PHP, but I've found some links that may contain useful information for PHP coder,: you can look for BMCreateButton api inside these source files:

  • PayPal "Authorization Failed"
  • Working example of paypal Website Payments Pro Hosted Solution Iframe?
  • http://code.google.com/p/my-project-phi/source/browse/trunk/Application/Services/PayPalService.php?r=61
  • http://plugins.svn.wordpress.org/stageshow/tags/1.1.4/include/mjslib_paypal_api.php
  • http://plugins.svn.wordpress.org/stageshow/trunk/include/mjslib_paypal_api.php
  • http://my-project-phi.googlecode.com/svn-history/r61/trunk/Application/Services/PayPalService.php
like image 132
Max Avatar answered Sep 25 '22 14:09

Max