由于业务需求,在项目里面要接入支付宝的支付功能,于是在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. 作为一名双非本科毕业的Java程序员,我该如何在日益严重的内卷化中避免被裁?

    前言 对一个 Java 程序员而言,并发编程能否熟练掌握是判断他是不是优秀的重要标准之一.因为并发编程在 Java 语言中最为晦涩的知识点,它涉及内存.CPU.操作系统.编程语言等多方面的基础能力,更 ...

  2. XML文件存在中文注释报错问题( 3 字节的 UTF-8 序列的字节 3 无效)

    今天在做mybatis项目的时候,给映射文件添加了中文注释后,程序就报错.把中文注释删除后,程序又可以正常执行.解决方法在下文提到. 我的xml映射文件如下: <?xml version=&qu ...

  3. 一、Nginx的安装

    1.下载nginx软件 http://nginx.org/download/ 2.安装依赖包 [root@client ~]# useradd -s /sbin/nologin nginx 创建ngi ...

  4. 【NX二次开发】创建老版的基准平面uf5374

    使用uf5374() 源码: double dP1[3] = { 0.0,0.0,0.0 }; double dP2[3] = { 0.0,1.0,0.0 }; double dP3[3] = { 0 ...

  5. 练习(time.tick定时器监控数据库)

    设立个定时器,监控数据库里fb_state(发布状态),并将数据库中一条记录的开始时间与截止时间和当前时间进行比对.若当前时间在开始时间与结束时间之间,则将发布状态设为1,否则为0. 同时,将此段代码 ...

  6. Django基础之cookie与session

    cookie与session 由来及简介 HTTP协议四大特性 1.基于请求响应 2.基于TCP.IP作用于应用层之上 3.无连接 4.无状态 基于HTTP协议的通信无法记录客户端状态 但是现在很多软 ...

  7. Nginx为什么能快到根本停不下来?

    Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名.本文从底层原理分析 Nginx 为什么这么快! Nginx 的进程模型 Nginx 服务器,正常运行过程中: 多进程:一个 M ...

  8. DOS命令行(10)——reg/regini-注册表编辑命令行工具

    注册表的介绍 注册表(Registry,台湾.港澳译作登錄檔)是Microsoft Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息.   1. 数据结构 注册表由键(key,或称 ...

  9. Java安全之Weblogic内存马

    Java安全之Weblogic内存马 0x00 前言 发现网上大部分大部分weblogic工具都是基于RMI绑定实例回显,但这种方式有个弊端,在Weblogic JNDI树里面能将打入的RMI后门查看 ...

  10. Linux中系统时间同步ntpdate简介

    Linux服务器运行久时,系统时间就会存在一定的误差,一般情况下可以使用date命令进行时间设置,但在做数据库集群分片等操作时对多台机器的时间差是有要求的,此时就需要使用ntpdate进行时间同步.所 ...