From d67d2e4fda7c32d72ea2dde424f50ca5d2e4378b Mon Sep 17 00:00:00 2001 From: wisdomanthoni Date: Tue, 27 Aug 2019 21:05:02 +0100 Subject: [PATCH 01/15] wip --- callback.php | 63 +++++++++++++++++ ...ystack_plugin_tracker.php => Paystack.php} | 68 ++++++++++++++++--- transaction.php | 24 +++++++ verify.php => webhook.php | 36 ++-------- 4 files changed, 151 insertions(+), 40 deletions(-) create mode 100644 callback.php rename classes/{paystack_plugin_tracker.php => Paystack.php} (50%) create mode 100644 transaction.php rename verify.php => webhook.php (91%) diff --git a/callback.php b/callback.php new file mode 100644 index 0000000..0fc6896 --- /dev/null +++ b/callback.php @@ -0,0 +1,63 @@ +. +/** + * Listens for Instant Payment Notification from Paystack + * + * This script waits for Payment notification from Paystack, + * then double checks that data by sending it back to Paystack. + * If Paystack verifies this then it sets up the enrolment for that + * user. + * + * @package enrol_paystack + * @copyright 2019 Paystack + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +// Disable moodle specific debug messages and any errors in output, +// comment out when debugging or better look into error log! + +require("../../config.php"); +require_once("$CFG->dirroot/enrol/paystack/lib.php"); + +$id = required_param('id', PARAM_INT); + +if (!$course = $DB->get_record("course", array("id"=>$id))) { + redirect($CFG->wwwroot); +} + +$context = context_course::instance($course->id, MUST_EXIST); +$PAGE->set_context($context); + +require_login(); + +if (!empty($SESSION->wantsurl)) { + $destination = $SESSION->wantsurl; + unset($SESSION->wantsurl); +} else { + $destination = "$CFG->wwwroot/course/view.php?id=$course->id"; +} + +$fullname = format_string($course->fullname, true, array('context' => $context)); + +if (is_enrolled($context, NULL, '', true)) { // TODO: use real paypal check + redirect($destination, get_string('paymentthanks', '', $fullname)); + +} else { /// Somehow they aren't enrolled yet! :-( + $PAGE->set_url($destination); + echo $OUTPUT->header(); + $a = new stdClass(); + $a->teacher = get_string('defaultcourseteacher'); + $a->fullname = $fullname; + notice(get_string('paymentsorry', '', $a), $destination); +} + + diff --git a/classes/paystack_plugin_tracker.php b/classes/Paystack.php similarity index 50% rename from classes/paystack_plugin_tracker.php rename to classes/Paystack.php index 3d4073a..d3a41af 100644 --- a/classes/paystack_plugin_tracker.php +++ b/classes/Paystack.php @@ -11,7 +11,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . /** - * Track Payment Transactions from this Plugin + * Paystack API Class * * @package enrol_paystack * @copyright 2019 Paystack @@ -22,22 +22,33 @@ defined('MOODLE_INTERNAL') || die(); -class paystack_plugin_tracker { - var $public_key; - var $plugin_name; - function __construct($plugin, $pk){ +class Paystack { + public $plugin_name; + public $public_key; + public $secret_key; + + public function __construct($plugin, $pk, $sk){ //configure plugin name //configure public key + $this->base_url = "https://api.paystack.co/"; $this->plugin_name = $plugin; $this->public_key = $pk; + $this->secret_key = $sk; } - - function log_transaction_success($trx_ref){ + + /** + * Track Payment Transactions from this Plugin + * + * @param string $trx_ref + * @return void + */ + public function log_transaction_success($reference) + { //send reference to logger along with plugin name and public key $url = "https://plugin-tracker.paystackintegrations.com/log/charge_success"; $params = [ 'plugin_name' => $this->plugin_name, - 'transaction_reference' => $trx_ref, + 'transaction_reference' => $reference, 'public_key' => $this->public_key ]; $params_string = http_build_query($params); @@ -50,4 +61,45 @@ function log_transaction_success($trx_ref){ $result = curl_exec($ch); // echo $result; } + + /** + * Verify Payment Transaction + * + * @param string $reference + * @return void + */ + public function verify_transaction($reference) + { + $paystackUrl = $this->base_url . "transaction/verify/" . $reference; + + $curl = curl_init(); + curl_setopt_array($curl, [ + CURLOPT_URL => $paystackUrl, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_CUSTOMREQUEST => "GET", + CURLOPT_HTTPHEADER => [ + "authorization: Bearer " . $this->secretkey, + "content-type: application/json", + "cache-control: no-cache" + ], + ]); + + $request = curl_exec($curl); + $res = json_decode($request, true); + $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + if (curl_errno($curl)) { + throw new moodle_exception( + 'errpaystackconnect', + 'enrol_paystack', + '', + array('url' => $paystackUrl, 'response' => $res), + json_encode($data) + ); + } + + curl_close($curl); + + return $res; + } } diff --git a/transaction.php b/transaction.php new file mode 100644 index 0000000..f2e3391 --- /dev/null +++ b/transaction.php @@ -0,0 +1,24 @@ +. +/** + * Listens for Instant Payment Webhook Notification from Paystack + * + * This script waits for Payment notification from Paystack, + * then double checks that data by sending it back to Paystack. + * If Paystack verifies this then it sets up the enrolment for that + * user. + * + * @package enrol_paystack + * @copyright 2019 Paystack + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ diff --git a/verify.php b/webhook.php similarity index 91% rename from verify.php rename to webhook.php index 8999a59..c20d3bd 100644 --- a/verify.php +++ b/webhook.php @@ -11,7 +11,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . /** - * Listens for Instant Payment Notification from Paystack + * Listens for Instant Payment Webhook Notification from Paystack * * This script waits for Payment notification from Paystack, * then double checks that data by sending it back to Paystack. @@ -35,7 +35,6 @@ require_once($CFG->libdir . '/enrollib.php'); require_once($CFG->libdir . '/filelib.php'); -require_login(); // Paystack does not like when we return error messages here, // the custom handler just logs exceptions and stops. set_exception_handler('enrol_paystack_charge_exception_handler'); @@ -93,39 +92,12 @@ $plugin_instance = $DB->get_record("enrol", array("id" => $data->instanceid, "enrol" => "paystack", "status" => 0), "*", MUST_EXIST); $plugin = enrol_get_plugin('paystack'); -$plugin_logger = new \enrol_paystack\paystack_plugin_tracker('moodle-enrol', $plugin->get_publickey()); +$paystack = new \enrol_paystack\Paystack('moodle-enrol', $plugin->get_publickey(), $plugin->secretkey()); // Set Course and Paystack Url $courseUrl = "$CFG->wwwroot/course/view.php?id=$course->id"; -$paystackUrl = "https://api.paystack.co/transaction/verify/" . $data->reference; -$curl = curl_init(); -curl_setopt_array($curl, [ - CURLOPT_URL => $paystackUrl, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_CUSTOMREQUEST => "GET", - CURLOPT_HTTPHEADER => [ - "authorization: Bearer " . $plugin->get_secretkey(), //replace this with your own test key - "content-type: application/json", - "cache-control: no-cache" - ], -]); - -$request = curl_exec($curl); -$res = json_decode($request, true); -$code = curl_getinfo($curl, CURLINFO_HTTP_CODE); - -if (curl_errno($curl)) { - throw new moodle_exception( - 'errpaystackconnect', - 'enrol_paystack', - '', - array('url' => $paystackUrl, 'response' => $res), - json_encode($data) - ); -} - -curl_close($curl); +$res = $paystack->verify_transaction($data->reference); if (!$res['status']) { notice($res['message'], $courseUrl); @@ -169,7 +141,7 @@ if ($data->payment_status == 'success') { // ALL CLEAR ! - $plugin_logger->log_transaction_success($data->reference); + $paystack->log_transaction_success($data->reference); $DB->insert_record("enrol_paystack", $data); From baf58cb35846feea1a5f4df6ccc5cbe415d7afc0 Mon Sep 17 00:00:00 2001 From: wisdomanthoni Date: Wed, 28 Aug 2019 11:54:50 +0100 Subject: [PATCH 02/15] wip --- classes/Paystack.php | 93 ++++++++--- enrol.html | 43 +++--- transaction.php => initialize.php | 24 ++- callback.php => verify.php | 39 +++-- webhook.php | 247 ++++++++++++++---------------- 5 files changed, 248 insertions(+), 198 deletions(-) rename transaction.php => initialize.php (60%) rename callback.php => verify.php (64%) diff --git a/classes/Paystack.php b/classes/Paystack.php index d3a41af..4ad925b 100644 --- a/classes/Paystack.php +++ b/classes/Paystack.php @@ -35,40 +35,57 @@ public function __construct($plugin, $pk, $sk){ $this->public_key = $pk; $this->secret_key = $sk; } - - /** - * Track Payment Transactions from this Plugin + + /** + * Verify Payment Transaction * - * @param string $trx_ref + * @param string $reference + * @param array $data * @return void */ - public function log_transaction_success($reference) + public function initialize_transaction($data) { - //send reference to logger along with plugin name and public key - $url = "https://plugin-tracker.paystackintegrations.com/log/charge_success"; - $params = [ - 'plugin_name' => $this->plugin_name, - 'transaction_reference' => $reference, - 'public_key' => $this->public_key - ]; - $params_string = http_build_query($params); - $ch = curl_init(); - curl_setopt($ch,CURLOPT_URL, $url); - curl_setopt($ch,CURLOPT_POST, true); - curl_setopt($ch,CURLOPT_POSTFIELDS, $params_string); - curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); - //execute post - $result = curl_exec($ch); - // echo $result; - } + $paystackUrl = $this->base_url . "transaction/initialize"; - /** + $curl = curl_init(); + curl_setopt_array($curl, [ + CURLOPT_URL => $paystackUrl, + CURLOPT_CUSTOMREQUEST => "POST", + CURLOPT_POSTFIELDS => $data, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => [ + "authorization: Bearer " . $this->secretkey, + "content-type: application/json", + "cache-control: no-cache" + ], + ]); + + $request = curl_exec($curl); + $res = json_decode($request, true); + + if (curl_errno($curl)) { + throw new moodle_exception( + 'errpaystackconnect', + 'enrol_paystack', + '', + array('url' => $paystackUrl, 'response' => $res), + json_encode($data) + ); + } + + curl_close($curl); + + return $res; + } + + /** * Verify Payment Transaction * * @param string $reference + * @param array $data * @return void */ - public function verify_transaction($reference) + public function verify_transaction($reference, $data = []) { $paystackUrl = $this->base_url . "transaction/verify/" . $reference; @@ -86,7 +103,7 @@ public function verify_transaction($reference) $request = curl_exec($curl); $res = json_decode($request, true); - $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + // $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); if (curl_errno($curl)) { throw new moodle_exception( @@ -102,4 +119,30 @@ public function verify_transaction($reference) return $res; } + + /** + * Track Payment Transactions from this Plugin + * + * @param string $trx_ref + * @return void + */ + public function log_transaction_success($reference) + { + //send reference to logger along with plugin name and public key + $url = "https://plugin-tracker.paystackintegrations.com/log/charge_success"; + $params = [ + 'plugin_name' => $this->plugin_name, + 'transaction_reference' => $reference, + 'public_key' => $this->public_key + ]; + $params_string = http_build_query($params); + $ch = curl_init(); + curl_setopt($ch,CURLOPT_URL, $url); + curl_setopt($ch,CURLOPT_POST, true); + curl_setopt($ch,CURLOPT_POSTFIELDS, $params_string); + curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); + //execute post + $result = curl_exec($ch); + // echo $result; + } } diff --git a/enrol.html b/enrol.html index 35c0bd4..f88a750 100644 --- a/enrol.html +++ b/enrol.html @@ -5,24 +5,30 @@

wwwroot/enrol/paystack/verify.php"?>"> - - - - - - " /> - - id}-{$course->id}-{$instance->id}" ?>" /> - - - - - - - " /> - - - + "_xclick", + "charset" => "utf-8", + "item_name" => p($coursefullname), + "item_name" => p($coursefullname), + "item_number" => p($courseshortname), + "quantity" => "1", + "on0" => print_string("user"), + "os0" => p($userfullname), + "custom" => echo "{$USER->id}-{$course->id}-{$instance->id}", + "currency_code" => p($instance->currency), + "amount" => p($cost), + "for_auction" => "false", + "no_note" => "1", + "no_shipping" => "1" , + "rm" => "2", + "cbt" => print_string("continuetocourse"), + "first_name" => p($userfirstname), + "last_name" => p($userlastname), + "email" => p($USER->email), + ]; + + ?>
diff --git a/transaction.php b/initialize.php similarity index 60% rename from transaction.php rename to initialize.php index f2e3391..6c92273 100644 --- a/transaction.php +++ b/initialize.php @@ -11,14 +11,26 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . /** - * Listens for Instant Payment Webhook Notification from Paystack - * - * This script waits for Payment notification from Paystack, - * then double checks that data by sending it back to Paystack. - * If Paystack verifies this then it sets up the enrolment for that - * user. + * Intialize Payment Transaction on Paystack * * @package enrol_paystack * @copyright 2019 Paystack * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + +require("../../config.php"); +require_once("$CFG->dirroot/enrol/paystack/lib.php"); + +$plugin = enrol_get_plugin('paystack'); +$paystack = new \enrol_paystack\Paystack('moodle-enrol', $plugin->get_publickey(), $plugin->secretkey()); + +$data = [ + 'amount' => $_POST['amount'], + 'email' => $_POST['email'], + 'reference' => $plugin->getHashedToken(), + 'callback_url' => $_POST['callback'], + +]; +$res = $paystack->initialize_transaction($data); + +redirect($res['data']['authorization_url']); \ No newline at end of file diff --git a/callback.php b/verify.php similarity index 64% rename from callback.php rename to verify.php index 0fc6896..d316c16 100644 --- a/callback.php +++ b/verify.php @@ -11,30 +11,23 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . /** - * Listens for Instant Payment Notification from Paystack - * - * This script waits for Payment notification from Paystack, - * then double checks that data by sending it back to Paystack. - * If Paystack verifies this then it sets up the enrolment for that - * user. + * Verify Payment Callback from Paystack * * @package enrol_paystack * @copyright 2019 Paystack * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -// Disable moodle specific debug messages and any errors in output, -// comment out when debugging or better look into error log! - require("../../config.php"); require_once("$CFG->dirroot/enrol/paystack/lib.php"); $id = required_param('id', PARAM_INT); -if (!$course = $DB->get_record("course", array("id"=>$id))) { +if (!$course = $DB->get_record("course", array("id" => $id))) { redirect($CFG->wwwroot); } $context = context_course::instance($course->id, MUST_EXIST); + $PAGE->set_context($context); require_login(); @@ -46,12 +39,30 @@ $destination = "$CFG->wwwroot/course/view.php?id=$course->id"; } +if (empty(required_param('paystack-trxref', PARAM_RAW))) { + notice(get_string('paystack_sorry', 'enrol_paystack'), $destination); +} + +$ref = required_param('paystack-trxref', PARAM_RAW); + $fullname = format_string($course->fullname, true, array('context' => $context)); -if (is_enrolled($context, NULL, '', true)) { // TODO: use real paypal check +if (is_enrolled($context, NULL, '', true)) { + // use real paystack check + $plugin = enrol_get_plugin('paystack'); + $paystack = new \enrol_paystack\Paystack('moodle-enrol', $plugin->get_publickey(), $plugin->secretkey()); + $data = $paystack->verify_transaction($ref); + if ($data->payment_status != "success") { + $plugin->unenrol_user($plugin_instance, $data->userid); + message_paystack_error_to_admin( + "Status not successful. User unenrolled from course", + $data + ); + redirect($CFG->wwwroot); + } redirect($destination, get_string('paymentthanks', '', $fullname)); - -} else { /// Somehow they aren't enrolled yet! :-( +} else { + // Somehow they aren't enrolled yet! :-( $PAGE->set_url($destination); echo $OUTPUT->header(); $a = new stdClass(); @@ -59,5 +70,3 @@ $a->fullname = $fullname; notice(get_string('paymentsorry', '', $a), $destination); } - - diff --git a/webhook.php b/webhook.php index c20d3bd..8e58509 100644 --- a/webhook.php +++ b/webhook.php @@ -46,13 +46,10 @@ } // Keep out casual intruders. -if (empty($_POST) or !empty($_GET)) { +if (empty($_POST)) { http_response_code(400); throw new moodle_exception('invalidrequest', 'core_error'); } -if (empty(required_param('paystack-trxref', PARAM_RAW))) { - print_error(get_string('paystack_sorry', 'enrol_paystack')); -} $data = new stdClass(); @@ -97,129 +94,106 @@ // Set Course and Paystack Url $courseUrl = "$CFG->wwwroot/course/view.php?id=$course->id"; -$res = $paystack->verify_transaction($data->reference); - -if (!$res['status']) { - notice($res['message'], $courseUrl); -} +$res = $paystack->verify_transaction($data->reference, $data); -// Send the file, this line will be reached if no error was thrown above. -$data->tax = $res['data']['amount'] / 100; -$data->memo = $res['data']['gateway_response']; -$data->payment_status = $res['data']['status']; -$data->reason_code = $code; +if ($res['status']) { + // Send the file, this line will be reached if no error was thrown above. + $data->tax = $res['data']['amount'] / 100; + $data->memo = $res['data']['gateway_response']; + $data->payment_status = $res['data']['status']; + $data->reason_code = $code; -// If currency is incorrectly set then someone maybe trying to cheat the system -if ($data->currency_code != $plugin_instance->currency) { - $message = "Currency does not match course settings, received: " . $data->currency_code; - message_paystack_error_to_admin( - $message, - $data - ); - notice($message, $courseUrl); -} + // If currency is incorrectly set then someone maybe trying to cheat the system + if ($data->currency_code != $plugin_instance->currency) { + message_paystack_error_to_admin( + "Currency does not match course settings, received: " . $data->currency_code, + $data + ); + die; + } -// Check that amount paid is the correct amount -if ((float) $plugin_instance->cost <= 0) { - $cost = (float) $plugin->get_config('cost'); -} else { - $cost = (float) $plugin_instance->cost; -} + // Check that amount paid is the correct amount + if ((float) $plugin_instance->cost <= 0) { + $cost = (float) $plugin->get_config('cost'); + } else { + $cost = (float) $plugin_instance->cost; + } -// Use the same rounding of floats as on the enrol form. -$cost = format_float($cost, 2, false); + // Use the same rounding of floats as on the enrol form. + $cost = format_float($cost, 2, false); -// If cost is greater than payment_gross, then someone maybe trying to cheat the system -if ($data->payment_gross < $cost) { - $message = "Amount paid is not enough ($data->payment_gross < $cost))"; - message_paystack_error_to_admin( - $message, - $data - ); - notice($message, $courseUrl); -} + // If cost is greater than payment_gross, then someone maybe trying to cheat the system + if ($data->payment_gross < $cost) { + message_paystack_error_to_admin( + "Amount paid is not enough ($data->payment_gross < $cost))", + $data + ); + die; + } -if ($data->payment_status == 'success') { - // ALL CLEAR ! - $paystack->log_transaction_success($data->reference); + if ($data->payment_status == 'success') { + // ALL CLEAR ! + $paystack->log_transaction_success($data->reference); - $DB->insert_record("enrol_paystack", $data); + $DB->insert_record("enrol_paystack", $data); - if ($plugin_instance->enrolperiod) { - $timestart = time(); - $timeend = $timestart + $plugin_instance->enrolperiod; - } else { - $timestart = 0; - $timeend = 0; - } - // Enrol user. - $plugin->enrol_user($plugin_instance, $user->id, $plugin_instance->roleid, $timestart, $timeend); - // Pass $view=true to filter hidden caps if the user cannot see them. - if ($users = get_users_by_capability( - $context, - 'moodle/course:update', - 'u.*', - 'u.id ASC', - '', - '', - '', - '', - false, - true - )) { - $users = sort_by_roleassignment_authority($users, $context); - $teacher = array_shift($users); - } else { - $teacher = false; - } - $mailstudents = $plugin->get_config('mailstudents'); - $mailteachers = $plugin->get_config('mailteachers'); - $mailadmins = $plugin->get_config('mailadmins'); - $shortname = format_string($course->shortname, true, array('context' => $context)); - if (!empty($mailstudents)) { - $a = new stdClass(); - $a->coursename = format_string($course->fullname, true, array('context' => $coursecontext)); - $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id"; - $eventdata = new \core\message\message(); - $eventdata->modulename = 'moodle'; - $eventdata->component = 'enrol_paystack'; - $eventdata->name = 'paystack_enrolment'; - $eventdata->userfrom = empty($teacher) ? core_user::get_support_user() : $teacher; - $eventdata->userto = $user; - $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); - $eventdata->fullmessage = get_string('welcometocoursetext', '', $a); - $eventdata->fullmessageformat = FORMAT_PLAIN; - $eventdata->fullmessagehtml = ''; - $eventdata->smallmessage = ''; - message_send($eventdata); - } - if (!empty($mailteachers) && !empty($teacher)) { - $a->course = format_string($course->fullname, true, array('context' => $coursecontext)); - $a->user = fullname($user); - $eventdata = new \core\message\message(); - $eventdata->modulename = 'moodle'; - $eventdata->component = 'enrol_paystack'; - $eventdata->name = 'paystack_enrolment'; - $eventdata->userfrom = $user; - $eventdata->userto = $teacher; - $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); - $eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a); - $eventdata->fullmessageformat = FORMAT_PLAIN; - $eventdata->fullmessagehtml = ''; - $eventdata->smallmessage = ''; - message_send($eventdata); - } - if (!empty($mailadmins)) { - $a->course = format_string($course->fullname, true, array('context' => $coursecontext)); - $a->user = fullname($user); - $admins = get_admins(); - foreach ($admins as $admin) { + if ($plugin_instance->enrolperiod) { + $timestart = time(); + $timeend = $timestart + $plugin_instance->enrolperiod; + } else { + $timestart = 0; + $timeend = 0; + } + // Enrol user. + $plugin->enrol_user($plugin_instance, $user->id, $plugin_instance->roleid, $timestart, $timeend); + // Pass $view=true to filter hidden caps if the user cannot see them. + if ($users = get_users_by_capability( + $context, + 'moodle/course:update', + 'u.*', + 'u.id ASC', + '', + '', + '', + '', + false, + true + )) { + $users = sort_by_roleassignment_authority($users, $context); + $teacher = array_shift($users); + } else { + $teacher = false; + } + $mailstudents = $plugin->get_config('mailstudents'); + $mailteachers = $plugin->get_config('mailteachers'); + $mailadmins = $plugin->get_config('mailadmins'); + $shortname = format_string($course->shortname, true, array('context' => $context)); + if (!empty($mailstudents)) { + $a = new stdClass(); + $a->coursename = format_string($course->fullname, true, array('context' => $coursecontext)); + $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id"; + $eventdata = new \core\message\message(); + $eventdata->modulename = 'moodle'; + $eventdata->component = 'enrol_paystack'; + $eventdata->name = 'paystack_enrolment'; + $eventdata->userfrom = empty($teacher) ? core_user::get_support_user() : $teacher; + $eventdata->userto = $user; + $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); + $eventdata->fullmessage = get_string('welcometocoursetext', '', $a); + $eventdata->fullmessageformat = FORMAT_PLAIN; + $eventdata->fullmessagehtml = ''; + $eventdata->smallmessage = ''; + message_send($eventdata); + } + if (!empty($mailteachers) && !empty($teacher)) { + $a->course = format_string($course->fullname, true, array('context' => $coursecontext)); + $a->user = fullname($user); $eventdata = new \core\message\message(); $eventdata->modulename = 'moodle'; $eventdata->component = 'enrol_paystack'; $eventdata->name = 'paystack_enrolment'; $eventdata->userfrom = $user; - $eventdata->userto = $admin; + $eventdata->userto = $teacher; $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); $eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a); $eventdata->fullmessageformat = FORMAT_PLAIN; @@ -227,27 +201,32 @@ $eventdata->smallmessage = ''; message_send($eventdata); } + if (!empty($mailadmins)) { + $a->course = format_string($course->fullname, true, array('context' => $coursecontext)); + $a->user = fullname($user); + $admins = get_admins(); + foreach ($admins as $admin) { + $eventdata = new \core\message\message(); + $eventdata->modulename = 'moodle'; + $eventdata->component = 'enrol_paystack'; + $eventdata->name = 'paystack_enrolment'; + $eventdata->userfrom = $user; + $eventdata->userto = $admin; + $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); + $eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a); + $eventdata->fullmessageformat = FORMAT_PLAIN; + $eventdata->fullmessagehtml = ''; + $eventdata->smallmessage = ''; + message_send($eventdata); + } + } + } else { + message_paystack_error_to_admin( + "Payment status not successful" . $data->memo, + $data + ); + die; } -} else { - $message = "Payment status not successful" . $data->memo; - message_paystack_error_to_admin( - $message, - $data - ); - notice($message, $courseUrl); -} - -$fullname = format_string($course->fullname, true, array('context' => $context)); - -if (is_enrolled($context, null, '', true)) { // TODO: use real paystack check. - redirect($courseUrl, get_string('paymentthanks', '', $fullname)); -} else { // Somehow they aren't enrolled yet! - $PAGE->set_url($courseUrl); - echo $OUTPUT->header(); - $a = new stdClass(); - $a->teacher = get_string('defaultcourseteacher'); - $a->fullname = $fullname; - notice(get_string('paymentsorry', '', $a), $courseUrl); } // --- HELPER FUNCTIONS --------------------------------------------------------------------------------------! From e1cf83e1c09e229aba7c21fe8e41e3ad02198b50 Mon Sep 17 00:00:00 2001 From: wisdomanthoni Date: Wed, 28 Aug 2019 13:40:36 +0100 Subject: [PATCH 03/15] fix enrol.html --- enrol.html | 67 ++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/enrol.html b/enrol.html index f88a750..25cf3e5 100644 --- a/enrol.html +++ b/enrol.html @@ -3,43 +3,36 @@

currency} {$localisedcost}"; ?>

- -
wwwroot/enrol/paystack/verify.php"?>"> - "_xclick", - "charset" => "utf-8", - "item_name" => p($coursefullname), - "item_name" => p($coursefullname), - "item_number" => p($courseshortname), - "quantity" => "1", - "on0" => print_string("user"), - "os0" => p($userfullname), - "custom" => echo "{$USER->id}-{$course->id}-{$instance->id}", - "currency_code" => p($instance->currency), - "amount" => p($cost), - "for_auction" => "false", - "no_note" => "1", - "no_shipping" => "1" , - "rm" => "2", - "cbt" => print_string("continuetocourse"), - "first_name" => p($userfirstname), - "last_name" => p($userlastname), - "email" => p($USER->email), - ]; - - ?> -
From d99330419a1b9a2f1b71c79a58589a1f770f1397 Mon Sep 17 00:00:00 2001 From: wisdomanthoni Date: Wed, 28 Aug 2019 14:04:17 +0100 Subject: [PATCH 04/15] fix enrol.html --- enrol.html | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/enrol.html b/enrol.html index 25cf3e5..0029412 100644 --- a/enrol.html +++ b/enrol.html @@ -7,12 +7,12 @@

$data = [ "cmd" => "_xclick", "charset" => "utf-8", - "item_name" => $coursefullname, - "item_name" => $coursefullname, - "item_number" => $courseshortname, + "item_name" => s($coursefullname), + "item_name" => s($coursefullname), + "item_number" => s($courseshortname), "quantity" => "1", - "on0" => print_string("user"), - "os0" => $userfullname, + "on0" => get_string("user"), + "os0" => s($userfullname), "custom" => "{$USER->id}-{$course->id}-{$instance->id}", "currency_code" => $instance->currency, "amount" => $cost, @@ -20,17 +20,14 @@

"no_note" => "1", "no_shipping" => "1" , "rm" => "2", - "cbt" => print_string("continuetocourse"), - "first_name" => $userfirstname, - "last_name" => $userlastname, - "email" => $USER->email, + "first_name" => s($userfirstname), + "last_name" => s($userlastname), + "email" => s($USER->email), ]; ?>
wwwroot/enrol/paystack/verify.php?id=$course->id"?>"> - From 42c82775b2f55aef2d45b7117c0dd0a10a79ab17 Mon Sep 17 00:00:00 2001 From: wisdomanthoni Date: Wed, 28 Aug 2019 14:32:10 +0100 Subject: [PATCH 05/15] add variable to lib.php --- enrol.html | 4 ++-- initialize.php | 36 ------------------------------------ lib.php | 2 ++ 3 files changed, 4 insertions(+), 38 deletions(-) delete mode 100644 initialize.php diff --git a/enrol.html b/enrol.html index 0029412..f48442a 100644 --- a/enrol.html +++ b/enrol.html @@ -22,12 +22,12 @@

"rm" => "2", "first_name" => s($userfirstname), "last_name" => s($userlastname), - "email" => s($USER->email), + "email" => s($useremail), ]; ?> wwwroot/enrol/paystack/verify.php?id=$course->id"?>"> diff --git a/initialize.php b/initialize.php deleted file mode 100644 index 6c92273..0000000 --- a/initialize.php +++ /dev/null @@ -1,36 +0,0 @@ -. -/** - * Intialize Payment Transaction on Paystack - * - * @package enrol_paystack - * @copyright 2019 Paystack - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -require("../../config.php"); -require_once("$CFG->dirroot/enrol/paystack/lib.php"); - -$plugin = enrol_get_plugin('paystack'); -$paystack = new \enrol_paystack\Paystack('moodle-enrol', $plugin->get_publickey(), $plugin->secretkey()); - -$data = [ - 'amount' => $_POST['amount'], - 'email' => $_POST['email'], - 'reference' => $plugin->getHashedToken(), - 'callback_url' => $_POST['callback'], - -]; -$res = $paystack->initialize_transaction($data); - -redirect($res['data']['authorization_url']); \ No newline at end of file diff --git a/lib.php b/lib.php index 45c204b..3b6acac 100644 --- a/lib.php +++ b/lib.php @@ -397,10 +397,12 @@ public function enrol_page_hook(stdClass $instance) $userfullname = fullname($USER); $userfirstname = $USER->firstname; $userlastname = $USER->lastname; + $useremail = $USER->email; $instancename = $this->get_instance_name($instance); $publickey = $this->get_publickey(); $reference = $this->getHashedToken(); + include($CFG->dirroot.'/enrol/paystack/enrol.html'); } } From b82cf7cfca5284a44c951e248282e2ad3f971019 Mon Sep 17 00:00:00 2001 From: wisdomanthoni Date: Wed, 28 Aug 2019 15:42:44 +0100 Subject: [PATCH 06/15] modify verify.php script --- verify.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/verify.php b/verify.php index d316c16..ed96989 100644 --- a/verify.php +++ b/verify.php @@ -44,7 +44,6 @@ } $ref = required_param('paystack-trxref', PARAM_RAW); - $fullname = format_string($course->fullname, true, array('context' => $context)); if (is_enrolled($context, NULL, '', true)) { @@ -68,5 +67,5 @@ $a = new stdClass(); $a->teacher = get_string('defaultcourseteacher'); $a->fullname = $fullname; - notice(get_string('paymentsorry', '', $a), $destination); + redirect($destination, get_string('paymentsorry', '', $a), 5); } From bdb285e7ea094edb6f9b30f4b6bec88662bf1f55 Mon Sep 17 00:00:00 2001 From: wisdomanthoni Date: Wed, 28 Aug 2019 16:38:24 +0100 Subject: [PATCH 07/15] wip: webhook response script --- classes/Paystack.php | 19 ++++++++++++++----- enrol.html | 7 ++++++- verify.php | 14 +++++++++----- webhook.php | 17 ++++++++++++----- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/classes/Paystack.php b/classes/Paystack.php index 4ad925b..89343c4 100644 --- a/classes/Paystack.php +++ b/classes/Paystack.php @@ -82,10 +82,9 @@ public function initialize_transaction($data) * Verify Payment Transaction * * @param string $reference - * @param array $data * @return void */ - public function verify_transaction($reference, $data = []) + public function verify_transaction($reference) { $paystackUrl = $this->base_url . "transaction/verify/" . $reference; @@ -111,7 +110,7 @@ public function verify_transaction($reference, $data = []) 'enrol_paystack', '', array('url' => $paystackUrl, 'response' => $res), - json_encode($data) + '' ); } @@ -142,7 +141,17 @@ public function log_transaction_success($reference) curl_setopt($ch,CURLOPT_POSTFIELDS, $params_string); curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); //execute post - $result = curl_exec($ch); - // echo $result; + curl_exec($ch); + } + + /** + * Validate Webhook Signature + * + * @param $input + * @return boolean + */ + public function validate_webhook($input) + { + return $_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] !== hash_hmac('sha512', $input, $this->secret_key); } } diff --git a/enrol.html b/enrol.html index f48442a..31ee7e2 100644 --- a/enrol.html +++ b/enrol.html @@ -23,9 +23,14 @@

"first_name" => s($userfirstname), "last_name" => s($userlastname), "email" => s($useremail), + "reference" => $reference, ]; ?> - wwwroot/enrol/paystack/verify.php?id=$course->id"?>"> + wwwroot/enrol/paystack/verify.php"?>"> + + + id}-{$course->id}-{$instance->id}" ?>" /> +