BSN区块链服务网络开发入门

开发部署nodejs服务端

小韦云科技-区块链+小程序+公众号+商城+分销+直播+企业官网+外贸电商-为您提供优质的开发服务-电话/微信联系:18123611282

由于我们业务端是使用PHP+uni-app实现,uni-app前端框架本身就是基于nodejs和vue的。本想在uni-app前端加直接安装fabric的nodejs SDK包与网络进行交互,不过安装fabric-network后还没开发直接报包里的各种报错,只好放弃。

目前的系统框架如下图

nodejs服务端处于后台PHP和智能合约之间。

我们使用参考bsn提供的示例和github.com/hyperledger/fabric-samples/fabcar/javascript案例进行开发。

服务端同时支持bsn网络和上一节部署的本地fabric测试网络

服务端的完整代码

'use strict';
//******** bsn 示例加载的包 ********//
const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');
const fs = require('fs');

const httpsClient = require('./common/httpsProvider');
const config = require('./config.json');
const ecdsa = require('./common/ecdsa');

const main = express();

//******** fabric-samples 示例加载的包 ********//
const {
    FileSystemWallet,
    Gateway
} = require('fabric-network');

//******** fabric-samples 示例初始化 ********//
var contract, gateway
async function init() {
    const ccpPath = process.env.GOPATH + '/src/github.com/hyperledger/fabric-samples/first-network/connection-org1.json'
    const walletPath = '/e/htdocs/xiaowei/BCCService-node.js/wallet';

    // Create a new file system based wallet for managing identities.
    const wallet = new FileSystemWallet(walletPath);
    console.log(`Wallet path: ${walletPath}`);

    // Check to see if we've already enrolled the user.
    const userExists = await wallet.exists('user2');
    if (!userExists) {
        console.log('An identity for the user "user2" does not exist in the wallet');
        console.log('Run the registerUser.js application before retrying');
    }
    // Create a new gateway for connecting to our peer node.
    gateway = new Gateway();
    await gateway.connect(ccpPath, {
        wallet,
        identity: 'user2',
        discovery: {
            enabled: true,
            asLocalhost: true
        }
    });
    // Get the network (channel) our contract is deployed to.
    const network = await gateway.getNetwork('mychannel');

    // Get the contract from the network.
    contract = network.getContract('clockin');
}
async function local(req, res) {
    let errorResponse = {
        code: -1,
        msg: ''
    };
    let dataObject = req.body;
    let method = dataObject.funcName;
    console.log(dataObject)
    try {
        await init();
        let result
        switch (method) {
            case "UserReg":
                console.log("用户账号注册!");
                result = await contract.submitTransaction(method, dataObject.userKey);
                break;
            case "EventReg":
                console.log("打卡挑战活动上链注册!");
                result = await contract.submitTransaction(method, dataObject.eventKey, dataObject.userKey, dataObject.PrizeMoney,
                    dataObject.PrizeCount, dataObject.JoinMoney, dataObject.Eventkeywords, dataObject.StartTime, dataObject.EndTime,
                    dataObject.IsEnd, dataObject.AdminPercent, dataObject.AnchorPercent
                );
                break;
            case "UserJoinEvent":
                console.log("用户参与活动!");
                result = await contract.submitTransaction(method, dataObject.userKey, dataObject.eventKey, dataObject.payType);
                break;
            case "UserClockIn":
                console.log("用户打卡操作!");
                result = await contract.submitTransaction(method, dataObject.userKey, dataObject.eventKey, dataObject.keyword,
                    dataObject.nowTime);
                break;
            case "CronEndEvent":
                console.log("奖金分配!");
                result = await contract.submitTransaction(method, dataObject.nowTime);
                break;
            case "GetValue":
                console.log("获取key值!");
                result = await contract.evaluateTransaction(method, dataObject.key);
                break;
            case "SetValue":
                console.log("设置或更新key值!");
                result = await contract.submitTransaction(method, dataObject.key, dataObject.value, dataObject.canUpdate);
        }

        gateway.disconnect();
        console.log("=====result====", result)
        errorResponse.msg = result.toString()
        errorResponse.code = 1
        res.send(errorResponse);

    } catch (error) {
        errorResponse.msg = error
        res.send(errorResponse);
    }

}
//main.use('/', express.static('webapp')); //不需要bsn的前端示例

//请求本地fabric测试网络
main.post('/api/local', bodyParser.json(),
    (req, res) => {
        local(req, res)
    });
//请求bsn网络
main.post('/api/work', bodyParser.json(),
    (req, res) => {
        let errorResponse = {
            code: -1,
            msg: ''
        };
        let dataObject = req.body;
        let method = dataObject.funcName;
        delete dataObject.funcName;
        switch (method) {
            case "UserReg":
                console.log("用户账号注册!");
                break;
            case "EventReg":
                console.log("打卡挑战活动上链注册!");
                break;
            case "UserJoinEvent":
                console.log("用户参与活动!");
                break;
            case "UserClockIn":
                console.log("用户打卡操作!");
                break;
            case "GetValue":
                console.log("获取key值!");
                break;
            case "SetValue":
                console.log("设置或更新key值!");
                break;
        }
        //构建请求内容
        let reqBody = {
            header: {
                userCode: config.userCode,
                appCode: config.appCode,
                tid: config.tid
            },
            body: {
                chainCode: config.chainCode,
                funcName: method
            }
        };
        reqBody.body.args = dataObject.values()
        //组装待签名内容
        let digestStr = reqBody.header.userCode + reqBody.header.appCode + reqBody.body.chainCode + reqBody.body.funcName +
            reqBody.body.args.join();
        //对哈希值获取签名
        try {
            reqBody.mac = _signData(digestStr);
        } catch (error) {
            errorResponse.msg = error.toString();
            res.send(errorResponse);
        }
        //发送请求
        httpsClient.sendHttpsPost(config.nodeUrl, reqBody).then(result => {
            console.log('响应结果为:' + result.toString());
            if (result != null) {
                let resModel = JSON.parse(result.toString());
                //开始验签
                let verifyRes = _verifyData(digestStr, resModel.mac);
                if (verifyRes) {
                    //封装数据返回前台
                    if (resModel.header.code != 0) {
                        res.send(resModel.header)
                    } else {
                        let data = {
                            code: resModel.header.code,
                            msg: resModel.header.msg
                        }

                        data.data = resModel.body.ccRes.ccData
                        res.send(data)
                    }
                } else {
                    errorResponse.msg = '验签失败!';
                    res.send(errorResponse);
                }
            } else {
                errorResponse.msg = '系统异常,稍后重试!';
                res.send(errorResponse);
            }
        }).catch(error => {
            errorResponse.msg = error.toString();
            res.send(errorResponse);
        })

    });
function _signData(digestStr) {
    //签名结果做 Base64 计算
    let digest = crypto.createHash('sha256').update(digestStr).digest('buffer');
    //获取私钥
    let privateKey = fs.readFileSync(config.private_cert_path).toString();
    //将 SHA 值与私钥进行椭圆曲线加密签名计算,并将签名结果做 Base64 计算
    return ecdsa.sign(privateKey, digest);

}

function _verifyData(digestStr, mac) {
    //签名结果做 Base64 计算
    let digest = crypto.createHash('sha256').update(digestStr).digest('buffer');
    //获取公钥
    let publicKey = fs.readFileSync(config.gateway_public_cert_path).toString();
    let verifyRes = false;
    //根据返回的MAC值做解密
    verifyRes = ecdsa.verify(publicKey, digest, mac);
    return verifyRes
}

var debug = require('debug')('my-application'); // debug模块
main.set('port', process.env.PORT || 3000); // 设定监听端口

//启动监听
var server = main.listen(main.get('port'), function() {
    debug('Express server listening on port ' + server.address().port);
});

开发和调试js服务端时,可以安装nodemon包进行实时编译

npm install nodemon -g

然后执行我们的代码

nodemon main.js

开发完后可以在服务器端正式启动服务

node main.js -d

PHP后台调用服务端的测试示例,后台使用的是我们自己的WEIPHP框架

<?php

namespace app\clock_in\controller;

use app\common\controller\WebBase;

//PC运营管理端的控制器
class ClockIn extends WebBase
{
    //定时触发活动
    function CronEndEvent()
    {
        $data['nowTime'] = (string)NOW_TIME;
        up_chain('CronEndEvent', $data);

    }
    //用户打卡
    function UserClockIn()
    {
        $data['userKey'] = 'user_4567';
        $data['eventKey'] = 'event_7';
        $data['keyword'] = '111';
        $data['nowTime'] = (string)NOW_TIME;
        up_chain('UserClockIn', $data);
    }
    //用户参与活动
    function UserJoinEvent()
    {
        $data['userKey'] = 'user_123';
        $data['eventKey'] = 'event_7';
        $data['payType'] = '0';
        up_chain('UserJoinEvent', $data);
    }
    //新增活动
    function EventReg()
    {
        $data['eventKey'] = 'event_7';
        $data['userKey'] = 'user_123';
        $data['PrizeMoney'] = '1000';
        $data['PrizeCount'] = '100';
        $data['JoinMoney'] = '100';
        $data['Eventkeywords'] = json_encode(['111' => ['123', '456']]);
        $data['StartTime'] = '123';
        $data['EndTime'] = '456';
        $data['IsEnd'] = '0';
        $data['AdminPercent'] = '10';
        $data['AnchorPercent'] = '20';
        up_chain('EventReg', $data);
    }
    //新增用户
    function UserReg()
    {
        $data['userKey'] = 'user_456';
        up_chain('UserReg', $data);
    }
    //获取key值
    function GetValue()
    {
        $data['key'] = 'user_456';
        up_chain('GetValue', $data);
    }
    //设置key值
    function SetValue()
    {
        $data['key'] = 'test_xiaowei';
        $data['value'] = 'hi xiaowei';
        $data['canUpdate'] = '1';
        up_chain('SetValue', $data);
    }
}

本文由小韦云原创,转载请注明出处:https://bctos.cn/doc/10/1855,否则追究其法律责任

关键词:

广告位招商