Date: @date
Payment method: @method
Amount: @amount
Name: @name
Email: @mail
');
define('SIGNUP_PAY_PAGER', 25);
define('SIGNUP_PAY_DEFAULT_PAID_STATUS_CODE', 0);
define('SIGNUP_PAY_DEFAULT_DENY_ANON', TRUE);
// Payment methods
define('SIGNUP_PAY_METHOD_PAYPAL', 1);
define('SIGNUP_PAY_METHOD_CHEQUE', 2);
define('SIGNUP_PAY_METHOD_CASH', 3);
define('SIGNUP_PAY_METHOD_BANK_TRANSFER', 4);
define('SIGNUP_PAY_METHOD_FREE', 5);
function signup_pay_get_methods($include_disabled = FALSE) {
$methods = array(
SIGNUP_PAY_METHOD_PAYPAL => t('Paypal'),
SIGNUP_PAY_METHOD_CHEQUE => t('Cheque'),
SIGNUP_PAY_METHOD_CASH => t('Cash'),
SIGNUP_PAY_METHOD_BANK_TRANSFER => t('Bank transfer'),
);
if ($include_disabled) {
return $methods;
}
else {
$enabled_methods = variable_get(SIGNUP_PAY_ENABLED_METHODS, array(SIGNUP_PAY_METHOD_PAYPAL => 1));
foreach($methods as $key => $value) {
if (!$enabled_methods[$key]) {
unset($methods[$key]);
}
}
return $methods;
}
}
function signup_pay_get_currency() {
return array(
'GBP' => t('UK Pounds'),
'EUR' => t('Euro'),
'USD' => t('US Dollar'),
'CAD' => t('Canadian Dollar'),
);
}
function signup_pay_settings() {
$form['signup_pay_general'] = array(
'#type' => 'fieldset',
'#title' => t('General Configuration'),
);
$form['signup_pay_general'][SIGNUP_PAY_ENABLED] = array(
'#type' => 'checkbox',
'#title' => t('Enable payment on signup for all new signup enabled nodes by default'),
'#default_value' => variable_get(SIGNUP_PAY_ENABLED, SIGNUP_PAY_DEFAULT_ENABLED),
);
$form['signup_pay_general'][SIGNUP_PAY_ENABLED_METHODS] = array(
'#type' => 'checkboxes',
'#title' => t('Accept payment using the following methods'),
'#options' => signup_pay_get_methods(TRUE),
'#default_value' => variable_get(SIGNUP_PAY_ENABLED_METHODS, array(SIGNUP_PAY_METHOD_PAYPAL => 1)),
);
$form['signup_pay_general'][SIGNUP_PAY_EMAIL] = array(
'#type' => 'textfield',
'#title' => t('Paypal email address'),
'#default_value' => variable_get(SIGNUP_PAY_EMAIL, SIGNUP_PAY_DEFAULT_EMAIL),
'#description' => t('If using PayPal to collect payments please specify your PayPal e-mail address.'),
);
$form['signup_pay_general'][SIGNUP_PAY_AMOUNT] = array(
'#type' => 'textfield',
'#title' => t('Default amount to charge, per node'),
'#default_value' => variable_get(SIGNUP_PAY_AMOUNT, SIGNUP_PAY_DEFAULT_AMOUNT),
'#description' => t('Default amount to charge each user. This can be changed on individual nodes. Do not change this after the first person pays.'),
);
$form['signup_pay_general'][SIGNUP_PAY_CURRENCY] = array(
'#type' => 'select',
'#title' => t('Default Currency'),
'#default_value' => variable_get(SIGNUP_PAY_CURRENCY, SIGNUP_PAY_DEFAULT_CURRENCY),
'#options' => signup_pay_get_currency(),
);
$form['signup_pay_general'][SIGNUP_PAY_DENY_ANON] = array(
'#type' => 'checkbox',
'#title' => t('Deny Anonymous access to Paying for an event.'),
'#default_value' => variable_get(SIGNUP_PAY_DENY_ANON,SIGNUP_PAY_DEFAULT_DENY_ANON),
);
//TODO stronger admin features per role for default price and weighting for selecting correct amount
$roles = user_roles(variable_get(SIGNUP_PAY_DENY_ANON,SIGNUP_PAY_DEFAULT_DENY_ANON), 'sign up for content');
$role_description = array();
$default_role_description = array();
foreach ($roles as $key => $value) {
$role_description[] = $key." = ".$value;
$default_role_description[] = $key;
}
$form['signup_pay_general'][SIGNUP_PAY_ROLE_WEIGHT] = array(
'#type' => 'textfield',
'#title' => t('Role Weight'),
'#default_value' => variable_get(SIGNUP_PAY_ROLE_WEIGHT, implode(", ", $default_role_description)),
'#description' => t('KEY [@legend]
Order the roles to prioritize thier use when determining the price to pay for signups. For now, enter the ID of the role in the order you would like them used.', array('@legend' => implode(", ", $role_description))),
);
$form['signup_pay_reciept_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Template for receipt page'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#description' => t('Template for receipt when displayed on the web site as a page. You can use any HTML, including the following tokens Date: @date, Payment method: @method, Amount: @amount, Name: @name, Email: @mail'),
);
$form['signup_pay_reciept_fieldset'][SIGNUP_PAY_RECEIPT_PAGE] = array(
'#type' => 'textarea',
'#title' => t('Template for receipt page'),
'#default_value' => variable_get(SIGNUP_PAY_RECEIPT_PAGE, SIGNUP_PAY_DEFAULT_RECEIPT),
);
$form['signup_pay_reciept_email_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Template for receipt email'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#description' => t('Template for receipt when emailed to the user. You can use any HTML, including the following tokens Date: @date, Payment method: @method, Amount: @amount, Name: @name, Email: @mail'),
);
$form['signup_pay_reciept_email_fieldset'][SIGNUP_PAY_RECEIPT_EMAIL] = array(
'#type' => 'textarea',
'#default_value' => variable_get(SIGNUP_PAY_RECEIPT_EMAIL, SIGNUP_PAY_DEFAULT_RECEIPT),
);
if (module_exists('signup_status')) {
$access = user_access('administer site configuration');
if ($access) {
$create_link = l("Insert New status code", "admin/settings/signup_status/add", array(), "destination=admin/settings/signup_pay");
}
$options = array();
foreach (signup_status_codes() as $cid => $code) {
$options[$cid] = $code['name'];
}
$form['signup_pay_status_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Signup Status Configuration'),
);
$form['signup_pay_status_fieldset'][SIGNUP_PAY_PAID_STATUS_CODE] = array(
'#type' => 'select',
'#title' => t('Paid Status Code'),
'#options' => $options,
'#default_value' => variable_get(SIGNUP_PAY_PAID_STATUS_CODE, SIGNUP_PAY_DEFAULT_PAID_STATUS_CODE),
'#description' => t('Select the status code which will be used when a payment transaction is completed successfully. !link', array('!link' => $create_link)),
);
}
return system_settings_form($form);
}
function signup_pay_check_payment($nid = 0, $anon = FALSE) {
global $user;
$email = $user->mail;
if ($anon) {
$email = $anon;
}
$num_rows = db_result(db_query("SELECT COUNT(*) FROM {signup_pay} WHERE uid = %d and nid = %d AND mail = '%s'", $user->uid, $nid, $email));
if (!$num_rows) {
return FALSE;
}
return TRUE;
}
function signup_pay_menu($may_cache) {
$items = array();
if ($may_cache) {
$access = user_access('administer site configuration');
$items[] = array(
'path' => 'ipn/signup_pay',
'title' => t('IPN post'),
'callback' => 'signup_pay_paypal_ipn',
'access' => TRUE,
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/settings/signup_pay',
'title' => t('Signup pay'),
'callback' => 'drupal_get_form',
'callback arguments' => array('signup_pay_settings'),
'description' => t('Administer signup pay settings'),
'access' => $access,
);
$items[] = array(
'path' => 'admin/content/signup_pay',
'title' => t('Signup pay'),
'access' => $access,
'callback' => 'signup_pay_admin',
'description' => t('Manages signup payments to your site via Paypal'),
);
$items[] = array(
'path' => 'admin/content/signup_pay/list',
'title' => t('List'),
'access' => $access,
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/content/signup_pay/add',
'title' => t('Add payment'),
'access' => $access,
'callback' => 'drupal_get_form',
'callback arguments' => array('signup_pay_edit', 'add'),
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/content/signup_pay/edit',
'title' => t('Edit payment'),
'access' => $access,
'callback' => 'drupal_get_form',
'callback arguments' => array('signup_pay_edit', 'edit'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/content/signup_pay/delete',
'title' => t('Delete payment'),
'access' => $access,
'callback' => 'drupal_get_form',
'callback arguments' => array('signup_pay_edit', 'delete'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'signup_pay/receipt',
'title' => t('Receipt'),
'access' => user_access('view receipt'),
'callback' => 'signup_pay_view_receipt',
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'signup_pay/thanks',
'title' => t('Thanks'),
'access' => TRUE,
'callback' => 'signup_pay_thanks',
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'signup_pay_do_payment',
'title' => t('Payment'),
'access' => TRUE,
'callback' => 'drupal_get_form',
'callback arguments' => array('signup_pay_do_payment'),
'type' => MENU_CALLBACK,
);
}
return $items;
}
/**
* Format currency.
*/
function _signup_pay_format_amount($amount, $currency) {
$amount = number_format($amount, 2);
switch($currency) {
case 'GBP':
return "$amount";
case 'EUR':
return "€ $amount";
case 'USD':
return "$ $amount";
case 'CAD':
return "C$ $amount";
default:
return check_plain($currency). " $amount";
}
}
function signup_pay_edit($mode) {
$time_paid = format_date(time(), 'custom', 'Y-m-d H:i O');
$amount = variable_get(SIGNUP_PAY_AMOUNT, SIGNUP_PAY_DEFAULT_AMOUNT);
switch($mode) {
case 'edit':
case 'delete':
$id = (int)arg(4);
if ($id) {
$result = db_query('SELECT * FROM {signup_pay} WHERE id = %d', $id);
$row = db_fetch_object($result);
$time_paid = format_date($row->time_paid, 'custom', 'Y-m-d H:i O');
$amount = $row->amount;
$net_amount = $row->net_amount;
}
}
$form['id'] = array(
'#type' => 'hidden',
'#value' => $id,
);
$form['time_paid'] = array(
'#type' => 'textfield',
'#title' => t('Date'),
'#default_value' => $time_paid,
'#size' => 30,
'#maxlength' => 30,
'#description' => 'Format: Y-M-D H:M Z',
);
$form['uid'] = array(
'#type' => 'textfield',
'#title' => t('uid of payer'),
'#size' => 60,
'#maxlength' => 60,
'#default_value' => $row->uid,
'#description' => t('The user ID of the person paying.'),
);
$form['nid'] = array(
'#type' => 'textfield',
'#title' => t('nid of event'),
'#size' => 60,
'#maxlength' => 60,
'#default_value' => $row->nid,
'#description' => t('The node ID of the event to be paid.'),
);
$form['amount'] = array(
'#type' => 'textfield',
'#title' => t('Gross amount'),
'#size' => 60,
'#maxlength' => 60,
'#default_value' => $amount,
'#description' => t('Amount to be paid.'),
);
$form['net_amount'] = array(
'#type' => 'textfield',
'#title' => t('Net amount'),
'#size' => 60,
'#maxlength' => 60,
'#default_value' => $net_amount,
'#description' => t('Amount after any fees are deducted.'),
);
$methods = signup_pay_get_methods();
$methods[SIGNUP_PAY_METHOD_FREE] = t('Free attendance');
$form['method'] = array(
'#type' => 'select',
'#title' => t('Method'),
'#options' => $methods,
'#default_value' => $row->method_id,
'#description' => t('Method of payment for this transaction.'),
);
$form['currency_code'] = array(
'#type' => 'select',
'#title' => t('Currency'),
'#default_value' => $row->currency,
'#options' => signup_pay_get_currency(),
'#name' => 'currency_code',
);
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Name of payer'),
'#size' => 60,
'#maxlength' => 60,
'#default_value' => $row->name,
'#description' => t('Name of person or business paying, as it appears on the invoice.'),
);
$form['mail'] = array(
'#type' => 'textfield',
'#title' => t('Email address'),
'#size' => 60,
'#maxlength' => 60,
'#default_value' => $row->mail,
'#description' => t('Email address of person or business paying.'),
);
if ($mode == 'delete') {
$form['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
);
}
else {
$form['add'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
}
$form['mode'] = array(
'#type' => 'hidden',
'#value' => $mode,
);
return($form);
}
function signup_pay_edit_submit($form_id, $form = NULL) {
global $user;
$mode = $form['mode'];
if ($form['delete'] == t('Delete')) {
$mode = 'delete';
}
switch($mode) {
case 'add':
db_query("INSERT INTO {signup_pay} (id, uid, nid, time_paid, method_id, currency, amount, net_amount, mail, name)
VALUES (0, %d, %d, %d, %d, '%s', %f, '%s', '%s')",
$form['uid'],
$form['nid'],
strtotime($form['time_paid']),
$form['method'],
$form['currency_code'],
$form['amount'],
$form['net_amount'],
$form['mail'],
$form['name']);
drupal_set_message(t('The payment has been added.'));
watchdog('payment', t('User @user added a transaction',
array('@user' => $user->name)));
break;
case 'edit':
db_query("UPDATE {signup_pay}
SET uid = %d, nid = %d, time_paid = %d, method_id = %d, currency = '%s', amount = %f, net_amount = %f, mail = '%s', name = '%s'
WHERE id = %d",
$form['uid'],
$form['nid'],
strtotime($form['time_paid']),
$form['method'],
$form['currency_code'],
$form['amount'],
$form['net_amount'],
$form['mail'],
$form['name'],
$form['id']);
drupal_set_message(t('The payment has been updated.'));
watchdog('payment', t('User @user updated transaction @id',
array(
'@user' => $user->name,
'@id' => $form['id'],
)));
break;
case 'delete':
db_query("DELETE FROM {signup_pay} WHERE id = %d", $form['id']);
drupal_set_message(t('The payment has been deleted.'));
watchdog('payment', t('User @user deleted transaction @id',
array(
'@user' => $user->name,
'@id' => $form['id'],
)));
break;
}
drupal_goto('admin/build/signup_pay');
}
function signup_pay_admin() {
$methods = signup_pay_get_methods();
$methods[SIGNUP_PAY_METHOD_FREE] = t('Free attendance');
$rows = array();
$header = array(
array('data' => t('Date'), 'field' => 'time_paid', 'sort' => 'desc'),
array('data' => t('User'), 'field' => 'uid'),
array('data' => t('Event'), 'field' => 'nid'),
array('data' => t('Method'), 'field' => 'method_id'),
array('data' => t('Amount'), 'field' => 'amount'),
array('data' => t('Name'), 'field' => 'invoice_name'),
array('data' => t('Operations'), 'colspan' => '2'),
);
$sql = 'SELECT u.uid, u.name, p.nid, u.mail,
p.id, p.name as invoice_name, p.currency, p.amount, p.time_paid, p.method_id
FROM {users} u
INNER JOIN {signup_pay} p USING(uid)' . tablesort_sql($header);
$result = pager_query($sql, SIGNUP_PAY_PAGER, 0, NULL);
while ($row = db_fetch_object($result)) {
$node = node_load($row->nid);
$rows[] = array(
format_date($row->time_paid, 'custom', 'Y-m-d H:i'),
theme('username', $row),
$node->title,
$methods[$row->method_id],
_signup_pay_format_amount($row->amount, $row->currency),
$row->invoice_name,
l(t('Edit'), "admin/build/signup_pay/edit/$row->id"),
l(t('Delete'), "admin/build/signup_pay/delete/$row->id"),
);
}
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, SIGNUP_PAY_PAGER, 0);
print theme('page', $output);
}
function signup_pay_view_receipt() {
global $user;
$nid = arg(1);
$output = t('No receipt available.');
if ($user->uid && signup_pay_check_payment()) {
$output = theme('signup_pay_receipt', $user->uid, $nid);
}
print theme('page', $output);
}
function theme_signup_pay_receipt($uid, $nid, $mode = 'page') {
if ($mode == 'mail') {
$receipt = variable_get(SIGNUP_PAY_RECEIPT_EMAIL, SIGNUP_PAY_DEFAULT_RECEIPT);
}
else {
$receipt = variable_get(SIGNUP_PAY_RECEIPT_PAGE, SIGNUP_PAY_DEFAULT_RECEIPT);
}
$methods = signup_pay_get_methods();
$methods[SIGNUP_PAY_METHOD_FREE] = t('Free attendance');
$result = db_query('SELECT u.mail, p.name as invoice_name, p.nid, p.currency, p.amount, p.time_paid, p.method_id
FROM {users} u
INNER JOIN {signup_pay} p USING(uid)
WHERE p.uid = %d
AND p.nid = %d', $uid, $nid);
while ($row = db_fetch_object($result)) {
$node = node_load($row->nid);
$output = t($receipt, array(
'@mail' => $row->mail,
'@title' => $node->title,
'@name' => $row->invoice_name,
'@amount' => _signup_pay_format_amount($row->amount, $row->currency),
'@method' => $methods[$row->method_id],
'@date' => format_date($row->time_paid, 'custom', 'Y-m-d'),
));
}
return $output;
}
function signup_pay_thanks() {
print theme('page', t('Thank you for registering.'));
}
function signup_pay_paypal_ipn() {
// Verify that the request came from Paypal, and not from some intrusion
if (!simple_paypal_ipn_verify($_POST)) {
// Verification failed
return;
}
if ($_POST['receiver_email'] != variable_get(SIGNUP_PAY_EMAIL, SIGNUP_PAY_DEFAULT_EMAIL)) {
// Payment is not for the email address configured
watchdog('signup_pay', t('Payment email (@payment) is not for the email address configured (@configured)',array('@payment'=>variable_get(SIGNUP_PAY_EMAIL, SIGNUP_PAY_DEFAULT_EMAIL),'@configured'=>$_POST['receiver_email'])));
return;
}
// Parse the custom field, and break it into its components
$data = explode(':', $_POST['custom']);
$custom = array();
foreach($data as $row) {
list($key, $value) = explode('=', $row);
$custom[$key] = $value;
}
$time_paid = check_plain(strtotime($_POST['payment_date']));
$name = check_plain($_POST['first_name'] .' '. $_POST['last_name'] . ($_POST['payer_business_name'] ? ' ('. $_POST['payer_business_name'] .')' : ''));
$gross_amount = check_plain((float)$_POST['mc_gross']);
$net_amount = check_plain((float)$_POST['mc_gross'] - (float)$_POST['mc_fee']);
//TODO test emails and display a message indicating these emails are not the same
if (!$custom['mail']) {
$mail = check_plain($_POST['payer_email']);
}
else {
$mail = $custom['mail'];
}
$currency = check_plain($_POST['mc_currency']);
db_query("INSERT INTO {signup_pay} (id, uid, nid, method_id, time_paid, name, mail, currency, net_amount, amount)
VALUES (0, %d, %d, %d, %d, '%s', '%s', '%s', %f, %f)",
(int)$custom['uid'],
(int)$custom['nid'],
SIGNUP_PAY_METHOD_PAYPAL,
$time_paid,
$name,
$mail,
$currency,
$net_amount,
$gross_amount);
$body = theme('signup_pay_receipt', $custom['uid'], $custom['nid'], 'mail');
$from = variable_get('site_mail', ini_get('sendmail_from'));
$subject = t('[@site] Receipt for payment paid', array('@site' => variable_get('site_name', 'Drupal')));
drupal_mail('signup_pay', $mail, $subject, $body, $from);
watchdog('signup_pay', t('Payment from @name (@mail) amount of @amount @currency.', array(
'@name' => $name,
'@mail' => $mail,
'@amount' => $amount,
'@currency' => $currency,
)));
if (module_exists('signup_status')) {
$user = (int)$custom['uid'] ? (int)$custom['uid'] : (int)$custom['uid'].":".$mail;
$users = array($user);
$new_code = variable_get(SIGNUP_PAY_PAID_STATUS_CODE, SIGNUP_PAY_DEFAULT_PAID_STATUS_CODE);
signup_status_operations($users, $custom['nid'], 'status_code', $new_code);
}
}
function signup_pay_form_alter($form_id, &$form) {
global $user;
// Intercept signup form
switch ($form_id) {
case 'signup_form':
$node = $form['#parameters'][1];
if ($node->signup_pay_enabled) {
$default_rid = signup_pay_find_user_role($user);
$pay_roles = signup_pay_get_node_pay_roles($form['nid']['#value']);
$amount = $pay_roles[$default_rid]['amount'];
// Invoke all adjustment modules, allows for multiple adjustments
$amount = signup_pay_adjust($node, $user, $amount);
$form['collapse']['signup_user_form']['payment'] = array(
'#value' => t('