ACHs

You can add bank accounts as payment methods in Spreedly to be used with a gateway’s ACH service. We currently support ACHs at the following gateways:

A custom transparent redirect form can be used like so:


<form accept-charset="UTF-8" action="https://core.spreedly.com/v1/payment_methods" method="POST">
  <fieldset>
    <input name="redirect_url" type="hidden" value="http://example.com/transparent_redirect_complete" />
    <input name="environment_key" type="hidden" value="C7cRfNJGODKh4Iu5Ox3PToKjniY" />
    <input name="utf8" type="hidden" value="✓" />

    <input name="payment_method_type" type="hidden" value="bank_account" />

    <label for="full_name">Name</label>
    <input id="full_name" name="full_name" type="text" />

    <label for="bank_name">Bank Name</label>
    <input id="bank_name" name="bank_name" type="text" />

    <label for="bank_routing_number">Bank Routing Number</label>
    <input id="bank_routing_number" name="bank_routing_number" type="text" />

    <label for="bank_account_number">Account Number</label>
    <input id="bank_account_number" name="bank_account_number" type="text" />

    <label for="bank_account_type">Account Type</label>
    <select id="bank_account_type" name="bank_account_type">
      <options value="checking" />
      <options value="savings" />
    </select>

    <label for="bank_account_holder_type">Account Holder</label>
    <select id="bank_account_holder_type" name="bank_account_holder_type">
      <options value="personal" />
      <options value="business" />
    </select>

    <button type='submit'>Submit Payment</button>
  </fieldset>
</form>

http://example.com/transparent_redirect_complete?token=OpUmh75ttxO1TxEg7nPhEMeiqZ6

The only required fields for a bank account are full_name (or first_name/last_name), bank_routing_number, and bank_account_number. The rest are optional at the Spreedly level, and whether you want to collect them will depend on what your gateway requires.

Currently only US and Canadian bank accounts are supported. For accounts issued by US banks, the bank_routing_number must be a valid US ABA Number. For accounts issued by Canadian banks, the bank_routing_number should be the nine-digit electronic routing number, beginning with a zero and followed by a valid financial institution number.

Valid values for bank_account_type are checking and savings, and valid values for bank_account_holder_type are personal and business.

A bank account looks like this when you pull it back out:


curl https://core.spreedly.com/v1/payment_methods/OpUmh75ttxO1TxEg7nPhEMeiqZ6.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml'

<payment_method>
  <token>VX0ackf05WGJwvjkl0epp1852CL</token>
  <created_at type="dateTime">2017-07-27T17:51:37Z</created_at>
  <updated_at type="dateTime">2017-07-27T17:51:37Z</updated_at>
  <email nil="true"/>
  <data nil="true"/>
  <storage_state>cached</storage_state>
  <test type="boolean">true</test>
  <full_name>Bob Smith</full_name>
  <bank_name>First Bank of Elbonia</bank_name>
  <account_type>checking</account_type>
  <account_holder_type>personal</account_holder_type>
  <routing_number_display_digits>021</routing_number_display_digits>
  <account_number_display_digits>3210</account_number_display_digits>
  <first_name>Bob</first_name>
  <last_name>Smith</last_name>
  <address1 nil="true"/>
  <address2 nil="true"/>
  <city nil="true"/>
  <state nil="true"/>
  <zip nil="true"/>
  <country nil="true"/>
  <phone_number nil="true"/>
  <company nil="true"/>
  <payment_method_type>bank_account</payment_method_type>
  <errors>
  </errors>
  <routing_number>021*</routing_number>
  <account_number>*3210</account_number>
</payment_method>


env = Spreedly::Environment.new('C7cRfNJGODKh4Iu5Ox3PToKjniY', '4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ', base_url: 'https://core.spreedly.com')
env.find_payment_method('OpUmh75ttxO1TxEg7nPhEMeiqZ6')


#<Spreedly::BankAccount:0x007fe33394da90
@token="RLKWLhDu8zWhjNfGkgNVqK2TDk8",
@created_at="2017-07-27T17:51:38Z",
@updated_at="2017-07-27T17:51:38Z",
@email="",
@storage_state="cached",
@data="",
@first_name="Bob",
@last_name="Smith",
@full_name="Bob Smith",
@bank_name="First Bank of Elbonia",
@account_type="checking",
@account_holder_type="personal",
@routing_number_display_digits="021",
@account_number_display_digits="3210",
@routing_number="021*",
@account_number="*3210",
@errors=[]>

Once you have a bank account payment method, you can run a purchase like so:


curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.xml \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/xml' \
  -d '<transaction>
        <payment_method_token>VX0ackf05WGJwvjkl0epp1852CL</payment_method_token>
        <amount>100</amount>
        <currency_code>USD</currency_code>
    </transaction>'

<transaction>
  <on_test_gateway type="boolean">true</on_test_gateway>
  <created_at type="dateTime">2017-07-27T17:53:07Z</created_at>
  <updated_at type="dateTime">2017-07-27T17:53:07Z</updated_at>
  <succeeded type="boolean">true</succeeded>
  <state>succeeded</state>
  <token>Bsj7WKWGvkADanTqndkDTZbYW76</token>
  <transaction_type>Purchase</transaction_type>
  <order_id nil="true"/>
  <ip nil="true"/>
  <description nil="true"/>
  <email nil="true"/>
  <merchant_name_descriptor nil="true"/>
  <merchant_location_descriptor nil="true"/>
  <gateway_specific_fields nil="true"/>
  <gateway_specific_response_fields>
  </gateway_specific_response_fields>
  <gateway_transaction_id>45</gateway_transaction_id>
  <gateway_latency_ms type="integer">0</gateway_latency_ms>
  <amount type="integer">100</amount>
  <currency_code>USD</currency_code>
  <retain_on_success type="boolean">false</retain_on_success>
  <payment_method_added type="boolean">false</payment_method_added>
  <message key="messages.transaction_succeeded">Succeeded!</message>
  <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token>
  <shipping_address>
    <name nil="true"/>
    <address1 nil="true"/>
    <address2 nil="true"/>
    <city nil="true"/>
    <state nil="true"/>
    <zip nil="true"/>
    <country nil="true"/>
    <phone_number nil="true"/>
  </shipping_address>
  <response>
    <success type="boolean">true</success>
    <message>Successful purchase</message>
    <avs_code nil="true"/>
    <avs_message nil="true"/>
    <cvv_code nil="true"/>
    <cvv_message nil="true"/>
    <pending type="boolean">false</pending>
    <result_unknown type="boolean">false</result_unknown>
    <error_code></error_code>
    <error_detail nil="true"/>
    <cancelled type="boolean">false</cancelled>
    <fraud_review nil="true"/>
    <created_at type="dateTime">2017-07-27T17:53:07Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:07Z</updated_at>
  </response>
  <api_urls>
  </api_urls>
  <payment_method>
    <token>FUbGgOeOdo1mT7j7Tndmz6zfdRg</token>
    <created_at type="dateTime">2017-07-27T17:53:06Z</created_at>
    <updated_at type="dateTime">2017-07-27T17:53:06Z</updated_at>
    <email nil="true"/>
    <data nil="true"/>
    <storage_state>cached</storage_state>
    <test type="boolean">true</test>
    <full_name>Bob Smith</full_name>
    <bank_name>First Bank of Elbonia</bank_name>
    <account_type>checking</account_type>
    <account_holder_type>personal</account_holder_type>
    <routing_number_display_digits>021</routing_number_display_digits>
    <account_number_display_digits>3210</account_number_display_digits>
    <first_name>Bob</first_name>
    <last_name>Smith</last_name>
    <address1 nil="true"/>
    <address2 nil="true"/>
    <city nil="true"/>
    <state nil="true"/>
    <zip nil="true"/>
    <country nil="true"/>
    <phone_number nil="true"/>
    <company nil="true"/>
    <payment_method_type>bank_account</payment_method_type>
    <errors>
    </errors>
    <routing_number>021*</routing_number>
    <account_number>*3210</account_number>
  </payment_method>
</transaction>


env = Spreedly::Environment.new('C7cRfNJGODKh4Iu5Ox3PToKjniY', '4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ', base_url: 'https://core.spreedly.com')
env.purchase_on_gateway("LlkjmEk0xNkcWrNixXa1fvNoTP4", "VX0ackf05WGJwvjkl0epp1852CL", 4432)


#<Spreedly::Purchase:0x007fe3328c20b8
@token="OPD8mGu7i3yh5Ol1AO12ADs3M90",
@created_at="2017-07-27T17:53:08Z",
@updated_at="2017-07-27T17:53:09Z",
@state="succeeded",
@message="Succeeded!",
@succeeded="true",
@order_id="",
@ip="",
@description="",
@gateway_token="T11bJAANtTWnxl36GYjKWvbNK0g",
@gateway_transaction_id="58",
@email="",
@merchant_name_descriptor="",
@merchant_location_descriptor="",
@on_test_gateway="true",
@currency_code="USD",
@amount="4432",
@response,=
#<Spreedly::Response:0x007fe33286b358
@success="true",
@pending="false",
@cancelled="false",
@fraud_review="",
@created_at="2017-07-27T17:53:09Z",
@updated_at="2017-07-27T17:53:09Z",
@message="Successful purchase",
@avs_code="",
@avs_message="",
@cvv_code="",
@cvv_message="",
@error_code="",
@error_detail="">,
@shipping_address,=
#<Spreedly::ShippingAddress:0x007fe3328099f0
@name="",
@address1="",
@address2="",
@city="",
@state="",
@zip="",
@country="",
@phone_number="">,
@gateway_specific_fields={},
@payment_method,=
#<Spreedly::BankAccount:0x007fe33209fca0
@token="V64F4zaCSgfbFkvsTt7ylnrGFkX",
@created_at="2017-07-27T17:53:08Z",
@updated_at="2017-07-27T17:53:08Z",
@email="",
@storage_state="cached",
@data="",
@first_name="Bob",
@last_name="Smith",
@full_name="Bob Smith",
@bank_name="First Bank of Elbonia",
@account_type="checking",
@account_holder_type="personal",
@routing_number_display_digits="021",
@account_number_display_digits="3210",
@routing_number="021*",
@account_number="*3210",
@errors=[]>>

The settlement process for ACHs is different from credit card transaction settlements. The docs on the Authorize.net site can help to explain. Authorize.net notifies you via email if an ACH transaction eventually fails to settle, whether it be for insufficient funds, chargebacks, etc.