ProPay API ACH Payment Refunds

ProPay Void vs. Refund Logic
ProPay’s API provides one method for voids and refunds.  That is to say, you use the same method to request both events.  What happens when you make this request depends on a number of factors.
  • An account can be configured to require a refund for every transaction that has been captured.
  • A transaction that has been sent to the card brand can no longer be voided and must be refunded. ProPay sends transactions multiple times per day (This makes it possible for us to get merchants their money more quickly).
  • A transaction whose proceeds have been given to the merchant can no longer be voided, and must be refunded.
  • Additionally, any partial reversal of a transaction is a refund rather than a void.
The difference between a void and a refund
  • When you void a transaction, it’s like it never happened, and ProPay sends a message to the credit or debit card issuing bank asking them to cancel any authorizations already on the cardholder’s account (It’s up to each bank, though, and some banks ignore this message).
  • A refund is an entirely separate transaction. Not only does the merchant still have to pay for the original authorization.  He or she must also pay a per-transaction fee for the refund.  The credit card brands, after all, are going to get their money.
Okay, which outcome will occur when I make the API call
You have three ways to determine whether a void or refund happens when you make the void/refund API request.
  1. Examine our response. New transaction number = Refund.  Same transaction number = void.
  2. Make an API call in advance of the request. You can get the up-to date status of any transaction using API method 34 – Get Transaction Info.
How to call this method?

Example Request

Example Response

Implementation Details
Request Submission

Response Handling

Request Submission

Response Handling

Request Submission

Response Handling

Request Submission

Response Handling

Request Values
Response Values
How to call this method?

You should submit a post of XML data to the following URL
 
HTTP URL(s)
Example Request

Example Response

<?xml version='1.0'?>
<!DOCTYPE Request.dtd>
<XMLRequest>
<certStr>MyTestCertStr00000001</certStr>
<class>partner</class>
<XMLTrans>
<transType>07</transType>
<accountNum>3130000</accountNum>
<transNum>453123</transNum>
<amount>4000</amount>
<invNum>4578A</invNum>
</XMLTrans>
</XMLRequest>
<XMLTrans>
<transType>07</transType>
<accountNum>3130000</accountNum>
<transNum>453123</transNum>
<status>00</status>
</XMLTrans>
</XMLResponse>
Implementation Details
Request Submission

namespace MSAPI_ProcessTransaction
  {
  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  using System.Net;
  using System.Text;
  using System.Xml;
  using System.Xml.Linq;
  using System.Xml.Serialization;


/*
  ProPay provides the following code “AS IS.”
ProPay makes no warranties and ProPay disclaims all warranties and conditions, express, implied or statutory,
  including without limitation the implied warranties of title, non-infringement, merchantability, and fitness for a particular purpose.
  ProPay does not warrant that the code will be uninterrupted or error free,
  nor does ProPay make any warranty as to the performance or any results that may be obtained by use of the code.
  */
  public class ProcessTransactionTransType07
  {
  public static void ProcessTransaction()
  {
  var processRequest = new XmlTransactionRequest { CertificationString = "YourCertStringGoesHere", TerminalID = "YourTermId", };
  var xmlTransaction = new XmlProcessTransaction
  {
  TransType = "07",
  accountNum = "12345678",
  amount = "1000",
  transNum = "189",
  invNum = "abc123",
  };
  processRequest.Transactions.Add(xmlTransaction);
  string request = XmlSerializer<XmlTransactionRequest>.WriteToString(processRequest);
  SubmitRequest(request);
  }

private static void SubmitRequest(string request)
  {
  byte[] dataToSend = Encoding.UTF8.GetBytes(request);

// Change the following URL to point to production instead of integration
  WebRequest webRequest = WebRequest.Create("https://xmltest.propay.com/API/PropayAPI.aspx");
  webRequest.Method = "POST";
  webRequest.ContentLength = dataToSend.Length;
  webRequest.ContentType = "text/xml";
  Stream dataStream = webRequest.GetRequestStream();
  dataStream.Write(dataToSend, 0, dataToSend.Length);
  dataStream.Close();

string response = string.Empty;

try
  {
  WebResponse apiResponse = webRequest.GetResponse();


using (StreamReader sr = new StreamReader(apiResponse.GetResponseStream()))
  {
  response += sr.ReadToEnd();
  }
  }
  catch (WebException wex)
  {
  HttpWebResponse httpResponse = wex.Response as HttpWebResponse;
  using (Stream responseStream = httpResponse.GetResponseStream())
  using (StreamReader reader = new StreamReader(responseStream))
  {
  response = reader.ReadToEnd();
  }
  }

 ParseResponse(response);
  }

private static void ParseResponse(string response)
  {
  var load = XDocument.Parse(response);
  var transType = Convert.ToInt32(load.Descendants().First(p => p.Name.LocalName == "transType").Value);
  var status = load.Descendants().First(p => p.Name.LocalName == "status").Value;
  var transNum = load.Descendants().First(p => p.Name.LocalName == "transNum").Value;
  }
  }

public class XmlProcessTransaction : XmlTransaction
  {
  [XmlElement("accountNum")]
  public string accountNum = string.Empty;
  [XmlElement("amount")]
  public string amount = string.Empty;
  [XmlElement("transNum")]
  public string transNum = string.Empty;
  [XmlElement("invNum")]
  public string invNum = string.Empty;
  }

public static class XmlSerializer<T>
  {
  public static XmlSerializer Serializer = new XmlSerializer(typeof(T));
  public static string WriteToString(T data)
  {
  return WriteToString(data, Encoding.UTF8);
  }
  public static string WriteToString(T data, Encoding encoding)
  {
  string retVal;
  using (MemoryStream memoryStream = new MemoryStream())
  {
  using (XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, encoding))
  {
  Serializer.Serialize(xmlTextWriter, data);
  }

retVal = encoding.GetString(memoryStream.ToArray());
  }

return retVal;
  }
  }

[XmlInclude(typeof(XmlProcessTransaction))]
  public class XmlTransaction
  {
  [XmlElement("transType")]
  public string TransType = string.Empty;
  }
  [XmlRoot("XMLRequest")]
  public class XmlTransactionRequest
  {
  [XmlElement("certStr")]
  public string CertificationString = string.Empty;
  [XmlElement("termid")]
  public string TerminalID = string.Empty;
  [XmlElement("XMLTrans")]
  public List<XmlTransaction> Transactions = new List<XmlTransaction>();
  }
}

Response Handling

Request Submission

/**
 * ProPay provides the following code “AS IS.” ProPay makes no warranties and
 * ProPay disclaims all warranties and conditions, express, implied or
 * statutory, including without limitation the implied warranties of title,
 * non-infringement, merchantability, and fitness for a particular purpose.
 * ProPay does not warrant that the code will be uninterrupted or error free,
 * nor does ProPay make any warranty as to the performance or any results that
 * may be obtained by use of the code.
 */


<?php
class ProPayApi
{
/* change this to the production url for going live after testing https://api.propay.com */
private $_apiBaseUrl = 'https://xmltestapi.propay.com';

/* for xml */
/** @var \SimpleXMLElement */
private $_xmlRequestObject;
/** @var \SimpleXMLElement */
private $_xmlResponseObject;
/** @var string */
private $_xmlUrl;

/**
* sets the xml request object
* @param string $xmlData - containing XML
* @return $this
*/
public function setXMLRequestData($xmlData) {
$this->_xmlRequestObject = simplexml_load_string($xmlData);
return $this;
}

/**
* @param string $xmlData - containing XML
* @return $this
*/
public function setXMLResponseData($xmlData) {
$this->_xmlResponseObject = simplexml_load_string($xmlData);
return $this;
}

/**
* @return mixed
*/
public function getXMLRequestObject() {
return $this->_xmlRequestObject;
}

/**
* @return mixed
*/
public function getXMLResponseObject() {
return $this->_xmlResponseObject;
}

/**
* @param \SimpleXMLElement $xmlObject
* @return $this
*/
public function setXMLRequestObject(\SimpleXMLElement $xmlObject) {
$this->_xmlRequestObject = $xmlObject;
return $this;
}

/**
* @param \SimpleXMLElement $xmlObject
* @return $this
*/
public function setXMLResponseObject(\SimpleXMLElement $xmlObject) {
$this->_xmlResponseObject = $xmlObject;
return $this;
}

/**
* sets the url for the XML request
* @param string $xmlUrl
* @return $this
*/
public function setXMLUrl($xmlUrl) {
$this->_xmlUrl = $xmlUrl;
return $this;
}

/**
* posts XML to the server
* @return $this
*/
public function postXML() {
$header = [
"Content-type:text/xml; charset=\"utf-8\"",
"Accept: text/xml"
];


$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $this->_xmlUrl,
CURLOPT_TIMEOUT => 30,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $this->_xmlRequestObject->asXML(),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $header,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_HTTPAUTH => CURLAUTH_ANY
]);
$result = curl_exec($curl);
$this->_xmlResponseObject = simplexml_load_string($result);
curl_close($curl);
return $this;
}
}

$proPayAPI = new ProPayApi();
$data = "<?xml version='1.0'?>
<!DOCTYPE Request.dtd>
<XMLRequest>
</XMLRequest>";
$simpleXML = new \SimpleXMLElement($data);
$simpleXML->addChild('certStr','cert string here');
$simpleXML->addChild('termid','terminal id here');
$simpleXML->addChild('class','partner');
$simpleXML->addChild('XMLTrans');
$simpleXML->XMLTrans->addChild('transType', 36);
$simpleXML->XMLTrans->addChild('accountNum', 123456789);
$simpleXML->XMLTrans->addChild('amount', 1000);
$simpleXML->XMLTrans->addChild('transNum', 179);
$simpleXML->XMLTrans->addChild('invNum', 'abc123');

// returns XML
$result =
$proPayAPI->setXMLUrl('https://xmltest.propay.com/API/PropayAPI.aspx')
->setXMLRequestData($simpleXML->asXML())
->postXML()
->getXMLResponseObject()->asXML();

// if you prefer a simpleXML object you just retrieve the object back to work with that
$result = $proPayAPI->getXMLResponseObject();

Response Handling

Request Submission

Response Handling

Request Submission

Response Handling

Request Values

Element

Type

Max

Required

Notes

accountNum

Int(32)

 

Required

Assigned to each account by ProPay

transNum

Integer

 

Required

The ProPay transaction identifier

amount

Int(64)

 

Optional

The value representing the number of pennies in USD, or the number of [currency] without decimals.

*Minimum of 100 and if not passed, the entire transaction amount will be refunded or voided.

currencyCode

String

3

Optional*

ISO standard 3 character currency code for a foreign currency transaction. *Required if the currency of the original transaction is different than the currency of the ProPay account.

invNum

String

50

Optional

If not passed, invoice number will be the same as the transaction invNum being refunded

Response Values

Element

Type

Notes

status

string

Result of the transaction request. See ProPay Appendix for result code definitions

accountNum

integer

ProPay merchant account transaction was processed against

convertedAmount

integer

Amount expressed in the currency of the merchant account. * Returned on multi-currency transactions.

convertedCurrencyCode

string

ISO standard currency code of the ProPay merchant account. *Returned on multi-currency transactions.

currencyConversionRate

decimal

Exchange rate of the currency conversion. See 3.3 *Returned on multi-currency transactions.

transNum

integer

The ProPay transaction identifier

How to call this method?

Example Request

Example Response

Implementation Details
Request Submission

Response Handling

Request Submission

Response Handling

Request Submission

Response Handling

Request Submission

Response Handling

Request Values
Response Values