Refunds

Refunds allow your merchants to transfer the full or partial amount of a previous charge transaction back to the shopper.

Linked Refunds

Refunds are implemented as Linked Refunds, meaning you need to provide the transactionIdentifier of the previous charge transaction in order to perform the refund. For Linked Refunds it is not required for the shopper to present his card again and the refund will be paid out on the exact same card as used for the charge.

To run a full or partial Linked Refund, you need to create TransactionParameters with the transactionIdentifier of the previous charge transaction you want to refund. For partial refunds, you also need to specify the amount that should be refunded.

To start the refund process, you then need to call AmendTransaction on the ITransactionModule with the created TransactionParameters:

var refundParameters = new TransactionParameters.Builder()
    .Refund("<transactionIdentifier>")
    // For partial refunds, also specify refund amount and currency
    // .AmountAndCurrency(10.00m, Currency.EUR)
    .Build();

// delegate methods are similar to start transaction
var process = PosClient.GetTransactionModule().AmendTransaction(refundParameters,
     (transaction, transactionProcessDetails, abortable) =>
    {
        // transaction update information
    },
    (transaction, transactionStateDetails, error) =>
    {
        // check for error
        if (error != null)
        {
            // error indicates that there was a problem refunding the transaction
            // check error.Type and error.Message for more information
        }
        else
        {
            // Let the merchant know that he can return the goods to the shopper
            // You can access details of the refund in transaction.RefundDetails
            Console.WriteLine("Refund successful");
            
         
            // Provide a refund receipt:
            
            // Get all refundTransactions from the CHARGE transaction
             List<Payworks.PayClient.Transactions.RefundTransaction> refundTransactions =
                 transaction.RefundDetails.RefundTransactions;
            
             // Access the last refund transaction (usually there is only one)
             RefundTransaction lastRefund = refundTransactions.Last();
            
             if(lastRefund != null
                 && lastRefund.Status == TransactionStatus.APPROVED)
             {
                 // Get REFUND transaction includung receipt data 
                 PosClient.GetTransactionModule().GetTransaction(lastRefund.Identifier,
                  (refundTransaction, err) =>
                     {
                         if(err == null)
                         {
                             // Provide a printed REFUND receipt to the merchant and shopper
                             // refundTransaction.MerchantReceipt
                             // refundTransaction.CustomerReceipt
                         }
                     });
             }
        }
    });

Standalone Refunds

There might be the rare occasion when the transactionIdentifier of the previous charge is not available, e.g. should your POS system not allow the merchant to retrieve the original invoice containing the transactionIdentifier.

In this scenario Standalone Refunds allow the merchant to perform a refund without reference to the previous charge transaction and the shopper needs to present his card again.

Standalone Refunds have a high risk profile, i.e. merchant money can be paid out without limitations. Only consider offering them after you are absolutly sure that Linked Refunds are not possible in your setup.

Should your merchants require Standalone Refunds, please talk to your account manager beforehand to ensure all prerequisites are met. Specifically you need to ensure that:

  • Each merchant provides you with a written confirmation that they understand that Standalone Refunds potentially allow to pay out merchant money without limitations and that only authorised store personal must be allowed to use them.
  • Your POS system protects usage of the Standalone Refund feature, i.e. your POS system make sures that only authorised store personal (like store owner or supervisor) can use it and that usage is protected by a password or PIN. Note that before allowing you to go LIVE with Standalone Refunds, we will verify this requirements as part of our Testing.

 

Once enabled, Standalone Refunds are run very similar to charge transactions, meaning a card reader Device needs to be provided to StartTransaction.

Standalone Refund with Transaction Parameters:
var transactionParameters = new TransactionParameters.Builder()
                .Refund(10.00m, Currency.EUR)
                .Subject("Refund of previous charge")
                .CustomIdentifier("yourReferenceForTheTransaction")
                .Build();

var transactionProcessParameters = new TransactionProcessParameters.Builder().Build();

InteractiveProcess = PosClient.GetTransactionModule().StartTransaction(Device, transactionParameters, transactionProcessParameters,
    (transaction, transactionProcessDetails, abortable) =>
    {
        // transaction update information

        // abortable indicates if the transaction can be aborted in the current state

        // transactionProcessDetails.Information array indicates human-readable the state information:
        // always show those two status lines in your merchant-facing UI

        // transactionProcessDetails.Information[0]
        // transactionProcessDetails.Information[1]
    },
    (actionType) =>
    {
        // Can be left empty, refunds will not raise an action
    },

        (transaction, transactionProcessDetails, error) =>
        {
            // check for error
            if (error != null)
            {
                // error indicates that there was a error with the transaction processing
                // check error.Type and error.Message for more information
            }
            else
            {
                // Inspect the transaction.Status to get the overall result / transaction completed
                if (transaction.Status == TransactionStatus.APPROVED) // DECLINED / ABORTED
                {
                    Console.WriteLine("APPROVED: " + transaction.Identifier);

                    // Provide printed refund receipts to the merchant and shopper
                    // transaction.MerchantReceipt
                    // transaction.CustomerReceipt
                }
            }
        }
    );