Refunding SplitPay Transactions

SplitPay refunds, can represent a challenge for Payment Facilitators.  Rolling back SplitPay first means reversing the in-network movement between two ProPay accounts...That’s the easy part.  Where things get dicey is when you try to refund the initial credit card.  While bigger, trusted ProPay merchants are able to issue refunds without any money in their accounts (We know they are good for it, and we can always pull negative balances from their bank), not everyone for whom you want to facilitate is going to be big and credit-worthy.   Neither you nor ProPay want a bunch of small merchants who spend the money in their ProPay account, then are allowed to do refunds with money that doesn’t exist.

For this reason, we’ve come up with a single all-in-one SplitPay reversal API method
  • This method checks to see if the credit card transaction upon which the split is based is still voidable. If so, the credit card transaction simply voids and the split will never occur.
  • This method then checks the balance in the originating account to see if the payment transaction can be refunded. The sum of the returned split funds and the available balance in the originating account must be equal to or greater than the amount of the credit card refund in order to succeed.
  • Finally, this transaction checks the value of the element <requireCCRefund>. If <requireCCRefund> is true, and the account would be unable to refund the CC charge, the method will fail. If requireCCRefund is false, and the originating account is unable to perform the CC refund, then ONLY the reverse of the split portion of the transaction will be sent back to the originating account.
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>MyCertStr</certStr>
<class>partner</class>
<XMLTrans>
<transType>43</transType>
<accountNum>123456</accountNum>
<transNum>143</transNum>
<amount>500</amount>
<ccAmount>1000</ccAmount>
<requireCCRefund>Y</requireCCRefund>
<invNum>testinvoicenumber</invNum>
</XMLTrans>
</XMLRequest>
<XMLResponse>
<XMLTrans>
<transType>43</transType>
<status>00</status>
<accountNum>123456</accountNum>
<transNum>143</transNum>
<secondaryTransNum>41</secondaryTransNum>
<amount>500</amount>
<secondaryAmount>1000</secondaryAmount>
</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 ProcessTransactionTransType43
  {
  public static void ProcessTransaction()
  {
  var processRequest = new XmlTransactionRequest { CertificationString = "YourCertStringGoesHere", TerminalID = "YourTermId", };
  var xmlTransaction = new XmlProcessTransaction
  {
  TransType = "43",
  accountNum = "12345678",
  transNum = "342",
  amount = 1000,
  ccAmount = 900,
  invNum = "abc123",
  requireCCrefund = "Y",
  };
  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;
  var secondaryTransNum = load.Descendants().First(p => p.Name.LocalName == "secondaryTransNum").Value;
  }
  }

public class XmlProcessTransaction : XmlTransaction
  {
  [XmlElement("accountNum")]
  public string accountNum = string.Empty;
  [XmlElement("transNum")]
  public string transNum = string.Empty;
  [XmlElement("amount")]
  public string amount = string.Empty;
  [XmlElement("ccAmount")]
  public string ccAmount = string.Empty;
  [XmlElement("requireCCRefund")]
  public string requireCCRefund = 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', 43);
$simpleXML->XMLTrans->addChild('accountNum', 123456789);
$simpleXML->XMLTrans->addChild('transNum', 237);
$simpleXML->XMLTrans->addChild('amount', 1000);
$simpleXML->XMLTrans->addChild('ccAmount', 900);
$simpleXML->XMLTrans->addChild('invNum', 'abc123');
$simpleXML->XMLTrans->addChild('requireCCRefund', 'Y');

// 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

Integer

 

Required

This is the account number for the destination of the original split.

amount

Integer

 

Required

This is the amount to be pushed back from the destination side of the original split to the originating side of the same.

ccAmount

Integer

 

Required

This is the amount to be refunded back to the cardholder.

requireCCRefund

Boolean

 

Required

Y or N

transNum

Integer

 

Required

This is the transaction number on the destination side of the original split.

comment1

String

120

Optional

Optional Comment Line 1

comment2

String

120

Optional

Optional Comment Line 2

invNum

String

50

Optional

Invoice Number for the transaction

sourceEmail

String

 

Optional

Omit unless specially instructed by ProPay.

Passing a customer email address will create an email receipt to be sent from ProPay.

Response Values

Element

Type

Notes

status

String

See Propay Appendix for explanation of each status

accountNum

Integer

This is the account number of the recipient of the original split.

amount

Integer

This is the amount pushed back.

recAccntNum

Integer

This is the account number of the original charger of the credit card.

secondaryAmount

Integer

This is the amount refunded to the credit card.

secondaryTransNum

Integer

This is the newly created transaction number for the credit card refund. What is returned is the identifier on the side of the original charger of the credit card.

transNum

Integer

This is the newly created transaction number for the split being reversed. What is returned is the identifier on the side of the recipient of the original split.

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