PHP--华为Saas服务对接

本文分享了在公司产品上架华为云SaaS平台过程中的对接经验,详细介绍了对接流程,包括官方文档查阅、对接流程复述及PHP代码实现。文章深入探讨了对接中遇到的问题与解决方案,如技术支持获取、流程理解、验签细节等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

起因

因为公司的产品要上华为Saas平台,所以需要去对接华为云Saas,但华为云那边只提供Java类型的代码,所以这一次的对接还是有一定的挑战难度的

对接流程

1、查看官方文档

SaaS类商品接入指南

2、对接流程复述

首先从华为云那边请求我们服务器的接口,我们这边先校验accessToken是否为华为云发出,校验成功后,我们服务器这边在header中添加Body-Sign,并返回华为云规定的接口返回值

3、PHP对接代码提供

官方只提供Java版本代码,demo只能去申请工单或发送邮件到华为云运营获取

<?php
/**
 * Date: 2019/12/11
 * Time: 16:28
 */

use think\Exception;

/**
 * 华为云信息解密
 * Class HwDataDecrypt
 * @package app\common\Service
 */
class HwDataDecrypt
{
    /**
     * 解密手机号码或邮箱
     * @param $key              秘钥
     * @param $str              密文
     * @param $encrypt_length    加密长度
     * @return null             解密结果
     */
    public function decryptMobilePhoneOrEMail( $key, $str, $encrypt_length)
    {

        $iv = substr( $str, 0, 16);
        $str = substr( $str, 16);
        $key = substr(openssl_digest(openssl_digest($key, 'sha1', true), 'sha1', true), 0, 16);
        $result = null;

        try
        {
            $result = $this->decryptAESCBCEncode( $str, $key, $iv, $encrypt_length);
        }
        catch (Exception $e)
        {
            //TODO:异常处理
        }

        return $result;
    }

    /**
     * 对资源开通后,返回的用户名和密码进行加密
     * @param $key              秘钥
     * @param $string           原文
     * @param $encrypt_length   加密长度
     * @return mixed
     */
    public function generateSaaSUsernameOrPwd( $key, $string, $encrypt_length)
    {
        $iv = $this->getRandomChars( 16);
        $key = substr(sha1(sha1($key, true), true), 0, 16);
        $after_encrypt_string = '';

        if( !empty($key) && !empty($string))
        {
            $after_encrypt_string = $this->encrypt_pass( $string, $key, $iv);
        }

        return $iv.$after_encrypt_string;
    }

    /**
     * 华为云signature加密
     * 这里必须修改hash_hmac的最后一个raw_output的参数,修改成true,输出原始二进制数据
     * @param $key
     * @param $data
     * @return string
     */
    public function getSignature( $key, $data)
    {
        //HMAC-SHA256加密
        return base64_encode(hash_hmac("sha256", $data, $key, true));   //
    }

    //生成随机值
    function getRandomChars( $length)
    {
        $random_chars = '';

        for ( $i =0; $i < $length; $i++)
        {
            //字母和数字中随机
            $random_chars .= chr( mt_rand( 33, 126));
        }

        return $random_chars;
    }

    /**
     * 解密AES CBC
     * @param $content          原文
     * @param $key              秘钥
     * @param $iv               盐值
     * @param $encrypt_type     解密结果
     * @return null|string
     */
    function decryptAESCBCEncode( $content, $key, $iv, $encrypt_type)
    {
        if ( empty( $content) || empty($key) || empty($iv) )
        {
            return null;
        }

        //return $this->decryptAESCBC( $content, $key, $iv, $encrypt_type);

        /*if( $encrypt_type == 1)
        {
            $cipher = MCRYPT_RIJNDAEL_256;
        }
        else
        {
            $cipher = MCRYPT_RIJNDAEL_128;
        }*/

        return $this->decrypt_pass( $content, $key, $iv);
    }

    /**
     * AES解密
     * @param $sStr
     * @param $sKey
     * @param $iv
     * @param string $cipher
     * @param string $mode
     * @return bool|string
     */
    function decrypt_pass($sStr, $sKey, $iv, $cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC)
    {
        $decrypted = mcrypt_decrypt( $cipher, $sKey, base64_decode($sStr), $mode, $iv);
        $decrypted = $this->pkcs5_unpad($decrypted);

        return $decrypted;
    }

    /**
     * 格式化参数格式化成url参数
     * @param $data
     * @return mixed
     */
    public function ToUrlParams($data)
    {
        $buff = "";
        foreach ($data as $k => $v)
        {
            if($k != "authToken" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     * 生成accessToken
     * @param $data
     * @param $key
     * @return mixed|string
     */
    function MakeSignString2($data, $key)
    {
        //签名步骤一:按字典序排序参数
        ksort($data);
        $string = $this->ToUrlParams($data);
        //根据要求排序
        $string = base64_encode(hash_hmac("sha256", $string, $key));

        return $string;
    }

    /**
     * 生成signature
     * @param $data
     * @param $key
     * @return mixed|string
     */
    function MakeSignString($data, $key)
    {
        //签名步骤一:按字典序排序参数
        //ksort($data);
        //$string = $this->ToUrlParams($data);
        //根据要求排序
        $string = base64_encode(hash_hmac("sha256", $data, $key));

        return $string;
    }

    /**
     *
     * @param $data
     * @param $key
     * @param $iv
     * @param string $cipher
     * @param string $mode
     * @return string
     */
    function encrypt_pass( $data, $key, $iv, $cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC)
    {
        $result = '';

        $size = mcrypt_get_block_size( $cipher, $mode);
        $padded_data = $this->pkcs5_pad($data, $size);
        $encrypt_data = mcrypt_encrypt( $cipher, $key, $padded_data, $mode, $iv);
        $result = base64_encode($encrypt_data);

        return $result;
    }

    //填充
    function pkcs5_pad ($text, $blocksize)
    {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }

    function pkcs5_unpad($text)
    {
        $end = substr($text, -1);
        $last = ord($end);
        $len = strlen($text) - $last;
        if (substr($text, $len) == str_repeat($end, $last))
        {
            return substr($text, 0, $len);
        }

        return false;
    }
}

以上方法分别对应华为云官方文档中的 ISV Server对响应消息体进行签名ISV Server对资源开通后的用户名和密码加密以及ISV Server解密手机号和邮箱

4、对接中所遇到的坑

1、我们这边让与我们对接的华为云商务提供技术支持,但对方没有提供,最后还是提交了华为云的工单,由客服出来回答

2、华为云的客服不指出我这边的错误在哪,回答的内容有点生硬太固定化

3、一开始理解错流程,去请求华为云文档中所提供的URL

4、在对返回值进行验签的时候,虽然华为云技术说要进行二进制对其,但因为对函数的不理解,那天晚上没做到,第二天才去翻查PHP的官方文档,查到有这么一种二进制输出的内容【默认是false】

5、返回值验签,华为云的文档中没有标注好,说明是我们返回给华为云的值进行验签,对于我这样的初级程序员来说会有这么一种操作误解,以为是获取header的值进行验签

6、华为云的新购商品接口描述中,在响应参数instanceId的备注中(建议使用请求参数bussinessId作为instanceId。)这句话中,bussinessId是错的,多了一个s,应改为businessId

总结

在进行华为云的SaaS对接中,没有好好的阅读华为云的文档,没有细细品读内容,造成一早上的测试浪费。另外就是对PHP所提供的的加密参数的不理解,若不是那天去翻查文档,那我还陷入找bug的循环中。总的来说还是自己的不细心,不认真所造成的一些问题,希望写出来,可以帮助到大家。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值