Updating Bank Accounts via the API

 
The Edit Account API method can be used to maintain a ProPay merchant’s on-file deposit destination.  This is required for partners who wish to control the ACH experience on their own portal.  When you want to own this step, you also need to accept ownership over keeping the destination accurate.  ProPay’s API does NOT allow you to specify the destination bank account at the time of the ACH transaction.  You need to update the account separately.  (ProPay maintains a record of updates as part of our efforts to prevent money-laundering.)

Automatic disablement of ACH-Out
Another important reason we provide our partners with the ability to update bank account details is that our system will automatically disable the ability to push out funds if, in a previous attempt to do so, those funds are rejected by the depository bank.  When a reject occurs (usually a few days after the money is sent), we will automatically apply the funds back into the ProPay account.  It wouldn’t be a very pleasant experience if, when that happened, we turned around and sent it right back out…a vicious circle of rejects and re-attempts.  When you find out this is happening, (because our reports or a web-hook tell you) you really need to update the bank account, and this API is there for you.

Special rules for Edit Account for both updating bank accounts, and for making other changes
  • Updating the bank account is only one of the ways you can make an edit. While others exist as an option for this API call, only one group (kind of edit) can be passed per request.
  • If a group is passed, the API user must pass all data elements that comprise that group. If a value from a group is passed empty then the data related to that information is updated in the ProPay system.
  • Allowance to perform an edit of each group is subject to approval. If you try to perform an edit for a disallowed group, your request will fail.
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>42</transType>
<AccountCountryCode>USA</AccountCountryCode>
<accountType>Checking</accountType>
<AccountNumber>123456</AccountNumber>
<BankName>First Bank of Banking</BankName>
<RoutingNumber>123456789</RoutingNumber>
<accountNum>12345678</accountNum>
</XMLTrans>
</XMLRequest>
<XMLResponse>
<XMLTrans>
<transType>42</transType>
<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 ProcessTransactionTransType42
  {
  public static void ProcessTransaction()
  {
  var processRequest = new XmlTransactionRequest { CertificationString = "YourCertStringGoesHere", TerminalID = "YourTermId", };
  var xmlTransaction = new XmlProcessTransaction
  {
  TransType = "42",
  accountNum = "12345678",
  AccountNumber = "1234567",
  BankName = "First Bank of Bank",
  RoutingNumber = "123456789",
  AccountCountryCode = "USA",
  AccountType = "Checking",
  };
  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";
  webRequest.Headers.Add("X509Certificate", GetBase64Cert(“your certificate thumbprint goes here”));
  webRequest.ProtocolVersion = HttpVersion.Version10;
  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;
  }
  }

public class XmlProcessTransaction : XmlTransaction
  {
  [XmlElement("accountNum")]
  public string accountNum = string.Empty;
  [XmlElement("AccountCountryCode")]
  public string AccountCountryCode = string.Empty;
  [XmlElement("AccountType")]
  public string AccountType = string.Empty;
  [XmlElement("AccountNumber")]
  public string AccountNumber = string.Empty;
  [XmlElement("BankName")]
  public string BankName = string.Empty;
  [XmlElement("RoutingNumber")]
  public string RoutingNumber = 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>();
  }
 
public string GetBase64Cert(string certificateThumbprint)
  {
  using (X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
  {
  store.Open(OpenFlags.ReadOnly);
  var foundCertificates = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false);
  if (foundCertificates.Count != 1)
  {
  return null;
  }
  var certByteArray = foundCertificates[0].Export(X509ContentType.Cert);
  store.Close();
  return Convert.ToBase64String(certByteArray);
  }
}

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;
}

/**
* creates custom header value by pulling array from x509 certificate file and converting to base64
* @param string $x509file
* @return $this
*/
public function setx509($x509file) {
$cert = openssl_x509_parse($x509file);
$base64cert = base64_encode($cert);
return $base64cert;
}

/**
* posts XML to the server
* @return $this
*/
public function postXML() {
$header = [
"Content-type:text/xml; charset=\"utf-8\"",
"Accept: text/xml",
"X509Certificate: ".setx509([Put your certificate file name here])
];

$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', 42);
$simpleXML->XMLTrans->addChild('accountNum', 123456789);
$simpleXML->XMLTrans->addChild('AccountNumber', 123456789);
$simpleXML->XMLTrans->addChild('BankName', 'First Bank of Bank');
$simpleXML->XMLTrans->addChild('RoutingNumber', 123456789);
$simpleXML->XMLTrans->addChild('AccountCountryCode', 'USA');
$simpleXML->XMLTrans->addChild('AccountType', 'Checking');

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

Int(32)

Required

The ProPay account to be updated

 

Group: Primary Bank Information - Optional

Element

Type

Max

Required

Notes

AccountCountryCode

string

25

Required

ISO 3166 standard 3 character country codes. Current allowed values are: USA and CAN

accountType

string

 

Required

Valid values are: Checking, Savings, and GeneralLedger

AccountNumber

integer

20

Optional

Bank Account Number

BankName

string

50

Optional

Bank Name

RoutingNumber

Integer

20

Optional

Valid ABA routing number or CPA EFT code.

 

 

Group: Secondary Bank Information - Optional

Element

Type

Max

Required

Notes

SecondaryAccountCountryCode

string

 

Required

ISO 3166 standard 3 character country codes. Current allowed values are: USA and CAN

SecondaryAccountType

string

 

Required

Valid values are: Checking, Savings, and GeneralLedger

SecondaryAccountName

string

32

Optional

Name on the Bank Account

SecondaryAccountNumber

string

20

Optional

Bank Account Number

SecondaryAccountOwnershipType

string

 

Optional

Valid values are: Personal and Business

SecondaryBankName

string

50

Optional

Bank Name

SecondaryRoutingNumber

string

9

Optional

Valid ABA routing number or CPA EFT code

 

Response Values

Element

Type

Notes

transType

string

Will always return as 42.

status

string

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

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