Skip to content

Instantly share code, notes, and snippets.

@ryandao
Forked from frankmullenger/OrderPage.php
Created May 17, 2012 08:33
Show Gist options
  • Save ryandao/2717397 to your computer and use it in GitHub Desktop.
Save ryandao/2717397 to your computer and use it in GitHub Desktop.
Payment Module Outlines
<?php
class OrderPage extends Page {
}
/**
* Represents a page with a form which a user fills out to process payment
*/
class OrderPage_Controller extends Page_Controller {
function OrderForm() {
$fields = new FieldList();
//Get form fields for payment methods
$paymentFields = Payment::combined_form_fields(); //Perhaps a nicer way of doing this?
$fields->push($paymentFields);
$actions = new FieldList(
new FormAction('ProcessOrder', 'Proceed to pay')
);
$validator = new OrderFormValidator();
return new Form($this, 'OrderForm', $fields, $actions, $validator);
}
function ProcessOrder($data, $form) {
//What is the payment method? Find out from $data?
// The environment (Production/Sandbox/Mock) is chosen based on the _config.php file
$paymentManager = new PaymentManager('PayPal');
$result = $paymentManager->processPayment($data);
//If instant payment success
if ($result->isSuccess()) {
}
//If payment is being processed
//e.g gateway payment process redirected to another website (PayPal, DPS)
if ($result->isProcessing()) {
}
//If payment failed
if (!$result->isSuccess() && !$result->isProcessing()) {
}
}
}
<?php
class Payment {
const STATUS_SUCCESS = 1;
const STATUS_PROCESSING = 0;
const STATUS_FAILURE = -1;
/**
* Both Member and Object are optional.
* Object to represent object being paid for e.g: an order
*
* @var Array
*/
public static $has_one = array(
'Member' => 'Member',
'Object' => 'Object'
);
}
class Payment_Controller extends Controller {
/**
* Inject Payment
*
* @param Payment $payment
*/
public function __construct(Payment $payment = null) {
//DI here
}
}
interface Payment_Controller_Interface {
public function getFormFields();
public function getFormRequirements();
public function processRequest();
public function processResponse();
}
<?php
class PaymentManager {
public function __construct($paymentModuleName) {
$payment = new Payment($paymentModuleName);
$paymentController = new PaymentController($paymentModuleName, $payment);
$paymentProcessor = new PaymentProcessor($paymentController);
}
public function processPayment($data) {
return $paymentProcessor->processPayment($data);
}
}
<?php
class PaymentProcessor {
public function __construct(Payment_Controller $paymentController) {
//DI here
}
/**
* Process payment using injected payment controller.
*
* @param Array $data Form data
* @return PaymentProcessor_Result
*/
function processPayment(Array $data) {
$payment = $this->paymentController->processRequest($data);
if ($payment->isSuccess()) {
return new PaymentProcessor_Success;
}
if ($payment->isProcessing()) {
return new PaymentProcessor_Processing;
}
if ($payment->isFailed()) {
return new PaymentProcessor_Failure;
}
}
}
abstract class PaymentProcessor_Result {
protected $value;
function __construct($value = null) {
$this->value = $value;
}
function getValue() {
return $this->value;
}
abstract function isSuccess();
abstract function isProcessing();
}
class PaymentProcessor_Success extends PaymentProcessor_Result {
function isSuccess() {
return true;
}
function isProcessing() {
return false;
}
}
class PaymentProcessor_Processing extends PaymentProcessor_Result {
function isSuccess() {
return false;
}
function isProcessing() {
return true;
}
}
class PaymentProcessor_Failure extends PaymentProcessor_Result {
function isSuccess() {
return false;
}
function isProcessing() {
return false;
}
}
<?php
class PayPalPayment extends Payment {
}
class PayPalPayment_Gateway extends PayPalPayment {
/**
* Gets fields for processing via gateway e.g: fields required for PayPal API
*
* @return FieldList
*/
public function getFormFields() {
}
public function getFormRequirements() {
}
}
class PayPalPayment_Merchant extends PayPalPayment {
/**
* Gets fields for processing credit card on site e.g: CreditCardField, month, year, cvv fields
*
* @return FieldList
*/
public function getFormFields() {
}
public function getFormRequirements() {
}
}
class PayPalPayment_Controller extends Payment_Controller implements Payment_Controller_Interface {
public function getFormFields() {
return $this->Payment->getFormFields();
}
/**
* Getting required fields, perhaps there is a better approach?
* Need to set rules for Validator on OrderPage::OrderForm()
* Maybe wait until form validation GSOC work completed?
*/
public function getFormRequirements() {
}
public function processRequest() {
}
public function processResponse() {
}
}
class PayPalPayment_Controller_Production extends Payment_Controller {
/**
* Not sure what to return here
*
* @param Array $data
* @return Payment
*/
public function processRequest(Array $data) {
if ($this->Payment instanceof PayPalPayment_Gateway) {
//send data to API with production account details
//save Payment with status 'processing'
}
if ($this->Payment instanceof PayPalPayment_Merchant) {
//save data to DB
}
//Maybe return Payment object?
return $this->Payment;
}
public function processResponse() {
}
}
class PayPalPayment_Controller_Sandbox extends Payment_Controller {
/**
* Probably pretty much identical to PayPalPayment_Controller_Production::processRequest()
* TODO find a way to keep this DRY - shared parent class?
*/
public function processRequest(Array $data) {
//If payment gateway, send data to API with sandbox account details
//If payment merchant, save data
}
public function processResponse() {
}
}
class PayPalPayment_Controller_Mock extends Payment_Controller {
public function processRequest(Array $data) {
//If payment gateway, redirect to processResponse() with mocked HTTP response from gateway
//If payment merchant, save data
}
public function processResponse() {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment