Tuesday, July 21, 2009

PayPal DoDirectPayment .NET API

I just implemented PayPal's Web Payment Pro API DoDirectPayment into my site using their sample .NET SOAP code (replacing the sample API credentials with my own of course).

HOWEVER, it didn't work...go figure. I searched the net for a super long time, and finally found the solution. So I figured I would write it on here in a little more coherent fashion.


The original code (does not work!!!) is shown below:
/*
* Copyright 2005, 2008 PayPal, Inc. All Rights Reserved.
*
* DoDirectPayment SOAP example; last modified 08MAY23.
*
* Process a credit card payment.
*/
using System;
using com.paypal.sdk.services;
using com.paypal.soap.api;
using com.paypal.sdk.profiles;
/**
* PayPal .NET SDK sample code
*/
namespace GenerateCodeSOAP
{
public class DoDirectPayment
{
public DoDirectPayment()
{
}
public string DoDirectPaymentCode(string paymentAmount, string buyerLastName, string buyerFirstName, string buyerAddress1, string buyerAddress2, string buyerCity, string buyerState, string buyerZipCode, string creditCardType, string creditCardNumber, string CVV2, int expMonth, int expYear, PaymentActionCodeType paymentAction)
{
CallerServices caller = new CallerServices();

IAPIProfile profile = ProfileFactory.createSignatureAPIProfile();
/*
WARNING: Do not embed plaintext credentials in your application code.
Doing so is insecure and against best practices.
Your API credentials must be handled securely. Please consider
encrypting them for use in any production environment, and ensure
that only authorized individuals may view or modify them.
*/

// Set up your API credentials, PayPal end point, and API version.
profile.APIUsername = "REPLACE_USERNAME_HERE";
profile.APIPassword = "REPLACE_PASSWORD_HERE";
profile.APISignature = "REPLACE_SIGNATURE_HERE";
profile.Environment = "sandbox";
caller.APIProfile = profile;


// Create the request object.
DoDirectPaymentRequestType pp_Request = new DoDirectPaymentRequestType();
pp_Request.Version = "51.0";

// Add request-specific fields to the request.
// Create the request details object.
pp_Request.DoDirectPaymentRequestDetails = new DoDirectPaymentRequestDetailsType();

pp_Request.DoDirectPaymentRequestDetails.IPAddress = "10.244.43.106";
pp_Request.DoDirectPaymentRequestDetails.MerchantSessionId = "1X911810264059026";
pp_Request.DoDirectPaymentRequestDetails.PaymentAction = paymentAction;

pp_Request.DoDirectPaymentRequestDetails.CreditCard = new CreditCardDetailsType();

pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardNumber = creditCardNumber;
switch (creditCardType)
{
case "Visa":
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Visa;
break;
case "MasterCard":
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.MasterCard;
break;
case "Discover":
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Discover;
break;
case "Amex":
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Amex;
break;
}
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CVV2 = CVV2;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.ExpMonth = expMonth;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.ExpYear = expYear;

pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner = new PayerInfoType();
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Payer = "";
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerID = "";
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerStatus = PayPalUserStatusCodeType.unverified;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerCountry = CountryCodeType.US;

pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address = new AddressType();
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Street1 = buyerAddress1;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Street2 = buyerAddress2;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CityName = buyerCity;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.StateOrProvince = buyerState;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.PostalCode = buyerZipCode;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CountryName = "USA";
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Country = CountryCodeType.US;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CountrySpecified = true;

pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName = new PersonNameType();
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName.FirstName = buyerFirstName;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName.LastName = buyerLastName;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.
pp_Request.DoDirectPaymentRequestDetails.PaymentDetails = new PaymentDetailsType();
pp_Request.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal = new BasicAmountType();
// NOTE: The only currency supported by the Direct Payment API at this time is US dollars (USD).

pp_Request.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal.currencyID = CurrencyCodeType.USD;
pp_Request.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal.Value = paymentAmount;

// Execute the API operation and obtain the response.
DoDirectPaymentResponseType pp_response = new DoDirectPaymentResponseType();
pp_response = (DoDirectPaymentResponseType)caller.Call("DoDirectPayment", pp_Request);
return pp_response.Ack.ToString();
}
}
}


In order to get the code to work you must add two lines, shown in bold (works!!!):

/*
* Copyright 2005, 2008 PayPal, Inc. All Rights Reserved.
*
* DoDirectPayment SOAP example; last modified 08MAY23.
*
* Process a credit card payment.
*/
using System;
using com.paypal.sdk.services;
using com.paypal.soap.api;
using com.paypal.sdk.profiles;
/**
* PayPal .NET SDK sample code
*/
namespace GenerateCodeSOAP
{
public class DoDirectPayment
{
public DoDirectPayment()
{
}
public string DoDirectPaymentCode(string paymentAmount, string buyerLastName, string buyerFirstName, string buyerAddress1, string buyerAddress2, string buyerCity, string buyerState, string buyerZipCode, string creditCardType, string creditCardNumber, string CVV2, int expMonth, int expYear, PaymentActionCodeType paymentAction)
{
CallerServices caller = new CallerServices();

IAPIProfile profile = ProfileFactory.createSignatureAPIProfile();
/*
WARNING: Do not embed plaintext credentials in your application code.
Doing so is insecure and against best practices.
Your API credentials must be handled securely. Please consider
encrypting them for use in any production environment, and ensure
that only authorized individuals may view or modify them.
*/

// Set up your API credentials, PayPal end point, and API version.
profile.APIUsername = "REPLACE_USERNAME_HERE";
profile.APIPassword = "REPLACE_PASSWORD_HERE";
profile.APISignature = "REPLACE_SIGNATURE_HERE";
profile.Environment = "sandbox";
caller.APIProfile = profile;


// Create the request object.
DoDirectPaymentRequestType pp_Request = new DoDirectPaymentRequestType();
pp_Request.Version = "51.0";

// Add request-specific fields to the request.
// Create the request details object.
pp_Request.DoDirectPaymentRequestDetails = new DoDirectPaymentRequestDetailsType();

pp_Request.DoDirectPaymentRequestDetails.IPAddress = "10.244.43.106";
pp_Request.DoDirectPaymentRequestDetails.MerchantSessionId = "1X911810264059026";
pp_Request.DoDirectPaymentRequestDetails.PaymentAction = paymentAction;

pp_Request.DoDirectPaymentRequestDetails.CreditCard = new CreditCardDetailsType();

pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardNumber = creditCardNumber;
switch (creditCardType)
{
case "Visa":
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Visa;
break;
case "MasterCard":
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.MasterCard;
break;
case "Discover":
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Discover;
break;
case "Amex":
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Amex;
break;
}
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CVV2 = CVV2;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.ExpMonthSpecified = true;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.ExpYearSpecified = true;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.ExpMonth = expMonth;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.ExpYear = expYear;

pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner = new PayerInfoType();
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Payer = "";
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerID = "";
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerStatus = PayPalUserStatusCodeType.unverified;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerCountry = CountryCodeType.US;

pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address = new AddressType();
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Street1 = buyerAddress1;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Street2 = buyerAddress2;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CityName = buyerCity;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.StateOrProvince = buyerState;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.PostalCode = buyerZipCode;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CountryName = "USA";
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Country = CountryCodeType.US;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CountrySpecified = true;

pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName = new PersonNameType();
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName.FirstName = buyerFirstName;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName.LastName = buyerLastName;
pp_Request.DoDirectPaymentRequestDetails.CreditCard.CardOwner.
pp_Request.DoDirectPaymentRequestDetails.PaymentDetails = new PaymentDetailsType();
pp_Request.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal = new BasicAmountType();
// NOTE: The only currency supported by the Direct Payment API at this time is US dollars (USD).

pp_Request.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal.currencyID = CurrencyCodeType.USD;
pp_Request.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal.Value = paymentAmount;

// Execute the API operation and obtain the response.
DoDirectPaymentResponseType pp_response = new DoDirectPaymentResponseType();
pp_response = (DoDirectPaymentResponseType)caller.Call("DoDirectPayment", pp_Request);
return pp_response.Ack.ToString();
}
}
}


To call the API and make a direct payment, I used the call (in another aspx file):

Dim r As New GenerateCodeSOAP.DoDirectPayment
r.DoDirectPaymentCode("5.00", "Doe", "John", "123 Main St #1A", "", "Maintown", "MA", "01011", "Visa", "123456781234567", "999", 11, 2012, com.paypal.soap.api.PaymentActionCodeType.Sale)

Wednesday, July 16, 2008

More Facebook Programming - Application Login Issues

Alright Facebook programmers....
I developed my first facebook app, only to be stumbled by an annoying Facebook issue. First off, FB requires users to be logged into applications in order to use them. I am ok with this. It helps log statistics, etc...metrics developers shoud have access to.

My problem...

When a user would view my application (I didn't want them to be required to add it), they would login and be redirected INCORRECTLY.

I.e.
http://apps.facebook.com/appName/main.phphttp://my.appsite.com/appName/?auth_token=XXXXX

Note the "...main.phphttp://..."

Ultimately, this is due to the "next" variable in the query string on the login page, but unfortunately, it is difficult to change. There have been a few comments on this at: http://forum.developers.facebook.com/viewtopic.php?id=16199
as well as some other threads...seems to be quite an issue.

HOWEVER:
I have an alternative way around this that I find to be much easier to control!

PHP Code as follows (using the FB PHP5 library):

require_once 'facebook.php';

$appapikey = '3b2XXXXXXXX14';
$appsecret = 'aa2XXXXXXXX06';

$facebook = new Facebook($appapikey, $appsecret,
$_GET['fb_sig_session_key'].$_POST['fb_sig_session_key']);

$user = $facebook->get_loggedin_user();

if($user=="") {
//Force a login to the app with the CORRECT "next" url
$urlRedirect="http://www.facebook.com/tos.php?api_key=XXXXXXXXXX
&next=page.php&v=1.0&canvas";

$facebook->redirect($urlRedirect);
}



If the user is NOT logged into the application, the user will be asked to login and redirected to whichever page follows the "next" variable in the query string. In the above example, the user would be redirected to: http://apps.facebook.com/appName/page.php

There you have it! Enjoy, and comments are welcome!

Monday, May 12, 2008

Who is viewing my Facebook page? I'll tell you!

Many people have asked me, "how can I tell which of my friends are viewing my profile?"
I know some people may say that entering some very simple logging code onto your Facebook account would be a violation of the owners privacy. However, I beg to differ. In fact, social network sites are prone to stalkers in the worst way. Granted, Facebook does an excellent job in protecting the privacy of people (well maybe not by default, but you have the option to turn all the "alerts" off).

Ultimately this code came out of a quest for logging MySpace traffic, which in my opinion, does very little to protect it's users. Yes, you can set your profile to "private," but I think that is the extent of it.

So which of my friends is viewing my Facebook profile? Let me tell you how to find out.

---------------------------------------------------------------------------------

As it turns out, Facebook does an EXCELLENT job of NOT giving you any information regarding who views you. However, I have found a pseudo-work-around.

There is a canvas application called "SuperProfile" (http://apps.facebook.com/logpages/) which displays much of your Facebook profile information (should you allow it to). Personally, I think it does a much better job than the Facebook published profile by separating the information in tabs. It also uses some Apple-ish looking animations and better photo viewing (just my opinion, after all this is a blog).

The app has a function (via "Setup" after you have installed the app) for profile monitoring which seems to be run by Logpages.net. They do charge $1 per month, but you get to see who views your SuperProfile pages, where they are located, and some other information.

So, all in all, not a perfect solution. But when you realize that people who view your SuperProfile must have entered the app via your Facebook Profile...the rest is history.