Table of Contents

Payment_Process2

A PHP5 rework of payment_process

Developers: doconnor, dbezborodow

Migrating

To migrate code which uses payment_process

  1. Find and replace Payment_Process to Payment_Process2
  2. Find and replace Payment/Process to Payment/Process2
  3. If you set up any driver specific options with curl, you will need to swap to injecting a preconfigured instance of HTTP_Request2.
$payment = Payment_Process::factory('MyDriver');
$payment->setOption('curl_options', array('monkeys' => true));

becomes

$adapter = new HTTP_Request2_Adapter_Curl();
$adapter->setOption('monkies', true);
 
$request = new HTTP_Request2($adapter);
 
$payment = Payment_Process2::factory('MyDriver', $request);

Implementing a driver

You need to implement two classes and some unit tests.

The first is Payment_Process2_YourDriver, which should implement all of the methods in the interfacePayment_Process2_Driver.

The second is Payment_Process2_Result_YourDriver, which should implement all of the methods in the interfacePayment_Process2_Result_Driver.

The interface documentation should provide more detail on this.

Testing a driver

You want to build a small script pointed at a test server which var_dump()s out results. This is used to quickly verify that it actually works. You take that test data and save it in tests/data/Driver/foo.html

To test the driver; implement coverage of:

  1. It calls the HTTP_Request object to send off a request via process()
  2. It reads the response from the server and makes a result object via process()
  3. It renders a request correctly via process()
  4. It builds any request data correctly via prepareRequestData()
public function testShouldSendPaymentsAndReturnResults() {
    $response = new HTTP_Request2_Response('HTTP/1.1 200 OK');
    $response->appendBody(file_get_contents(dirname(__FILE__) . '/tests/data/Driver/foo.html'));
 
    $adapter = new HTTP_Request2_Adapter_Mock();
    $adapter->addResponse($response);
 
    $request = new HTTP_Request2($adapter);
 
    $payment = Payment_Process2::factory('Driver', $request);
 
    $result = $payment->process();
 
    $this->assertSame($expected_code, $result->getCode());
    $this->assertSame($expected_message, $result->getMessage());
}

You also want very good coverage of your result object, which a variety of test cases like:

public function testShouldParseDataAndPopulateResultObject() {
    $data = file_get_contents(dirname(__FILE__) . '/tests/data/Driver/foo.html');
 
    $fake_driver = new Payment_Process2_YourDriver(new HTTP_Request2());
    $result = new Payment_Process2_Result_YourDriver($data, $fake_driver);
 
    $result->parse();
 
    $this->assertSame($expected_code, $result->getCode());
    $this->assertSame($expected_message, $result->getMessage());
}

Roadmap

0.1.0

0.2.0

API changes

Anything which used

PAYMENT_PROCESS_SOMETHING_CONSTANT

will be

Payment_Process2::SOMETHING_CONSTANT

Also; setPayment() is now a lot more angry about things.

Finally; Payment_Process2_Type::isValid() doesn't exist anymore.

0.3.0

<?php
 
$process = Payment_Process2::factory('ANZ');
$process->setLogin('Damo');
$process->setPassword('secret');
 
$cc = Payment_Process2_Type::factory('CreditCard');
$cc->setType(Payment_Process2_Type_CreditCard::MASTERCARD);
$cc->setCardNumber('5123456789012346');
$cc->setExpDate('05/2011');
$cc->setCvv('123');
 
$action = Payment_Process2_Action::factory($process, 'Normal');
$action->setPayment($cc);
$action->setOrderInfo('123432');
$action->setTransactionReference('123432/1');
 
$result = $process->process($action);
 
/*
 
Responsibilities:
 
  Processor:
    Knows the endpoint, prepares the request from data.
    Knows credentials.
    Has a translator for the action types.
    Has a translator for the base fields such as credentials.
    Has a process() method that:
      Passes response data into a Result and call the parser method.
      Returns the Result.
 
  Action:
    Has a translator for the data
    Prepares data.
 
  Translator:
    Very generic. Is never extended so that we don't litter
      the class tree; instead, we set up the translator in
      constructor methods.
 
  Result:
    Has a parser that transforms the response into data that is given to it
      by the processor.
    Has a translator for the result data.
 
*/
1)
needs clearing