#ifndef __ALIPAY_H__
#define __ALIPAY_H__
#include "base64/base64.h"
#include
#include
#include
#include
#include
#include
classRsa {
public:
staticboolverify(constchar*public_key,
conststring &content,conststring &sign) {
BIO *bufio = NULL;
RSA *rsa = NULL;
EVP_PKEY *evpKey = NULL;
boolverify =false;
EVP_MD_CTX ctx;
intresult = 0;
string decodedSign = base64_decode(sign);
char*chDecodedSign =const_cast(decodedSign.c_str());
bufio = BIO_new_mem_buf((void*)public_key, -1);
if(bufio == NULL) {
ERR("BIO_new_mem_buf failed");
gotosafe_exit;
}
rsa = PEM_read_bio_RSA_PUBKEY(bufio, NULL, NULL, NULL);
if(rsa == NULL) {
ERR("PEM_read_bio_RSA_PUBKEY failed");
gotosafe_exit;
}
evpKey = EVP_PKEY_new();
if(evpKey == NULL) {
ERR("EVP_PKEY_new failed");
gotosafe_exit;
}
if((result = EVP_PKEY_set1_RSA(evpKey, rsa)) != 1) {
ERR("EVP_PKEY_set1_RSA failed");
gotosafe_exit;
}
EVP_MD_CTX_init(&ctx);
if(result == 1 && (result = EVP_VerifyInit_ex(&ctx,
EVP_sha1(), NULL)) != 1) {
ERR("EVP_VerifyInit_ex failed");
}
if(result == 1 && (result = EVP_VerifyUpdate(&ctx,
content.c_str(), content.size())) != 1) {
ERR("EVP_VerifyUpdate failed");
}
if(result == 1 && (result = EVP_VerifyFinal(&ctx,
(unsigned char*)chDecodedSign,
decodedSign.size(), evpKey)) != 1) {
ERR("EVP_VerifyFinal failed");
}
if(result == 1) {
verify = true;
} else{
ERR("verify failed");
}
EVP_MD_CTX_cleanup(&ctx);
safe_exit:
if(rsa != NULL) {
RSA_free(rsa);
rsa = NULL;
}
if(evpKey != NULL) {
EVP_PKEY_free(evpKey);
evpKey = NULL;
}
if(bufio != NULL) {
BIO_free_all(bufio);
bufio = NULL;
}
returnverify;
}
staticstring sign(constchar*private_key,
conststring &content) {
BIO *bufio = NULL;
RSA *rsa = NULL;
EVP_PKEY *evpKey = NULL;
boolverify =false;
EVP_MD_CTX ctx;
intresult = 0;
unsigned intsize = 0;
char*sign = NULL;
string signStr = "";
bufio = BIO_new_mem_buf((void*)private_key, -1);
if(bufio == NULL) {
ERR("BIO_new_mem_buf failed");
gotosafe_exit;
}
rsa = PEM_read_bio_RSAPrivateKey(bufio, NULL, NULL, NULL);
if(rsa == NULL) {
ERR("PEM_read_bio_RSAPrivateKey failed");
gotosafe_exit;
}
evpKey = EVP_PKEY_new();
if(evpKey == NULL) {
ERR("EVP_PKEY_new failed");
gotosafe_exit;
}
if((result = EVP_PKEY_set1_RSA(evpKey, rsa)) != 1) {
ERR("EVP_PKEY_set1_RSA failed");
gotosafe_exit;
}
EVP_MD_CTX_init(&ctx);
if(result == 1 && (result = EVP_SignInit_ex(&ctx,
EVP_sha1(), NULL)) != 1) {
ERR("EVP_SignInit_ex failed");
}
if(result == 1 && (result = EVP_SignUpdate(&ctx,
content.c_str(), content.size())) != 1) {
ERR("EVP_SignUpdate failed");
}
size = EVP_PKEY_size(evpKey);
sign = (char*)malloc(size+1);
memset(sign, 0, size+1);
if(result == 1 && (result = EVP_SignFinal(&ctx,
(unsigned char*)sign,
&size, evpKey)) != 1) {
ERR("EVP_SignFinal failed");
}
if(result == 1) {
verify = true;
} else{
ERR("verify failed");
}
signStr = base64_encode((constunsignedchar*)sign, size);
EVP_MD_CTX_cleanup(&ctx);
free(sign);
safe_exit:
if(rsa != NULL) {
RSA_free(rsa);
rsa = NULL;
}
if(evpKey != NULL) {
EVP_PKEY_free(evpKey);
evpKey = NULL;
}
if(bufio != NULL) {
BIO_free_all(bufio);
bufio = NULL;
}
returnsignStr;
}
private:
staticvoidERR(conststring &pre) {
ERR_load_crypto_strings();
charbuf[512];
ERR_error_string_n(ERR_get_error(), buf, sizeofbuf);
// log error here
}
};
// partner number, start with 2088
#define PARTNER ""
// alipay verify url, used to check notify_id
// to confirm the data is sent by alibaba
#define HTTPS_VERIFY_URL "https://mapi.alipay.com/gateway.do?service=notify_verify"
// our private key, PKCS#8 format
#define PRIVATE_KEY ""
// alipay public key, used to check data from alibaba
#define PUBLIC_KEY ""
#define SUBJECT ""
#define SELLER_ID ""
#define BODY ""
classAlipay {
public:
/* verify callback data */
staticboolverify(CgiUtil &cgi) {
string responseTxt = "true";
string notifyId = cgi.get_str("notify_id","");
if(!notifyId.empty()) {
responseTxt = verify_response(notifyId);
}
string sign = cgi.get_str("sign","");
boolisSign = get_sign_verify(cgi, sign);
if(isSign && responseTxt =="true") {
returntrue;
}
returnfalse;
}
staticstring get_order(conststring &oid,
unsigned intprice,conststring &cb_url) {
string orderInfo = get_order_info(oid, price, cb_url);
// we just support RSA right now, don't bother
string sign = Rsa::sign(PRIVATE_KEY, orderInfo);
stringstream ss;
ss <
<
<
<
<
returnss.str();
}
private:
staticstring get_order_info(conststring &oid,
unsigned intprice,conststring &cb_url) {
floatpayMoney = (float)price / 100.0;
string encode_url = url_encode(cb_url);
stringstream ss;
ss <
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
returnss.str();
}
staticstring verify_response(conststring ?ifyId) {
stringstream ss;
ss <
<
<
<
<
// do it yourself using curl
returncheck_alipay_cb_url(ss.str().c_str());
}
staticboolget_sign_verify(CgiUtil &cgi, string sign) {
std::map map;
para_filter(cgi, map);
string preSignStr = create_link_string(map);
boolisSign =false;
// RSA verify
if(Rsa::verify(PUBLIC_KEY, preSignStr, sign)) {
isSign = true;
}
returnisSign;
}
staticvoidpara_filter(CgiUtil &cgi,
std::map &hmap) {
vector entry = cgi.getElements();
vector::iterator it = entry.begin();
for(; it != entry.end(); it++) {
FormEntry fe = *it;
string name = fe.getName();
string value = fe.getValue();
if(value ==""|| iequal(name,"sign") ||
iequal(name, "sign_type")) {
continue;
}
hmap.insert(pair(name, value));
}
}
staticstring create_link_string(std::map &map) {
std::map::iterator it = map.begin();
unsigned intsize = map.size();
stringstream ss;
for(unsignedinti = 0; it != map.end() &&
i
if(i == size - 1) {
ss <first <second;
} else{
ss <first <second <
}
}
returnss.str();
}
staticstring url_encode(conststring &url) {
string encode = "";
char*data_encode = curl_easy_escape(NULL, url.c_str(), 0);
if(data_encode) {
encode = data_encode;
curl_free(data_encode);
}
returnencode;
}
};
#endif /* __ALIPAY_H__ */