如何在Android端集成区块链支付?

361 阅读4分钟

Web3区块链钱包,在未来将充当支付和登录授权的相关功能。在Web3的世界中,一个助记词生成的钱包地址就代表你的一切,你的所有Web3平台的数据都跟它绑定。那么我们如何调用别人的区块链冷钱包给你支付呢?

在Dora Fund注册一个账号

浏览器打开dorafund.com/ ,注册一个开发者账号。

截屏2025-02-25 20.07.57.png

我这里就直接登录了。

截屏2025-02-25 20.08.45.png

右上角管理你的应用。

截屏2025-02-25 20.09.44.png

可以看到我这里已有两个带有激活状态的访问密钥的应用,一个账号最多创建12个应用。

截屏2025-02-25 20.11.31.png

当然你新创建的状态会显示红色的未激活。创建应用只需要填写应用名称、应用包名,并选择一个分类即可,方便官方统计各类应用的情况。

支付统计报表

所有支付记录

截屏2025-04-06 22.42.56.png

每日支付量柱状图

截屏2025-04-06 22.44.46.png

项目支付占比

截屏2025-04-06 22.45.53.png

环比增长率

季度财报

截屏2025-04-06 22.54.15.png

季度财报(详细信息)

营业额,投资人要看,哈哈!

截屏2025-04-18 00.31.05.png

集成SDK到你的应用中

打开朵拉支付SDK项目github.com/dora4/dora-… ,可以查看Java层源代码。

Gradle依赖配置

添加以下代码到项目根目录下的settings.gradle.kts

dependencyResolutionManagement {
    repositories {
        maven { setUrl("https://jitpack.io") }
    }
}

添加以下代码到app模块的build.gradle.kts

dependencies {
    // 扩展包必须在有主框架dora的情况下使用
    implementation("com.github.dora4:dora:1.3.5")
    implementation("com.github.dora4:dora-walletconnect-support:1.81")
}

SDK要求

minSdk = 23

使用方式

在Application类的onCreate()中调用。

// 通过chainId指定支持的以太坊兼容链
val chains: Array<Modal.Model.Chain> = arrayOf(
            Web3ModalChainsPresets.ethChains["1"]!!,      // 支持Ethereum
            Web3ModalChainsPresets.ethChains["137"]!!,    // 支持Polygon
            Web3ModalChainsPresets.ethChains["42161"]!!   // 支持Arbitrum
)
DoraTrade.init(this, "App Name", "App Description", "https://yourdomain.com", chains)

在Activity中与冷钱包建立连接。

DoraTrade.connectWallet(this)

(非必须)如果只有一个Activity进行支付,可在Activity中设置冷钱包支付的监听器。如果PayListener在Application的 init()中注册,则在回调处发送消息给处理界面。

DoraTrade.setPayListener(object : DoraTrade.PayListener {
    override fun onSendTransactionToBlockchain(orderId: String, transactionHash: String) {
        // 转账消息上链,确认中
    }

    override fun onPayFailure(orderId: String, msg: String) {
        // 支付失败
    }
})

构建订单数据进行支付。

DoraTrade.pay(this,
                "填写朵拉支付的accessKey,如AyAD8J9M0R7H",
                "填写朵拉支付的32位secretKey,不要泄露给任何人,包括我们的工作人员",
                "填写订单信息,便于框架给你弹窗,以让用户知晓正在支付",
                "填写商品详细描述,便于框架给你弹窗,以让用户知晓正在支付",
                "填写收款方的钱包地址,如0xfF6FC0F28835F2C1FE23B15fb4488d976B06Dcd9",
                0.01,
                object: DoraTrade.OrderListener {
                    override fun onPrintOrder(orderId: String,
                    chain: Modal.Model.Chain,
                    value: Double) {
                        // 在此记录该笔订单的交易订单号,便于以后查询支付状态和统计订单数据
                    }
                })

查询订单支付情况。

// 查询当前选中链的交易
PayUtils.queryTransactionByHash("填写该笔订单的交易哈希")
// 查询Ethereum主网的交易
PayUtils.queryTransactionByHash("填写该笔订单的交易哈希", PayUtils.DEFAULT_RPC_ETHEREUM)
// 查询Polygon主网的交易
PayUtils.queryTransactionByHash("填写该笔订单的交易哈希", PayUtils.DEFAULT_RPC_POLYGON)
// 查询Arbitrum主网的交易
PayUtils.queryTransactionByHash("填写该笔订单的交易哈希", PayUtils.DEFAULT_RPC_ARBITRUM)

添加混淆规则。

-keep class org.json.JSONObject { *; }
-keep class dora.trade.DoraTrade { *; }
-keep class dora.trade.DoraTrade$PayListener { *; }
-keep class org.web3j.** { *; }
-keep class com.walletconnect.web3.modal.client.Web3Modal { *; }
-keep class com.walletconnect.web3.modal.client.models.request.Request { *; }
-keep class com.walletconnect.web3.modal.client.Modal$Params$Init { *; }
-keep class com.walletconnect.web3.modal.client.Modal$Model$SessionRequestResponse { *; }
-keep class com.walletconnect.web3.modal.client.Modal$Model$JsonRpcResponse$JsonRpcResult { *; }
-keep class com.walletconnect.web3.modal.client.Modal$Model$JsonRpcResponse$JsonRpcError { *; }
-keep class com.walletconnect.android.Core$Model$AppMetaData { *; }
-keep class com.walletconnect.android.CoreClient { *; }
-keep class com.walletconnect.android.relay.ConnectionType { *; }

运行Demo跑通支付流程

由于官方提供了测试应用,你可以尽情往官方的账户充值,不要把账户充爆哦!github.com/dora4/dora_… ,你clone下来componentization分支的代码,编译运行即可。

package com.example.dora.ui

import android.os.Bundle
import android.util.Log
import android.view.View
import com.alibaba.android.arouter.facade.annotation.Route
import com.example.common.ARouterPath
import com.example.dora.R
import com.example.dora.databinding.ActivityWeb3PayBinding
import com.walletconnect.web3.modal.client.Web3Modal
import dora.BaseActivity
import dora.trade.DoraTrade
import dora.trade.PayUtils
import dora.util.ToastUtils

@Route(path = ARouterPath.ACTIVITY_WEB3_PAY)
class Web3PayActivity : BaseActivity<ActivityWeb3PayBinding>() {

    private var lastTransactionHash: String = ""

    override fun getLayoutId(): Int {
        return R.layout.activity_web3_pay
    }

    override fun initData(savedInstanceState: Bundle?, binding: ActivityWeb3PayBinding) {
        // 1.在Application中初始化支付SDK
        // 2.设置钱包支付监听
        DoraTrade.setPayListener(object : DoraTrade.PayListener {

            override fun onSendTransactionToBlockchain(orderId: String, transactionHash: String) {
                lastTransactionHash = transactionHash
                runOnUiThread {
                    binding.tvTransactionHash.text = "交易哈希:$transactionHash"
                    binding.tvTransactionHash.visibility = View.VISIBLE
                    binding.btnQueryTransaction.visibility = View.VISIBLE
                }
                Log.d(TAG, "支付消息上链,确认中,订单号:$orderId,交易哈希:$transactionHash")

            }

            override fun onPayFailure(orderId: String, msg: String) {
                Log.d(TAG, "支付失败,订单号:$orderId,错误信息:$msg")
            }
        })
        // 3.连接钱包
        binding.btnConnect.setOnClickListener {
            DoraTrade.connectWallet(this)
        }
        // 4.发起支付
        binding.btnPay.setOnClickListener {
            if (Web3Modal.getAccount() == null) {
                ToastUtils.showShort("请先连接钱包")
                return@setOnClickListener
            }
            DoraTrade.pay(
                this,
                "eTAIBZuUv0xw",
                "SvuYlqClCezj9UN55PXvHnaESnt62qpJ",
                "测试订单",
                "支付0.01个代币",
                "0xcBa852Ef29a43a7542B88F60C999eD9cB66f6000",
                0.01,
                object : DoraTrade.OrderListener {
                    override fun onPrintOrder(orderId: String, chain: Modal.Model.Chain, value: Double) {
                        // 在这里保存订单号,便于钱包支付完成后得到对应的交易哈希
                        Log.i(TAG, "生成支付订单,交易订单号:$orderId")
                    }
                }
            )
        }
        // 5.查询订单支付状态
        binding.btnQueryTransaction.setOnClickListener {
            Thread {
                val ok = PayUtils.queryTransaction(lastTransactionHash)
                ToastUtils.showShort("查询上笔支付订单:${if (ok) "成功" else "失败"}")
            }.start()
        }
    }
}

可以看到官方的示例支付流程写的很清晰,我这里归纳一下。首先需要在Application类中注册你的应用信息,便于在WalletConnect中显示你的平台信息。然后可以在Activity中设置冷钱包的监听器(不推荐),也可以在Application中注册(强烈推荐)。接下来需要准备有代币的冷钱包,创建或导入助记词。开发者调用代码去连接用户的冷钱包,比如imToken(token.im) 。再往后调用pay方法,填写accessKey和secretKey构建订单数据,并保存好orderId。最后在用户点击冷钱包的确认支付按钮后,消息就会上链,这个时候你并不能保证能够收到用户支付的代币,因为他可以再发起取消交易的消息。对于这种仅退款的恶意用户来说,对商户是很不公平的。这个时候你应该把你之前保存的订单号拿出来匹配商品,确认交易哈希。通过这个交易哈希查询链上数据,确认这笔交易已完成,并被多个去中心化的节点所确认。注意请最少确认一次才可以发货,发货过程需要用户手动提取。大致的支付流程就是这样,赶紧去试试吧。