Skip to content

Working with Payments

schmittjoh edited this page Sep 17, 2010 · 9 revisions

Working with Payments

UPDATE: You can also take a look at the paymentDemo module for some example code.

Creating Payments

A payment always needs to have one data container which contains all information that the payment method needs to process the transaction. For example, in the case of a credit card payment, the data container would contain the credit card number, card holder, cvc number, and the expiration date. So, when you have collected this data from the customer, you can simply create a payment by calling the static create() method:

$payment = Payment::create(123.45, 'EUR', $paymentData);

Transactions

Everytime, you want to change the state of a payment, you have to perform a transaction on it. Currently, the following transactions are available:

  • approve: This transaction ensures that a customer has adequate funds available. Depending on the payment method different actions can happen in this transaction. For example, in the case of a credit card payment, the requested amount will be set aside, and a authorization code will be generated. For some payment methods, this transaction makes no sense (e.g. electronic check), in these cases it can be skipped.
  • deposit: This transaction transfers the approved amount.
  • reverseApproval: Reverses an approval transaction, and releases the approved amount. If you execute this transaction, the entire amount of the payment will be released, and the payment’s state will be set to canceled.
  • reverseDeposit: Reverses a deposit transaction, and transfers the entire amount back to the customer. Partial reversals are not supported.

See also the State Flows for when you can perform which transaction on a payment.

Approving Payments

In order to approve a payment, you have to perform an APPROVE transaction against it. Not all payment methods support APPROVE transactions, in these cases the approval is considered to be successful anyway. This is simply done by calling performTransaction() on the payment:

$payment = Payment::create(123.45, 'EUR', $data);
$payment->performTransaction(FinancialTransaction::TYPE_APPROVE);

If you only pass the transaction’s type to performTransaction(), it will make some assumptions as to which amount you would like to approve, and in which currency. If you want to set these values manually, you need to create the transaction yourself. But you don’t need to worry, FinancialTransaction also provides a neat static constructor for you:

$payment = Payment::create(123.45, 'EUR', $data);
$transaction = FinancialTransaction::create(
  FinancialTransaction::TYPE_APPROVE,
  $payment, 
  100, 
  'USD'
);
$payment->performTransaction($transaction);

As you have probably noticed, the approval transaction does neither cover the entire amount of the payment nor does it have the same currency as the payment. This is absolutely permissible as the payment system will use the current exchange rates to convert amounts accordingly (in order for this to work, you need to execute php symfony jmsPaymentPlugin:updateRates via a daily cronjob).

You can perform multiple APPROVE transactions against a payment as long as the target amount of the payment has not been reached by these transactions. However, there can only be one open transaction at any given time.