记一次.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,实现接入支付宝-电脑网页支付 ...
随机推荐
- 09:jQuery(02)
内容概要 jQuery操作标签 jQuery绑定事件 jQuery补充知识点 jQuery动画效果(了解) 零散补充 内容详细 jQuery练习题 $('#i1') r.fn.init [div#i1 ...
- 工具篇:介绍几个好用的guava工具类
前言 平时我们都会封装一些处理缓存或其他的小工具.但每个人都封装一次,重复造轮子,有点费时间.有没有一些好的工具库推荐-guava.guava是谷歌基于java封装好的开源库,它的性能.实用性,比我们 ...
- 《四大点,搞懂Redis到底快在哪里?》
一.开发语言 二.纯内存访问 三.单线程 四.非阻塞多路I/O复用机制 前言 Redis是一种基于键值对(Key-Value)的NoSQL数据库 ,Redis的Value可以由String,hash, ...
- Manacher(马拉车)————O(n)回文子串
Manacher 一.背景 1975年,Manacher发明了Manacher算法(中文名:马拉车算法),是一个可以在O(n)的复杂度中返回字符串s中最长回文子串长度的算法,十分巧妙. 让我们举个栗子 ...
- 拦截导弹(CDQ分治,DP)
很好的题,值得细细说,(果然又是个假期望)....... 首先我们提取信息,显然这是个三维偏序问题 用简单的DP式子表示需要满足 f[i]=max(f[1--j]+1)(v[j]<v[i],h[ ...
- WPF Frame 的 DataContext 不能被 Page 继承
转载至https://blog.csdn.net/sinat_31608641/article/details/88914517 已测试解决方案可行,因为WPF相关资料稀少,防止日后404,特搬运到自 ...
- 谈谈fork/join实现原理
害,又是一个炒冷饭的时间.fork/join是在jdk1.7中出现的一个并发工作包,其特点是可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并进行输出.从而达到多 ...
- Ubuntu18.04下安装Docker并配置SSL证书加密远程连接
Docker下载与安装 下载安装包 国内网络连接docker镜像还是比较慢的,这里推荐直接下载docker镜像,Ubuntu镜像下载路径为:https://download.docker.com/li ...
- 31、服务器磁盘、内存、cpu使用率监控
31.1.监控磁盘: #!/bin/sh diskspace="`df -hT`" IFS="\n" disk_value="80" ech ...
- ROS2学习之旅(1)——初识ROS2
本系列用来记录ROS2的学习过程,有错误或者不合理的地方请大家指正.由于博主具有ROS1的学习经历,会添加一些与ROS1的一些对比,当然这对于ROS2本身的学习内容没有丝毫影响,欢迎大家积极与我在评论 ...