qt进行支付宝直连的开发

半年前做的功能了,由于是第一次在没有任何前辈帮忙,独立完成的功能开发,颇具纪念意义,因此写下博文以供大家参考。
准备工作:《支付宝条码支付开发文档.docx》
开发环境:qt 5.4.0
sdk or demo:no
寻求帮助途径:上网百度,其次就是在支付宝开发者平台那里提问了。。。。。
开发加自测周期:两周


其实,做这个功能最大的障碍在于进行RSA签名和验签,其它代码都很好实现。支付宝开发
者平台未提供相应的sdk,只是提供了c++的,c++的直接引用到程序中也不好使,因此,只
能通过上网查资料的方式来完成RSAwithSHA的签名和验签,关键问题时,网上关于qt开发
支付宝直连的资料不仅少之又少,而且找来的一些资料大多无用,最后在一篇技术贴中找到
了密钥读取以及签名和验签的函数实现。
直接贴代码:
密钥读取函数
bool getKey(QString &errMsg)
{
    //私钥读取
    QByteArray ba;
    BIO  * key_pri  =  NULL;
    priKey   =  NULL;


    QString filename_pri=QDir::currentPath()+"/ali_rsa_private_key.pem";
    ba=(filename_pri.replace("/","\\")).toLatin1();
    const char* filename_pri_formed=ba.data();


    key_pri  =  BIO_new(BIO_s_file());
    BIO_read_filename(key_pri,  filename_pri_formed );
    priKey =  PEM_read_bio_RSAPrivateKey(key_pri, NULL, NULL, NULL);
    if(priKey==NULL)
    {
        errMsg=QObject::tr("私钥指针为空");
        
        return false;
    }
    BIO_free_all(key_pri);




    //公钥读取
    BIO * key_pub=NULL;
    pubKey=NULL;


    QString filename_pub=QDir::currentPath()+"/ali_rsa_public_key.pem";
    ba.clear();
    ba =(filename_pub.replace("/","\\")).toLatin1();
    const char *filename_pub_formed = ba.data();


    key_pub  =  BIO_new(BIO_s_file());
    BIO_read_filename(key_pub,  filename_pub_formed );
    pubKey =PEM_read_bio_RSA_PUBKEY(key_pub, NULL, NULL, NULL);// 


PEM_read_bio_RSA_PUBKEY
    if(pubKey==NULL)
    {
        errMsg=QObject::tr("支付宝公钥指针为空");       
        return false;
    }
    BIO_free_all(key_pub);


    return true;
}


以上函数便是对密钥读取的函数,需要加载静态链接库:libeay32.lib和ssleay.lib,并
且包含相应的头文件文件夹openssl。


签名函数:
 QString rsaSign(const QString &content, RSA *p_rsa)
   {


       QString signed_str;
       QByteArray ba;
       if (p_rsa != NULL) {


           ba.clear();
           ba=content.toUtf8();
           const char *cstr = ba.data();
           unsigned char hash[SHA_DIGEST_LENGTH] = {0};
           SHA1((unsigned char *)cstr, strlen(cstr), hash);
           unsigned char sign[XRSA_KEY_BITS / 8] = {0};
           unsigned int sign_len = sizeof(sign);
           int r = RSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sign, 


&sign_len, p_rsa);


           if (0 != r && sizeof(sign) == sign_len)
           {
               signed_str = QString::fromStdString(base64Encode(sign, 


sign_len));
           }
       }


       RSA_free(p_rsa);
       return signed_str;
   }




验签函数:
bool rsaVerify(const QString &content, const QString &sign, RSA *p_rsa)
   {


       bool result = false;
       QByteArray ba;


       if (p_rsa != NULL) {
           ba.clear();
           ba=content.toUtf8();


           const char *cstr = ba.data();
           unsigned char hash[SHA_DIGEST_LENGTH] = {0};
           SHA1((unsigned char *)cstr, strlen(cstr), hash);
           unsigned char sign_cstr[XRSA_KEY_BITS / 8] = {0};
           int len = XRSA_KEY_BITS / 8;
           base64Decode(sign, sign_cstr, len);
           unsigned int sign_len = XRSA_KEY_BITS / 8;
           int r = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH, (unsigned 


char *)sign_cstr, sign_len, p_rsa);         


           if (r > 0) {
               result = true;
           }
       }


       RSA_free(p_rsa);
       return result;
   }




值得注意的是:使用这种方式进行密钥读取时,需要在每次进行签名和验签之前进行
getkey调用,如果签名和验签采用同一个指针,则可能造成崩溃。
其它需要注意的地方都是一些小的细节,比如base64的encode和decode以及url的encode和decode。
这些处理不好,有可能造成验签不过的情况。
程序写好之后,可以使用支付宝提供的沙箱进行测试,具体的测试方式以及步骤,参考支付

宝开发者平台。

你可能感兴趣的:(qt进行支付宝直连的开发)