Last active
January 26, 2016 08:02
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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