由于业务需求,在项目里面要接入支付宝的支付功能,于是在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的小插曲的更多相关文章

  1. cocos2dx工程中接入支付宝sdk

    1. 首先去支付宝官网下载开发者文档 2. 然后按着开发者文档将支付宝的sdk导入到你的工程中,并关联到工程中,步骤入下图: (1)将从支付宝官方网站获得的支付宝的sdk的jar包拷贝到工程中的lib ...

  2. cocos2d-x android工程接入第三方支付宝SDK

    1. 首先去支付宝官网下载开发者文档 2. 然后按着开发者文档将支付宝的sdk导入到你的工程中,并关联到工程中,步骤入下图: (1)将从支付宝官方网站获得的支付宝的sdk的jar包拷贝到工程中的lib ...

  3. 接入支付宝出现交易订单处理失败,请稍后再试(ALI64)的错误【转】

    接入第三方平台的时候,有时虽然按照文档来做,但是总是还会有各种各样的问题. 上次在接入支付宝的时候就碰到了交易订单处理失败,请稍后再试(ALI64)这样的错误,后来经过排查和总结,一般来讲这种问题都是 ...

  4. php接入支付宝的流程

    php接入支付宝的流程写在这里供像我一样的小白参考. 1.首先要有一个创建一个应用(选好自己想要的功能,关于支付的功能,貌似都需要签约) 2.下载SDK&Dome(网址https://doc. ...

  5. thinkphp5.0 微信公众号接入支付宝支付

    ---恢复内容开始--- 真是无力吐槽这个需求了,想骂客户,好端端的非要在微信公众号接入支付宝,都知道微信公众号是拒绝支付宝的,屏蔽了支付宝,所以在微信公众号接入支付宝的话就必须手动复制链接跳出微信内 ...

  6. TP3.2.3 接入支付宝

    TP3.2.3 接入支付宝 项目接入支付宝支付了,在做这个给我的感觉是,方便 ,毕竟是老马的产品是吧, 话不多说 , 首先我们先找到官方的SDK  ,不想去找的小伙伴复制此链接 https://doc ...

  7. ASP.NET Core Web 支付功能接入 支付宝-电脑网页支付篇

    这篇文章将介绍ASP.NET Core中使用 开源项目 Payment,实现接入支付宝-电脑网页支付接口及同步跳转及异步通知功能. 开发环境:Win 10 x64.VS2017 15.6.4..NET ...

  8. 集成支付宝SDK流程

    5.2 SDK集成流程 5.2.1 iOS 解压接口压缩文件(文件名是 WS_MOBILE_PAY_SDK_BASE.zip),找到iOS的压缩文件(文件名是支付宝移动支付SDK 标准版(iOS).z ...

  9. 【转载】ASP.NET Core Web 支付功能接入 支付宝-电脑网页支付篇

    转自:http://www.cnblogs.com/essenroc/p/8627775.html 这篇文章将介绍ASP.NET Core中使用 开源项目 Payment,实现接入支付宝-电脑网页支付 ...

随机推荐

  1. 使用Nucleus SE实时操作系统

    使用Nucleus SE实时操作系统 Using the Nucleus SE real-time operating system 到目前为止,在本系列文章中,我们详细介绍了Nucleus SE提供 ...

  2. C语言代码区错误以及编译过程

    C语言代码区错误 欲想了解C语言代码段会有如何错误,我们必须首先了解编译器是如何把C语言文本信息编译成为可以执行的机器码的. 背景介绍 测试使用的C语言代码 导入标准库,定义宏变量,定义结构体,重命名 ...

  3. Python集合:set

    集合 集合的描述 set是一个无序不重复的序列,可以用{}或者 set() 函数创建集合,它存放不可变类型(如字符串.数字.元组)数据. 注意:创建一个空集合必须使用set()方法,因为{}是用来生成 ...

  4. QueryTable的使用以及错误

    1.QuerySeter的filter使用遇到的错误 1.1 Filter里的字段名和操作符要用双下划线."__" 不是" _",否则会被认为成是列名的一部分, ...

  5. NOIP模拟测试8「寿司」

    考试时打的类似$n^2$暴力,然后炸了只有10分 后来验证我的算法伪了. 题解 显然你有一种解法,假设你要在一个B点断开将R分别移向最左 最右,这样只用分别计算B点右面蓝色数量左面蓝色数量就得到了一个 ...

  6. 【源码分析】- 在SpringBoot中你会使用REST风格处理请求吗?

    ​ 目录 前言 1.什么是 REST 风格 1.1  资源(Resources) 1.2  表现层(Representation) 1.3  状态转化(State Transfer) 1.4  综述 ...

  7. .NET Core/.NET5/.NET6 开源项目汇总5:权限管理系统项目

    系列目录     [已更新最新开发文章,点击查看详细] 企业管理系统一般包含后台管理UI.组织机构管理.权限管理.日志.数据访问.表单.工作流等常用必备功能.下面收集的几款优秀开源的管理系统,值得大家 ...

  8. Golang学习(用代码来学习) - 第一篇

    package main import ( "fmt" "time" "unsafe" ) //示例代码 var isActive bool ...

  9. Tkinter 吐槽之一:多线程与 UI 交互

    背景 最近想简单粗暴的用 Python 写一个 GUI 的小程序.因为 Tkinter 是 Python 自带的 GUI 解决方案,为了部署方便,就直接选择了 Tkinter. 本来觉得 GUI 发展 ...

  10. js笔记11

    1.针对表单的 from  input  select  textarea type="radio/checkbox/password/button/tetx/submit/reset/&q ...