Make a Purchase

Once you have provisioned a gateway for your environment and collected payment information from your users, you can begin making purchases and other transactions.

Create a purchase transaction

Submitting the payment form to Spreedly doesn’t do anything except store that payment method - regardless of whether it’s valid or not - for later use. Now that you have a token representing the payment method, you can actually run a purchase against a specific gateway from your authenticated server environment (where you can safely store and access your Spreedly environment’s access secret).

Using the token of the gateway you want to transact against and the token of the payment method you want to charge, you can create a purchase by sending a POST request to the Spreedly API endpoint at https://core.spreedly.com/v1/gateways/<gateway_token>/purchase.<format>

$ curl https://core.spreedly.com/v1/gateways/LlkjmEk0xNkcWrNixXa1fvNoTP4/purchase.json \
  -u 'C7cRfNJGODKh4Iu5Ox3PToKjniY:4UIuWybmdythfNGPqAqyQnYha6s451ri0fYAo4p3drZUi7q2Jf4b7HKg8etDtoKJ' \
  -H 'Content-Type: application/json' \
  -d '{
        "transaction": {
          "payment_method_token": "56wyNnSmuA6CWYP7w0MiYCVIbW6",
          "amount": 100,
          "currency_code": "USD",
          "retain_on_success": true
        }
      }'

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

The amount is always given as an integer number of cents, so if you’d like to run a purchase of $83.45, you’d pass an amount of 8345.

Sending that request would give you the following response:

{
  "transaction": {
    "on_test_gateway": true,
    "created_at": "2018-11-07T15:05:09Z",
    "updated_at": "2018-11-07T15:05:09Z",
    "succeeded": true,
    "state": "succeeded",
    "token": "LjZEII3nej4v0Oq8wt5VAnWcMRq",
    "transaction_type": "Purchase",
    "order_id": null,
    "ip": null,
    "description": null,
    "email": null,
    "merchant_name_descriptor": null,
    "merchant_location_descriptor": null,
    "gateway_specific_fields": null,
    "gateway_specific_response_fields": {
    },
    "gateway_transaction_id": "53",
    "gateway_latency_ms": 19,
    "amount": 100,
    "currency_code": "USD",
    "retain_on_success": true,
    "payment_method_added": false,
    "message_key": "messages.transaction_succeeded",
    "message": "Succeeded!",
    "gateway_token": "T11bJAANtTWnxl36GYjKWvbNK0g",
    "gateway_type": "test",
    "response": {
      "success": true,
      "message": "Successful purchase",
      "avs_code": null,
      "avs_message": null,
      "cvv_code": null,
      "cvv_message": null,
      "pending": false,
      "result_unknown": false,
      "error_code": null,
      "error_detail": null,
      "cancelled": false,
      "fraud_review": null,
      "created_at": "2018-11-07T15:05:09Z",
      "updated_at": "2018-11-07T15:05:09Z"
    },
    "shipping_address": {
      "name": "Newfirst Newlast",
      "address1": null,
      "address2": null,
      "city": null,
      "state": null,
      "zip": null,
      "country": null,
      "phone_number": null
    },
    "api_urls": [
      {
        "referencing_transaction": [

        ]
      }
    ],
    "payment_method": {
      "token": "1rpKvP8zOUhj4Y9EDrIoIYQzzD5",
      "created_at": "2017-06-26T17:04:38Z",
      "updated_at": "2018-11-07T15:05:08Z",
      "email": "joey@example.com",
      "data": {
        "my_payment_method_identifier": "448",
        "extra_stuff": {
          "some_other_things": "Can be anything really"
        }
      },
      "storage_state": "retained",
      "test": true,
      "metadata": {
        "key": "string value",
        "another_key": 123,
        "final_key": true
      },
      "last_four_digits": "1111",
      "first_six_digits": "411111",
      "card_type": "visa",
      "first_name": "Newfirst",
      "last_name": "Newlast",
      "month": 3,
      "year": 2032,
      "address1": null,
      "address2": null,
      "city": null,
      "state": null,
      "zip": null,
      "country": null,
      "phone_number": null,
      "company": null,
      "full_name": "Newfirst Newlast",
      "eligible_for_card_updater": null,
      "shipping_address1": null,
      "shipping_address2": null,
      "shipping_city": null,
      "shipping_state": null,
      "shipping_zip": null,
      "shipping_country": null,
      "shipping_phone_number": null,
      "payment_method_type": "credit_card",
      "errors": [

      ],
      "fingerprint": "e3cef43464fc832f6e04f187df25af497994",
      "verification_value": "",
      "number": "XXXX-XXXX-XXXX-1111"
    }
  }
}
<transaction>
  <on_test_gateway type="boolean">true</on_test_gateway>
  <created_at type="dateTime">2018-11-07T15:05:08Z</created_at>
  <updated_at type="dateTime">2018-11-07T15:05:08Z</updated_at>
  <succeeded type="boolean">true</succeeded>
  <state>succeeded</state>
  <token>1nAR9jhKTmb9YJPRECJaxZLVHBg</token>
  <transaction_type>Purchase</transaction_type>
  <order_id nil="true"></order_id>
  <ip nil="true"></ip>
  <description nil="true"></description>
  <email nil="true"></email>
  <merchant_name_descriptor nil="true"></merchant_name_descriptor>
  <merchant_location_descriptor nil="true"></merchant_location_descriptor>
  <gateway_specific_fields nil="true"></gateway_specific_fields>
  <gateway_specific_response_fields>
  </gateway_specific_response_fields>
  <gateway_transaction_id>67</gateway_transaction_id>
  <gateway_latency_ms type="integer">31</gateway_latency_ms>
  <amount type="integer">100</amount>
  <currency_code>USD</currency_code>
  <retain_on_success type="boolean">true</retain_on_success>
  <payment_method_added type="boolean">false</payment_method_added>
  <message key="messages.transaction_succeeded">Succeeded!</message>
  <gateway_token>T11bJAANtTWnxl36GYjKWvbNK0g</gateway_token>
  <gateway_type>test</gateway_type>
  <shipping_address>
    <name>Newfirst Newlast</name>
    <address1 nil="true"></address1>
    <address2 nil="true"></address2>
    <city nil="true"></city>
    <state nil="true"></state>
    <zip nil="true"></zip>
    <country nil="true"></country>
    <phone_number nil="true"></phone_number>
  </shipping_address>
  <response>
    <success type="boolean">true</success>
    <message>Successful purchase</message>
    <avs_code nil="true"></avs_code>
    <avs_message nil="true"></avs_message>
    <cvv_code nil="true"></cvv_code>
    <cvv_message nil="true"></cvv_message>
    <pending type="boolean">false</pending>
    <result_unknown type="boolean">false</result_unknown>
    <error_code nil="true"></error_code>
    <error_detail nil="true"></error_detail>
    <cancelled type="boolean">false</cancelled>
    <fraud_review nil="true"></fraud_review>
    <created_at type="dateTime">2018-11-07T15:05:08Z</created_at>
    <updated_at type="dateTime">2018-11-07T15:05:08Z</updated_at>
  </response>
  <api_urls>
  </api_urls>
  <payment_method>
    <token>1rpKvP8zOUhj4Y9EDrIoIYQzzD5</token>
    <created_at type="dateTime">2017-06-26T17:04:38Z</created_at>
    <updated_at type="dateTime">2018-11-07T15:05:08Z</updated_at>
    <email>joey@example.com</email>
    <data>
      <my_payment_method_identifier>448</my_payment_method_identifier>
      <extra_stuff>
        <some_other_things>Can be anything really</some_other_things>
      </extra_stuff>
    </data>
    <storage_state>retained</storage_state>
    <test type="boolean">true</test>
    <metadata>
      <key>string value</key>
      <another_key type="integer">123</another_key>
      <final_key type="boolean">true</final_key>
    </metadata>
    <last_four_digits>1111</last_four_digits>
    <first_six_digits>411111</first_six_digits>
    <card_type>visa</card_type>
    <first_name>Newfirst</first_name>
    <last_name>Newlast</last_name>
    <month type="integer">3</month>
    <year type="integer">2032</year>
    <address1 nil="true"></address1>
    <address2 nil="true"></address2>
    <city nil="true"></city>
    <state nil="true"></state>
    <zip nil="true"></zip>
    <country nil="true"></country>
    <phone_number nil="true"></phone_number>
    <company nil="true"></company>
    <full_name>Newfirst Newlast</full_name>
    <eligible_for_card_updater nil="true"></eligible_for_card_updater>
    <shipping_address1 nil="true"></shipping_address1>
    <shipping_address2 nil="true"></shipping_address2>
    <shipping_city nil="true"></shipping_city>
    <shipping_state nil="true"></shipping_state>
    <shipping_zip nil="true"></shipping_zip>
    <shipping_country nil="true"></shipping_country>
    <shipping_phone_number nil="true"></shipping_phone_number>
    <payment_method_type>credit_card</payment_method_type>
    <errors>
    </errors>
    <verification_value></verification_value>
    <number>XXXX-XXXX-XXXX-1111</number>
    <fingerprint>e3cef43464fc832f6e04f187df25af497994</fingerprint>
  </payment_method>
</transaction>

The succeeded element indicates whether the transaction was successful, and the message element provides further details if it was not. Once you have a successful transaction, you can show a success page to your customer - you’ve successfully collected payment!

You can also execute other transactions against the gateway with your collected payment information, such as authorize, capture, void and refund. See the API reference docs for additional details.

Decimal Shifting for 3- and 0-Decimal Currencies

Because different gateway APIs have differing expectations for the format of amount values, and this format differs further depending on the minor unit and decimal placement (“exponent”) of each currency, the Spreedly API accepts amounts in a standardized format by decimals/exponent following ISO-4217, and handles reformatting of these values by gateway to preserve the intended amount.

Spreedly accepts amount values only as an integer, meaning there should not be a decimal in the amount value. Care should be taken when applying this standard format for currencies with 0 and 3 decimals, also called “decimal-shifting”:

  • 2-decimal currencies should be shifted two digits
  • 3-decimal currencies should be shifted three digits
  • 0-decimal currencies should have the “implicit decimal” shifted two digits (appending two 0s)

Explicit Examples:

  • To charge a value of 12.34 in a 2-decimal currency, the amount that should be sent to Spreedly is 1234. This could be achieved by multiplying the original amount by 100 or simply removing the decimal.
  • To charge a value of 1.234 in a 3-decimal currency, the amount that should be sent to Spreedly is 1234. This could be achieved by multiplying the original amount by 1000 or simply removing the decimal.
  • To charge a value of 1234 in a 0-decimal currency, the amount that should be sent to Spreedly is 123400. This could be achieved by multiplying the original amount by 100 or by removing any implicit decimal and appending two 0s.

Note that different gateways expect different formats in the request to their API, so these values may appear differently in the transcript of a request, but in the values of the Spreedly response and transaction objects themselves, they will appear as they are originally passed to us in your API call to Spreedly.

Retain

By default, when a payment method is added to Spreedly, it is placed in a “cached” storage state. This state indicates that unless told otherwise, the card will be purged from Spreedly after a short period of time (approximately 12 hours). If you are performing a one-time transaction in which you collect payment information and then immediately charge the card, then you don’t need to do anything else. However, if you want to charge the card again in the future or if you have a longer period of time between collecting the payment information and executing a purchase, then you will need to retain the card.

Since it’s so common to want to keep valid cards around for future purchases, Spreedly provides a retain_on_success parameter that can be used to automatically retain a card when it’s used in a successful transaction. The example purchase call above shows an example of retaining a card by setting the retain_on_success element to true.

Note: In this scenario, the initial transaction response from the Spreedly API will show that the payment method’s storage_state is cached even if the transaction was successful. This is because the response shows a snapshot of the payment method at the time the transaction was executed. The storage_state will be updated to retained immediately after the transaction succeeds.

If you don’t want to automatically retain a card when it’s used in a transaction, you can omit the retain_on_success parameter.

Redact

When you no longer need to store a card and want to remove it from Spreedly, you can redact it. Redacting a card will wipe all sensitive information related to the payment method and make the card inoperable.

Next

You should now be successfully integrated with Spreedly now that you have created a gateway, collected payment information, and executed a purchase. Merchant aggregators should review the merchant registration setup to optimize their account setup. If you would like to explore more advanced topics, we recommend the following as a starting point: