在App中对接微信和支付宝

目录

准备工作

微信登录和支付

支付宝登录和支付

对比

准备工作

微信

注册微信开放平台,成为开发者(开发)

微信开放平台

注册你的App,会给你一个AppId和AppSecret

AppID和AppSecret

注册微信商户平台,成为商户(收钱)

微信商户平台

会给你一个商户ID

商户ID

共有三个ID:AppID、AppSecret、PID

支付宝

注册蚂蚁金服开放平台,成为开发者(开发)

开放平台

开放平台会给你的App一个AppId(支付宝没有AppSecret)

AppId

注册蚂蚁金服商家中心,成为商家(收钱)

商家中心

商家中心会给你一个商家ID

商家ID

共有两个ID:AppID、PID

微信登录和支付

开放平台创建应用

首先,你在微信开放平台上要有自己的应用

应用上开放平台

平台会让你上传你的App的logo,名称,简述什么的,因为这些在你调用微信App的时候用得着。

微信登录

微信第三方授权登录

首先,要在开放平台中为你的App申请相关接口(微信登录是默认开放给你的)

开放平台申请接口功能

然后,就是代码工作了。

我是用ShareSDK套件统一实现的微信登录,集成ShareSDK的方法见在App中集成ShareSDK

登录过程就是调用ShareSDK的函数,传入微信登录的参数

调起ShareSDK登录

然后,用一个listener去监听登录授权

登录授权

这个listener会监听到一个Platform对象,从Plateform对象中可以取出用户id、昵称、头像等

取出用户信息

so easy

多么美好

微信支付

微信第三方支付

支付的基本流程

实现微信支付,流程上比登录复杂多了,具体流程如下:

1.授权

微信第三方支付是需要去开放平台申请权限的:

申请微信支付

2.签约

相关的商家需要去在线签约:

签约

3.文档

微信在官方文档中提供了很多种支付方式,我们使用的是其中的App支付:

多种支付方式

查看微信App支付官方文档

根据官方文档,支付流程如下:

微信支付流程

看起来很复杂,其实大概分这么几步:

1.你的业务服务器和微信后台交互生成订单,微信后台给业务服务器一个预交易订单号

(微信后台准备好支付数据)

2.你的业务服务器给你的App预交易订单号

(你的后台通知你的App去调起微信支付)

3.你的App调起微信App支付,把预交易订单号传给微信App

(你的App发起微信App支付)

4.微信App告知你的App支付完成,微信后台告知你的业务服务器支付完成

(App对App,后台对后台)

整个故事情节大概是这样的

支付故事情节

需要注意的是,微信官方文档有这么一句话:

注意一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准。

就是说,你的App只负责触发下一步业务流程,是否支付成功要以你的业务服务器收到的通知为准。

支付的具体实现

代码实现上,微信的官方文档说的挺明白的,照做吧:

1.在gradle里添加引用

添加引用

2.初始化一个IWXAPI实例

初始化IWXAPI

3.利用IWXAPI实例去请求调起支付

调起支付

4.实现一个给微信支付回调的Activity

回调Activity

在支付完成时,微信App会自动打开这个回调Activity,如果你没有定义这个Activity的外观,你会发现,手机白屏了

白屏

你可以好好画画这个Activity的界面,也可以不去管它,在完成下面的操作后,直接关掉。

这个回调Activity,主要功能是接收微信反馈的支付结束事件

接收支付反馈

反馈的BaseResp对象没啥有用信息,因为微信的App支付接口纯粹是个触发器,只能用来通知支付结束,你从它的反馈信息里,无法得到订单号。

那业务服务器怎么知道是哪个订单完成了支付呢?

你的App和业务服务器自己想办法吧。

我能怎么办,我也很无奈啊

支付宝登录和支付

【高能预警】支付宝的文档,真的超级烂!超级烂!超级烂!可以信任它的支付,不可以信任它的文档!

【严正警告】除了你抓到的真实数据,不要相信支付宝的官方文档和Demo代码,要小心支付宝!要小心支付宝!要小心支付宝!

开放平台创建应用

首先,你在蚂蚁金服开放平台上要有自己的应用

应用上开放平台

平台会让你上传你的App的logo,名称,简述什么的,因为这些在你调用支付宝App的时候用得着。

支付宝登录

支付宝第三方登录

ShareSDK里没有集成支付宝登录,我们需要自己实现。

登录的基本流程

1.授权

首先,你要去开放平台请求授权

进入蚂蚁金服开放平台

每个App有对应的授权功能列表

在开放平台为你的App申请授权

点击图中右上角的“继续添加”,可以看到支付宝提供的接口列表,其中有很多迷惑性的名字,要选择恰当的接口服务,我们需要选择的是App支付宝登录

选择恰当的接口服务

2.签约

很多服务,是需要签约之后才能生效的

签约后生效

签约过程需要一定的周期,而且需要公司相关人员出面

签约流程

3.文档

是的,虽然支付宝的文档很烂,但是,原始文档还是要看的,App支付宝登录产品介绍

把里面的流程图摘出来

支付宝授权登录流程

眼花了是不是?梳理一下步骤:

1.你的App调起支付宝App授权,用户确认后,支付宝App返回一个openid和authcode

(支付宝App认可你,给你两样东西,一个是用户id,一个是安全信物)

2.你拿着authcode向支付宝后台服务换一个token

(因为你有安全信物,所以支付宝后台也认可你)

3.有了这个token,其实你就有权限去做很多事情了,比如,再去支付宝后台查查用户的昵称,头像什么的,对应的接口是支付宝用户信息查询接口(这是一个后台接口,我也是在后台做的查询)

(因为支付宝后台认可你,所以你可以去后台查询用户的昵称和头像)

整个流程涉及到你和支付宝双方的App,双方的后台服务器,故事情节大概可以这样理解

登录故事情节

这个故事还有另外一个版本:

支付宝:“你要用户ID,还要登录?好啊,没问题”

支付宝:“神马?你要用户昵称和头像?保安!保安!保安!...”

登录的具体实现

在调起支付宝App登录时,其实就是从我们的App里调用支付宝App一个接口函数的过程,大概分三步:

1.准备函数的参数(按照规定的格式,拼出一个请求的String)

2.调用函数(支付宝接口中AuthTask的authV2)

3.接收函数的返回值(一个Map),从中取出authcode和用户openid

步骤很简单吧,支付宝还贴心的提供了demo代码,具体流程是这样的

1.用开放平台给你的AppId,商户PId,RSA私钥一起,拼出请求的String

拼出授权参数

最终拼出来的authInfo大概长这个样子

authInfo

2.调用AuthTask的authV2函数

调用授权函数

3.把返回的Map映射为AuthResult函数,从中取出authcode和用户id

获取返回值

当然这个过程是异步的,看起来很简单是吧?可是,当我们仔细观摩支付宝官方Demo代码的时候,我们就会发现...

坑...

demo代码里有这样一段话

一段提示

也就是说,第一步是错的,你不要自己去拼参数,因为你的App不能持有RSA私钥!

为什么?因为不安全啊,RSA私钥放在App里,攻击者很容易通过逆向你的App来搞出你的RSA私钥,所以这几乎就相当于面向社会公开了你的银行卡密码啊

那你怎么获取这个参数呢?也就是这个authInfo呢?

authInfo

我们看authInfo里面的这些字段,其实就是sign需要用到RSA加密,而sign又是安全不可逆的,所以我们可以向我们自己的业务服务要这个sign。

那么业务服务器是怎样生成的这个sign呢?

业务服务器保存有RSA喽...

业务服务器,请你一定要安全啊...

万古长青

支付宝支付

支付宝第三方支付

支付的基本流程

1.授权(参考登录)

2.签约(参考登录)

3.文档(参考登录,这次的官方文档位置在App支付

根据官方文档,App支付的流程是这样的:

支付流程

我再来梳理一下步骤,梳理一下步骤:

1.你的业务服务器做好订单信息,安全签名后发给你的App

(你的业务服务器负责RSA加密)

2.你的App拿着订单信息,去请求支付宝App支付

(支付宝App解密订单信息,确认订单安全)

3.支付宝App通知你的App支付完成;同时,支付宝后台服务通知你的业务服务器支付完成)

(App对App,后台对后台)

整个流程涉及到你和支付宝双方的App,双方的后台服务器,故事情节大概可以这样理解

支付故事情节

需要注意的是,支付宝官方文档里有这么一句话:

同步返回的数据,只是一个简单的结果通知,商户确定该笔交易付款是否成功需要依赖服务端收到支付宝异步通知的结果进行判断

这句话的意思就是说,虽然你的App也会收到反馈,但是必须以业务服务器为准

你的App收到支付成功的反馈,其实是用来触发下一步业务操作的

支付的具体实现

支付的具体实现如下:

1.业务服务器发订单信息到你的App,你可能会给服务器开放一个这样的接口:

public void payAli(String orderinfo) {...}

2.你的App调用支付宝的接口

Map result = alipay.payV2(orderInfo, true);

3.你的App收到支付结束的通知,从支付宝App的返回值中寻找自己需要的数据

支付宝App返回信息

然后,你就可以告诉你的业务服务器:

“哥,支付宝App刚刚跟我说,他们给过钱了”

你的业务服务器很可能会问你:

“给钱的是靠墙的那桌,还是靠窗的那桌?”

你说:

“我...我找找”

然后,你就会栽进坑里...

自求多福

要小心支付宝!

关于支付结果的一个坑

前面说过,App支付时,需要异步调起一个PayTask执行支付操作,真正执行支付的是这行代码:

Map result = alipay.payV2(orderInfo, true); //执行支付操作

result就是支付宝反馈给App的支付结果,在(成功/失败/超时/取消)支付操作后,我们把这个Map通过Message传递给Handler,Handler里会把这个Map映射为PayResult对象,根据PayResult去处理后续逻辑。

根据支付宝官方文档及Demo代码,我们通过PayResult对象的ResultStatus(=9000)就可以判断是否支付成功,交易订单号也可以从PayResult中找到,但是这里有个潜在的大坑:如何获取交易订单号,支付宝并没有做完全的说明,事实上:

--当交易成功时,我们要从PayResult的result字段中获取成功交易信息(但是,交易失败时result字段为空,而且官方文档没有提到这一点

--当交易失败时,我们要从PayResult的memo字段中获取原始交易信息(但是,官方文档没有确认这一点)

--当交易取消时,PayResult的result字段为空,memo字段值为“操作已取消”

而且我们不能根据这个现象做决策,还记得吗,要小心支付宝!要小心支付宝!要小心支付宝!

对自己负责任的做法是,在支付的一开始,就要对支付宝的不靠谱有所防备,我的做法是,在异步执行PayTask的时候,我自己把原始支付信息记录下来,因为原始支付信息是我们自己的后台业务服务器发给我们的,在与支付宝的合作中,只有我们自己人是可信赖的,所以原始信息是可信赖的,我从原始信息中取出交易订单号,放进Map里,哪个Map?这个Map:

Map result = alipay.payV2(orderInfo, true); //执行支付操作

在这行代码下,我会向Map中增加一条信息,就是我们自己的后台业务服务器发给我的原始支付信息。

这样的话,原始支付信息会在Map中,随着Message一起发给处理支付结果的Handler。

Handler仍然会把Map转换为PayResult

而我会这样获取交易订单号:

1.先从PayResult的result字段中,尝试解析支付宝的成功交易信息

成功交易信息

2.如果上一步取到的结果为空,就从Map中取出我们的原始交易信息

原始交易信息

实际上就是加一层保险,以确保可以获取到交易订单号

如果有人问,为什么不根据交易成功或失败,分别从PayResult的result或memo中获取交易信息?

我只能说,too naive,这可是文档超级烂的支付宝,你可以信任它的支付,不可以信任它的文档

我最后说一遍,要小心支付宝!要小心支付宝!要小心支付宝!

关于支付宝沙箱

支付宝在蚂蚁金服的官方开放平台提供了一个貌似很有用的沙箱环境,可以在沙箱中模拟支付行为。

支付宝沙箱环境

这个沙箱呢,其实还是挺有用的,这个测试环境会提供一套虚拟的账户,用来模拟交易行为,帮助检查你的接口写得有没有问题(支付宝:反正给你沙箱了,文档我就随便写写吧)。

支付宝沙箱的测试账号

另外,你顺便还可以在沙箱里体验一下,拥有1/10个亿,是什么感觉...

1/10个小目标

当然,支付宝沙箱提供了对应的沙箱App

支付宝沙箱的沙箱版App

不过,等你兴冲冲去下载的时候,你会发现,沙箱App只提供Android版,而且...

沙箱版App基本没什么功能

这个沙箱App,基本没啥用啊!没啥用啊!!没啥用啊!

坑,无处不在...

没错,如果你要在App中对接支付宝登录和支付宝支付,沙箱环境跟你是没有关系的,后台能用上沙箱环境,至于App端么...

还是老老实实等真实线上环境搭好,用1分钱大法来测试吧...

1分钱大法

对比

ID

微信需要三个ID:AppID、AppSecret、PID

支付宝需要亮哥ID:AppID、PID

多平台跳转

微信过于分散,从开放平台就不容易跳转到商户平台

蚂蚁金服集中的比较好,各平台互相跳转地很舒服

引用

微信使用gradle引用;支付宝使用jar包引用

登录

微信登录已经集成在ShareSDK了;支付宝没有集成

支付

双方都要求以服务器收到的信息为准,但是微信要求的更彻底,微信的返回值连订单号都没有

调微信App支付时,你的App不知道订单号(预交易订单号不是订单号);调支付宝App支付时,你的App知道订单号(而且知道详细的交易信息)

微信App是通过接口回调异步反馈的;支付宝App是通过函数返回值异步反馈的

微信主要通过后台对后台的方式传递订单和支付信息;支付宝则是主要通过App

(如果说支付行为好像是上楼签合同的话,在微信App支付里,你的后台是那个上楼送合同的人,你的App只是个按电梯开关的;在支付宝App支付,你的App是那个拿着合同上楼的人)

微信先通过后台完成支付,然后通知App;支付宝先通过App完成支付,然后后台跟进

微信支付成功会跳转Activity(要自己写);支付宝是纯逻辑处理

分享

都在ShareSDK中集成了

文档

微信的文档结构是这样的

微信文档

支付宝的文档结构是这样的

支付宝文档

看起来好像差不多,但是你真正用过之后就会发现,这就是两种文档,它们之间的区别是这样的:

文档之间的区别
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,829评论 1 331
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,603评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,846评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,600评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,780评论 3 272
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,695评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,136评论 2 293
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,862评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,453评论 0 229
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,942评论 2 233
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,347评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,790评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,293评论 3 221
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,839评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,448评论 0 181
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,564评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,623评论 2 249

推荐阅读更多精彩内容