COINQVEST is now Whalestack

You are looking at a blog post that was published when Whalestack was still known as COINQVEST. The content might be referencing our old name.

Blog Guides

Mar 2, 2020

Guide: Accept Cryptocurrency Payments with COINQVEST Merchant APIs

This guide will walk you through accepting cryptocurrency payments programmatically with minimal overhead. Make sales in Bitcoin, Ethereum, or any asset on the Stellar Network and settle in your preferred fiat currency (e.g. USD, EUR, or NGN) with a few lines of code.

Guide: Accept Cryptocurrency Payments with COINQVEST Merchant APIs

Get Started

Getting paid online has just become a whole lot easier. Today, all you need is your favorite IDE and an HTTP REST client for your favorite programming language. If you're a seasoned web developer, jump right over to the API docs. Otherwise, this guide is just what you need to get started.

Set up COINQVEST

Collect your API key and secret for your account. Use your favorite REST client or our official libraries for access to the COINQVEST API from your application:

#!/usr/bin/php
include('CQMerchantClient.class.php');

$client = new CQMerchantClient(
    'YOUR-API-KEY',
    'YOUR-API-SECRET'
);

Our libraries automatically take care of authentication. If your programming language is not supported by any of our SDKs yet, then the authentication section in our API documentation walks you through our Digest or Basic-Auth authentication mechanisms step-by-step.

Create a Checkout

COINQVEST uses a checkout object to represent your intent to collect payment from a customer and track payment state changes throughout the process.

A checkout includes information about your charge, which customer the payment should be associated with and which currency you would like to get credited in when the payment completes.

First create a customer:

# create a customer
$response = $client->post('/customer', array('customer' => array(
    'email' => 'name@email-address.com',
    'firstname' => 'John',
    'lastname' => 'Doe',
    // more fields optional
)));
$customerId = json_decode($response, true)['customerId']; // use this in the checkout

Then use it in a checkout:

#create a checkout
$response = $client->post('/checkout/hosted', array(
    'charge' => array(
        'customerId' => $customerId,
        'currency' => 'USD', // specifies the billing currency
        'lineItems' => array( // a list of line items included in this charge
            array(
                'description' => 'T-Shirt',
                'netAmount' => 10, // denominated in the currency specified above
                'quantity' => 1
            )
        ),
        'shippingCostItems' => array( // any shipping costs?
            array(
                'description' => 'Shipping and Handling',
                'netAmount' => '3.99',
                'taxable' => false // sometimes shipping costs are taxable
            )
        ),
        'taxItems' => array( // any taxes?
            array(
                'name' => 'CA Sales Tax',
                'percent' => '0.0825' // 8.25% CA sales tax
            )
        ),
        'discountItems' => array( // an optional list of discounts
            array(
                'description' => 'Loyalty Discount',
                'netAmount' => '0.5'
            )
        )
    ),
    'settlementCurrency' => 'EUR' // specifies in which currency you want to settle
    'webhook' => 'https://www.merchant.com/webhook', // listen for payment events     
    'links' => array( // link targets on the hosted checkout page
        'returnUrl' => 'https://www.merchant.com/payment-complete',
        'cancelUrl' => 'https://www.merchant.com/payment-canceled'
    )
);

$data = json_decode($response, true); 
$checkoutId = $data['checkoutId']; // store this persistently for later reference
$checkoutUrl = $data['checkoutUrl']; // display this to your customer

Above request creates a hosted checkout on COINQVEST and returns a URL, which is displayed back to your customer. Upon visiting the URL the customer is presented with everything he needs in order to complete the payment. The hosted checkout UI is responsive and will play well with large desktop monitors as well as tiny mobile phone screens.

Hosted Checkout

COINQVEST automatically calculates the payment prices in supported cryptocurrencies, generates deposit addresses and monitors blockchains for inbound payments.

If you're not into hosted checkouts and prefer to implement a payment process entirely branded by you and fully hosted within your own web application, we got you covered. Have a look at our white-label checkout documentation.

Handle Post-Payment Events

COINQVEST sends a WEBHOOK checkout-completed event to your server when the payment completes. Use the webhook, your dashboard, or a third party solution, to receive this event and trigger actions like sending an order confirmation email to your customer, generating an invoice, logging the sale in your database, or starting a shipping workflow.

Example webhook payload:

{
   "eventType":"CHECKOUT_COMPLETED",
   "data":{
      "checkout":{
         "id":"efd667b61725",
         "timestamp":"2020-09-16T21:34:28+00:00",
         "state":"COMPLETED",
         "type":"HOSTED",
         "origin":"API",
         "settlementAssetId":"USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
         "settlementAmountRequired":"10.0000000",
         "settlementAmountReceived":"10.0000000",
         "settlementAmountFeePaid": "0",
         "sourceAssetId":"ETH:GBDEVU63Y6NTHJQQZIKVTC23NWLQVP3WJ2RI2OTSJTNYOIGICST6DUXR",
         "sourceAmountRequired":"0.0069518",
         "sourceAmountReceived":"0.0069518",
         "sourceBlockchain":"Ethereum",
         "sourceBlockchainAssetCode":"ETH",
         "depositAddress": "0xA2Bf179E09C503262E418FC72261837726f68F36",
         "blockchainTransactions":[
            {
               "type":"ORIGIN",
               "typeDescription":"Blockchain payment transaction initiated by customer.",
               "blockchain":"Ethereum",
               "blockchainAssetCode":"ETH",
               "tx":"0x02f45bce7e17acca417591018322bbf3721a1849cee2bbc9dfdcb526b2ba4a4f",
               "amount":"0.0069518",
               "amountAssetCode":"ETH",
               "exception":null
            },
            {
               "type":"TRANSFER",
               "typeDescription":"Asset issuer fund transfer from native blockchain to Stellar Network.",
               "blockchain":"Stellar Network",
               "blockchainAssetCode":"XLM",
               "tx":"1c1ba2bc2504c3081ce4bf0f51ec1792e919aded6fc178b112ac4393e7f2ab6a",
               "amount":"0.0069518",
               "amountAssetCode":"ETH",
               "exception":null
            },
            {
               "type":"SETTLEMENT",
               "typeDescription":"Stellar transaction crediting your COINQVEST merchant account.",
               "blockchain":"Stellar Network",
               "blockchainAssetCode":"XLM",
               "tx":"63dab32ba979e41e43a718aaf51c61cadf6dec944715d9fd04f1f61d9ee8800f",
               "amount":"10.000000",
               "amountAssetCode":"USDC",
               "exception":null
            }
         ],
         "payload":{
            "charge":{
               "lineItems":[
                  {
                     "description":"T-Shirt",
                     "quantity":"1",
                     "netAmount":"10",
                     "productId":"yellow"
                  }
               ],
               "currency":"USD:GDUKMGUGDZQK6YHYA5Z6AY2G4XDSZPSZ3SW5UN3ARVMO6QSRDWP5YLEX",
               "customerId":"a2df67b61725"
            },
            "settlementCurrency":"USD:GDUKMGUGDZQK6YHYA5Z6AY2G4XDSZPSZ3SW5UN3ARVMO6QSRDWP5YLEX"
         }
      }
   }
}

Rather than waiting on the customer to be redirected back from the hosted checkout page, use the webhook for notification. The customer could close the browser window or quit the app before the callback executes. We also notify you via email about completed payments.

Alternatively, you can also choose to poll the GET /checkout endpoint to query payment state updates. However, using this method is probably more complex than simply waiting for WEBHOOK checkout-completed events server side.

$response = $client->get('/checkout', array('id' => $checkoutId));

if ($response->httpStatusCode == 200) {   
    $state = json_decode($response->responseBody, true)['checkout']['state'];
    if ($state == 'COMPLETED') {
        // you can now ship your items...
        echo "The payment has completed and your account was credited."
    } else {
        // try again in 30 seconds or so...
    }
}

Query your Wallets

Completed payments are credited to your crypto- or fiat currency wallets on COINQVEST. You decide which currency you'd like to receive by setting the settlementCurrency attribute in the checkout request. It can be any crypto- or fiat currency supported by our platform. If you don't specify your settlement currency you are credited in the asset your customer paid with.

You can query all your wallets using GET /wallets or a specific currency like this:

$response = $client->get('/wallet', array('assetCode' => 'USD'));

Withdraw Funds

Once a payment has completed, it is instantly available in your wallet and the funds can be withdrawn to your bank account or any supported blockchain. For example, you can settle in Bitcoin but withdraw to your NGN bank account or to the Stellar Network instead. Use the POST /withdrawal endpoint to initiate a payout.

Withdraw USDC to your Bitcoin Account:

$response = $client->post('/withdrawal', array(
    // withdraw from your USDC wallet
    'sourceAsset' => 'USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN', 
    'sourceAmount' => '100',
    'targetNetwork' => 'BTC', // send to a BTC address
    'targetAccount' => array(
        'address' => 'bc1qj633nx575jm28smgcp3mx6n3gh0zg6ndr0ew23'
    )
));

Withdraw USDC to your Stellar Account:

$response = $client->post('/withdrawal', array(
    // withdraw from your USDC wallet
    'sourceAsset' => 'USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN', 
    'sourceAmount' => '100',
    'targetNetwork' => 'XLM', // send to a Stellar account
    'targetAsset' => 'USD:GDUKMGUGDZQK6YHYA5Z6AY2G4XDSZPSZ3SW5UN3ARVMO6QSRDWP5YLEX'
    'targetAccount' => array(
        'account' => 'GDONUHZKLSYLDOZWR2TDW25GFXOBWCCKTPK34DLUVSOMFHLGURX6FNU6',
        'memo' => 'Exodus',
        'memoType' => 'text'
    )
));

With above request you can withdraw funds to any arbitrary asset on the Stellar Network directly, as long as a market exists on the Stellar Decentralized Exchange and the target account has a trustline for the target asset you are trying to send. Otherwise the withdrawal gracefully fails and provides additional error information.

Housekeeping

Update a customer (PUT /customer):

$response = $client->post('/customer', array('customer' => array(
    'id' => 'fd4f47a50c7f',
    'email' => 'new@email-address.com'
)));

Delete a customer (DELETE /customer):

$response = $client->delete('/customer', array('customer' => array(
    'id' => 'fd4f47a50c7f'
)));

List your 250 newest checkouts (GET /checkouts):

$response = $client->get('/checkouts', array('limit' => 250));

List your 250 newest customers (GET /customers):

$response = $client->get('/customers', array('limit' => 250));

List all available assets (GET /blockchains):

$response = $client->get('/assets');

List all available networks (GET /fiat-currencies):

$response = $client->get('/networks');

Feedback

Please let us know anytime if there are questions or if there is anything else that we can assist you with. We're available via email and you can chat with us directly in our public Keybase channel coinqvest.public.

guidemerchant api
Marcin Olszowy
Marcin Olszowy Co-Founder
Space Cat
Space Cat! Meow. 🐱🚀