Paysystem
Developing a new payment system plugin is quite easy with aMember Pro v4 once you become familiar with API details. In general, developing a new payment system plugin consists in several parts:
- Redirect customer to payment system with correct parameters
- Once the customer is returned, show the "thank you" page and (optionally) handle additional parameters payment system sent in return URL
Define payment system plugin
You may use the following payment system plugin template. Put it into application/default/plugins/payment/yourps.php
<?php
// note the class name - it must match filename (but start with upcase letter)
class Am_Paysystem_Yourps extends Am_Paysystem_Abstract
{
const PLUGIN_STATUS = self::STATUS_DEV; // do not add plugin into production build
const PLUGIN_REVISION = '@@VERSION@@'; // auto-replaced with production version
const URL = "https://yourps.com/payment.page/url";
protected $defaultTitle = 'YourPS';
protected $defaultDescription = 'purchase using PayPal or Credit Card';
// here you add elements to HTML_QuickForm2 form with
// parameters necessary to configure your form
// saved parameters are available with $this->getConfig('paramname')
// api call in other plugin functions
public function _initSetupForm(Am_Form_Setup $form)
{
$form->addInteger('merchant_id', array('size'=>20))
->setLabel('Account#');
$form->addPassword('pass', array('size'=>10))
->setLabel('Validation Password');
}
/// now lets write payment redirect function
public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result)
{
$a = new Am_Paysystem_Action_Redirect(self::URL);
// set URL parameter [t] to value of product title
$a->t = $invoice->getLineDescription();
// set [vp] parameter to total of first subscription payment
$a->vp = $invoice->first_total;
// set [sp] parameter to total of second subscription payment
$a->sp = $invoice->second_total;
// set [s] to configured [merchant_id]
$a->s = $this->getConfig('merchant_id');
// set [fn] to customer first name
$a->fn = $invoice->getFirstName();
// set [sn] to customer last name
$a->sn = $invoice->getLastName();
// set [em] to customer email address
$a->em = $invoice->getEmail();
// set [ret] to unique, expiring return URL for that invoice
$a->ret = $this->getReturnUrl();
// set [lnk] to "cancel" url where customer may choose other payprocessor for this payment
$a->lnk = $this->getCancelUrl();
// now return it to core and aMember will do the rest
$result->setAction($a);
}
// let aMember know how this plugin is going to deal with recurring payments
public function getRecurringType()
{
return self::REPORTS_EOT;
}
public function getReadme()
{
return <<<CUT
My payment plugin readme
Readme instructions here....
CUT;
}
public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
return new Am_Paysystem_Transaction_Yourps_Ipn($this, $request, $response, $invokeArgs);
}
}
This code makes possible to:
- enable [yourps] plugin at aMember Cp -> Configuration -> Add-ons
- configure plugin at aMember Cp -> Configuration -> Setup/Configuration -> YourPS
- get a working redirect to your payment system when customer chooses it in signup form
- when customer returned to 'Thank You' page after payment, receipt and welcome words will be automatically displayed
But the plugin does not yet handle mark received payments as paid, and does not make customer active. Lets continue...
Handle IPN posts
Add the following code to the file:
// the following class takes incoming IPN post from your payment system, parses
// it if necessary, checks that it came unchanged, from trusted source, finds
// corresponding amember invoice for it, and adds payment record to the invoice
// it is all what is required to handle payment
class Am_Paysystem_Transaction_Yourps_Ipn extends Am_Paysystem_Transaction_Incoming
{
public function validateSource()
{
// there must be some code to validate if IPN came from payment system, and not from a "hacker"
return true;
}
public function validateStatus()
{
// there must be code to check post variables and confirm that the post indicates successful payment transaction
return true;
}
public function findInvoiceId()
{
// it takes invoiceId from request as sent by payment system
return $this->request->getFiltered('invoiceId');
}
public function getUniqId()
{
// take unique transaction id from yourps IPN post
return $this->request->get('psReceipt');
}
public function validateTerms()
{
// compare our invoice payment settings, and what payment system handled
// if there is difference, it is possible that redirect url was modified
// before payment
return ($this->request->get('vp') == $this->invoice->first_total)
&& ($this->request->get('sp') == $this->invoice->second_total);
}
}
Once you implement and test this, the plugin will be able to handle IPN posts coming from payment system and plugin will become functional. There are lot more complex cases. Check existing amember payment plugins as examples, and if that is not necessary, do not hesitate to contact CGI-Central staff via helpdesk for explanation.