David Shaffer
Shaffer Consulting

What is SmallMerchant?

SmallMerchant is a VisualWorks framework for processing payments through payment processing systems. Currently SmallMerchant only supports portions of Paypal's Website Payments Pro. Depending on your Payment Processing needs, you may find that you need to fill in some of the gaps in SmallMerchant. Please contribute your changes back!

Is it free?

SmallMerchant is free (see the license information in the source bundle) but Paypal Website Payments Pro is not. At the time of this writing it is US$30 per month with an additional 2.2% - 2.9% + US$0.30 per transaction. Details are provided by Paypal during the registration process.

Are other payment processing systems going to be supported?

I don't have any specific plan in this regard at the moment but the design of SmallMerchant should allow the integration of other PPS's without too much work. If you need to access another PPS and don't want to implement it yourself, contact me. My consulting fee is reasonable. :-)

If you implement support for another PPS, I would really like you to contribute your work back to SmallMerchant. Just publish it in the Cincom Repository. This is certainly not a requirement of the license and I understand that some employment situations make this impossible.

Can I use SmallMerchant in my product?

Probably. SmallMerchant is available under the MIT license. See package comments for details.

What Smalltalks are supported?

Currently only VisualWorks 7.6 and 7.7 are supported.

Getting Started

I recommend that you start by reading the Website Payments Pro integration guide. This guide discusses how you will integrate Paypal into your web site. Note that Website Payments Pro requires that you provide the "express checkout" option to your customers. It is your responsibility to meet the terms of the Website Payment Pro agreement. SmallMerchant enables you to perform express checkout but it doesn't automatically provide this functionality in your application.

Creating Paypal developer and sandbox accounts

Note: If you have problems during this process, please try clearing your browser cookies and cache. In my experience the sandbox is extremely unreliable for creating Website Payment Pro accounts. I posted my problems to the support group and was given this feedback from a paypal developer: Can't create WPP account in sandbox. You should expect to have to contact Paypal to get Website Payments Pro enabled on your sandbox account. Rest assured that the sandbox works very well (it is just the account creation process that is problematic).

The Paypal sandbox permits developers to experiment with Paypal and test their application without any real money being exchanged. In the following text I make reference to two account types:

  1. Developer -- account which permits you to manage sandbox accounts.
  2. Sandbox -- "fake" Paypal seller/buyer accounts

You should begin by creating a Paypal developer account (bookmark this'll use it a lot!). Even if you already have a Paypal account you need to create a separate developer account. You may use the same e-mail address for both your normal paypal account and your developer account.

From within your developer account you'll need to create "fake" accounts for a single seller and as many buyers as you like (you may need buyer accounts to generate sandbox credit card numbers and to test your support for Paypal Express). Read the Paypal Sandbox User's Guide for instructions.

API Credentials

To perform a transaction on behalf of your seller account you need the API credentials for this seller. You should be able to obtain those by clicking on the "API Credentials" link in your developer sandbox account menu:

Clicking on that link should present you with the credentials for your sandbox seller account:

You will need these credentials to perform transactions with SmallMerchant. I will call them your "seller credentials".

Go back to the "Test Accounts" section (using the top-left menu). You should now log into your seller account by selecting it and clicking the "Enter Sandbox Test Site" button. Your username should be completed for you. The password is the one you chose when you created the account (not your API password!). Once logged in you are looking at a merchant's view of a Paypal account. Use this to look at transactions made against this account. See the sandbox user's guide for more details.

Loading SmallMerchant

Load the bundle SmallMerchant-Development from the Cincom Public Store Repository. This bundle contains both the SmallMerchant bundle and the SmallMerchant-Tests package. If you want to run the SUnit tests, go ahead. You will be prompted for your seller credentials (username, password and signature). If you enter one of them incorrectly, you can reset the test credentials by evaluating the following expression:

PaypalCredentialsResource queryUserForCredentials

If the acceptance tests fail, double check your seller signature on your API credentials page. Some web browsers cut off this long string. You might need to view the HTML source to get the full string. The tests will modify your seller account balance so don't be surprised if it isn't zero any more.

Quick demo: Performing a balance inquiry

This is a quick example of how to use a payment gateway. Evaluate the following code and "inspect" the result:

gw := WebsitePaymentsPro
	username: 'your-seller-username'
	password: 'your-seller-api-password'
	signature: 'your-seller-signature'.
gw useSandbox.

gw getBalance inCurrency: SMCurrency usd

In the resulting inspector you'll see that you got back a SMMoney instance. It should correspond to the account balance you get from the web interface for your seller sandbox account.

The basics


SmallMerchant avoids interpreting monetary values going to or coming from the Payment Processing System. Monetary amounts, along with their currencies, are stored as strings in instances of SMMoney. Here's a sample of creating an SMMoney instance representing US$100:

amount := SmallMerchant.SMMoney amount: '100.00' currency: SMCurrency usd

The buyer and addresses

SmallMerchant includes the Buyer and Address classes for representing a Buyer and their addresses. Only two buyer addresses are relevant to any transaction currently supported by SmallMerchant: shipping and billing. Buyer has accessors for each of these address. Here is a sample of creating a buyer:

(address := SmallMerchant.Address new)
	name: 'Fred Jones';
	street: '123 N. Main St.';
	street2: 'Apt 4';
	city: 'New Wilmington';
	state: 'PA';
	country: (Country withCode: 'US');
	phoneNumber: '412-555-1212';
	zip: '16172'.

(buyer := SmallMerchant.Buyer new)
	firstName: 'Bob';
	lastName: 'Smith';
	shippingAddress: address;
	billingAddress: address.

Notice that the address can specify different names than the buyer. This is to support the ability of Paypal (and probably other PPS's) to list a different name on a shipping label or credit card verification.

Since the seller identity is generally part of the authentication process for the PPS, there is no separate class to represent the seller (see "Seller credentials" below).

Credit card

Credit cards are commonly used during PPS transactions. SmallMerchant includes the CreditCard class. Here is a sample instance:

(creditCard := SmallMerchant.CreditCard new)
	name: 'Foo S. Bar';
	number: '2222111122223333';
	type: SmallMerchant.CreditCardType visa;
	verificationCode: '111';
	expirationMonth: 6;
	expirationYear: 2012.

Payment description

The class PaymentDescription is used in several places to describe a payment to be made using the PPS. Here is a sample of creating a simple payment description:

(payment := SmallMerchant.PaymentDescription new)
	amount: amount;
	buyer: buyer;
	ipAddress: '';
	creditCard: creditCard.

For Paypal at least, the IP Address of the computer used by the buyer is supposed to be included in the payment description.

Seller credentials

All that is needed to act on behalf of the seller is their credentials. As discussed above these credentials are: username, API password, and API signature. A credentials instance is created as follows:

(credentials := SmallMerchant.Paypal.Credentials new)
	login: 'Your api username here';
	password: 'Your api password here';
	signature: 'Your api signature here'.

Payment gateway

All transactions are initiated through a payment gateway. The only existing concrete gateway is SmallMerchant.Paypal.WebsitePaymentsPro typically created using a credentials instance as:

gateway := SmallMerchant.Paypal.WebsitePaymentsPro credentials: credentials.

Most payment processing systems provide some sort of sandbox for testing. To connect the above gateway to a sandbox, rather than the live site, send it #useSandbox.

gateway useSandbox.

Transactions and queries

Transactions and queries are issued via a PPS gateway. All concrete gateways in SmallMerchant are subclasses of the abstract PaymentGateway class. The only concrete gateway included in SmallMerchant right now is WebsitePaymentsPro.

Getting the seller's account balance

An example was already given Quick demo: Performing a balance inquiry. There is one generic PaymentGateway API method for fetching your account balance: #getBalance. Paypal also provides a balance inquiry that returns your balance in multiple currencies. This Paypal-specific balance inquiry method is #getBalanceAllCurrencies:. Using the gateway created above (make sure you sent it #useSandbox) inspect the result of the following:

response := gateway getBalanceAllCurrencies: true

You should receive an instance of GetBalanceResponse. You can get the balances by sending it #amounts:

response amounts inspect

or you can get the amount of any specific currency by sending it #inCurrency:

response inCurrency: SMCurrency usd

which answers a string with the balance in the specified currency (or an error if there are no balances listed in that currency).

Posting a payment

Payments are specified by instances of PaymentDescription. See Payment description for an example of creating a PaymentDescription. Assuming you have such a object in a variable called payment you can post this payment to your payment gateway via:

gateway post: payment

If you used the CreditCard instance that I created above, you may get an error because the credit card number is invalid. It is worth studying this error because any applications that use SmallMerchant will need to be able to handle errors. We will discuss error processing in the Errors section. In the mean time you can find a valid sandbox credit card number by logging into your paypal sandbox account, selecting the "Test Accounts" tab and then picking "View Details" for one of you accounts. Here is a complete example of posting a payment. You will have to insert the credit card and API credentials:

(address := SmallMerchant.Address new)
	name: 'Fred Jones';
	street: '123 N. Main St.';
	street2: 'Apt 4';
	city: 'New Wilmington';
	state: 'PA';
	country: (SmallMerchant.Country withCode: 'US');
	phoneNumber: '412-555-1212';
	zip: '16172'.

(buyer := Buyer new)
	firstName: 'Bob';
	lastName: 'Smith';
	shippingAddress: address;
	billingAddress: address.

(creditCard := CreditCard new)
	name: 'Foo S. Bar';
	number: 'Insert your sandbox credit card number here';
	type: SmallMerchant.CreditCardType visa;
	verificationCode: '111';
	expirationMonth: insert your credit card expiration month number here;
	expirationYear: insert your credit card expiration year number here.

(payment := SmallMerchant.PaymentDescription new)
	amount: (SMMoney amount: '100.0' currency: SMCurrency usd);
	buyer: buyer;
	ipAddress: '';
	creditCard: creditCard.

(credentials := SmallMerchant.Paypal.Credentials new)
	login: 'your API username';
	password: 'your API password';
	signature: 'your API signature'.

gateway := SmallMerchant.Paypal.WebsitePaymentsPro credentials: credentials.
gateway useSandbox.

gateway post: payment.

Authorize and capture a payment

Often times web boutiques use two phase payment processing. During the order phase, the buyer's payment information is captured and a payment authorization is obtained from the payment processing system. The authorization process normally yields some sort of authorization token. At the time the order is fulfilled the payment is captured using this authorization token. At the time of payment capture the credit card account is debited the total order amount (which may differ from the original authorization amount).

A payment is authorized via the #authorize: method in the gateway:

token := gw authorize: payment.

and later the payment is captured using #capture: which requires a SmallMerchant.PaymentCapture instance as its argument:

(capture := SmallMerchant.PaymentCapture new)
	amount: (SMMoney amount: '110.00' currency: SMCurrency usd);
	authorizationId: token transactionId;
	descriptionOnCreditCardStatement: 'Foo bar'.

gw capture: capture

Notice that, in this example, we captured a slightly different amount than we authorized. Often times authorization happens at the time an order is placed and capture occurs when the order is fulfilled. Sometimes there are additional charges that occur during fulfillment (such as shipping charges) that can be captured with the same authorization. Read the Website Payments Pro documentation to determine the limits in differences between the authorize and capture amounts.

Paypal Express Checkout