链接:https://github.com/ArthasModern/AlipayOpenapiCpp

如果你想以C\C++方式接入支付宝开放平台调用支付宝的各种开放接口(比如收款等),那么你可以参考这个项目;

这个项目里帮你解决了参数组装、排序、OpenSSL加签验签、网络请求等问题,能帮助你轻松接入支付宝;

并且该项目依赖C\C++标准库STL以及几个开源的第三方库,代码精简(只有几个class),非常易于集成;

使用起来很简便:

#include <iostream>
#include "stdlib.h"#define _DEBUG#include "openapi/openapi_client.h"using namespace std;/** ++++++++++++++++++++++++++++++++++++++++++++++++ **/
/** 此处替换为开发者在支付宝开放平台申请的应用ID **/
string appId = "2016000066668888";/** 此处替换为开发者使用openssl生成的rsa私钥 **/
string pKey = "-----BEGIN RSA PRIVATE KEY-----\n""MIICXQIBAAKBgQDTI0/RaV/YKWDGbKkQGYpD9I/UljBCCf3rWm09sXiif8MN5rLA\n""3TjC4gZ478n6Dys5yO23h1HGVTWu+mQ8071+pwLHGQ+dyDNrGWR89VLb9yanOeRf\n""efOcN19ATZgGAzheM28E/iqaYkh8F2NlCjOiZAsBG6eVvxachwVAQUIWwwIDAQAB\n""AoGAdVr8Q46JenHNW50L/2niw1DNHUF5g0tgeo+hhpf9UH0pIrHnC3Iq2Y+eP1ww\n""7K+/u/elwcwSNOYp159PVcvvV9LwPwH29DdH6KEWIDiyFpjbXPcMMFwgakyLnFTL\n""sxxa6DYznFokT+IPkF6esoypa7VQFU1RIal5Sgphq7CGCDECQQDqyL3QjYT6ffLd\n""NRiMBB13+eIxvXGy5AEQcH4pNt6kYHWONCWeZ34miNp2UliIBvBHZ1uuGoO4F/Jx\n""2sWwWlSpAkEA5jeQGFx/RDzzi0qPMpSOR50d2IC4NbbresY+hgJEBbI6n5hPR1ts\n""MUuO1e3L5I5rzRKNzD1um1DdSgmqaqmHiwJBANLnRpNsPRMjRqHtS0Kjg7E9mDIk\n""Qll3NXmGA96T+oXgXFlEgLJ9tzV4Y/471GlFClyp/RI1oTMi19fstP7I9hkCQBjr\n""bseUS5phVqN/QJzjA7uwwChNVqNJ15eEmgP7fs13C213GS3KMZ3sZdu2T9m/qN+b\n""4Il5JN3fFPUMssu06h0CQQCGBdmtRLi+9ws57qTPHR/BdHGUxdBRWllc9sGVVaRw\n""+EOMGXus6/BssTRjwplx7w8uUR0U3s1KYDJMHMCjW25x\n""-----END RSA PRIVATE KEY-----";/** 支付宝公钥,用来验证支付宝返回请求的合法性 **/
string aliPubKey = "-----BEGIN PUBLIC KEY-----\n""MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkr\n""IvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsra\n""prwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUr\n""CmZYI/FCEa3/cNMW0QIDAQAB\n""-----END PUBLIC KEY-----";/** 注:appid,私钥,支付宝公钥等信息建议不要写死在代码中 **/
/** 这些信息应以配置等方式保存,此处写在代码中只是为了示例的简便 **/
/** ++++++++++++++++++++++++++++++++++++++++++++++++ **//** some examples **/
JsonMap getPrecreateContent();int main(int argc, char *argv[])
{/** 实例化OpenapiClient工具类 **/OpenapiClient openapiClient(appId,pKey,OpenapiClient::default_url,OpenapiClient::default_charset,aliPubKey);/** ++++++++++++++++++++++++++++++++++++++++++++++++ **//** 各个具体业务接口参数组装模式具体参看Openapi官方文档 **//** https://doc.open.alipay.com/ **/// demo1:当面付预下单示例string method = "alipay.trade.precreate";JsonMap contentMap = getPrecreateContent();/** ++++++++++++++++++++++++++++++++++++++++++++++++ **//** ++++++++++++++++++++++++++++++++++++++++++++++++ **//** 网关扩展参数,例如商户需要回传notify_url等,可以在extendParamMap中传入 **//** 这是一个可选项,如不需要,可不传 **//* StringMap extendParamMap;extendParamMap.insert(StringMap::value_type("notify_url", "http://api.test.alipay.net/atinterface/receive_notify.htm"));*//** ++++++++++++++++++++++++++++++++++++++++++++++++ **//** 调用Openapi网关 **/JsonMap respMap;respMap = openapiClient.invoke(method, contentMap);/* 如果有扩展参数,则按如下方式传入respMap = openapiClient.invoke(method, contentMap, extendParamMap);*//** 解析支付宝返回报文 **/JsonMap::const_iterator iter = respMap.find("code");if (iter != respMap.end()) {string respCode = iter->second.toString();DebugLog("code:%s", respCode.c_str());} else {DebugLog("cannot get code from response");}iter = respMap.find("msg");if (iter != respMap.end()) {string respMsg = iter->second.toString();DebugLog("msg:%s", respMsg.c_str());} else {DebugLog("cannot get msg from response");}system("pause");return 0;
}/*** 组装支付宝预下单业务请求*/
JsonMap getPrecreateContent() {JsonMap contentMap;contentMap.insert(JsonMap::value_type(JsonType("out_trade_no"), JsonType("20160606121212")));contentMap.insert(JsonMap::value_type(JsonType("total_amount"), JsonType(0.01)));contentMap.insert(JsonMap::value_type(JsonType("subject"), JsonType("好东西")));return contentMap;
}

Readme.txt:

该项目为C++项目,包含访问支付宝开放平台(Openapi)网关的源码;/** ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ **/工程中有两个项目文件:
Openapi.pro为QtCreater项目文件,可用QtCreater打开;
Openapi.sln为VS(2008版)项目文件,可用VS打开;注:该项目源码依赖C\C++标准库(STL)以及几个开源的第三方库(cJSON,libcurl,openssl);
开发者可以在其它支持C\C++的平台(linux等)编译适配;/** ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ **/项目主要源码包含在目录“/openapi”中;1)主工具类 -- ./openapi/openapi_client
---- 访问支付宝开放平台(openapi)网关的工具类;
---- 外部主要依赖该类访问支付宝网关;
---- 具体使用示例可参见main.cpp中的源码及注释;2)其它依赖的工具类:
HttpClient -- ./openapi/http/http_client
---- 该工具类提供Http(Https)网络通信的功能;
---- 该工具类依赖第三方库libcurlJsonUtil -- ./openapi/json/json_util
---- 该工具类提供Json串与C++对象之间的转换功能;
---- 该工具类依赖第三方库cJSON;openssl & libcurl -- ./libs/
---- 这两个第三方库已经编译成静态库(windows平台);
---- 其它平台的静态库,开发者可自行下载源码进行编译;/** ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ **/集成/调试之前的准备工作:1)入住支付宝开放平台,申请应用并获得应用ID(appId);2)本地生成rsa密钥对,并上传公钥到支付宝开放平台相应的应用下,并保存好自己的私钥(privateKey -- 严格保密);rsa密钥生成方式参看支付宝开放平台官方文档;注:C++使用的是标准格式的rsa私钥,不是pkcs8格式的;3)各个具体业务接口参数组装模式具体参看Openapi官方文档;4)支付宝开放平台文档中心:https://doc.open.alipay.com/

其中关键工具类的构建如下:

#ifndef OPENAPICLIENT_H
#define OPENAPICLIENT_H#include "http/http_client.h"
#include "json/json_util.h"
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <time.h>#ifndef XRSA_KEY_BITS
#define XRSA_KEY_BITS (1024)
#endif/** STL map default sort order by key **/
typedef map<string, string> StringMap;/*** @brief The OpenapiClient class*/
class OpenapiClient {
public:OpenapiClient(const string &appId,const string &privateKey,const string &url = default_url,const string &charset = default_charset,const string &alipayPublicKey = string());public:static const string default_charset;static const string default_url;static const string default_sign_type;static const string default_version;static const string KEY_APP_ID;static const string KEY_METHOD;static const string KEY_CHARSET;static const string KEY_SIGN_TYPE;static const string KEY_SIGN;static const string KEY_TIMESTAMP;static const string KEY_VERSION;static const string KEY_BIZ_CONTENT;private:string appId;string privateKey;string signType;string version;string charset;string url;string alipayPublicKey;public:string invoke(const string &method, const string &content, const StringMap &extendParamMap = StringMap());JsonMap invoke(const string &method, const JsonMap &contentMap, const StringMap &extendParamMap = StringMap());private:/**** STL map default sort order by key** STL map 默认按照key升序排列* 这里要注意如果使用的map必须按key升序排列**/string buildContent(const StringMap &contentPairs);string analyzeResponse(const string &responseStr);public:static string base64Encode(const unsigned char *bytes, int len);static bool base64Decode(const string &str, unsigned char *bytes, int &len);static string rsaSign(const string &content, const string &key);static bool rsaVerify(const string &content, const string &sign, const string &key);public:string getAppId();string getSignType();string getVersion();string getCharset();string getUrl();string getAlipayPublicKey();};#endif // OPENAPICLIENT_H

源文件:

#include "openapi_client.h"const string OpenapiClient::default_charset      = "utf-8";
const string OpenapiClient::default_url          = "https://openapi.alipay.com/gateway.do";
const string OpenapiClient::default_sign_type    = "RSA";
const string OpenapiClient::default_version      = "2.0";const string OpenapiClient::KEY_APP_ID           = "app_id";
const string OpenapiClient::KEY_METHOD           = "method";
const string OpenapiClient::KEY_CHARSET          = "charset";
const string OpenapiClient::KEY_SIGN_TYPE        = "sign_type";
const string OpenapiClient::KEY_SIGN             = "sign";
const string OpenapiClient::KEY_TIMESTAMP        = "timestamp";
const string OpenapiClient::KEY_VERSION          = "version";
const string OpenapiClient::KEY_BIZ_CONTENT      = "biz_content";OpenapiClient::OpenapiClient(const string &appId,const string &privateKey,const string &url,const string &charset,const string &alipayPublicKey): appId(appId),privateKey(privateKey),signType(default_sign_type),version(default_version),url(url),charset(charset),alipayPublicKey(alipayPublicKey) {}JsonMap OpenapiClient::invoke(const string &method, const JsonMap &contentMap, const StringMap &extendParamMap) {string content = JsonUtil::objectToString(JsonType(contentMap));string responseContent = invoke(method, content, extendParamMap);JsonType jsonObj = JsonUtil::stringToObject(responseContent);return jsonObj.toMap();
}string OpenapiClient::invoke(const string &method, const string &content, const StringMap &extendParamMap) {time_t t = time(0);char tmp[64];strftime(tmp, sizeof(tmp), "%Y-%m-%d %X", localtime(&t));StringMap requestPairs;requestPairs.insert(StringMap::value_type(OpenapiClient::KEY_APP_ID, appId));requestPairs.insert(StringMap::value_type(OpenapiClient::KEY_BIZ_CONTENT, content));requestPairs.insert(StringMap::value_type(OpenapiClient::KEY_CHARSET, charset));requestPairs.insert(StringMap::value_type(OpenapiClient::KEY_METHOD, method));requestPairs.insert(StringMap::value_type(OpenapiClient::KEY_SIGN_TYPE, signType));requestPairs.insert(StringMap::value_type(OpenapiClient::KEY_TIMESTAMP, tmp));requestPairs.insert(StringMap::value_type(OpenapiClient::KEY_VERSION, version));/** 追加外部传入的网关的补充参数,如notify_url等 **/for (StringMap::const_iterator iter = extendParamMap.begin(); iter != extendParamMap.end(); ++iter) {requestPairs.insert(StringMap::value_type(iter->first, iter->second));}string wholeContent = buildContent(requestPairs);string sign = OpenapiClient::rsaSign(wholeContent, privateKey);requestPairs.insert(StringMap::value_type(OpenapiClient::KEY_SIGN, sign));wholeContent = buildContent(requestPairs);DebugLog("Request:%s", wholeContent.c_str());HttpClient httpClient;string responseStr = httpClient.sendSyncRequest(url, requestPairs);DebugLog("Response:%s", responseStr.c_str());string responseContent = analyzeResponse(responseStr);return responseContent;
}/**** STL map default sort order by key** STL map 默认按照key升序排列* 这里要注意如果使用的map必须按key升序排列**/
string OpenapiClient::buildContent(const StringMap &contentPairs) {string content;for (StringMap::const_iterator iter = contentPairs.begin();iter != contentPairs.end(); ++iter) {if (!content.empty()) {content.push_back('&');}content.append(iter->first);content.push_back('=');content.append(iter->second);}return content;
}string OpenapiClient::analyzeResponse(const string &responseStr) {JsonType responseObj = JsonUtil::stringToObject(responseStr);JsonMap responseMap = responseObj.toMap();//获取返回报文中的alipay_xxx_xxx_response的内容;int beg = responseStr.find("_response\"");int end = responseStr.rfind("\"sign\"");if (beg < 0 || end < 0) {return string();}beg = responseStr.find('{', beg);end = responseStr.rfind('}', end);//注意此处将map转为json之后的结果需要与支付宝返回报文中原格式与排序一致;//排序规则是节点中的各个json节点key首字母做字典排序;//Response的Json值内容需要包含首尾的“{”和“}”两个尖括号,双引号也需要参与验签;//如果字符串中包含“http://”的正斜杠,需要先将正斜杠做转义,默认打印出来的字符串是已经做过转义的;//此处转换之后的json字符串默认为"Compact"模式,即紧凑模式,不要有空格与换行;string responseContent = responseStr.substr(beg, end - beg + 1);DebugLog("ResponseContent:%s", responseContent.c_str());//此处为校验支付宝返回报文中的签名;//如果支付宝公钥为空,则默认跳过该步骤,不校验签名;//如果支付宝公钥不为空,则认为需要校验签名;if (!alipayPublicKey.empty()) {DebugLog("AlipayPublicKey:%s", alipayPublicKey.c_str());JsonMap::const_iterator iter = responseMap.find(OpenapiClient::KEY_SIGN);if (iter == responseMap.end()) {DebugLog("Cannot get Sign from response, Verify Failed");return string();}//获取返回报文中的sign;string responseSign = iter->second.toString();DebugLog("ResponseSign:%s", responseSign.c_str());//调用验签方法;bool verifyResult = OpenapiClient::rsaVerify(responseContent, responseSign, alipayPublicKey);if (!verifyResult) {DebugLog("Verify Failed");return string();}DebugLog("Verify Success");} else {DebugLog("AlipayPublicKey is empty, Skip the Verify");}return responseContent;
}string OpenapiClient::rsaSign(const string &content, const string &key) {string signed_str;const char *key_cstr = key.c_str();int key_len = strlen(key_cstr);BIO *p_key_bio = BIO_new_mem_buf((void *)key_cstr, key_len);RSA *p_rsa = PEM_read_bio_RSAPrivateKey(p_key_bio, NULL, NULL, NULL);if (p_rsa != NULL) {const char *cstr = content.c_str();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 = base64Encode(sign, sign_len);}}RSA_free(p_rsa);BIO_free(p_key_bio);return signed_str;
}bool OpenapiClient::rsaVerify(const string &content, const string &sign, const string &key) {bool result = false;const char *key_cstr = key.c_str();int key_len = strlen(key_cstr);BIO *p_key_bio = BIO_new_mem_buf((void *)key_cstr, key_len);RSA *p_rsa = PEM_read_bio_RSA_PUBKEY(p_key_bio, NULL, NULL, NULL);if (p_rsa != NULL) {const char *cstr = content.c_str();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);BIO_free(p_key_bio);return result;
}string OpenapiClient::base64Encode(const unsigned char *bytes, int len) {BIO *bmem = NULL;BIO *b64 = NULL;BUF_MEM *bptr = NULL;b64 = BIO_new(BIO_f_base64());BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);bmem = BIO_new(BIO_s_mem());b64 = BIO_push(b64, bmem);BIO_write(b64, bytes, len);BIO_flush(b64);BIO_get_mem_ptr(b64, &bptr);string str = string(bptr->data, bptr->length);BIO_free_all(b64);return str;
}bool OpenapiClient::base64Decode(const string &str, unsigned char *bytes, int &len) {const char *cstr = str.c_str();BIO *bmem = NULL;BIO *b64 = NULL;b64 = BIO_new(BIO_f_base64());BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);bmem = BIO_new_mem_buf((void *)cstr, strlen(cstr));b64 = BIO_push(b64, bmem);len = BIO_read(b64, bytes, len);BIO_free_all(b64);return len > 0;
}string OpenapiClient::getAppId() {return appId;
}string OpenapiClient::getSignType() {return signType;
}string OpenapiClient::getVersion() {return version;
}string OpenapiClient::getCharset() {return charset;
}string OpenapiClient::getUrl() {return url;
}string OpenapiClient::getAlipayPublicKey() {return alipayPublicKey;
}

支付宝开放平台C++方式接入相关推荐

  1. 支付宝开放平台开发助手_支付宝:如何创建和接入支付宝电脑网站支付-新手必备...

    1.登录支付宝 1.打开支付宝官网,以"我是支付宝商家"用户登录 https://www.alipay.com/ 2.进入"产品中心",选择并申请支付类型 2. ...

  2. 支付宝开放平台api接口封装统一调用方式

    在对接支付宝过程中,发现支付宝每个接口例子,都定义了AlipayClient和xxxRequest.xxxResponse. 老的写法就是每次都去写new一个AlipayClient package ...

  3. Node接入支付宝开放平台的沙箱实现支付功能

    一些重要的支付宝沙箱文档及网址 支付宝开放平台:https://open.alipay.com/ 简单介绍:https://www.yuque.com/chenqiu/alipay-node-sdk/ ...

  4. Go语言接入支付宝开放平台

    首先登录支付宝开放平台 https://open.alipay.com/platform/home.htm 身份验证什么的按照提示来就行 选择 开发中心-网页&移动应用,选择应用类型 ,写名字 ...

  5. c语言 支付宝接口开发平台,支付宝开放平台的C++版接入代码

    该项目为C++项目,包含访问支付宝开放平台(Openapi)网关的源码: /** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...

  6. php对接支付宝当面付对接,支付宝开放平台当面付对接网站

    最近才发现当面付这个支付宝官方审核不严格,不审核网站有没有备案,比直接对接支付宝的电脑手机支付好. 先去支付宝商家用户中心签约下当面付功能,不过据说现在当面付签约要求挺严格的,需要门头照啥的,我们旗下 ...

  7. android支付宝开放平台开发,支付宝开放平台支付更新升级全解析

    由于支付宝增加开放平台的概念,支付申请和调用有了较大的更新和升级,本篇文章会带你介绍开放平台的支付申请方式和新支付接口和之前的区别. 0 系列文章 1 背景介绍 支付宝现在开始着重推开发平台这个概念, ...

  8. 在线支付系列【24】支付宝开放平台产品介绍

    有道无术,术尚可求,有术无道,止于术. 文章目录 前言 支付产品 App 支付 手机网站支付 电脑网站支付 新当面资金授权 当面付 营销产品 营销活动送红包 会员产品 App 支付宝登录 人脸认证 信 ...

  9. 支付宝支付_支付宝开放平台_API _SpringBoot_沙箱环境

    文章目录 一.支付宝接口 1-1]官网中设置 配置信息 1-2]创建项目 1-3]测试 及 Bug 排除 一.支付宝接口 1-1]官网中设置 配置信息 注:未登录方式 -- 百度[支付宝开放平台]-[ ...

最新文章

  1. 注会用计算机,注会准备什么计算器?有型号要求吗?
  2. windows使用ssh2远程登陆ubuntu
  3. 使用Charles在iOS6上进行抓包
  4. P4430-小猴打架【perfer序列】
  5. php中source,PHP中source #N问题的解决方法
  6. php生成cookie在哪,php程序中cookie的使用方法
  7. 行政区划代码转为字典形式
  8. chmod简介及其使用方法
  9. Web App开发入门
  10. 华硕物联网机器人今年推出 开发进入最后阶段
  11. 机器学习编译入门课程学习笔记第一讲 机器学习编译概述
  12. 几何向量:空间三角形内心
  13. php开发支付宝支付密码忘记了怎么办_php开发支付宝支付密码忘记了怎么办_玩机小技巧:OPPO手机忘记锁屏密码怎么办?......
  14. 小象学院——面向对象的特点
  15. 获取java时间 小时_Java 如何获取当前时间前一个小时的时间
  16. 最近成了三等奖专业户
  17. 趣学算法NYOJ加勒比海盗船
  18. Flink (四) Flink 的安装和部署- Flink on Yarn 模式 / 集群HA / 并行度和Slot
  19. android资源列表对应国家名称
  20. div与p标签均为块级元素,区别是什么?

热门文章

  1. 设备配置的保存命令【save详解】
  2. 日语助词まで的语法汇总,请牢记
  3. KITTI 数据集--下载链接
  4. raid5通常需要几块盘_Raid什么意思 Raid5需要几块硬盘?
  5. 展现量、点击量、点击率
  6. 【软件测试小知识】冷启动和热启动
  7. GraphIA: An In-situ Accelerator for Large-scale Graph Processing
  8. Ubuntu18.04安装安装ROS2-Dashing
  9. linux smartgit客户端,跨平台Git客户端SmartGit 18.1.5发布下载
  10. mysql数据库常规备份还原 (常用增量备份)2018_lcf