Powered by Coinflow
Payments · Documentation
Operational

One-Time Purchase Integration - Solana Contract Settlement

This page is for advanced / cryptocurrency-native companies. If that’s not you, head back to the Quickstart for the standard flows.

This guide walks you through integrating Coinflow checkout to accept one-time credit card purchases with USDC settlement to your whitelisted Solana program.

Prerequisites

Complete these steps before starting the integration.

Create your sandbox account

Register or login to your sandbox merchant account

Generate API keys

Create a sandbox API key for authentication

Add chargeback protection

Add the protection script to every page of your app

Whitelist your Solana program

Whitelist your program to receive USDC settlement

Quick Reference

Authorization Headers

Header Description
Authorization Your API key from the merchant dashboard
x-coinflow-auth-wallet User’s Solana wallet address
x-coinflow-auth-blockchain Use solana for Solana contract settlement
x-coinflow-auth-session-key JWT token authorizing the payer

Helpful Resources


Choose Your Implementation

Best for simple integrations. Generate a hosted checkout URL to redirect users or embed in an iframe.

curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/link \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-blockchain: solana' \
     --header 'x-coinflow-auth-wallet: USER_WALLET_ADDRESS' \
     --data '{
       "webhookInfo": {
         "depositId": "123-abc-456"
       },
       "subtotal": {
         "currency": "USD",
         "cents": 500
       },
       "settlementType": "Credits",
       "email": "customer@example.com",
       "blockchain": "solana",
       "chargebackProtectionData": [{
         "productType": "inGameProduct",
         "productName": "In-Game Credits",
         "quantity": 1,
         "rawProductData": {
           "description": "Purchase credits for gameplay"
         }
       }],
       "deviceId": "123456789",
       "supportEmail": "support@yourcompany.com"
     }'
{
  "link": "https://sandbox.coinflow.cash/solana/purchase-v2/your-merchant?sessionKey=..."
}

Step 2: Create a redeem transaction

After the payer completes checkout, create a redeem transaction to settle USDC to your contract. Create a base58 encoded transaction for your whitelisted program.

curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/redeem \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-blockchain: solana' \
     --header 'x-coinflow-auth-wallet: USER_WALLET_ADDRESS' \
     --data '{
       "subtotal": {
         "currency": "USD",
         "cents": 500
       },
       "merchantId": "YOUR_MERCHANT_ID",
       "transaction": "BASE58_ENCODED_TRANSACTION",
       "chargebackProtectionData": [{
         "productType": "inGameProduct",
         "productName": "In-Game Credits",
         "quantity": 1
       }]
     }'
{
  "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEd..."
}

Step 3: Sign and send the transaction

Have the user’s wallet sign and send the transaction.

const { Connection, Keypair, VersionedTransaction } = require('@solana/web3.js');
const bs58 = require('bs58');

async function signTransaction(base58Transaction, keypair) {
  const decodedTransactionBytes = bs58.decode(base58Transaction);
  const versionedTransaction = VersionedTransaction.deserialize(decodedTransactionBytes);
  versionedTransaction.sign([keypair]);
  const serializedTransaction = versionedTransaction.serialize();
  return bs58.encode(serializedTransaction);
}
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/utils/send-coinflow-tx \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
       "merchantId": "YOUR_MERCHANT_ID",
       "signedTransaction": "SIGNED_BASE58_TRANSACTION"
     }'

React SDK

Best for React applications. Provides a pre-built checkout component.

Step 1: Install the SDK

npm install @coinflowlabs/react

Step 2: Render the checkout component

import { CoinflowPurchase, SettlementType, Currency } from '@coinflowlabs/react';
import { Connection, PublicKey } from '@solana/web3.js';

function Checkout({ wallet, connection }) {
  return (
    <CoinflowPurchase
      wallet={{
        publicKey: new PublicKey(wallet.publicKey),
        signMessage: wallet.signMessage,
        sendTransaction: wallet.sendTransaction
      }}
      connection={connection}
      blockchain="solana"
      merchantId="your-merchant-id"
      env="sandbox"
      settlementType={SettlementType.Credits}
      subtotal={{ cents: 500, currency: Currency.USD }}
      email="customer@example.com"
      webhookInfo={{
        productId: "123abc",
        item: "sword"
      }}
      chargebackProtectionData={[{
        productName: "In-Game Credits",
        productType: "inGameProduct",
        quantity: 1,
        rawProductData: {
          productID: "credits-500",
          productDescription: "500 in-game credits"
        }
      }]}
      onSuccess={(paymentId) => {
        console.log('Payment successful:', paymentId);
        // Create redeem transaction after success
      }}
    />
  );
}

Step 3: Create a redeem transaction on success

After the card payment completes, create and submit the redeem transaction.

curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/redeem \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-blockchain: solana' \
     --header 'x-coinflow-auth-wallet: USER_WALLET_ADDRESS' \
     --data '{
       "subtotal": {
         "currency": "USD",
         "cents": 500
       },
       "merchantId": "YOUR_MERCHANT_ID",
       "transaction": "BASE58_ENCODED_TRANSACTION",
       "chargebackProtectionData": [{
         "productType": "inGameProduct",
         "productName": "In-Game Credits",
         "quantity": 1
       }]
     }'
{
  "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEd..."
}

Step 4: Sign and send the transaction

async function signTransaction(base58Transaction, keypair) {
  const decodedTransactionBytes = bs58.decode(base58Transaction);
  const versionedTransaction = VersionedTransaction.deserialize(decodedTransactionBytes);
  versionedTransaction.sign([keypair]);
  const serializedTransaction = versionedTransaction.serialize();
  return bs58.encode(serializedTransaction);
}
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/utils/send-coinflow-tx \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
       "merchantId": "YOUR_MERCHANT_ID",
       "signedTransaction": "SIGNED_BASE58_TRANSACTION"
     }'

API Only

Best for custom checkout UIs. Full control over the payment flow.

Step 1: Get a session key

curl --request GET \
     --url https://api-sandbox.coinflow.cash/api/auth/session-key \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'accept: application/json' \
     --header 'x-coinflow-auth-blockchain: solana' \
     --header 'x-coinflow-auth-wallet: USER_WALLET_ADDRESS'
{
  "key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Session keys expire after 24 hours. Refresh them before expiration.

Step 2: Get pricing totals

curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/totals/YOUR_MERCHANT_ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-session-key: SESSION_KEY' \
     --data '{
       "subtotal": { "cents": 500 }
     }'
{
  "card": {
    "subtotal": { "cents": 500 },
    "creditCardFees": { "cents": 0 },
    "total": { "cents": 500 }
  }
}

Step 3: Tokenize the credit card

See PCI-compliant card tokenization for implementation details.

Step 4: Process the new card payment

curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/card/YOUR_MERCHANT_ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-session-key: SESSION_KEY' \
     --data '{
       "subtotal": { "currency": "USD", "cents": 500 },
       "webhookInfo": {
         "description": "Purchase credits"
       },
       "card": {
         "expYear": "29",
         "expMonth": "10",
         "email": "customer@example.com",
         "firstName": "John",
         "lastName": "Doe",
         "address1": "123 Main St",
         "city": "Chicago",
         "zip": "60606",
         "state": "IL",
         "country": "US",
         "cardToken": "TOKENIZED_CARD"
       },
       "settlementType": "Credits",
       "authentication3DS": {
         "colorDepth": 30,
         "screenHeight": 1000,
         "screenWidth": 2000,
         "timeZone": 5
       },
       "chargebackProtectionData": [{
         "productType": "inGameProduct",
         "productName": "In-Game Credits",
         "quantity": 1
       }]
     }'
{
  "paymentId": "bdc22a87-fb72-4f9d-a445-f26c04c8376c"
}

Step 5: Process saved card payments (returning users)

Re-tokenize the saved card with CVV first (see card tokenization docs), then:

curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/token/YOUR_MERCHANT_ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-session-key: SESSION_KEY' \
     --header 'x-device-id: 123456789' \
     --data '{
       "settlementType": "Credits",
       "subtotal": { "currency": "USD", "cents": 500 },
       "webhookInfo": {
         "description": "Purchase credits"
       },
       "authentication3DS": {
         "colorDepth": 30,
         "screenHeight": 1000,
         "screenWidth": 2000,
         "timeZone": 5
       },
       "chargebackProtectionData": [{
         "productType": "inGameProduct",
         "productName": "In-Game Credits",
         "quantity": 1
       }],
       "token": "REFRESHED_CARD_TOKEN"
     }'
{
  "paymentId": "e416a462-33a3-4e80-ab8d-ffa2de666a2b"
}

Step 6: Create a redeem transaction

curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/redeem \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-blockchain: solana' \
     --header 'x-coinflow-auth-wallet: USER_WALLET_ADDRESS' \
     --data '{
       "subtotal": { "currency": "USD", "cents": 500 },
       "merchantId": "YOUR_MERCHANT_ID",
       "transaction": "BASE58_ENCODED_TRANSACTION",
       "chargebackProtectionData": [{
         "productType": "inGameProduct",
         "productName": "In-Game Credits",
         "quantity": 1
       }]
     }'
{
  "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEd..."
}

Step 7: Sign and send the transaction

async function signTransaction(base58Transaction, keypair) {
  const decodedTransactionBytes = bs58.decode(base58Transaction);
  const versionedTransaction = VersionedTransaction.deserialize(decodedTransactionBytes);
  versionedTransaction.sign([keypair]);
  const serializedTransaction = versionedTransaction.serialize();
  return bs58.encode(serializedTransaction);
}
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/utils/send-coinflow-tx \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
       "merchantId": "YOUR_MERCHANT_ID",
       "signedTransaction": "SIGNED_BASE58_TRANSACTION"
     }'

Chargeback Protection

Add the protection script

Add the chargeback protection script to every page of your app.

Send user events

Track key user actions throughout their journey.

curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/events \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'content-type: application/json' \
     --data '{
       "eventType": "SignUp",
       "customerId": "user-123-abc",
       "country": "US",
       "username": "johndoe",
       "email": "john@example.com",
       "firstName": "John",
       "lastName": "Doe"
     }'
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/events \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'content-type: application/json' \
     --data '{
       "eventType": "SignIn",
       "customerId": "user-123-abc",
       "country": "US",
       "email": "john@example.com"
     }'

On sandbox, use the test partnerId provided by the Coinflow team when configuring the protection script.


Next Steps

Test Your Integration

Use sandbox test cards to verify your implementation

Configure Webhooks

Receive real-time payment notifications

Go Live

Create your production merchant account

API Reference

Explore the complete API documentation