Skip to content
This repository has been archived by the owner on May 29, 2023. It is now read-only.

Unable to enroll users after successful payments #7

Open
wants to merge 42 commits into
base: webhook
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
990b4f1
Merge pull request #2 from webong/webhook
webong Aug 28, 2019
0309850
Add files via upload
webong Aug 29, 2019
bf66387
Delete Group.png
webong Aug 29, 2019
ad86a40
Add files via upload
webong Aug 29, 2019
3e51425
Update README.md
webong Aug 29, 2019
2d4a0d3
Update README.md
webong Aug 29, 2019
abb424d
set verify to handle course enrolment too as well as webhook
webong Sep 1, 2019
93bb7e2
update plugin version
webong Sep 1, 2019
dccc4b1
update verify script
webong Sep 1, 2019
5b3a25f
Merge pull request #3 from webong/verify
webong Sep 1, 2019
3f7009d
Merge pull request #1 from webong/master
lukman008 Sep 1, 2019
e92392d
a
webong Sep 1, 2019
6534d66
update version
webong Sep 1, 2019
8a4573c
update version
webong Sep 1, 2019
853f6d6
r
webong Sep 1, 2019
c12041e
paystack.php
webong Sep 1, 2019
a99ec51
Merge pull request #2 from webong/master
lukman008 Sep 2, 2019
b2f3ef4
minor fix
lukman008 Sep 2, 2019
f4764e3
Update paystack.php
lukman008 Sep 2, 2019
933c3ed
update plugin settings to add profile fields to be used as custom fie…
webong May 11, 2020
0fe24f8
update plugin lang
webong May 11, 2020
42f58a2
update lib.php with getting activated custom fields
webong May 11, 2020
107aa12
update enrol.html view
webong May 11, 2020
fc04150
update edit.php
webong May 11, 2020
fde1569
update plugin version
webong May 11, 2020
635786f
Update paystack.php
webong Oct 19, 2020
19f35b9
Merge pull request #3 from webong/patch-1
whales-paystack Oct 19, 2020
fbf1d69
hotfix
webong Jan 14, 2021
1579f15
Fix bugs
whales-paystack Jan 18, 2021
b74eb79
Add South African Rand currency code (ZAR) to lib
Vladdermouse May 10, 2021
db903d4
Merge pull request #4 from Vladdermouse/master
lukman-paystack Jan 5, 2023
20be0c2
Added more currencies
Segtel1 Jan 5, 2023
cff2281
Merge pull request #6 from Segtel1/master
lukman-paystack Jan 5, 2023
5d2ef26
enrol_paystack_charge_exception_handler defined
OgheneTega Jun 3, 2023
0a4e297
get_exception_handler called in verify.php
OgheneTega Jun 5, 2023
2a88bc8
Merge pull request #7 from OgheneTega/set_exception_handler
lukman-paystack Jun 7, 2023
3d325b9
add support for EGP, KES, and XOF
lukman-paystack Jun 8, 2023
f620ac0
add support for EGP, KES, and XOF
lukman-paystack Jun 8, 2023
b1acd85
Merge branch 'master' into patch/currency-support
lukman-paystack Jun 8, 2023
48fb370
Merge pull request #8 from PaystackHQ/patch/currency-support
lukman-paystack Jun 8, 2023
b5ffc2e
added the $a variable where missing
OgheneTega Oct 27, 2023
fe30fc1
Merge pull request #9 from OgheneTega/fix-windows-redirect
lukman-paystack Oct 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
# Paystack Enrolment Plugin #
<p align="center"><a href="https://paystack.com/"><img src="./pix/banner.png?raw=true" alt="Payment Forms for Paystack"></a></p>


# Paystack Enrolment Plugin

Enrolment in Moodle using the Paystack gateway for paid courses

This plugin helps admins and webmasters use Paystack as the payment gateway. This plugin has all the settings for development as well as for production usage. Its easy to install, set up and effective.
This plugin helps admins and webmasters use Paystack as the payment gateway. This plugin has all the settings for development as well as for production usage. Its easy to install, set up and effective.

## Installation

Login to your moodle site as an “admin user” and follow the steps.

1) Upload the zip package from Site administration > Plugins > Install plugins. Choose Plugin type 'Enrolment method (enrol)'. Upload the ZIP package, check the acknowledgement and install.

2) Go to Enrolments > Manage enrol plugins > Enable 'Paystack' from list

3) Click 'Settings' which will lead to the settings page of the plugin

4) Provide merchant credentials for Paystack. Note that, you will get all the details from your merchant account. Now select the checkbox as per requirement.
Choose the paystack connection mode, for test mode it uses the test api keys and for live mode uses the live api keys. Save the settings.

5) Select any course from course listing page.

6) Go to Course administration > Users > Enrolment methods > Add method 'Paystack' from the dropdown. Set 'Custom instance name', 'Enrol cost' etc and add the method.

This completes all the steps from the administrator end. Now registered users can login to the Moodle site and view the course after a successful payment.



## Contribution

TODO Provide more detailed description here.
Here you can browse the source, look at open issues and keep track of development.

## License ##

Expand Down
62 changes: 38 additions & 24 deletions classes/Paystack.php → classes/paystack.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@

defined('MOODLE_INTERNAL') || die();

class paystack {
class paystack
{
public $plugin_name;
public $public_key;
public $secret_key;

public function __construct($plugin, $pk, $sk){
//configure plugin name
//configure public key
public function __construct($plugin, $pk, $sk)
{
$this->base_url = "https://api.paystack.co/";
$this->plugin_name = $plugin;
$this->public_key = $pk;
$this->secret_key = $sk;
}

/**
/**
* Verify Payment Transaction
*
* @param string $reference
Expand All @@ -61,10 +61,13 @@ public function initialize_transaction($data)
]);

$request = curl_exec($curl);

$res = json_decode($request, true);

curl_close($curl);

if (curl_errno($curl)) {
throw new moodle_exception(
throw new \moodle_exception(
'errpaystackconnect',
'enrol_paystack',
'',
Expand All @@ -73,12 +76,10 @@ public function initialize_transaction($data)
);
}

curl_close($curl);

return $res;
}
/**

/**
* Verify Payment Transaction
*
* @param string $reference
Expand All @@ -89,6 +90,7 @@ 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,
Expand All @@ -101,11 +103,13 @@ public function verify_transaction($reference)
]);

$request = curl_exec($curl);
$res = json_decode($request, true);
// $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$res = json_decode($request, true);

curl_close($curl);

if (curl_errno($curl)) {
throw new moodle_exception(
throw new \moodle_exception(
'errpaystackconnect',
'enrol_paystack',
'',
Expand All @@ -114,8 +118,6 @@ public function verify_transaction($reference)
);
}

curl_close($curl);

return $res;
}

Expand All @@ -129,19 +131,31 @@ 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 = [
'public_key' => $this->public_key,
'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
curl_exec($ch);

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"content-type: application/json",
"cache-control: no-cache"
],
]);

// execute post
curl_exec($curl);

// close conection
curl_close($curl);
}

/**
Expand All @@ -152,6 +166,6 @@ public function log_transaction_success($reference)
*/
public function validate_webhook($input)
{
return $_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] !== hash_hmac('sha512', $input, $this->secret_key);
return $_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] !== hash_hmac('sha512', $input, $this->secret_key);
}
}
89 changes: 89 additions & 0 deletions classes/util.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* PayPal enrolment plugin utility class.
*
* @package enrol_paystack
* @copyright 2019 Paystack
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace enrol_paystack;

defined('MOODLE_INTERNAL') || die();

/**
* Paystack enrolment plugin utility class.
*
* @package enrol_paystack
* @copyright 2019 Paystack
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class util {

/**
* Send payment error message to the admin.
*
* @param string $subject
* @param stdClass $data
*/
public static function message_paystack_error_to_admin($subject, $data)
{
$admin = get_admin();
$site = get_site();
$message = "$site->fullname: Transaction failed.\n\n$subject\n\n";
foreach ($data as $key => $value) {
$message .= s($key) . " => " . s($value) . "\n";
}
$eventdata = new \core\message\message();
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_paystack';
$eventdata->name = 'paystack_enrolment';
$eventdata->userfrom = $admin;
$eventdata->userto = $admin;
$eventdata->subject = "PAYSTACK PAYMENT ERROR: " . $subject;
$eventdata->fullmessage = $message;
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
message_send($eventdata);
}

/**
* Silent exception handler.
*
* @return callable exception handler
*/
public static function get_exception_handler() {
return function($ex) {
$info = get_exception_info($ex);

$logerrmsg = "enrol_paystack exception handler: ".$info->message;
if (debugging('', DEBUG_NORMAL)) {
$logerrmsg .= ' Debug: '.$info->debuginfo."\n".format_backtrace($info->backtrace, true);
}
error_log($logerrmsg);

if (http_response_code() == 200) {
http_response_code(500);
}

exit(0);
};
}

}
12 changes: 10 additions & 2 deletions edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,16 @@
}

} else {
$fields = array('status' => $data->status, 'name' => $data->name, 'cost' => unformat_float($data->cost),
'currency' => $data->currency, 'roleid' => $data->roleid, 'enrolperiod' => $data->enrolperiod, 'customint3' => $data->customint3, 'enrolstartdate' => $data->enrolstartdate, 'enrolenddate' => $data->enrolenddate);
$fields = array('status' => $data->status,
'name' => $data->name,
'cost' => unformat_float($data->cost),
'currency' => $data->currency,
'roleid' => $data->roleid,
'enrolperiod' => $data->enrolperiod,
'customint3' => $data->customint3,
'enrolstartdate' => $data->enrolstartdate,
'enrolenddate' => $data->enrolenddate
);
$plugin->add_instance($course, $fields);
}

Expand Down
21 changes: 16 additions & 5 deletions enrol.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,28 @@ <h3><?php echo $instancename; ?></h3>
"last_name" => s($userlastname),
"email" => s($useremail),
"reference" => $reference,
"custom_fields" => $customfields
];
?>
<form method="post" action="<?php echo "$CFG->wwwroot/enrol/paystack/verify.php"?>">
<input type="hidden" name="cmd" value="_xclick" />
<?php
foreach ($data as $key => $value) {
echo '<input type="hidden" name="' . $key . '" value="' . $value . '" />';
}
?>
<input type="hidden" name="charset" value="utf-8" />
<input type="hidden" name="custom" value="<?php echo "{$USER->id}-{$course->id}-{$instance->id}" ?>" />

<script src="https://js.paystack.co/v1/inline.js" data-key="<?php echo $publickey; ?>"
data-ref="<?php echo $reference; ?>" data-email="<?php p($useremail) ?>"
data-currency="<?php p($instance->currency) ?>" data-amount="<?php p($cost * 100) ?>"
data-metadata='<?php echo json_encode($data) ?>' data-locale="<?php echo current_language(); ?>">
<script src="https://js.paystack.co/v1/inline.js"
data-key="<?php echo $publickey; ?>"
data-ref="<?php echo $reference; ?>"
data-firstname="<?php echo s($userfirstname) ?>"
data-lastname="<?php echo s($userlastname) ?>"
data-email="<?php p($useremail) ?>"
data-currency="<?php p($instance->currency) ?>"
data-amount="<?php p($cost * 100) ?>"
data-metadata='<?php echo json_encode($data) ?>'
data-locale="<?php echo current_language(); ?>">
</script>
</form>

Expand Down
2 changes: 2 additions & 0 deletions lang/en/enrol_paystack.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
$string['costerror'] = 'The enrolment cost is not numeric';
$string['costorkey'] = 'Please choose one of the following methods of enrolment.';
$string['currency'] = 'Currency';
$string['customfields'] = 'Profile fields to be used as custom fields';
$string['customfields_desc'] = 'Which user profile fields can be used during enrolment';
$string['customwelcomemessage'] = 'Custom welcome message';
$string['customwelcomemessage_help'] = 'If you enter some text here, it will be shown instead of the standard text "This course requires a payment for entry." on the Enrolment options page that students see when they attempt to access a course they are not enrolled in. If you leave this blank, the standard text will be used.';
$string['defaultrole'] = 'Default role assignment';
Expand Down
33 changes: 32 additions & 1 deletion lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ public function enrol_page_hook(stdClass $instance)
$userlastname = $USER->lastname;
$useremail = $USER->email;
$instancename = $this->get_instance_name($instance);
$customfields = $this->get_custom_fields();

$publickey = $this->get_publickey();
$reference = $this->getHashedToken();
Expand All @@ -409,14 +410,44 @@ public function enrol_page_hook(stdClass $instance)
return $OUTPUT->box(ob_get_clean());
}

/**
* Get all custom fields available for plugin.
*
* @return $customfields.
*/
public function get_custom_fields()
{
global $USER, $DB;

$customfieldrecords = $DB->get_records('user_info_field');
$configured_customfields = explode(',', get_config('enrol_paystack', 'customfields'));

$customfields = [];

foreach ($customfieldrecords as $cus) {
foreach($configured_customfields as $con) {
if($con == $cus->shortname){
$customfields[] = [
'display_name' => $cus->name ,
'variable_name' => $cus->shortname,
'value' => $USER->profile[$con]
];
}
}
}

return $customfields;
}

/**
* Lists all currencies available for plugin.
*
* @return $currencies.
*/
public function get_currencies()
{
$codes = array('NGN', 'USD', 'GHS');
$codes = array('NGN', 'USD', 'GHS', 'KES', 'XOF', 'ZAR','EGP');

$currencies = array();
foreach ($codes as $c) {
$currencies[$c] = new lang_string($c, 'core_currencies');
Expand Down
Binary file added pix/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading