如何使用 Go 接入 imsafu

imsafu 是一个支付处理服务,允许您创建和查询支付。本文档将引导您完成访问 imsafu 服务。

准备

在开始之前,请确保满足以下先决条件:

  1. 在您的计算机上安装了 Go 编程语言。
  2. 配置了 Go 的开发环境。

安装依赖项

imsafu 服务的访问并不需要特定的依赖项,这里提供了一些默认的依赖库,您可以根据需要选择相应的库。

运行以下命令来安装依赖库:

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

导入所需模块

在您的 Go 文件中,导入所需的模块。添加以下导入语句到文件顶部:

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

创建 imsafu 所需变量

连接到 imsafu 测试服务器,您可以使用以下变量。如果您想连接到正式服务器,请加入等待列表以获取相关信息。

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",
	}
}

创建新的支付

首先,我们需要生成一个 32 位的十六进制字符串作为新订单的 ID。

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

要创建新的支付,我们需要实现一个 createPayment 方法。此方法接受支付金额作为参数,并返回一个解析为 PaymentResponse 对象的结构。

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
}

生成支付链接

首先编写一个方法来生成支付链接:

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 {
    // 处理错误
}

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

用户支付

向用户展示生成的 paymentURL,用户点击后可以在网页中打开支付界面。具体支付流程可以参考 使用 imsafu 支付

检索支付信息

在用户完成支付后,imsafu 将通过向创建订单时传入的 notifyURL 发送包含 payIDPOST 请求。我们需要通过 getPayment 接口检索支付信息,并确认用户的支付是否成功。

要检索支付信息,我们需要实现 getPayment 方法。此方法接受支付ID(payID)作为参数,并返回解析为 PaymentResponse 对象的结构。

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
}
// 从 notify 请求中获取 payID
paymentResponse, err := getPayment(payID, options)
if err != nil {
    // 处理错误
}

// 进行其他操作

附录:在代码中使用的类型定义

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"`
}

请注意,上述代码仅为示例,可能需要根据您的具体情况进行修改和适应。

Last Updated:
Contributors: xavierdiff