Skip to content

Instantly share code, notes, and snippets.

@ffub
Last active January 26, 2016 08:02
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ffub/4493175 to your computer and use it in GitHub Desktop.
Save ffub/4493175 to your computer and use it in GitHub Desktop.
A basic Processwire module to send payments to PayPal and process the IPN response using the website payments standard API.
<?php
class PaymentGatewayPayPal extends WireData implements Module, ConfigurableModule {
/*
* Module details, defaults and initialisation
*
*/
public static function getModuleInfo()
{
return array(
'title' => 'PayPal Payment Processing',
'version' => 001,
'summary' => 'Send payments to PayPal and validate their IPN responses',
'singular' => true,
'autoload' => true
);
}
static public function getDefaultData() {
return array(
'paypalAccount' => null,
'paypalDeveloperAccount' => null,
'paypalUrl' => "https://www.paypal.com/cgi-bin/webscr?",
'sandbox' => false,
'ipnListener' => false,
'completedPage' => false,
'currency' => null
);
}
public function __construct() {
foreach(self::getDefaultData() as $key => $value) {
$this->$key = $value;
}
}
public function init() {
// Set localised title
$this->title = $this->_("PayPal");
// Set PayPal URL depending on whether we are in sandbox mode
$paypalHost = $this->sandbox ? "www.sandbox.paypal.com" : "www.paypal.com";
$this->paypalUrl = "https://$paypalHost/cgi-bin/webscr?";
// Set ipnListener URL
$this->ipnListener = $this->pages->get("/")->httpUrl . "ipnlistener/";
// Intercept requests to 'ipnlistener' and process the IPN
if (strpos($_SERVER['REQUEST_URI'], wire('config')->urls->root . 'ipnlistener') !== FALSE) {
$this->processIpn($_POST);
exit;
}
}
/*
* Send a payment to PayPal using Website Payments Standard. Full documentation can be found at:
* https://www.x.com/developers/paypal/documentation-tools/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables
*
* $payment = array(
* 'quantity' => 1,
* 'item_name' => "Socks",
* 'amount' => "2.50",
* 'invoice' => "123",
* 'cancel_return' => $page->httpUrl . "cancelled/",
* 'currency_code' => "GBP"
* );
* $modules->PaymentsPayPal->beginPayment($payment);
*
*
*/
public function beginPayment($payment) {
// Defaults
$account = $this->sandbox ? $this->paypalDeveloperAccount : $this->paypalAccount;
$return = $this->completedPage ? $this->pages->get($this->completedPage)->httpUrl : $this->pages->get("/")->httpUrl;
// Create a payment with the defaults and merge it with the provided payment
$paypalObj = array(
'cmd' => "_xclick",
'business' => $account,
'return' => $return,
'notify_url' => $this->ipnListener
);
$paypalObj = array_merge($paypalObj,$payment);
// Send the payment to PayPal
$endpoint = $this->paypalUrl . http_build_query($paypalObj);
$this->session->redirect($endpoint,false);
}
/*
* Process the IPN
*
*/
public function ___processIpn($post) {
if(!$this->validateIpn($post)) {
mail($this->config->adminEmail, "Invalid IPN response", print_r($post, true));
return false;
}
// Testing
mail($this->config->adminEmail, "Valid IPN response", print_r($post, true));
return true;
}
/*
* Validate the IPN by returning it to PayPal
*
*/
public function validateIpn($post) {
$data = array(
'cmd' => "_notify-validate"
);
$url = $this->paypalUrl;
$data = array_merge($post,$data);
$options = array(
'http' => array(
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if (strcmp ($result, "VERIFIED") == 0) {
return true;
}
return false;
}
/*
* Configuration
*
*/
static public function getModuleConfigInputfields(Array $data) {
// Get the defaults and alias $modules
$data = array_merge(self::getDefaultData(), $data);
$modules = wire('modules');
// Build config form
$fields = new InputfieldWrapper();
$f = $modules->get("InputfieldEmail");
$f->name = 'paypalAccount';
$f->value = $data['paypalAccount'];
$f->label = "PayPal Account Email";
$f->description = "The email address of the account you would like to pay money into.";
$f->required = 1;
$fields->add($f);
$f = $modules->get("InputfieldEmail");
$f->name = 'paypalDeveloperAccount';
$f->value = $data['paypalDeveloperAccount'];
$f->label = "PayPal Developer Account Email";
$f->description = "A developer account for use with the PayPal developer sandbox.";
$fields->add($f);
$f = $modules->get("InputfieldCheckbox");
$f->name = 'sandbox';
$f->label = "Use PayPal developer sandbox?";
$f->value = 1;
$f->attr('checked', empty($data['sandbox']) ? '' : 'checked');
$fields->add($f);
$f = $modules->get("InputfieldPageListSelect");
$f->attr('name', 'completedUrl');
$f->attr('value', $data['completedUrl']);
$f->derefAsPage = 1; // single page reference
$f->label = "Thank you page";
$f->description = 'The page the user is returned to after completion of the payment.';
$fields->add($f);
$f = $modules->get("InputfieldText");
$f->name = 'currency';
$f->value = $data['currency'];
$f->label = "Currency code";
$f->description = "Three letter currency code. The PayPal default is USD.";
$fields->add($f);
return $fields;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment