Sure! Here's a translation of the guide on how to integrate imsafu using Go:

How to Integrate imsafu with Go

imsafu is a payment processing service that allows you to create and query payments. This document will guide you through accessing the imsafu service.

Prerequisites

Before you begin, make sure you have the following prerequisites:

  1. Go programming language installed on your computer.
  2. Go development environment set up.

Install Dependencies

Accessing the imsafu service doesn't require specific dependencies. Here are some default libraries provided, and you can choose the appropriate ones as needed.

Run the following command to install the dependencies:

go get github.com/go-resty/resty/v2
go get github.com/go-playground/validator/v10

Import Required Modules

In your Go file, import the required modules. Add the following import statements at the top of your file:

import (
	"fmt"
	"net/http"
	"encoding/json"
	"github.com/go-resty/resty/v2"
	"github.com/go-playground/validator/v10"
)

Create Required imsafu Variables

To connect to the imsafu test server, you can use the following variables. If you want to connect to the production server, join the waitlist to obtain the relevant information.

type Options struct {
	URL                 string `validate:"required"`
	API                 string `validate:"required"`
	APISecret           string `validate:"required"`
	Receiver            string `validate:"required"`
	MerchantBrand       string `validate:"required"`
	MerchantRedirectURL string `validate:"required"`
}

func main() {
	options := Options{
		URL:                 "https://devnet.imsafu.com",
		API:                 "https://allowpay-api-devnet.fly.dev/v1",
		APISecret:           "your-api-secret",
		Receiver:            "your-wallet-account",
		MerchantBrand:       "imsafu demo",
		MerchantRedirectURL: "https://merchant.com/redirect",
	}
}

Create a New Payment

First, we need to generate a 32-character hexadecimal string as the ID for a new order.

func createOrderID() string {
	str := uuid.Must(uuid.NewRandom()).String()
	return fmt.Sprintf("0x%s", strings.Join([]string{strings.Repeat("0", 32-len(str)), str}, ""))
}

To create a new payment, we need to implement a createPayment method. This method takes the payment amount as a parameter and returns a structure parsed as a PaymentResponse object.

type Payment struct {
	OrderID        string `json:"orderID"`
	Receiver       string `json:"receiver"`
	Amount         string `json:"amount"`
}

type PaymentResponse struct {
	Status         string `json:"status"`
	Payment        Payment `json:"payment"`
}

func createPayment(amount int64, options Options) (*PaymentResponse, error) {
	orderID := createOrderID()
	paymentResponse := &PaymentResponse{}

	payload := struct {
		Payment   Payment `json:"payment"`
		NotifyURL string  `json:"notifyURL"`
	}{
		Payment: Payment{
			OrderID:  orderID,
			Receiver: options.Receiver,
			Amount:   strconv.FormatInt(amount, 10),
		},
		NotifyURL: options.URL + "/notify",
	}

	client := resty.New()
	resp, err := client.R().
		SetHeader("Content-Type", "application/json").
		SetHeader("Authorization", "Bearer " + options.APISecret).
		SetBody(payload).
		SetResult(&paymentResponse).
		Post(options.API + "/depositPay")

	if err != nil {
		return nil, err
	}

	return &paymentResponse, nil
}

Generate Payment URL

Next, write a method to generate the payment URL:

func buildPaymentURL(itemMemo string, paymentResponse *PaymentResponse, options Options) string {
	paymentURL := fmt.Sprintf("%s/payment_qrcode", options.URL)
	url := fmt.Sprintf("%s?payID=%s&brand=%s&memo=%s&redirect_url=%s&currency=USD",
		paymentURL, paymentResponse.Payment.OrderID, options.MerchantBrand, itemMemo, options.MerchantRedirectURL)
	return url
}
amount := int64(100)
paymentResponse, err := createPayment(amount, options)
if err != nil {
    // Handle error
}

paymentURL := buildPaymentURL("test item", paymentResponse, options)

User Payment

Display the generated paymentURL to the user, who can click on it to open the payment interface in a web page. For the specific payment process, you can refer to the Using imsafu for Payments guide.

Retrieve Payment Information

After the user completes the payment, imsafu will send a POST request to the notifyURL provided during the order creation, containing the payID. We need to retrieve the payment information through the getPayment API and confirm if the user's payment was successful.

To retrieve payment information, we need to implement the getPayment method. This method takes the payment ID (payID) as a parameter and returns a structure parsed as a PaymentResponse object.

func getPayment(payID string, options Options) (*PaymentResponse, error) {
	client := resty.New()
	paymentResponse := &PaymentResponse{}
	resp, err := client.R().
		SetResult(&paymentResponse).
		Get(options.API + "/depositPays/" + payID)

	if err != nil {
		return nil, err
	}
	return &paymentResponse, nil
}
// Get payID from the notify request
paymentResponse, err := getPayment(payID, options)
if err != nil {
    // Handle error
}

// Perform other operations

Appendix: Type Definitions Used in the Code

type Payment struct {
	PayID           string `json:"payID"`
	OrderID         string `json:"orderID"`
	Receiver        string `json:"receiver"`
	Amount          string `json:"amount"`
	OriginalAmount  string `json:"originalAmount"`
	MaxFeeAmount    string `json:"maxFeeAmount"`
	Deadline        string `json:"deadline"`
}

type Chain struct {
	ID     int    `json:"id"`
	Symbol string `json:"symbol"`
	Name   string `json:"name"`
}

type Token struct {
	Symbol  string `json:"symbol"`
	Address string `json:"address"`
}

type ReceiveTx struct {
	Chain         Chain  `json:"chain"`
	TxID          string `json:"txID"`
	ConfirmedAt   string `json:"confirmedAt"`
	Amount        string `json:"amount"`
	FeeAmount     string `json:"feeAmount"`
	Token         Token

  `json:"token"`
}

type Deposit struct {
	ChainID int    `json:"chainID"`
	Token   string `json:"token"`
}

type PaymentResponse struct {
	Status         string       `json:"status"`
	Payment        Payment      `json:"payment"`
	Owner          string       `json:"owner"`
	DepositAddress string       `json:"depositAddress"`
	CallID         int          `json:"callID"`
	ReceiveTx      *ReceiveTx   `json:"receiveTx,omitempty"`
	Deposits       []Deposit    `json:"deposits,omitempty"`
}

Please note that the above code is provided as an example and may need to be modified and adapted according to your specific requirements.

Last Updated:
Contributors: xavierdiff