Skip to main content

Payments App System Design

This doc should serve as the starting point of the system design for the Solana Payment App.

Note: Given we are in the very early stages of development, this should change over time with the build out.

Components

  • Backend - Orcastration logic that connects merchants to consumers who want to complete a payment over the Solana network and handles the communication with Shopify as a side effect of the actions taken
  • Mertchant UI - General merchant managment portal
  • Payment UI - UI for completing a payment on Solana, lightly coupled to the Solana Payments Appp
  • Transaction Request Server - Generalized transaction building engine for payments

Main Flows

  • Payment Flow
  • Refund Flow
  • Auth Flow

Payment Flow

The Payment Flow is broken up into three phases.

Phase One - Shopify notifies the payment's app backend of a payment that needs to be made. We will respond with a url that the customer can checkout from.

Phase Two - The customer requests a payment transaction from the backend.

Phase Three - We discover a completed transaction, notify Shopify it's been completed, and send the customer back to Shopify.

Refund Flow

The Refund Flow is broken up into three phases.

Phase One - The merchant initates a refund for a customer. Shopify notifies us of the refund that needs to be proccessed.

Phase Two - The merchant starts the process of completing a pending refund on our merchant-ui.

Phase Three - We discover a completed transaction. Figure out what refund it's for and notify Shopify it's been completed.

Auth Flow

Database Schema

Merchant

nametypenotes
idIntAutogenerated ID
nameStringDisplay Name
shopStringShopify Merhcant Id
accessTokenStringShopify Access Token
scopesStringMost Recent Shopify Scopes
lastNonceStringMost Recent Auth Nonce
paymentAddressStringDestination for funds
paymentAddressStringUSDC destination for funds
acceptedTermsAndConditionsStringflag for terms and conditions
dismissCompletedStringflag for dismissing completed message

PaymentRecord

nametypenotes
statusStringtracks the progress of a payment
merchantIdStringlinks the merchant to the payment
amountNumberhow much fiat the payment was for in the currency specified
currencyStringcurrency that the amount specifies
usdcAmountNumberamount and currency converted to USDC price
shopIdString'id' value passed to us from shopify
shopGidString'gid' value passed to us from shopify
shopGroupString'group' value passed to us from shopify
testBoolpayment is just for merchant testing
idStringinternal unique id
cancelURLStringlocation to send the customer if they cancel
redirectURLStringsuccess URL to send a customer to when they pay
transactionSignatureString?links the payment to the transaction that paid it

RefundRecord

nametypenotes
statusStringtracks the progress of a refund
merchantIdStringlinks the merchant to the refund
amountStringhow much fiat the refund was for in the currency specified
currencyStringcurrency that the amount specifies
usdcAmountNumberamount and currency converted to USDC price
shopIdString'id' value passed to us from shopify
shopGidString'gid' value passed to us from shopify
shopPaymentIdString'payment_id' value passed to us from shopify
testBoolrefund is just for merchant testing
idStringinternal unique id
transactionSignatureString?links the refund to the transaction that paid it

TransactionRecord

nametypenotes
signatureStringtransaction Signature
typeString'payment' or 'refund'
createdAtStringtimestamp the transaction was built and signed
paymentRecordIdString?links the transaction to the payment
refundRecordIdString?links the transaction to the refund

Novel Concepts We Use

Single Use Accounts

A Single Use Account is an account with 0 data that we add on to transactions. They serve as a solution to a few problems we face when building on chain payment that integrate with web2 commerce platforms. You can view the instruction that handles this here.

Indexing Refrence Keys

We add refrence keys onto transactions for look ups later. Small data < 32 bytes can be made into a public key that only serves as a way to look up the transaction later. We can create keys for things like merchants, payments, and refunds. This will serve as a way to determinstically find transactions if we run into database issues. You can view the instruction that handles this here.