\documentclass{article}
\usepackage{ulem}
\usepackage{graphicx}
\usepackage{hyperref}
\pagestyle{headings}
\begin{document}
\part{Horde\_Payment}
Unified payment processor providing payment gateway for any Horde module.

\section{Bugs}
List any tickets on <a href="http://bugs.horde.org/">http://bugs.horde.org/</a> that cover this issue or are relevant to it.

\section{People}
Duck [mailto:<a href="https://wiki.horde.org/mailto:duck@obala.net">duck@obala.net</a> <a href="https://wiki.horde.org/mailto:duck@obala.net">duck@obala.net</a>]

\section{Code}
<a href="http://cvs.horde.org/incubator/Horde\_Payment/">http://cvs.horde.org/incubator/Horde\textbackslash\{\}\_Payment/</a>

\section{Description}
A payment processing module encapsulating all communications with various payment interfaces.

The application just pushes a payment request with the authorizationRequest API call. When a payment is processed, the payment module calls the selling application's authorizationResponse callback API method to notify it of the results. After payment processing is finished, the user will be redirected to the calling application's webroot, or to the URL provided by authorizationReturn result if the selling application provides it.

The payment module provides an administrative interface to list and search payment requests per module, amount, user status etc.

\subsection{Features}
\begin{itemize}
\item Built in payment methods
\begin{itemize}
\item Cash on delivery


\item Proforma invoice


\end{itemize}

\item Known statuses
\begin{itemize}
\item pending


\item revoked


\item successful


\item void


\end{itemize}

\item Configurable payment methods


\item Limit payment methods per user


\item Limit payment methods per application


\item Limit payment methods per amount


\item Virtual host support


\item Possibility to add a testing process request


\end{itemize}
\section{Payment process for user}
\subsection{Step 1: Type selection}
When the user is redirected to the selling interface, he/her will be asked to select a payment module. The list will be populated with all modules available that are active, linked to application owning the transaction and in the amount value parameters. If there is only one module available, the selection screen is avoided and user is redirected directly to the next step. User can always come back and choose another method, as revoke a transaction at any time.

\subsection{Step 2: Enter data}
User is asked for additional data required by the selected module. Values are stored in database for administrative purposes. This step is automatically skipped for modules does not need additional data entered by user. (See Horde\_Payment\_Method::hasLocalForm())

\subsection{Step 3: Validation}
The validation process of the payment module will be called or the user will be redirected to the remote validation page if the module has it. Here is where the selling application will be called back to be notified about authorization status change. (See Horde\_Payment\_Method::hasRemoteValidation(), Horde\_Payment\_Method::process())

\subsection{Step 4: Redirection page}
The user will be redirected back to the selling application page or to the result of the authorizationReturn call.

\section{Writing your payment module}
\subsection{Files}
A payment module is class extension of Horde\_Payment\_Method and should reside in a sub-directory /of lib/Modules named the same as you module. Inside this directory there must be:

\begin{itemize}
\item version.php  telling the configuration screen the version of your module


\item conf.xml  a configuration options


\item Module.php  man class file.


\end{itemize}
\section{List user payment request}
A lot of payment request ends by user abort (they change their mind, the line falls, system creases...) To remind them about their order, you can use the listAthorizations method  to list user's pending authorizations. So they can restart the process where they finish wherever they want.

<pre><code class="language-php">
// Get authorisations for current application and user
\$authorizations = \$registry->call('payment/listAuthorizations',
                                        array(array('module\_name' => \$registry->getApp(),
                                                    'user\_uid' => Auth::getAuth())));

// Get status names
\$statuses = \$registry->call('payment/getStatuses');

// List all authorizations and link pending ones to paymnet procces
foreach (\$authorizations as \$authorization) \{
    echo date('y-m-d h:i:s', \$authorization['created']) . '<br />';
    echo \$authorization['amount'] . '<br />';
    echo \$statuses[\$authorization['status']] . '<br />';
    if (\$authorization['status'] == Horde\_Payment::PENDING) \{
        \$link = \$registry->link('payment/show', array('id' => \$authorization['authorization\_id']));
        echo ' - <a href="' . \$link . '" target="\_blank"><strong>' . \_("Please click here to continue!") . '</strong></a>';
    \}
    echo '<hr />';
\}
</code></pre>
\section{Implementation Api calls}
\subsection{authorizationRequest() usage example}
<pre><code class="language-php">

\$app = \$registry->getApp(); // Calling app
\$transaction\_id = "myID123"; // App internal unique id
\$total = 500; // Total requested amount
\$params = array(); // Optional: Additional payment parameters, like user details (name, address etc..)

// Check if any authorization method exits and is linked to this
\$authorization\_methods = \$registry->call('payment/getMethods', array(\$app));
if (\$authorization\_methods instanceof PEAR\_Error) \{
    echo sprintf(\_("Authorization error. \%s"), \$authorization\_methods->getMessage());
    exit;
\}

// Push an paymnet authorization request
\$authorizationID = \$registry->call('payment/authorizationRequest',
                                    array(\$app, \$transaction\_id, \$total, \$params));
if (\$authorizationID instanceof PEAR\_Error) \{
    echo sprintf(\_("Authorization error. \%s"), \$authorizationID->getMessage());
    exit;
\}

// Redirect to paymnet system
// \$redirect\_url = \$registry->link('payment/show', array('id' => \$transaction\_id, 'module' => \$app));
\$redirect\_url = \$registry->link('payment/show', array('id' => \$authorizationID));

header('Location:' . \$redirect\_url);
exit;
</code></pre>
\subsection{authorizationResponse() API example}
<pre><code class="language-php">

...

\$\_services['authorizationResponse'] = array(
    'args' => array('id' => 'id', 'params' => '\{urn:horde\}stringArray'),
    'type' => 'string'
);

....

/**
 * Handle authorization response.
 *
 * @param string \$id         Invoice identification number
 * @param string \$params     Additional parameters
 */
function \_manios\_authorizationResponse(\$id, \$params)
\{
    require\_once dirname(\_\_FILE\_\_) . '/base.php';

    \$manios\_driver = Manios\_Driver::singleton();
    if (\$manios\_driver instanceof PEAR\_Error) \{
        return \$manios\_driver;
    \}

    \$transaction = \$manios\_driver->getTransaction(\$id);
    if (\$transaction instanceof PEAR\_Error) \{
        return \$transaction;
    \}

    switch (\$params['status\_id']) \{
    case Horde\_Payment::PENDING:
        // We have noting to do
        return true;
        break;

    case Horde\_Payment::VOID:
    case Horde\_Payment::REVOKED:
        // Cancle order
        return \$manios\_driver->deleteTransaction(\$id, \$transaction['advertiser\_id']);

    case Horde\_Payment::SUCCESSFUL:
        // Payment was successfully, process order
        return \$manios\_driver->confirmTransaction(\$id);

    default:
        // Unknown
        return PEAR::raiseError(\_("Unknown response status"));

    \}
\}
</code></pre>
\subsection{authorizationReturn() API example}
<pre><code class="language-php">

...

\$\_services['authorizationReturn'] = array(
    'args' => array('id' => 'id'),
    'type' => 'string'
);

....

/**
 * Returns authorization comeback url.
 *
 * @param string \$id         Invoice identification number
 */
function \_manios\_authorizationReturn(\$id)
\{
    require\_once dirname(\_\_FILE\_\_) . '/base.php';

    \$manios\_driver = Manios\_Driver::singleton();
    if (\$manios\_driver instanceof PEAR\_Error) \{
        return \$manios\_driver;
    \}

    \$transaction = \$manios\_driver->getTransaction(\$id);
    if (\$transaction instanceof PEAR\_Error) \{
        return \$transaction;
    \}

    // The transaction has no campaign linked
    if (empty(\$transaction['campaign\_id'])) \{
        return Horde::applicationUrl('impressions/transfer.php', true);
    \}

    // Redirect to campaign management
    return Util::addParameter(Horde::applicationUrl('banners/', true), 'c', \$transaction['campaign\_id']);
\}
</code></pre>
\section{Screenshots}
Configure payment methods<br />
\includegraphics{config.png}

Link payment methods to application<br />
\includegraphics{links.png}

Search authorizations<br />
\includegraphics{search.png}

Add a testing process request<br />
\includegraphics{testing.png}

\section{Resources}
Credit card test \#s: <a href="https://www.paypal.com/en\_US/vhelp/paypalmanager\_help/credit\_card\_numbers.htm">https://www.paypal.com/en\textbackslash\{\}\_US/vhelp/paypalmanager\textbackslash\{\}\_help/credit\textbackslash\{\}\_card\textbackslash\{\}\_numbers.htm</a>


\noindent\rule{\textwidth}{1pt}
Back to the <a href="https://wiki.horde.org/Project">Project List</a>

\end{document}
