文档章节

java后台实现支付宝支付接口、支付宝订单查询接口 前端为APP

 陈刚生
发布于 09/16 21:48
字数 4185
阅读 40
收藏 14

区块链几乎是数日间成为人尽皆知的名词,这个名词也勾起了我强烈的兴趣,但是通过在网上搜罗资料,多方阅读,发现很多介绍区块链的文献要么模棱两可,要么作者本身的理解也很有限,导致很多关键的问题叙述不清。本人花了一些时间总结归纳,希望可以给读者一个比较全面清晰的认识。

区块链的官方定义是:一个分布式账本,一种通过去中心化、去信任的方式集体维护一个可靠数据库的技术方案。那么对于圈外人该如何理解呢?以下我会详细描述一个区块链的产生过程和实现意义,从而给大家构建出一个清晰的区块链概念。我们先讲原理、再说特点、然后论用途、最后回归代码,这样你就会有一种恍然大悟的感觉。

我们以btc为例:“区块链”,顾名思义,就是由一个个区块依次连接起来组成的链条,可以类比为一条无限长度的直线铁链,每个铁环就是一个区块。那么区块的内容应该是什么呢?区块狭义上是有两种的,一个是普通区块,一个就是创世区块。创世区块就是一项区块链项目中的第一个区块,由于个人水平有限,对创世区块没有做过详细研究,但是根据我的了解,创世区块应该是具备与普通区块相似结构的,但会肯定会加入一些创始人想说的东西,并且在有些项目中可能会多一条记录,就是coin的发行量,例如swtc的6000亿数目就是写在创世区块之中的,一旦发行,无法修改。

那么,一个普通区块中到底有什么?

1.index:就是从0-n依次产生的数字,可以称之为链高度。

2.hash:一个长度为256位随机数,是这个区块的唯一编号。

3.previous hash:上一个区块的hash,一个普通区块有且仅有一个previous hash,这就是区块链之所以称为链的原因,就是这么一环套一环链接而成的。

4.tempstamp:用于记录该区块诞生的时间。

5.difficulty:直观体现创造该区块的难度。

6.nonce:随机数,用于产生下一个区块。

上述的都存在区块头中。

7.data:存储的交易记录。只有这个存在区块体中。

Ok,上述提到了一个区块需要具备的最基本的几条要素,可能你现在还处于一脸懵逼的状态:这些东西到底是怎么工作的呢?下面我将一步步分析区块链的工作过程,不过,这里要先问两个问题:为什么要产生新的区块?怎么产生新的区块?

为什么产生新区快?

之前说了,一个区块记录的就是一份账单,账单中存储着若干条交易记录,是买卖双方具体活动的最有力的证明,例如我们在淘宝上的购买记录,就是我们的消费账单。人们每天的消费记录是不断增长的,不可能永远放在一个区块里,那么跟现在的中心化存储机制还有什么区别?所以,随着买卖记录的不断增加,就需要不断产生新的区块来存储这些数据。

http://rc.haian.gov.cn/company/company-show.php?id=1588232
http://rc.haian.gov.cn/company/company-show.php?id=1588233
http://rc.haian.gov.cn/company/company-show.php?id=1588234
http://rc.haian.gov.cn/company/company-show.php?id=1588235
http://rc.haian.gov.cn/company/company-show.php?id=1588236

怎么产生新的区块?

我相信,最近除了区块链这个名词如雷贯耳以外,“挖矿”应该也没少听吧。挖矿实际上就是由那些矿工来生成新的区块的过程。在btc项目中,btc矿工挖矿成功(其实就是成功的创建了一个区块)就可以获得一定数量的被btc奖励,所以btc数量是在一定范围内慢慢增加的。在一般允许挖矿的区块链项目(也存在限制coin数量不允许挖矿的区块链项目)中,矿工的数量一般会大于6个,一般超过6个矿工认可的新区块就可以加入到区块链中。到此为止,有人会说:哇!btc这么值钱,挖矿不是很爽?其实不然,如果区块无限制的快速增加,会引起很大的问题,根据中本聪的设定,目前全网每10分钟只能产生一个新区块。而且这10分钟不是靠自己掐表算的,生成新的区块是需要大量的运算的,这10分钟是人家预先设计好的,让计算量大到全网10分钟一般只能产生一个。

好了,至此,区块链的基本概念已经介绍的差不多了,下面言归正传,讲下区块的工作流程:

1.如果A要和B达成一笔交易,比如A转给B一个btc,B给A打10w的RMB。A首先将自己的btc来源信息、交易人等发送给B,同时还要拷贝一份发到全网。什么?这样还有隐私可言吗?当然,聪明的中本聪当然不会犯这么低级的错误。在区块链中,每个交易个体(也可以理解为每个网络节点)都会有一对公钥和私钥,公钥相当于一个“收款地址”,而私钥是一个表明自己身份的256位的数字,目前一般是用sha265来生成的,这样,别人并不知道交易的双方是谁。发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私钥对摘要进行加密,加密后的摘要将作为报文的数字签名和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用发送方的公钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该数字签名是发送方的。

2.那么此时,这笔交易是否就完成了呢?如果这就算完成了,那跟A直接用包裹装10w现金快递给B有什么区别呢?此时,全网的矿工都会得到这个交易记录,那么全网的矿工都会为了若干奖励开始创建区块的工作,矿工会利用hash函数生成一个256位的唯一编号赋予这个区块,但是这个编号并不是简简单单随便生成的。编号是根据区块的具体内容如交易内容、nonce等唯一确定的,换句话说,两块内容相同的区块所对应的编号一定是唯一的。可是你会问:这又怎么了?并不难啊。错!中本聪为了控制区块的生成时间,使区块的生成速率满足全网的每10分钟一个的标准,制定了严格的区块生成校验规则,也就是说,能不能生成一个成功的区块要看你的编号是否符合这个规则。例如:生成编号中的前n位必须为‘0’。

由于区块的交易内容是无法修改的,因此矿工们只能通过修改nonce去不断尝试这个函数,直到生成了一个成功的区块为止。如果当区块平均生成时间变快或者变慢,那么系统会对区块校验规则进行相应的调整,从而使平均的生成时间能够控制在规定范围。

如果一个矿工完成了一个区块,会立刻告知其他矿工,如果其他矿工此时没有完成新的区块生成,则会停下手头的工作,对区块进行验证,需要确认的信息主要有如下几点:

1).区块的编号有效;这个只要将区块放入哈希函数中,看产生的编号是否和该区块中的编号一致即可。

2).区块的前一个区块有效;之前提过,区块是一个串联的,每一个普通区块都会记载前一个区块的编号,这需要其他矿工对比当前的区块链的最后一个区块,看是否相同。

3).交易清单有效;就是说要验证A到底有没有这一个btc可以给B。在区块链的交易信息中,会记录交易中所有btc的前世今生,区块链可以做到追本溯源,因此每一个btc在哪里,为什么在这里都可以一目了然,所以这点也没问题。

当验证完一个全新的区块后,全网就会认为这个区块有效,会将它添加到现有的区块链末端,同时结束针对该区块的挖矿工作,投入到下一个挖矿周期中。

3.但是不难想象,这样的机制是存在冲突的隐患的,就是这么巧,两个矿工同时制作了一个正确的区块,那么此时不必二选一,可以将原来线性的区块链改成树状:

但是这样会导致未来在A、B后都会增加相应的区块,那么谁长谁将作为主链延伸下去,另一个也许会渐渐被遗忘,除非哪天它变得更长。

好啦,这就是区块链最基本的知识,接下来应该谈谈优缺点了。

世界上没有一样东西可以称为完美无瑕的,要知道区块链一样,虽然它被扣上了可以颠覆未来的帽子,但是仍然存在它的局限性:1.时效性。很容易发现,区块链中存在很多的验证、传递环节,这就会导致其时效性较差。2、能耗,这点也是显而易见的,区块链需要大量无用计算来控制区块的生成时间。所以区块链不适用于高时效的网络中。

至于区块链的优点,诸如安全、去中心化等等在网络上已经描述的非常清楚,这里就不再赘述。接下来我用一段python代码来简单实现一个挖矿的流程。

 

代码示例

首先创建一个表示区块链的类:

 

class BlockChain:
    def __init__(self, initialHash):
        # init block chain
        self.chain = []

        # init pitman
        self.pitmen = []
        for i in range(6):
            self.pitmen.append(Pitman)

        # collect mine results
        self.results = []

        # generate GenesisBlock
        self.new_block(initialHash)

初始化函数中的chain表示当前的区块链,我会在其中存储区块对象;pitmen表示为这个区块链服务的矿工们,这个列表中也会存有矿工对象;results则会存储每个阶段产生的区块;new_block方法是创建区块的方法,如果当前生成的区块为第一个区块,则产生创世区块。

下面看看区块链类型的方法:

 

@property
def last_block(self):
    if len(self.chain):
        return self.chain[-1]
    else:
        return None

last_block会返回当前区块链的最后一个区块对象。

 

def get_trans(self):
    return json.dumps({
        'sender': ''.join(random.sample(string.ascii_letters + string.digits, 8)),
        'recipient': ''.join(random.sample(string.ascii_letters + string.digits, 8)),
        'amount': random.randrange(1, 10000)
    })

get_trans方法则用来随机生成一份交易信息。

 

def new_block(self, initialHash=None):
    if initialHash:
        # generate Genesis Block
        block = Block()
        block.index = 0
        block.nonce = random.randrange(0, 99999)
        block.previousHash = '0'
        block.difficulty = 0
        block.transactionData = self.get_trans()
        guess = f'{block.previousHash}{block.nonce}{block.transactionData}'.encode()
        block.hash = hashlib.sha256(guess).hexdigest()
        block.time = time()
        self.chain.append(block)
    else:
        for i in range(len(self.pitmen)):
            pm = MyThread(target=self.pitmen[i].mine,
                                  args=(self.pitmen[i],
                                        len(self.chain),
                                        self.last_block.get_block()['Hash'],
                                        self.get_trans()))
            pm.start()
            pm.join()
            self.results.append(pm.get_result())

        # show all blocks
        print("All blocks generated by pitmen:")
        for result in self.results:
            print(result[0].get_block())

        # get new block
        firstblock = self.results[0][0]
        mintime = Decimal(self.results[0][1])
        for i in range(1, len(self.results)):
            if Decimal(self.results[i][1]) < mintime:
                firstblock = self.results[i][0]
            else:
                continue
        self.chain.append(firstblock)
        self.results = []

这是生成区块的核心部分,这个方法主要分成两个部分:根据传参区分是否是创世区块,如果需要的是创世区块,那就由该类型自动生成一个区块占据区块链的头一个位置。如果需要生成的是普通区块,那么则会将一些基本信息分发给矿工们进行挖矿操作。我在这里设置了6个矿工,为了公平起见,这里也开了个多线程尽量让矿工们同时收到消息从而可以同时进行挖矿操作。按理说,最先挖矿成功的矿工会将消息发给其他矿工,其他矿工会立刻停止进行校验,但由于时间有限,这一步校验环节我没有实现。在这里,我允许所有矿工都完成工作,并提交成果和相应的工作时间,生成耗时最短的区块讲作为正确的区块添加到区块链上。本质上也是依照了“快者优先”的区块链生成原则。

说了半天,区块内部到底是什么样的呢?

 

class Block:
    def __init__(self):
        self.index = None
        self.time = None
        self.difficulty = None
        self.nonce = None
        self.hash = None
        self.previousHash = None
        self.transactionData = None

    def get_block(self):
        return {
            'Index': self.index,
            'Time': self.time,
            'Difficulty': self.difficulty,
            'Hash': self.hash,
            'Nonce': self.nonce,
            'PreviousHash': self.previousHash,
            'TransactionData': self.transactionData
        }

我用了一个相对简单的类型表示区块,在这里区块就是一个非常简单的数据结构,这里的所有字段在上述中已经有了详细的说明,因此不再赘述。

那么我们再看看矿工,毕竟矿工才是区块链的生产者和推动者,地位最为核心。矿工类中我设计了两个方法,一个mine方法,也就是挖矿的意思,用来生成新的区块,并会返回该区块生成的用时长短。

 

def mine(self, index, previousHash, transactionData):
    beginTime = time()

    block = Block()
    block.index = index
    block.previousHash = previousHash
    block.transactionData = transactionData
    block.difficulty, block.hash, block.nonce = self.generate_hash(previousHash, transactionData)
    block.time = time()
    endTime = time()

    return block, endTime - beginTime

另一个方法是hash生成的方法,生成原则我自己意淫了一个,大家莫怪,因为本人计算机的实在不给力,区块的成功标准很简单,就是用sha256生成的编码最后结尾是0就满足要求,如果改成00,那会半天看不到结果。

下面我们看下这套实例的运行结果,我设置了一个长度为6的区块链,由于第一个区块是创世区块,所以真正开始创建的区块是从第二个开始的,大家注意index。

这是6个矿工完成的第一区块:

All blocks generated by pitmen:
{'Index': 1, 'Time': 1516268156.5971138, 'Difficulty': 2, 'Hash': '01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30', 'Nonce': 91554, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "OY8z0Rrx", "recipient": "iSGFJsEm", "amount": 8723}'}
{'Index': 1, 'Time': 1516268156.5971138, 'Difficulty': 5, 'Hash': 'c3ba406bad0d87f816f629830a15e2997638bfa230484c224e5470eaa24d8790', 'Nonce': 62372, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "9o8UMDLe", "recipient": "qTOQu7kv", "amount": 2746}'}
{'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 5, 'Hash': '8ff243885e9017296aa2ef1a611ef5b3927ddce818cb7255a04ff3228c982c60', 'Nonce': 67644, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "kIqy1c8C", "recipient": "WSdK0EXh", "amount": 9329}'}
{'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 3, 'Hash': 'ff9716bf9379e2ab7a8640419e7c7b7c7329a5e6e1bbf83a1249f49d070ca8b0', 'Nonce': 37336, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "vBwU0luH", "recipient": "d7o6cRCj", "amount": 5628}'}
{'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 3, 'Hash': '3410c70c31f9bacbfcbd74d63f25f69f27d36075e2d44bddaa60bd72fa042e60', 'Nonce': 34617, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "yzcNpBnh", "recipient": "vbIr7SKo", "amount": 6387}'}
{'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 27, 'Hash': '91e3dc3ef1a151557a1edd837528410b916362bcfb77dbb14dc54c8929f5a0d0', 'Nonce': 49121, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "p1MguhVz", "recipient": "gVSom4D3", "amount": 7356}'}

很明显前两个是最快的,为了简单,我在最快的里面随便选取一个,意思到了就行。大家可以看到,难度值,根据上文所说,这是反应一个区块生成的难易程度的,难度高的,在我这里会表示这个矿工为了得到这个区块进行了多少次尝试。看到这里也许你会问:为什么难度最大的时间并没有明显长呢?也就是用时并没有按照难度的增加而增加。我猜想应该是因为我的示例算法简单,因此结果也不是十分精确,如果计算量达到一定的规模,应该会有明显的差距。(如果有高人知道,可以回复我,在此谢过!)第三到第六个的区块创建结果格式是与之一样的,就不刷屏了。

© 著作权归作者所有

共有 人打赏支持
粉丝 3
博文 23
码字总数 33581
作品 0
私信 提问
加载中

评论(1)

昵称已被使用
这和支付宝有啥关系~
Android 微信支付开发流程

首先奉上调起支付页面截图 一:介绍 项目中要用到支付功能,需要支付宝支付、微信支付、银联支付,所以打算总结一下,方便以后的查阅,也方便大家, 用到的地方避免再次被坑。 今天我们就主要...

展菲
2017/11/10
0
0
JAVA支付宝APP支付接口整合总结

对于现在日新月异的信息化社会,我们的日常生活也有了翻天覆地的变化;最最有力的证明就是我们的支付方式;不管我们身处那个城市,只要我们有一部手机,就可以轻松的进行各种支付,根本不用担心自己...

ge洋
2017/11/07
0
0
轻量级支付整合轻松嵌入任何系统 - pay-java-parent

轻量级支付模块集成(微信支付,友店扫码,支付宝,富友,银联, payoneer皮卡 )支付整合,app,扫码,即时到帐刷卡付条码付、支持多种支付类型多支付账户,支付与业务完全剥离,简单几行代码即可实...

egzosn
2017/02/17
0
8
支付宝支付之扫码支付(电脑网站支付)、H5支付(手机网站支付)相关业务流程分析总结

前言 在上一篇文章《微信支付之扫码支付、公众号支付、H5支付、小程序支付相关业务流程分析总结》中,分析和总结了微信支付相关支付类型的业务流程,这里作为与微信支付平起平坐不相伯仲的支...

龙行天涯
08/22
0
0
Android 银联控件支付开发流程

一:介绍 项目中要用到支付功能,需要支付宝支付、微信支付、银联支付,所以打算总结一下,方便以后的查阅,也方便大家, 用到的地方避免再次被坑。 今天我们就主要介绍一下银联控件支付,其...

展菲
2017/11/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Ubuntu常用操作

查看端口号 netstat -anp |grep 端口号 查看已使用端口情况 netstat -nultp(此处不用加端口号) netstat -anp |grep 82查看82端口的使用情况 查找被占用的端口: netstat -tln netstat -tl...

hc321
昨天
0
0
网站cdn的静态资源突然访问变的缓慢,问题排查流程

1.首先我查看了一下是否自己的网络问题,通过对比其他资源的访问速度和下载速度,确认不是 2.通过ping 和 tracert 判断cdn域名能否正常访问,(最后回想感觉这一步可以省略,因为每次最终能访...

小海bug
昨天
0
0
Mybatis 学习笔记四 MyBatis-Plus插件

Mybatis 学习笔记四 MyBatis-Plus插件 maven依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <ve......

晨猫
昨天
2
0
小白带你认识netty(二)之netty服务端启动(下)

承接上一篇小白带你认识netty(二)之netty服务端启动(上),还剩下两步骤:3、注册Selector:将Channel注册到Selector上 和 4、端口的绑定:服务端端口的监听。 3、注册Selector:将Chann...

天空小小
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部