Building a custom Webform handler
Cornell DrupalCamp 2019
Cheng Chen
Cheng Chen
Sr. Drupal Developer
Case Western Reserve University
Cleveland, OH
Drupal 6/7/8
Agenda
- Brief intro to QuikPAY
- Why use webform?
- Form Demo
- Code Demo
- Q & A
QuikPAY
How does it work - 1/2
$orderNumber = round(microtime(true)*1000);
$orderType = "MED_IDEAS";
$amountDue = "";
$timestamp = round(microtime(true)*1000);
$secret = "ftkFgD57nh4371yOuI2";
$redirect_url = "http://yoursite.com/confirmation" ......
$hash = md5($orderNumber.$orderType.$amountDue.$userChoice3.$userChoice4.
$userChoice5.$userChoice6.$userChoice7.$userChoice8.$userChoice9.$userChoice10.
$redirectUrl.$redirectUrlParameters.$retriesAllowed.$timestamp.
$userChoice11.$userChoice12.$userChoice13.$userChoice14.$userChoice15.$userChoice16.
$userChoice17.$userChoice18.$userChoice19.$userChoice20.$userChoice21.$secret);
$URL_TO_QUIKPAY = "https://quikpayasp.com/cwru2/commerce_manager/payer.do?
orderNumber=$orderNumber&orderType=$orderType&amountDue=$amountDue
&userChoice3=$userChoice3&userChoice4=$userChoice4
&userChoice5=$userChoice5&userChoice6=$userChoice6&userChoice7=$userChoice7
&userChoice8=$userChoice8&userChoice9=$userChoice9&userChoice10=$userChoice10
&userChoice11=$userChoice11&userChoice12=$userChoice12&userChoice13=$userChoice13
&userChoice14=$userChoice14&userChoice15=$userChoice15&userChoice16=$userChoice16
&userChoice17=$userChoice17&userChoice18=$userChoice18&userChoice19=$userChoice19
&userChoice20=$userChoice20&userChoice21=$userChoice21&redirectUrl=$redirectUrl
&redirectUrlParameters=$redirectUrlParameters&retriesAllowed=$retriesAllowed
×tamp=$timestamp&hash=$hash";
QuikPAY
How does it work - 2/2
http://yoursite.com/confirmation
?transactionType=1&transactionStatus=1&transactionId=5001601231
&transactionTotalAmount=500&transactionDate=201908141917&transactionAcountType=VISA
&transactionDescription=Verification%2C+Transaction+Payments
&orderType=MED_Registrar_Payments&payerFullName=Commerce+Manager+Payer
&accountHolderName=cheng+chen&email=example%40gmail.com
&userChoice3=$userChoice3&userChoice4=$userChoice4
&userChoice5=$userChoice5&userChoice6=$userChoice6&userChoice7=$userChoice7
&userChoice8=$userChoice8&userChoice9=$userChoice9&userChoice10=$userChoice10
&userChoice11=$userChoice11&userChoice12=$userChoice12&userChoice13=$userChoice13
&userChoice14=$userChoice14&userChoice15=$userChoice15&userChoice16=$userChoice16
&userChoice17=$userChoice17&userChoice18=$userChoice18&userChoice19=$userChoice19
&userChoice20=$userChoice20&userChoice21=$userChoice21×tamp=1565824644370&hash=cfea01350ba0a7a881750a42039ba1c2
Webform
PHP files
PHP files | Webform |
---|---|
Manually get and validate user inputs | Robust Client/Server side validations |
Manually compose emails | Email handler |
Manually deal with database CRUD, etc... | WebformSubmission Entity (extends core's EntityInterface) |
Repeating process | Webform template |
Editors cannot help. | Webform template |
Quikpay_handler dir
quikpay_handler
quikpay_handler.info.yml
quikpay_handler.routing.yml
quikpay_handler.module
- src/
- Controller/
- ResponseActionController.php
- Plugin/
- WebformHandler
- QuikpayHandler.php
- templates/
- quikpay-confirmation.html.twig
- quikpay-confirmation-session-expire.html.twig
- test/...
quikpay_handler.info.yml
name: 'QuikPay Handler'
type: module
description: 'Custom handler for QuikPAY webforms'
core: 8.x
package: 'Custom'
dependencies:
- webform:webform
- webform:webform_ui
quikpay_handler.routing.yml
quikpay_handler.response_action_controller_update:
path: '/form/{webform_id}/confirmation'
defaults:
_controller: '\Drupal\quikpay_handler\Controller\ResponseActionController::update'
_title: 'update'
requirements:
_permission: 'access content'
options:
no_cache: 'TRUE'
quikpay_handler.module
<?php
/**
* @file
* Contains quikpay_handler.module.
*/
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\webform\Entity\WebformSubmission;
/**
* Implements hook_help().
*/
function quikpay_handler_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the quikpay_handler module.
case 'help.page.quikpay_handler':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Custom handler for Quikpay webforms') . '</p>';
return $output;
default:
}
}
/**
* Implements hook_theme().
*/
function quikpay_handler_theme($existing, $type, $theme, $path) {
return [
'quikpay_confirmation' => [
'variables' => ['payment_var' => NULL],
],
'quikpay_confirmation_session_expire' => [
],
];
}
/**
* Implements hook_cron().
*/
function quikpay_handler_cron() {
$webform_id = 'transcript_and_mspe_request_form';
$submission_ids = \Drupal::service('database')
->select('webform_submission_data', 'wsd')
->fields('wsd', ['sid'])
->condition('wsd.webform_id', $webform_id)
->condition('wsd.name', 'transaction_id')
->condition('wsd.value', '')
->execute()
->fetchAllAssoc('sid');
foreach ($submission_ids as $sid => $v) {
WebformSubmission::load($sid)->delete();
}
}
QuikpayHandler.php
<?php
namespace Drupal\quikpay_handler\Plugin\WebformHandler;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\WebformSubmissionInterface;
/**
* Form submission handler.
*
* @WebformHandler(
* id = "quikpay_form_handler",
* label = @Translation("QuikPay Webform Handler"),
* category = @Translation("Form Handler"),
* description = @Translation("Generate string and redirect to QuikPay"),
* cardinality =
* \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
* )
*/
class QuikpayHandler extends WebformHandlerBase {
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
return $form;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [];
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::submitConfigurationForm($form, $form_state); // TODO: Change the autogenerated stub
....
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
$message = parent::validateForm($form, $form_state, $webform_submission); // TODO: Change the autogenerated stub
return $message;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
return $form_state->setResponse(new TrustedRedirectResponse($redirect_url));
}
}
ResponseActionController.php
<?php
namespace Drupal\quikpay_handler\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\webform\Entity\WebformSubmission;
use Symfony\Component\HttpFoundation\Request;
/**
* Class ResponseActionController.
*/
class ResponseActionController extends ControllerBase {
/**
* Update Submission records with transaction related data
* @var $webform_id
* @return
* Return a confirmation page via template.
*/
public function update($webform_id) {
$request = Request::createFromGlobals();
$query = $request->query->all();
$order_number = $query['userChoice3'];
$transaction_id = $query['transactionId'];
$transaction_status = $query['transactionStatus'];
$transaction_type = $query['transactionType'];
$transaction_accounttype = $query['transactionAcountType'];
$transaction_accountholdername = $query['accountHolderName'];
$transaction_amount = $query['transactionTotalAmount'];
$session = \Drupal::request()->getSession();
$payment_clear = FALSE;
if ($session->get('quikpay_session') == $order_number) {
$submission_id = \Drupal::service('database')
->select('webform_submission_data', 'wsd')
->fields('wsd', ['sid'])
->condition('wsd.webform_id', $webform_id, '=')
->condition('wsd.name', 'order_number', '=')
->condition('wsd.value', $order_number, '=')
->execute()
->fetchAssoc();
// use submission update to update the value
$sid = $submission_id['sid'];
$webform_submission = WebformSubmission::load($sid);
$webform = $webform_submission->getWebform();
$twig_var = [];
$twig_var['payment_type'] = $transaction_type;
$twig_var['transaction_id'] = $transaction_id;
$twig_var['confirmation_message'] = $webform->getSettings()['confirmation_message'];
if ((($transaction_type == 1 or $transaction_type == 2) && $transaction_status == 1) or ($transaction_type == 3 && in_array($transaction_status, [
5,
6,
8,
]))) {
$payment_clear = TRUE;
$twig_var['payment_clear'] = $payment_clear;
}
$webform_submission->setElementData('transaction_id', $transaction_id);
$webform_submission->setElementData('transaction_status', $transaction_status);
$webform_submission->setElementData('transaction_type', $transaction_type);
$webform_submission->setElementData('transaction_accounttype', $transaction_accounttype);
$webform_submission->setElementData('transaction_accountholdername', $transaction_accountholdername);
$webform_submission->setElementData('transaction_amount', $transaction_amount / 100);
$webform_submission->save();
$session->remove('quikpay_session');
return [
'#theme' => 'quikpay_confirmation',
'#payment_var' => $twig_var,
];
}
else {
return [
'#theme' => 'quikpay_confirmation_session_expire',
];
}
}
}
Building a custom webform handler
By Cheng Chen
Building a custom webform handler
a custom module case study with QuikPAY
- 1,028