拉卡拉商户入网api接口接入,  提供方便数据。 代码使用是yii2框架, 使用拉卡拉测试参数。

<?php


namespace common\libraries\lakala\merchant;

/**
 * 商户入网
 * Class MerchantNetForm
 * @package common\libraries\lakala\merchant
 */
class MerchantNetForm
{
    public $version = '1.0';        //接口版本号
    public $orderNo;                //订单编号
    public $posType;                //进件POS类型 —按接入系统做控制
    public $orgCode;                //机构代码 (合作方在拉卡拉的标识,请联系业务员
    public $merRegName;             //商户注册名称
    public $merRegDistCode = '1';   //商户地区代码
    public $merRegAddr;             //商户详细地址(去除省,市,区后的详细地址,6-200字符)
    public $mccCode;                //商户MCC编号
    public $merBlis;                //营业执照号
    public $merBlisStDt;            //营业执照开始日期
    public $merBlisExpDt;           //营业执照有效期
    public $merBusiContent;         //商户经营内容
    public $larName;                //商户法人姓名
    public $larIdType;              //法人证件类型
    public $larIdcard;              //法人身份证号码
    public $larIdcardStDt;          //法人身份证开始日期 yyyy-MM-dd
    public $larIdcardExpDt;         //法人身份证有效期 yyyy-MM-dd
    public $merContactMobile;       //商户联系人手机号码
    public $merContactName;         //商户联系人
    public $openningBankCode;       //结算账户开户行号
    public $openningBankName;       //结算账户开户行名称
    public $clearingBankCode;       //结算账户清算行号
    public $acctNo;                 //结算账户账号
    public $acctName;               //结算账户名称
    public $acctTypeCode;           //结算账户性质( 57 对公 58 对私)
    public $settlePeriod;           //结算周期
    public $retUrl;                 //回调地址
    public $feeData;                //费率信息集合

    public function setVersion($version) {
        $this->version = $version;
    }
    public function getVersion($version) {
        return $this->version;
    }

    /**
     * @return mixed
     */
    public function getMerBlis()
    {
        return $this->merBlis;
    }

    /**
     * @param mixed $merBlis
     * @return MerchantNetForm
     */
    public function setMerBlis($merBlis)
    {
        $this->merBlis = $merBlis;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getOrderNo()
    {
        return $this->orderNo;
    }

    /**
     * @param mixed $orderNo
     * @return MerchantNetForm
     */
    public function setOrderNo($orderNo)
    {
        $this->orderNo = $orderNo;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getPosType()
    {
        return $this->posType;
    }

    /**
     * @param mixed $posType
     * @return MerchantNetForm
     */
    public function setPosType($posType)
    {
        $this->posType = $posType;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getOrgCode()
    {
        return $this->orgCode;
    }

    /**
     * @param mixed $orgCode
     * @return MerchantNetForm
     */
    public function setOrgCode($orgCode)
    {
        $this->orgCode = $orgCode;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getMerRegName()
    {
        return $this->merRegName;
    }

    /**
     * @param mixed $merRegName
     * @return MerchantNetForm
     */
    public function setMerRegName($merRegName)
    {
        $this->merRegName = $merRegName;
        return $this;
    }

    /**
     * @return string
     */
    public function getMerRegDistCode()
    {
        return $this->merRegDistCode;
    }

    /**
     * @param string $merRegDistCode
     * @return MerchantNetForm
     */
    public function setMerRegDistCode($merRegDistCode)
    {
        $this->merRegDistCode = $merRegDistCode;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getMerRegAddr()
    {
        return $this->merRegAddr;
    }

    /**
     * @param mixed $merRegAddr
     * @return MerchantNetForm
     */
    public function setMerRegAddr($merRegAddr)
    {
        $this->merRegAddr = $merRegAddr;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getMccCode()
    {
        return $this->mccCode;
    }

    /**
     * @param mixed $mccCode
     * @return MerchantNetForm
     */
    public function setMccCode($mccCode)
    {
        $this->mccCode = $mccCode;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getMerBlisStDt()
    {
        return $this->merBlisStDt;
    }

    /**
     * @param mixed $merBlisStDt
     * @return MerchantNetForm
     */
    public function setMerBlisStDt($merBlisStDt)
    {
        $this->merBlisStDt = $merBlisStDt;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getMerBlisExpDt()
    {
        return $this->merBlisExpDt;
    }

    /**
     * @param mixed $merBlisExpDt
     * @return MerchantNetForm
     */
    public function setMerBlisExpDt($merBlisExpDt)
    {
        $this->merBlisExpDt = $merBlisExpDt;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getMerBusiContent()
    {
        return $this->merBusiContent;
    }

    /**
     * @param mixed $merBusiContent
     * @return MerchantNetForm
     */
    public function setMerBusiContent($merBusiContent)
    {
        $this->merBusiContent = $merBusiContent;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getLarName()
    {
        return $this->larName;
    }

    /**
     * @param mixed $larName
     * @return MerchantNetForm
     */
    public function setLarName($larName)
    {
        $this->larName = $larName;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getLarIdType()
    {
        return $this->larIdType;
    }

    /**
     * @param mixed $larIdType
     * @return MerchantNetForm
     */
    public function setLarIdType($larIdType)
    {
        $this->larIdType = $larIdType;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getLarIdcard()
    {
        return $this->larIdcard;
    }

    /**
     * @param mixed $larIdcard
     * @return MerchantNetForm
     */
    public function setLarIdcard($larIdcard)
    {
        $this->larIdcard = $larIdcard;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getLarIdcardStDt()
    {
        return $this->larIdcardStDt;
    }

    /**
     * @param mixed $larIdcardStDt
     * @return MerchantNetForm
     */
    public function setLarIdcardStDt($larIdcardStDt)
    {
        $this->larIdcardStDt = $larIdcardStDt;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getLarIdcardExpDt()
    {
        return $this->larIdcardExpDt;
    }

    /**
     * @param mixed $larIdcardExpDt
     * @return MerchantNetForm
     */
    public function setLarIdcardExpDt($larIdcardExpDt)
    {
        $this->larIdcardExpDt = $larIdcardExpDt;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getMerContactMobile()
    {
        return $this->merContactMobile;
    }

    /**
     * @param mixed $merContactMobile
     * @return MerchantNetForm
     */
    public function setMerContactMobile($merContactMobile)
    {
        $this->merContactMobile = $merContactMobile;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getMerContactName()
    {
        return $this->merContactName;
    }

    /**
     * @param mixed $merContactName
     * @return MerchantNetForm
     */
    public function setMerContactName($merContactName)
    {
        $this->merContactName = $merContactName;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getOpenningBankCode()
    {
        return $this->openningBankCode;
    }

    /**
     * @param mixed $openningBankCode
     * @return MerchantNetForm
     */
    public function setOpenningBankCode($openningBankCode)
    {
        $this->openningBankCode = $openningBankCode;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getOpenningBankName()
    {
        return $this->openningBankName;
    }

    /**
     * @param mixed $openningBankName
     * @return MerchantNetForm
     */
    public function setOpenningBankName($openningBankName)
    {
        $this->openningBankName = $openningBankName;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getClearingBankCode()
    {
        return $this->clearingBankCode;
    }

    /**
     * @param mixed $clearingBankCode
     * @return MerchantNetForm
     */
    public function setClearingBankCode($clearingBankCode)
    {
        $this->clearingBankCode = $clearingBankCode;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getAcctNo()
    {
        return $this->acctNo;
    }

    /**
     * @param mixed $acctNo
     * @return MerchantNetForm
     */
    public function setAcctNo($acctNo)
    {
        $this->acctNo = $acctNo;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getAcctName()
    {
        return $this->acctName;
    }

    /**
     * @param mixed $acctName
     * @return MerchantNetForm
     */
    public function setAcctName($acctName)
    {
        $this->acctName = $acctName;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getAcctTypeCode()
    {
        return $this->acctTypeCode;
    }

    /**
     * @param mixed $acctTypeCode
     * @return MerchantNetForm
     */
    public function setAcctTypeCode($acctTypeCode)
    {
        $this->acctTypeCode = $acctTypeCode;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getSettlePeriod()
    {
        return $this->settlePeriod;
    }

    /**
     * @param mixed $settlePeriod
     * @return MerchantNetForm
     */
    public function setSettlePeriod($settlePeriod)
    {
        $this->settlePeriod = $settlePeriod;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getRetUrl()
    {
        return $this->retUrl;
    }

    /**
     * @param mixed $retUrl
     * @return MerchantNetForm
     */
    public function setRetUrl($retUrl)
    {
        $this->retUrl = $retUrl;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getFeeData()
    {
        return $this->feeData;
    }

    /**
     * @param mixed $feeData
     * @return MerchantNetForm
     */
    public function setFeeData($feeData = [])
    {
        if (!empty($feeData)) {
            $this->feeData = $feeData;
        } else {
            $this->feeData = [
                [
                    "feeRateTypeCode" => "300",
                    "feeRatePct" => "0.38",
                    "feeUpperAmtPcnt" => "20",
                    "feeLowerAmtPcnt" => "10"
                ],
                [
                    "feeRateTypeCode" => "301",
                    "feeRatePct" => "0.58"
                ],
                [
                    "feeRateTypeCode" => "302",
                    "feeRatePct" => "0.48"
                ],
                [
                    "feeRateTypeCode" => "303",
                    "feeRatePct" => "0.48"
                ]
            ];
        }

        return $this;
    }


    public function toArray() {
        $array = (array) $this;
        foreach ($array as $key => $value) {
            if ($value === null || $value === '') {
                unset($array[$key]);
            }
        }
        return $array;
    }
}
<?php

namespace common\libraries\lakala\merchant;

use common\libraries\lakala\RequestService;
use common\models\db\MerchantNetApply;

/**
 * 拉卡拉商户入网
 * Class MerchantNetService
 */
class MerchantNetService
{
    public $reqId = '48066e7ce3551149cd9ebdaf924582794137feb6';
    public $returnUrl = 'http://xxx/api/lakala/contract-notify';

    /**
     * @param $reqId
     */
    public function setReqId($reqId) {
        $this->reqId = $reqId;
    }

    /**
     * @return string
     */
    public function getReqId() {
        return $this->reqId;
    }

    /**
     * 构造商户入网请求参数
     * @param MerchantNetApply $merchantNetApply
     * @return array|MerchantNetForm
     */
    public function merchantNetApplyToArray(MerchantNetApply $merchantNetApply) {
        $merchantNetForm = new MerchantNetForm();
        $merchantNetForm->setOrderNo($merchantNetApply->order_no);
        $merchantNetForm->setPosType($merchantNetApply->post_type);
        $merchantNetForm->setMerRegName($merchantNetApply->merchant_name);
        $merchantNetForm->setMerRegDistCode($merchantNetApply->district_id);
        $merchantNetForm->setMerRegAddr($merchantNetApply->business_address);
        $merchantNetForm->setMccCode($merchantNetApply->mcc_code);
        $merchantNetForm->setMerBlis($merchantNetApply->business_license_number);
        $merchantNetForm->setMerBlisStDt($merchantNetApply->business_license_start_date);
        $merchantNetForm->setMerBlisExpDt($merchantNetApply->business_license_end_date);
        $merchantNetForm->setMerBusiContent($merchantNetApply->business_content);
        $merchantNetForm->setLarName($merchantNetApply->legal_name);
        $merchantNetForm->setLarIdType($merchantNetApply->legal_id_type);
        $merchantNetForm->setLarIdcard($merchantNetApply->legal_id_number);
        $merchantNetForm->setLarIdcardStDt($merchantNetApply->legal_id_start_date);
        $merchantNetForm->setLarIdcardExpDt($merchantNetApply->legal_id_expire_date);
        $merchantNetForm->setMerContactMobile($merchantNetApply->contract_mobile);
        $merchantNetForm->setMerContactName($merchantNetApply->contract_name);
        $merchantNetForm->setAcctName($merchantNetApply->account_name);
        $merchantNetForm->setAcctNo($merchantNetApply->account_no);
        $merchantNetForm->setAcctTypeCode($merchantNetApply->account_type_code);
        $merchantNetForm->setOpenningBankCode($merchantNetApply->openning_bank_code);
        $merchantNetForm->setOpenningBankName($merchantNetApply->openning_bank_name);
        $merchantNetForm->setClearingBankCode($merchantNetApply->clearing_bank_code);
        $merchantNetForm->setFeeData();
        return $merchantNetForm;
    }

    /**
     *  新填商户进件
     * @param MerchantNetApply|\yii\db\ActiveRecord $merchantNetApply
     */
    public function addMerchant(MerchantNetApply $merchantNetApply) {
        $merchantNetForm = $this->merchantNetApplyToArray($merchantNetApply);
        $merchantNetForm->setVersion('1.0');
        $merchantNetForm->setOrgCode('1');
        $merchantNetForm->setSettlePeriod('T+1');
        $merchantNetApply->fee_data_json = json_encode($merchantNetForm->getFeeData());
        $merchantNetApply->create_time = date('Y-m-d H:i:s');
        $merchantNetForm = $merchantNetForm->toArray();
        $merchantNetForm['retUrl'] = $this->returnUrl;
        $requestService = new RequestService();
        if($result = $requestService->send('api/v2/mms/openApi/addMer', $this->commonData($merchantNetForm))) {
            $merchantNetApply->contract_id = $result['respData']['contractId'];
            $merchantNetApply->update_time = date('Y-m-d H:i:s');
            if (!$merchantNetApply->save()) {
                throw new \RuntimeException('保存失败'.implode('', $merchantNetApply->getFirstErrors()));
            }
        } else {
            throw new \RuntimeException($requestService->getErrorMessage(), '-1');
        }
    }

    /**
     * 商户信息变更
     * @param MerchantNetApply|\yii\db\ActiveRecord $merchantNetApply
     */
    public function changeMerchant(MerchantNetApply $merchantNetApply) {
        $merchantNetForm = $this->merchantNetApplyToArray($merchantNetApply);
        $merchantNetForm->setVersion('1.0');
        $merchantNetForm->setOrgCode('1');
        $merchantNetForm->setSettlePeriod('T+1');
        $merchantNetForm = $merchantNetForm->toArray();
        $merchantNetForm['retUrl'] = $this->returnUrl;
        $merchantNetForm['merInnerNo'] = $merchantNetApply->merchant_inner_no;
        $merchantNetForm['merCupNo'] = $merchantNetApply->unionpay_no;
        $requestService = new RequestService();
        if($result = $requestService->send('api/v2/mms/openApi/changeMer', $this->commonData($merchantNetForm))) {
            $merchantNetApply->contract_id = $result['respData']['contractId'];
            $merchantNetApply->update_time = date('Y-m-d H:i:s');
            if (!$merchantNetApply->save()) {
                throw new \RuntimeException('保存失败'.implode('', $merchantNetApply->getFirstErrors()));
            }
        } else {
            throw new \RuntimeException($requestService->getErrorMessage(), '-1');
        }
    }

    /**
     * 入网进件检验
     * @param MerchantNetApply $merchantNetApply
     */
    public function verifyContractInfo(MerchantNetApply $merchantNetApply) {
        $merchantNetForm = new MerchantNetForm();
        $merchantNetForm->setMerRegName($merchantNetApply->merchant_name);
        $merchantNetForm->setMerBlis($merchantNetApply->business_license_number);
        $merchantNetForm->setLarIdcard($merchantNetApply->legal_id_number);
        $merchantNetForm->setAcctNo($merchantNetApply->account_no);
        $merchantNetForm->setVersion('1.0');
        $merchantNetForm->setOrderNo(UtilsService::getOrderNumber());
        $merchantNetForm->setOrgCode('1');
        $merchantNetForm = $merchantNetForm->toArray();
        $requestService = new RequestService();
        if($result = $requestService->send('api/v2/mms/openApi/verifyContractInfo', $this->commonData($merchantNetForm))) {
            if (!empty($result['retMsg'])) {
                throw new \RuntimeException($result['retMsg'], '-1');
            }
        } else {
            throw new \RuntimeException($requestService->getErrorMessage(), '-1');
        }
    }

    /**
     * 进件查询
     * @param MerchantNetApply $merchantNetApply
     */
    public function queryContract(MerchantNetApply $merchantNetApply) {
        $data = [
            "version" => "1.0",
            "orderNo" => "{$merchantNetApply->order_no}",
            "orgCode" => "1",
            "contractId" => "{$merchantNetApply->contract_id}"
        ];
        $requestService = new RequestService();
        if ($result = $requestService->send('api/v2/mms/openApi/queryContract', $this->commonData($data))) {
            if (isset($result['code']) && $result['code'] === '000000') {
                $this->sychMerchantContractAuditInfo($result['data']);
            } else {
                throw new \RuntimeException('人工审核中');
            }
        } else {
            throw new \RuntimeException($requestService->getErrorMessage(), '-1');
        }
    }

    /**
     * 结算信息变更
     * @param MerchantNetApply $merchantNetApply
     */
    public function changeSett(MerchantNetApply $merchantNetApply) {

    }

    /**
     * 附件上传
     * @param string $attType 拉卡拉附件类型枚举
     * @param string $filePath 文件路径
     * @param string $ext 文件后缀
     * @return array|\RuntimeException
     */
    public function uploadFile($attType, $filePath, $ext) {
        $data = [
            "version" => "1.0",
            "orderNo" => UtilsService::getOrderNumber(),
            "attType" => $attType,
            "attExtName" => $ext,
            "attContext" => base64_encode(file_get_contents($filePath)),
            "orgCode" => 1
        ];
        $requestService = new RequestService();
        if($result = $requestService->send('api/v2/mms/openApi/uploadFile', $this->commonData($data))) {
            return $result;
        } else {
            throw new \RuntimeException($requestService->getErrorMessage(), '-1');
        }
    }

    /**
     * 商户信息查询
     * @param string $merInnerNo 拉卡拉内部商户号
     * @return array|\RuntimeException
     */
    public function queryMerchant($merInnerNo) {
        $data = [
            "version" => "1.0",
            "orderNo" => UtilsService::getOrderNumber(),
            "merInnerNo" => $merInnerNo,
            "orgCode" => 1,
        ];
        $requestService = new RequestService();
        if ($result = $requestService->send('api/v2/mms/openApi/queryMerchant', $this->commonData($data))) {
            return $result['data'];
        } else {
            throw new \RuntimeException($requestService->getErrorMessage(), '-1');
        }
    }

    /**
     * 商户信息查询
     * @param string $cardNo 银行卡号
     * @return array|\RuntimeException
     */
    public function cardBin($cardNo) {
        $data = [
            "version" => "1.0",
            "orderNo" => UtilsService::getOrderNumber(),
            "cardNo" => $cardNo,
            "orgCode" => 1,
        ];
        $requestService = new RequestService();
        if ($result = $requestService->send('api/v2/mms/openApi/cardBin', $this->commonData($data))) {
            return $result['respData'];
        } else {
            throw new \RuntimeException($requestService->getErrorMessage(), '-1');
        }
    }

    /**
     * 商户公共请求参数
     * @param $data
     * @return array
     */
    private function commonData($data) {
        return [
            "ver" => "1.0.0",
            "timestamp" => time(),
            "rnd" => UtilsService::uniqueStr(),
            "reqId" => "baff59de4694438ca9089862253517a5",
            "reqData" => $data
        ];
    }

    /**
     * 进件审核状态列表
     * @return string[]
     */
    private static function contractStatusList() {
        return [
            'NO_COMMIT' => '未提交',
            'COMMIT' => '已提交',
            'COMMIT_FAIL' => '提交失败',
            'MANUAL_AUDIT' => '转人工审核',
            'REVIEW_ING' => '审核中',
            'WAIT_FOR_CONTACT' => '审核通过',
            'INNER_CHECK_REJECTED' => '审核驳回',
        ];
    }

    /**
     * 获取进件审核状态名称
     * @param $status
     * @return string
     */
    public static function getContractStatus($status) {
        $list = self::contractStatusList();
        return isset($list[$status]) ? $list[$status] : '';
    }

    /**
     * 商户入网进件结果更新
     * @param array $data 商户进件查询或进件回调成功返回参数
     * @return \RuntimeException
     */
    public function sychMerchantContractAuditInfo(array $data) {
        $merchantNetApply = MerchantNetApply::find()->where(['order_no' => $data['orderNo'], 'contract_id' => $data['contractId']])->one();
        if (!$merchantNetApply) {
            throw new \RuntimeException('没有相关进件信息');
        }
        if ($merchantNetApply->status == 1) {
            throw new \RuntimeException('已审核通过无需操作');
        }
        $merchantNetApply->contract_status = $data['contractStatus'];
        if ($merchantNetApply->contract_status == 'WAIT_FOR_CONTACT') {
            $merchantNetApply->status = 1;
            $merchantNetApply->merchant_inner_no = $data['merInnerNo'];
            $merchantNetApply->unionpay_no = $data['merCupNo'];
        } else if($merchantNetApply->contract_status == 'INNER_CHECK_REJECTED') {
            $merchantNetApply->status = 2;
            $merchantNetApply->audit_message = $data['contractMemo'];
        }
        $merchantNetApply->update_time = date('Y-m-d H:i:s');
        if (!$merchantNetApply->save()) {
            throw new \RuntimeException(implode("", $merchantNetApply->getFirstErrors()), '-1');
        }
    }
}
<?php

namespace common\libraries\lakala\merchant;

/**
 * 工具类 service
 * Class UtilsService
 * @package common\libraries\lakala\merchant
 */
class UtilsService
{
    /**
     * 获取随机订单号
     * @return string
     */
    public static function getOrderNumber() {
        return time().rand(1000000, 9999999);
    }

    /**
     * 获取随机字符
     * @return string
     */
    public static function uniqueStr() {
        return uniqid().rand(10000, 99999).rand(50000, 89999);
    }

    /**
     * 转utf8编码
     * @param $str
     * @return array|false|string|string[]|null
     */
    function strToUtf8($str)
    {
        $encode = mb_detect_encoding($str, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
        if ($encode == 'UTF-8') {
            return $str;
        } else {
            return mb_convert_encoding($str, 'UTF-8', $encode);
        }
    }

    /**
     * 商户地区代码
     * @return int
     */
    public function getMerRegDistCode() {
        $list = [
            "全国" => "1",
        ];
        return '1';
    }

    /**
     * 获取MCC 列表
     * @return array[]
     */
    public function getMCCList() {
        return [
            ['label' => '餐娱类', 'value' => 0, 'children' => [
                    ['value' => '5094', 'label' => '贵重珠宝、首饰,钟表零售'],
                    ['value' => '5811', 'label' => '包办伙食,宴会承包商'],
                    ['value' => 5812, 'label' => '就餐场所和餐馆'],
                    ['value' => 5813,	'label' => '饮酒场所(酒吧、酒馆、夜总会、鸡尾酒大厅、迪斯科舞厅)'],
                    ['value' => 5932,	'label' => '古玩店——出售、维修及还原'],
                    ['value' => 5937,	'label' => '古玩复制店'],
                    ['value' => 5944,	'label' => '银器店'],
                    ['value' => 5950,	'label' => '玻璃器皿和水晶饰品店'],
                    ['value' => 5970,	'label' => '工艺美术商店'],
                    ['value' => 5971,	'label' => '艺术商和画廊'],
                    ['value' => 7011,	'label' => '住宿服务(旅馆、酒店、汽车旅馆、度假村等)'],
                    ['value' => 7012,	'label' => '分时使用的别墅或度假用房'],
                    ['value' => 7032,	'label' => '运动和娱乐露营地'],
                    ['value' => 7033,	'label' => '活动房车场及露营场所'],
                    ['value' => 7297,	'label' => '按摩店'],
                    ['value' => 7298,	'label' => '保健及美容SPA'],
                    ['value' => 7631,	'label' => '手表、钟表和首饰维修店'],
                    ['value' => 7829,	'label' => '电影和录像创作、发行'],
                    ['value' => 7911,	'label' => '歌舞厅'],
                    ['value' => 7922,	'label' => '戏剧制片(不含电影)、演出和票务'],
                    ['value' => 7929,	'label' => '未列入其他代码的乐队、文艺表演'],
                    ['value' => 7932,	'label' => '台球、撞球场所'],
                    ['value' => 7933,	'label' => '保龄球馆'],
                    ['value' => 7941,	'label' => '商业体育场馆、职业体育俱乐部、运动场和体育推广公司'],
                    ['value' => 7992,	'label' => '公共高尔夫球场'],
                    ['value' => 7994,	'label' => '大型游戏机和游戏场所'],
                    ['value' => 7996,	'label' => '游乐园、马戏团、嘉年华、占卜'],
                    ['value' => 7997,	'label' => '会员俱乐部(体育、娱乐、运动等)、乡村俱乐部以及私人高尔夫课程班'],
                    ['value' => 7998,	'label' => '水族馆、海洋馆和海豚馆'],
                    ['value' => 7999,	'label' => '未列入其他代码的娱乐服务'],
                ]
            ],
            ['label' => '餐娱类(房产汽车)', 'value' => 1, 'children' => [
                    ['value' => 1520,	'label' => '一般承包商-住宅与商业楼'],
                    ['value' => 5511,	'label' => '汽车货车经销商-新旧车的销售、服务、维修、零件及出租'],
                    ['value' => 5521,	'label' => '汽车货车经销商-专门从事旧车的销售、服务、维修、零件及出租'],
                    ['value' => 5551,	'label' => '船只销售商'],
                    ['value' => 5561,	'label' => '旅行拖车、娱乐用车销售商'],
                    ['value' => 5571,	'label' => '摩托车商店和经销商'],
                    ['value' => 5592,	'label' => '露营、房车销售商'],
                    ['value' => 5598,	'label' => '雪车商'],
                    ['value' => 5599,	'label' => '汽车、飞行器、农用机车综合经营商'],
                    ['value' => 5933,	'label' => '典当、拍卖、信托'],
                    ['value' => 6012,	'label' => '金融机构-商品和服务'],
                    ['value' => 5998,	'label' => '其他批发商'],
                    ['value' => 7013,	'label' => '不动产代理——房地产经纪'],
                ]
            ],
            ['label' => '民生类', 'value' => 2, 'children' => [
                    ['value' => 3998,	'label' => 铁道部'],
                    ['value' => 4111,	'label' => '本市和市郊通勤旅客运输(包括轮渡)'],
                    ['value' => 4112,	'label' => '铁路客运'],
                    ['value' => 4121,	'label' => '出租车服务'],
                    ['value' => 4131,	'label' => '公路客运'],
                    ['value' => 4511,	'label' => '航空公司'],
                    ['value' => 4784,	'label' => '路桥通行费'],
                    ['value' => 4814,	'label' => '电信服务,包括本地和长途电话、信用卡电话、磁卡电话和传真'],
                    ['value' => 4899,	'label' => '有线和其他付费电视服务'],
                    ['value' => 4900,	'label' => '公共事业(电力、煤气、自来水、清洁服务)'],
                    ['value' => 5411,	'label' => '大型仓储式超级市场'],
                    ['value' => 5541,	'label' => '加油站、服务站'],
                    ['value' => 5542,	'label' => '自助加油站'],
                    ['value' => 5722,	'label' => '家用电器商店'],
                    ['value' => 5960,	'label' => '直销-保险直销'],
                    ['value' => 5994,	'label' => '报亭、报摊'],
                    ['value' => 7523,	'label' => '停车场'],
                    ['value' => 8651,	'label' => '政治组织(政府机构)'],
                    ['value' => 9211,	'label' => '法庭费用,包括赡养费和子女抚养费'],
                    ['value' => 9222,	'label' => '罚款'],
                    ['value' => 9223,	'label' => '保释金'],
                    ['value' => 9311,	'label' => '纳税'],
                    ['value' => 9399,	'label' => '未列入其他代码的政府服务(社会保障服务,国家强制)'],
                    ['value' => 9400,	'label' => '使领馆收费'],
                    ['value' => 9402,	'label' => '国家邮政服务']
                ]
            ],
            ['label' => '公益类', 'value' => 3, 'children' => [
                    ['value' => 8062,	'label' => '公立医院'],
                    ['value' => 8211,	'label' => '中小学校(公立)'],
                    ['value' => 8220,	'label' => '普通高校(公立)'],
                    ['value' => 8398,	'label' => '慈善和社会公益服务组织']
                ]
            ],
            ['label' => '一般类', 'value' => 4, 'children' => [
                    ['value' => 0742,	'label' => '兽医服务'],
                    ['value' => 0763,	'label' => '农业合作'],
                    ['value' => '0780',	'label' => '景观美化及园艺服务'],
                    ['value' => 4011,	'label' => '铁路运输'],
                    ['value' => 4119,	'label' => '救护车服务'],
                    ['value' => 4214,	'label' => '货物搬运和托运—当地和长途,移动和存储公司,以及当地递送服务'],
                    ['value' => 4215,	'label' => '快递服务(空运、地面运输或海运)'],
                    ['value' => 4225,	'label' => '公共仓储服务-农产品、冷冻品和家用产品'],
                    ['value' => 4411,	'label' => '轮船及巡游航线服务'],
                    ['value' => 4457,	'label' => '出租船只'],
                    ['value' => 4468,	'label' => '船舶、海运服务提供商'],
                    ['value' => 4582,	'label' => '机场服务'],
                    ['value' => 4722,	'label' => '旅行社'],
                    ['value' => 4733,	'label' => '大型景区售票'],
                    ['value' => 4789,	'label' => '未列入其他代码的运输服务'],
                    ['value' => 4812,	'label' => '通讯设备和电话销售'],
                    ['value' => 4816,	'label' => '计算机网络/信息服务'],
                    ['value' => 4821,	'label' => '电报服务'],
                    ['value' => 5211,	'label' => '木材和各类建材卖场'],
                    ['value' => 5231,	'label' => '玻璃、油漆涂料、墙纸零售'],
                    ['value' => 5251,	'label' => '五金商店'],
                    ['value' => 5261,	'label' => '草坪、花园用品商店'],
                    ['value' => 5310,	'label' => '折扣商店'],
                    ['value' => 5311,	'label' => '百货商店'],
                    ['value' => 5331,	'label' => '各类杂货店、便利店'],
                    ['value' => 5399,	'label' => '其他综合零售'],
                    ['value' => 5422,	'label' => '各类肉类零售商'],
                    ['value' => 5441,	'label' => '糖果及坚果商店'],
                    ['value' => 5451,	'label' => '乳制品店、冷饮店'],
                    ['value' => 5462,	'label' => '面包房、糕点商店'],
                    ['value' => 5499,	'label' => '各类食品店及专门食品零售店'],
                    ['value' => 5532,	'label' => '汽车轮胎经销商'],
                    ['value' => 5533,	'label' => '汽车零配件商店'],
                    ['value' => 5611,	'label' => '男子和男童服装及用品商店'],
                    ['value' => 5621,	'label' => '妇女成衣商店'],
                    ['value' => 5631,	'label' => '女性用品商店'],
                    ['value' => 5641,	'label' => '婴儿、儿童服装店'],
                    ['value' => 5651,	'label' => '家庭服装商店'],
                    ['value' => 5655,	'label' => '运动服饰商店'],
                    ['value' => 5661,	'label' => '鞋店'],
                    ['value' => 5681,	'label' => '皮货店'],
                    ['value' => 5691,	'label' => '成人成衣店'],
                    ['value' => 5697,	'label' => '裁缝、修补、改衣店'],
                    ['value' => 5698,	'label' => '假发商店'],
                    ['value' => 5699,	'label' => '各类服装及饰物店'],
                    ['value' => 5712,	'label' => '家具、家庭摆品、家用设备零售商'],
                    ['value' => 5713,	'label' => '地板商店'],
                    ['value' => 5714,	'label' => '帏帐、窗帘、室内装潢商店'],
                    ['value' => 5718,	'label' => '壁炉、壁炉防护网及配件商店'],
                    ['value' => 5719,	'label' => '各种家庭装饰专营店'],
                    ['value' => 5732,	'label' => '电子设备商店'],
                    ['value' => 5733,	'label' => '音乐商店-乐器、钢琴、乐谱'],
                    ['value' => 5734,	'label' => '计算机软件商店'],
                    ['value' => 5735,	'label' => '音像制品商店'],
                    ['value' => 5814,	'label' => '快餐店'],
                    ['value' => 5912,	'label' => '药房、药店'],
                    ['value' => 5921,	'label' => '瓶装酒零售店'],
                    ['value' => 5931,	'label' => '旧商品店、二手商品店'],
                    ['value' => 5935,	'label' => '海上船只遇难救助'],
                    ['value' => 5940,	'label' => '自行车商店'],
                    ['value' => 5941,	'label' => '体育用品店'],
                    ['value' => 5942,	'label' => '书店'],
                    ['value' => 5943,	'label' => '文具用品商店、各类办公用品商店'],
                    ['value' => 5945,	'label' => '玩具、游戏店'],
                    ['value' => 5946,	'label' => '照相器材商店'],
                    ['value' => 5947,	'label' => '礼品、卡片、装饰品、纪念品商店'],
                    ['value' => 5948,	'label' => '箱包、皮具店'],
                    ['value' => 5949,	'label' => '纺织品及针织品零售'],
                    ['value' => 5962,	'label' => '旅游相关服务直销'],
                    ['value' => 5963,	'label' => '门对门销售'],
                    ['value' => 5964,	'label' => '目录销售商户'],
                    ['value' => 5965,	'label' => '目录、零售兼营商户'],
                    ['value' => 5966,	'label' => '电话呼出直销'],
                    ['value' => 5967,	'label' => '电话呼入直销'],
                    ['value' => 5968,	'label' => '订阅/订购直销服务'],
                    ['value' => 5969,	'label' => '其他直销商户'],
                    ['value' => 5972,	'label' => '邮票和纪念币商店'],
                    ['value' => 5973,	'label' => '宗教品商店'],
                    ['value' => 5975,	'label' => '助听器-销售、服务和用品'],
                    ['value' => 5976,	'label' => '假肢店(整形外科用品、辅助设备)'],
                    ['value' => 5977,	'label' => '化妆品商店'],
                    ['value' => 5978,	'label' => '打字机商店—销售、服务和出租'],
                    ['value' => 5983,	'label' => '燃料经销商-燃油、木材、煤炭和液化石油'],
                    ['value' => 5992,	'label' => '花店'],
                    ['value' => 5993,	'label' => '香烟、雪茄专卖店'],
                    ['value' => 5995,	'label' => '宠物商店、宠物食品及用品'],
                    ['value' => 5996,	'label' => '游泳池-销售、供应和服务'],
                    ['value' => 5997,	'label' => '电动剃须刀商店-销售和服务'],
                    ['value' => 5999,	'label' => '其他专门零售店'],
                    ['value' => 6010,	'label' => '金融机构-人工现金支付'],
                    ['value' => 6011,	'label' => '金融机构-自动现金支付'],
                    ['value' => 6051,	'label' => '非金融机构-外币兑换、非电子转账的汇票、临时支付凭证和旅行支票'],
                    ['value' => 6211,	'label' => '证券公司-经纪人和经销商'],
                    ['value' => 6513,	'label' => '不动产管理-物业管理'],
                    ['value' => 7210,	'label' => '洗衣店'],
                    ['value' => 7211,	'label' => '洗熨服务(自助洗衣服务)'],
                    ['value' => 7216,	'label' => '干洗店'],
                    ['value' => 7217,	'label' => '室内清洁服务(地毯、沙发、家具表面的清洁服务)'],
                    ['value' => 7221,	'label' => '摄影工作室'],
                    ['value' => 7230,	'label' => '美容理发店'],
                    ['value' => 7251,	'label' => '修鞋店、擦鞋店、帽子清洗店'],
                    ['value' => 7261,	'label' => '殡葬服务'],
                    ['value' => 7273,	'label' => '婚姻介绍及陪同服务'],
                    ['value' => 7276,	'label' => '税收准备服务'],
                    ['value' => 7277,	'label' => '咨询服务-债务、婚姻和私人事务'],
                    ['value' => 7278,	'label' => '购物服务及会所(贸易、经纪服务)'],
                    ['value' => 7295,	'label' => '家政服务'],
                    ['value' => 7296,	'label' => '出租衣物-服装、制服和正式场合服装'],
                    ['value' => 7299,	'label' => '未列入其他代码的其他个人服务'],
                    ['value' => 7311,	'label' => '广告服务'],
                    ['value' => 7321,	'label' => '消费者信用报告机构'],
                    ['value' => 7333,	'label' => '商业摄影、工艺、绘图服务'],
                    ['value' => 7338,	'label' => '复印及绘图服务'],
                    ['value' => 7339,	'label' => '速记、秘书服务(包括各类办公服务)'],
                    ['value' => 7342,	'label' => '灭虫及消毒服务'],
                    ['value' => 7349,	'label' => '清洁、保养及门卫服务'],
                    ['value' => 7361,	'label' => '职业中介、临时工'],
                    ['value' => 7372,	'label' => '计算机编程、数据处理和系统集成设计服务'],
                    ['value' => 7375,	'label' => '信息检索服务'],
                    ['value' => 7379,	'label' => '未列入其他代码的计算机维护和修理服务'],
                    ['value' => 7392,	'label' => '管理、咨询和公共关系服务'],
                    ['value' => 7393,	'label' => '侦探、保安、安全服务'],
                    ['value' => 7394,	'label' => '设备、工具、家具和电器出租'],
                    ['value' => 7395,	'label' => '照相洗印服务'],
                    ['value' => 7399,	'label' => '未列入其他代码的商业服务'],
                    ['value' => 7512,	'label' => '汽车出租'],
                    ['value' => 7513,	'label' => '卡车及拖车出租'],
                    ['value' => 7519,	'label' => '房车和娱乐车辆出租'],
                    ['value' => 7531,	'label' => '车体维修店'],
                    ['value' => 7534,	'label' => '轮胎翻新、维修店'],
                    ['value' => 7535,	'label' => '汽车喷漆店'],
                    ['value' => 7538,	'label' => '汽车服务商店(非经销商)'],
                    ['value' => 7542,	'label' => '洗车'],
                    ['value' => 7549,	'label' => '拖车服务'],
                    ['value' => 7622,	'label' => '电器设备维修'],
                    ['value' => 7623,	'label' => '空调、制冷设备维修'],
                    ['value' => 7629,	'label' => '电器设备、小家电维修'],
                    ['value' => 7641,	'label' => '家具维修、翻新'],
                    ['value' => 7692,	'label' => '焊接维修服务'],
                    ['value' => 7699,	'label' => '各类维修店及相关服务'],
                    ['value' => 7832,	'label' => '电影院'],
                    ['value' => 7841,	'label' => '音像制品出租商店'],
                    ['value' => 7991,	'label' => '旅游与展览'],
                    ['value' => 7993,	'label' => '电子游戏供给'],
                    ['value' => 7995,	'label' => '彩票销售'],
                    ['value' => 8011,	'label' => '其他医疗卫生活动'],
                    ['value' => 8021,	'label' => '牙科医生'],
                    ['value' => 8031,	'label' => '正骨医生'],
                    ['value' => 8041,	'label' => '按摩医生'],
                    ['value' => 8042,	'label' => '眼科医生'],
                    ['value' => 8043,	'label' => '光学产品、眼镜店'],
                    ['value' => 8049,	'label' => '手足病医生'],
                    ['value' => 8050,	'label' => '护理和照料服务'],
                    ['value' => 8071,	'label' => '医学及牙科实验室'],
                    ['value' => 8099,	'label' => '其他医疗保健服务'],
                    ['value' => 8111,	'label' => '法律服务和律师事务所服务'],
                    ['value' => 8241,	'label' => '函授学校(成人教育)'],
                    ['value' => 8244,	'label' => '商业和文秘学校(中等专业学校)'],
                    ['value' => 8249,	'label' => '贸易和职业学校(职业技能培训)'],
                    ['value' => 8299,	'label' => '其他学校和教育服务'],
                    ['value' => 8351,	'label' => '儿童保育服务(含学前教育)'],
                    ['value' => 8641,	'label' => '市民、社会及友爱组织'],
                    ['value' => 8661,	'label' => '宗教组织'],
                    ['value' => 8675,	'label' => '汽车协会'],
                    ['value' => 8699,	'label' => '其他会员组织'],
                    ['value' => 8911,	'label' => '建筑、工程和测量服务'],
                    ['value' => 8912,	'label' => '装修、装潢、园艺'],
                    ['value' => 8931,	'label' => '会计、审计、财务服务'],
                    ['value' => 8999,	'label' => '未列入其他代码的专业服务'],
                ]
            ],
            ['label' => '一般类(批发)', 'value' => 5, 'children' => [
                    ['value' => 4458,	'label' => '烟草配送商户'],
                    ['value' => 5013,	'label' => '机动车供应及零配件(批发商)'],
                    ['value' => 5021,	'label' => '办公及商务家具(批发商)'],
                    ['value' => 5039,	'label' => '未列入其他代码的建材批发(批发商)'],
                    ['value' => 5044,	'label' => '办公、影印及微缩摄影器材(批发商)'],
                    ['value' => 5045,	'label' => '计算机、计算机外围设备(批发商)'],
                    ['value' => 5046,	'label' => '未列入其他代码的商用器材(批发商)'],
                    ['value' => 5047,	'label' => '牙科/实验室/医疗/眼科医院器材和用品(批发商)'],
                    ['value' => 5051,	'label' => '金属产品服务商和公司(批发商)'],
                    ['value' => 5065,	'label' => '电器零件和设备(批发商)'],
                    ['value' => 5072,	'label' => '三金器材及用品(批发商)'],
                    ['value' => 5074,	'label' => '管道和供暖设备(批发商)'],
                    ['value' => 5111,	'label' => '文具、办公用品、复印纸和书写纸(批发商)'],
                    ['value' => 5122,	'label' => '药品、药品经营者(批发商)'],
                    ['value' => 5131,	'label' => '布料、缝纫用品和其他纺织品(批发商)'],
                    ['value' => 5137,	'label' => '男女及儿童制服和服装(批发商)'],
                    ['value' => 5139,	'label' => '鞋类(批发商)'],
                    ['value' => 5172,	'label' => '石油及石油产品(批发商)'],
                    ['value' => 5192,	'label' => '书、期刊和报纸(批发商)'],
                    ['value' => 5193,	'label' => '花木栽种用品、苗木和花卉(批发商)'],
                    ['value' => 5198,	'label' => '油漆、清漆用品(批发商)'],
                    ['value' => 5271,	'label' => '活动房车销售商'],
                    ['value' => 5398,	'label' => '大型企业批发'],
                ]
            ],
            ['label' => '特殊类', 'value' => 6, 'children' => [
                    ['value' => 9498,	'label' => '信用卡还款']
                ]
            ]
        ];
    }

    /**
     * 商户经营内容
     * @return \string[][]
     */
    public function getBusinessContentList() {
        return [
            ['value' => '642', 'label' => '百货、中介、培训、景区门票等'],
            ['value' => '645', 'label' => '交通运输售票'],
            ['value' => '646', 'label' => '电气缴费'],
            ['value' => '647', 'label' => '政府类'],
            ['value' => '648', 'label' => '便民类'],
            ['value' => '649', 'label' => '公立医院、公立学校、慈善'],
            ['value' => '650', 'label' => '宾馆餐饮娱乐类'],
            ['value' => '651', 'label' => '房产汽车类'],
            ['value' => '652', 'label' => '批发类'],
            ['value' => '653', 'label' => '超市加油类'],
            ['value' => '654', 'label' => '一般类商户'],
            ['value' => '655', 'label' => '三农商户'],
        ];
    }

    /**
     * 法人证件类型
     * @return \string[][]
     */
    public function getLegalIDTypeList() {
        return [
            ['value' => '01', 'label' => '身份证'],
            ['value' => '02', 'label' => '护照'],
            ['value' => '03', 'label' => '港澳通行证'],
            ['value' => '04', 'label' => '台胞证'],
            ['value' => '99', 'label' => '其它证件'],
        ];
    }
}
<?php

namespace common\libraries\lakala;

use common\libraries\lakala\merchant\UtilsService;
use common\libraries\WriteLogSrv;

/**
 * 拉卡拉API请求
 * Class RequestService
 */
class RequestService
{
    public $apiUrl = 'https://test.wsmsd.cn/sit/';  //测试环境入口
    //public $apiUrl = 'https://s2.lakala.com/';    //正式环境入口
    public $publicKey = '/data/lakala/OP00000003_cert.pem';              //拉卡拉公钥文件
    public $privateKeyFile = '/data/lakala/OP00000003_private_key.pem';       //商户私钥
    public $appId = 'your appId';                              //拉卡拉appId
    public $serialNo = 'your serialNo';  //证书序列号
    public $password = '';
    public $signAlgorithm = 'LKLAPI-SHA256withRSA';         //签名算法
    public $nonceStr = '';
    public $timestamp = '';
    protected $errorMessage = '';
    public $orgCode = '1';

    public function __construct()
    {
        $this->setNonceStr();
        $this->setTimestamp();
    }

    /**
     * 设置错误信息
     * @param string $message
     */
    private function setErrorMessage($message) {
        $this->errorMessage = $message;
    }

    /**
     * 获取错误信息
     * @return string
     */
    public function getErrorMessage() {
        return $this->errorMessage;
    }

    /**
     * 设置当前时间戳
     */
    public function setTimestamp() {
        $this->timestamp = time();
    }

    /**
     * 获取当前时间戳
     */
    public function getTimestamp() {
        return $this->timestamp;
    }

    /**
     * 获取随机字符串
     * @return string
     */
    public function getNonceStr() {
        return $this->nonceStr;
    }

    /**
     * 获取随机12位字符串
     * @param string $nonceStr
     */
    public function setNonceStr($nonceStr = '') {
        if (!empty($nonceStr) && strlen($nonceStr) == 12) {
            $this->nonceStr = $nonceStr;
        } else {
            $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
            $nonceStr = '';
            for ($i = 0; $i < 12; $i++) {
                $nonceStr .= $chars[mt_rand(0, strlen($chars) - 1)];
            }
            $this->nonceStr = $nonceStr;
        }
    }

    /**
     * 签名 ${appid}\n+${serialNo}\n+${timeStamp}\n+${nonceStr}\n+${body}\n
     * @param $strSignSrc
     * @return string
     */
    public function handleSign($strSignSrc) {
        $sign = "{$this->appId}\n";
        if (!empty($this->serialNo)) {
            $sign .= "{$this->serialNo}\n";
        }
        $sign .= "{$this->timestamp}\n";
        $sign .= $this->nonceStr."\n";
        $sign .= $strSignSrc."\n";
        WriteLogSrv::writeLog("===拉卡拉签名字符串===: \n".$sign);
        return $sign;
    }

    /**
     * 测试
     */
    public function test() {
        $data = $sign = "";
        $data = json_decode($data, true);
        $strSignSrc = json_encode($data, 320);
        $strSignSrc = $this->handleSign($strSignSrc);
        /*$privateKey = file_get_contents($this->privateKeyFile);
        $pKeyId = openssl_pkey_get_private($privateKey);
        openssl_sign($strSignSrc, $signature, $pKeyId, OPENSSL_ALGO_SHA256);
        openssl_free_key($pKeyId);
        var_dump(base64_encode($signature));die;*/

        $pubKeyId = openssl_get_publickey(file_get_contents($this->publicKey));
        $flag = (bool) openssl_verify($strSignSrc, base64_decode($sign), $pubKeyId, OPENSSL_ALGO_SHA256);
        openssl_free_key($pubKeyId);
        var_dump($flag);
    }

    /**
     * 拼接签名字符串
     * @param array $body
     * @return string $signature
     */
    public function signStr(array $body) {
        $strSignSrc = json_encode($body, 320);
        return $this->handleSign($strSignSrc);
    }

    /**
     * 签名
     * @param $strSignSrc
     * @return string
     */
    public function sign($strSignSrc) {
        $privateKey = file_get_contents($this->privateKeyFile);
        $pKeyId = openssl_pkey_get_private($privateKey);
        openssl_sign($strSignSrc, $signature, $pKeyId, OPENSSL_ALGO_SHA256);
        openssl_free_key($pKeyId);
        WriteLogSrv::writeLog(' ===拉卡拉===签名:'.base64_encode($signature));
        return base64_encode($signature);
    }

    /**
     * 配置头部 authorization
     * @param string $signature
     * @return string $authorization
     */
    public function setAuthorization($signature) {
        $authorization = $this->signAlgorithm . " appid=\"{$this->appId}\",";
        if (!empty($this->serialNo)) {
            $authorization .= "serial_no=\"{$this->serialNo}\",";
        }
        $authorization .= "nonce_str=\"{$this->nonceStr}\",";
        $authorization .= "timestamp=\"{$this->timestamp}\",";
        $authorization .= "signature=\"{$signature}\"";
        return $authorization;
    }

    /**
     * 接入请求
     * @param string $url
     * @param array $data
     * @return array|false
     */
    public function send($url, array $data) {
        $signStr = $this->signStr($data);
        $signature = $this->sign($signStr);
        $authorization = $this->setAuthorization($signature);
        $response = $this->curlPost($url, $authorization, $data);
        return $this->handleResponse($response);
    }

    /**
     * 解析请求结果
     * @param string $response
     * @return array | false
     */
    public function handleResponse($response) {
        WriteLogSrv::writeLog('===拉卡拉=== 响应信息'.$response);
        $response = json_decode($response, true);
        if (empty($response)) {
            $this->setErrorMessage('请求失败');
            return false;
        }
        if ($response['retCode'] != '000000') {
            $this->setErrorMessage($response['retMsg']);
            return false;
        }
        return $response;
    }

    /**
     * 验签
     * @param string $responseSrc 拼接好的字符串
     * @param string $signature
     * @return boolean $flag
     */
    public function verifySign($responseSrc, $signature) {
        $pubKeyId = openssl_get_publickey(file_get_contents($this->publicKey));
        $flag = (bool) openssl_verify($responseSrc, base64_decode($signature), $pubKeyId, OPENSSL_ALGO_SHA256);
        openssl_free_key($pubKeyId);
        return $flag;
    }

    /**
     * 发送curl请求
     * @param string $actUrl
     * @param string $authorization
     * @param array $data
     * @return bool|string
     */
    public function curlPost($actUrl, $authorization, $data = []) {
        $url = $this->apiUrl.$actUrl;
        WriteLogSrv::writeLog(' ===拉卡拉请求=== url:'.$url);
        WriteLogSrv::writeLog(' ===拉卡拉请求=== authorization:'.$authorization);
        WriteLogSrv::writeLog(' ===拉卡拉请求=== 内容:'.json_encode($data, 320));
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Accept: application/json',
                'Content-Type: application/json',
                'Authorization: ' . $authorization,
            )
        );
        if (!empty($data)) {
            @curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, 320));
        }
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        return $response;
    }
}