记一次.Net5接入支付宝SDK的小插曲
由于业务需求,在项目里面要接入支付宝的支付功能,于是在github上找到了支付宝的官方sdk:https://hub.fastgit.org/alipay/alipay-easysdk
先说问题:
在按照官方实例的代码写了个demo,也就简单的一行,不愧是EasySDK,够easy
1 AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace()
2 .PreCreate("Apple iPhone11 128G", "2234567234890", "5799.00");
该代码在执行时,总抛出一个异常:

说字典不存在键 ”sign“ ,这异常给我看的的一愣一愣的,我当时想不通啊,这哪里来的这个东西。
仔细查看堆栈信息之后发现是SDK提供的方法PerCreate里面的问题,反手直接怼着源码就上了,进去一看:
1 public AlipayTradePrecreateResponse PreCreate(string subject, string outTradeNo, string totalAmount)
2 {
3 Dictionary<string, object> runtime_ = new Dictionary<string, object>
4 {
5 {"ignoreSSL", this._kernel.GetConfig("ignoreSSL")},
6 {"httpProxy", this._kernel.GetConfig("httpProxy")},
7 {"connectTimeout", 15000},
8 {"readTimeout", 15000},
9 {"retry", new Dictionary<string, int?>
10 {
11 {"maxAttempts", 0},
12 }},
13 };
14
15 TeaRequest _lastRequest = null;
16 Exception _lastException = null;
17 long _now = System.DateTime.Now.Millisecond;
18 int _retryTimes = 0;
19 while (TeaCore.AllowRetry((IDictionary) runtime_["retry"], _retryTimes, _now))
20 {
21 if (_retryTimes > 0)
22 {
23 int backoffTime = TeaCore.GetBackoffTime((IDictionary)runtime_["backoff"], _retryTimes);
24 if (backoffTime > 0)
25 {
26 TeaCore.Sleep(backoffTime);
27 }
28 }
29 _retryTimes = _retryTimes + 1;
30 try
31 {
32 TeaRequest request_ = new TeaRequest();
33 Dictionary<string, string> systemParams = new Dictionary<string, string>
34 {
35 {"method", "alipay.trade.precreate"},
36 {"app_id", this._kernel.GetConfig("appId")},
37 {"timestamp", this._kernel.GetTimestamp()},
38 {"format", "json"},
39 {"version", "1.0"},
40 {"alipay_sdk", this._kernel.GetSdkVersion()},
41 {"charset", "UTF-8"},
42 {"sign_type", this._kernel.GetConfig("signType")},
43 {"app_cert_sn", this._kernel.GetMerchantCertSN()},
44 {"alipay_root_cert_sn", this._kernel.GetAlipayRootCertSN()},
45 };
46 Dictionary<string, object> bizParams = new Dictionary<string, object>
47 {
48 {"subject", subject},
49 {"out_trade_no", outTradeNo},
50 {"total_amount", totalAmount},
51 };
52 Dictionary<string, string> textParams = new Dictionary<string, string>(){};
53 request_.Protocol = this._kernel.GetConfig("protocol");
54 request_.Method = "POST";
55 request_.Pathname = "/gateway.do";
56 request_.Headers = new Dictionary<string, string>
57 {
58 {"host", this._kernel.GetConfig("gatewayHost")},
59 {"content-type", "application/x-www-form-urlencoded;charset=utf-8"},
60 };
61 request_.Query = this._kernel.SortMap(TeaConverter.merge
62 (
63 new Dictionary<string, string>()
64 {
65 {"sign", this._kernel.Sign(systemParams, bizParams, textParams, this._kernel.GetConfig("merchantPrivateKey"))},
66 },
67 systemParams,
68 textParams
69 ));
70 request_.Body = TeaCore.BytesReadable(this._kernel.ToUrlEncodedRequestBody(bizParams));
71 _lastRequest = request_;
72 TeaResponse response_ = TeaCore.DoAction(request_, runtime_);
73
74 Dictionary<string, object> respMap = this._kernel.ReadAsJson(response_, "alipay.trade.precreate");
75 if (this._kernel.IsCertMode())
76 {
77 if (this._kernel.Verify(respMap, this._kernel.ExtractAlipayPublicKey(this._kernel.GetAlipayCertSN(respMap))))
78 {
79 return TeaModel.ToObject(this._kernel.ToRespModel(respMap));
80 }
81 }
82 else
83 {
84 if (this._kernel.Verify(respMap, this._kernel.GetConfig("alipayPublicKey")))
85 {
86 return TeaModel.ToObject(this._kernel.ToRespModel(respMap));
87 }
88 }
89 throw new TeaException(new Dictionary<string, string>
90 {
91 {"message", "验签失败,请检查支付宝公钥设置是否正确。"},
92 });
93 }
94 catch (Exception e)
95 {
96 if (TeaCore.IsRetryable(e))
97 {
98 _lastException = e;
99 continue;
100 }
101 throw e;
102 }
103 }
104
105 throw new TeaUnretryableException(_lastRequest, _lastException);
106 }
太长了不想看,于是直接另起个demo调试这段源码,发现每当走到第84行:this._kernel.Verify() 这句代码时就会出现异常,F12进去发现又是一个单独的程序集
通过dnSpy反编译看了一下这个方法的执行逻辑:

他直接从传入的字典中,读取了sign,可想而知当时传过去的字典肯定是没有这个键,回过头去看这个字典的内容,是读取的支付宝响应报文信息的
调试到verify执行前看了一下字典的内容

还真是,他并没有sign这个键,到这里我又楞住了,这... 这怎么玩?
响应报文没有这个键啊,咋整,总不能手动改个源码继续用吧,但是他这个校验,也是为了数据的安全性。
到这里得到两个信息:
1. 请求是能够正常收发的。
2. 抛出异常是因为代码判断了响应报文的sign,而响应报文没有sign。
只得从其他地方下手,响应报文提示无效的AppID参数,于是我重新核对了SDK的配置信息后再次调试,发现了问题所在。
在官方提供的demo中的配置信息是:
static private Config GetConfig()
{
return new Config()
{
Protocol = "https",
GatewayHost = "openapi.alipay.com",
SignType = "RSA2", AppId = "<-- 请填写您的AppId,例如:2019091767145019 -->", // 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
MerchantPrivateKey = "<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->", MerchantCertPath = "<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->",
AlipayCertPath = "<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->",
AlipayRootCertPath = "<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt -->", // 如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
// AlipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->" //可设置异步通知接收服务地址(可选)
NotifyUrl = "<-- 请填写您的支付类接口异步通知接收服务地址,例如:https://www.test.com/callback -->", //可设置AES密钥,调用AES加解密相关接口时需要(可选)
EncryptKey = "<-- 请填写您的AES密钥,例如:aa4BtZ4tspm2wnXLb1ThQA== -->"
};
}
我在测试时仅仅修改了注释掉的信息,忽略了上面的Protocol、GatwayHot、SignType,眼睛看的太快,发现HTTPS和RSA2都没啥问题,本能的认为GatewayHost也没啥问题,但是在我仔细查看支付宝沙箱环境提供的信息之后发现

沙箱的网关环境是openapi.alipaydev.com
这也就解释的通为什么他会提示AppID参数无效了
重新运行后的代码得到的响应报文为:

此时便能成功获取到sign了。
唉,也是怪自己太粗心了。
不过这种不判断键从字典拿数据,也有点内什么.... 如果不看源码,我还真不会想到是配置得问题
自己以后写代码,也会注意这些小细节了。
记一次.Net5接入支付宝SDK的小插曲的更多相关文章
- cocos2dx工程中接入支付宝sdk
1. 首先去支付宝官网下载开发者文档 2. 然后按着开发者文档将支付宝的sdk导入到你的工程中,并关联到工程中,步骤入下图: (1)将从支付宝官方网站获得的支付宝的sdk的jar包拷贝到工程中的lib ...
- cocos2d-x android工程接入第三方支付宝SDK
1. 首先去支付宝官网下载开发者文档 2. 然后按着开发者文档将支付宝的sdk导入到你的工程中,并关联到工程中,步骤入下图: (1)将从支付宝官方网站获得的支付宝的sdk的jar包拷贝到工程中的lib ...
- 接入支付宝出现交易订单处理失败,请稍后再试(ALI64)的错误【转】
接入第三方平台的时候,有时虽然按照文档来做,但是总是还会有各种各样的问题. 上次在接入支付宝的时候就碰到了交易订单处理失败,请稍后再试(ALI64)这样的错误,后来经过排查和总结,一般来讲这种问题都是 ...
- php接入支付宝的流程
php接入支付宝的流程写在这里供像我一样的小白参考. 1.首先要有一个创建一个应用(选好自己想要的功能,关于支付的功能,貌似都需要签约) 2.下载SDK&Dome(网址https://doc. ...
- thinkphp5.0 微信公众号接入支付宝支付
---恢复内容开始--- 真是无力吐槽这个需求了,想骂客户,好端端的非要在微信公众号接入支付宝,都知道微信公众号是拒绝支付宝的,屏蔽了支付宝,所以在微信公众号接入支付宝的话就必须手动复制链接跳出微信内 ...
- TP3.2.3 接入支付宝
TP3.2.3 接入支付宝 项目接入支付宝支付了,在做这个给我的感觉是,方便 ,毕竟是老马的产品是吧, 话不多说 , 首先我们先找到官方的SDK ,不想去找的小伙伴复制此链接 https://doc ...
- ASP.NET Core Web 支付功能接入 支付宝-电脑网页支付篇
这篇文章将介绍ASP.NET Core中使用 开源项目 Payment,实现接入支付宝-电脑网页支付接口及同步跳转及异步通知功能. 开发环境:Win 10 x64.VS2017 15.6.4..NET ...
- 集成支付宝SDK流程
5.2 SDK集成流程 5.2.1 iOS 解压接口压缩文件(文件名是 WS_MOBILE_PAY_SDK_BASE.zip),找到iOS的压缩文件(文件名是支付宝移动支付SDK 标准版(iOS).z ...
- 【转载】ASP.NET Core Web 支付功能接入 支付宝-电脑网页支付篇
转自:http://www.cnblogs.com/essenroc/p/8627775.html 这篇文章将介绍ASP.NET Core中使用 开源项目 Payment,实现接入支付宝-电脑网页支付 ...
随机推荐
- 深度学习框架集成平台C++ Guide指南
深度学习框架集成平台C++ Guide指南 这个指南详细地介绍了神经网络C++的API,并介绍了许多不同的方法来处理模型. 提示 所有框架运行时接口都是相同的,因此本指南适用于所有受支持框架(包括Te ...
- HAL库与Cubemx系列|Systick-系统滴答定时器详解
Systick是什么? 关于Systick,在Context-M3权威指南中如此描述: SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号: 15).在以前,大多操作系统需要一 ...
- Filebrowser 安装简介
官网地址: https://filebrowser.org https://github.com/filebrowser/filebrowser 官网安装方法: curl -fsSL https:// ...
- Shiro-JWT SpringBoot前后端分离权限认证的一种思路
JWT-Shiro 整合 JWT-与Shiro整合进行授权认证的大致思路 图示 大致思路 将登录验证从shiro中分离,自己结合JWT实现 用户登陆后请求认证服务器进行密码等身份信息确认,确认成功后 ...
- mybatis-generator的使用心得
之前开发了一个亚健康测评系统,使用的是SSM框架,里面第一次使用到了mybatis-generator逆向代码生成工具,很方便,省去了基本的增删改查的mapper文件及sql的编写,还能避免错误,这里 ...
- Django-Auth模块之auth_user表
一.Auth模块之auth_user表 在创建Django项目之后直接执行数据迁移命令会自动生成许多表. Django在启动之后就可以直接访问admin路由,需要输入用户名和密码,数据参考的就是aut ...
- .NET Core添加日志插件
二. 首先控制器的方法中写: private readonly ILogger<fluueController> _logger; public fluueController(ILogg ...
- 浅谈HttpDNS
今天了解了腾讯云的HTTPDNS,这里使用腾讯的资料以及网上查阅的资料做个记录. 对互联网高度依赖的企业,不可避免的需要通过域名来提供互联网服务,而在复杂的互联网环境下,域名被缓存,被劫持导致的业务影 ...
- 23、nginx动态添加nginx_upstream_check_module健康检查模块
nginx_upstream_check_module模块地址:https://github.com/yaoweibin/nginx_upstream_check_module 23.1.说明: 1. ...
- 13、windows下卸载oracle
13.1.停用oracle服务: 进入计算机管理,在服务中,找到oracle开头的所有服务,右击选择停止: 13.2.删除oracle: 在开始菜单中,找到oracle->Universal I ...