一、需求分析
用户去学习收费课程时引导其去支付,当用户点击“微信支付”或支付宝支付时执行流程如下:
1、请求学习中心服务创建选课记录
2、请求订单服务创建商品订单、生成支付二维码。
3、用户扫码请求订单支付服务,订单支付服务请求第三方支付平台生成支付订单。
4、前端唤起支付客户端,用户输入密码完成支付。
5、第三方支付平台支付完成发起支付通知。
6、订单支付服务接收第三方支付通知结果。
7、用户在前端查询支付结果,请求订单支付服务查询支付结果。
8、订单支付服务向学习中心服务通知支付结果。
9、学习中心服务收到支付结果,如果支付成功则更新选课记录,并添加到我的课程表。
通用订单服务设计:项目中不仅选课需要下单、购买学习资料、老师一对一答疑等所以收费项目都需要下单支付。
所以设计通用的订单服务,通用的订单服务承接各业务模块的收费支付需求,当用户需要交费时统一生成商品订单并进行支付。
所有收费业务最终转换为商品订单记录在订单服务的商品订单表。
以选课为例,选课记录表的ID记录在商品订单表的out_business_id字段。
二、支付接口调研
2.1 微信支付接口调研
微信目前提供的支付方式如下:
地址:https://pay.weixin.qq.com/static/product/product_index.shtml
1、付款码支付是指用户展示微信钱包内的“付款码”给商户系统扫描后直接完成支付,适用于线下场所面对面收银的场景,例如商超、便利店、餐饮、医院、学校、电影院和旅游景区等具有明确经营地址的实体场所。
2、JSAPI支付是指商户通过调用微信支付提供的JSAPI接口,在支付场景中调起微信支付模块完成收款
线下场所:调用接口生成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付
公众号场景:用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付
PC网站场景:在网站中展示二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付
3、小程序支付是指商户通过调用微信支付小程序支付接口,在微信小程序平台内实现支付功能;用户打开商家助手小程序下单,输入支付密码并完成支付后,返回商家小程序。
4、Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。该模式适用于PC网站、实体店单品或订单、媒体广告支付等场景。
5、APP支付是指商户通过在移动端应用APP中集成开放SDK调起微信支付模块来完成支付。适用于在移动端APP中集成微信支付功能的场景。
6、刷脸支付是指用户在刷脸设备前通过摄像头刷脸、识别身份后进行的一种支付方式,安全便捷。适用于线下实体场所的收银场景,如商超、餐饮、便利店、医院、学校等。
以上接口native和JSAPI都可以实现pc网站实现扫码支付,两者区别是什么?怎么选择?
JSAPI除了在pc网站扫码支付还可以实现公众号页面内支付,可以实现在手机端H5页面唤起微信客户端完成支付。
接口文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
如何开通JSAPI支付接口?
以企业身份注册微信公众号https://mp.weixin.qq.com/
登录公众号,点击左侧菜单“微信支付”开通微信支付,如下:
需要提供营业执照、身份证等信息。
点击申请接入,需要注册微信商户号。
注册微信商户号的过程请参考官方文档,本文档略。参考地址如下:
https://pay.weixin.qq.com/index.php/apply/applyment_home/guide_normal#none
开通微信支付后即可在微信商户平台(pay.weixin.qq.com)开通JSAPI支付。
登录商品平台,进入产品中心,开通JSAPI支付:
注意:JSAPI支付方式需要在公众号配置回调域名,此域名为已经备案的外网域名。
最后在公众号开发信息中获取:开发者id、开发者密码。
2.2 支付宝接口调研
支付宝支付产品如下:
文档:https://b.alipay.com/signing/productSetV2.htm
1、电脑网站支付
PC网站轻松收款,资金马上到账:用户在商家PC网站消费,自动跳转支付宝PC网站收银台完成付款。 交易资金直接打入商家支付宝账户,实时到账。
2、手机网站支付
用户在商家手机网站消费,通过浏览器自动跳转支付宝APP或支付宝网页完成付款。 轻松实现和APP支付相同的支付体验。
对比两种支付方式:手机网站支付方式可以在H5网页唤起支付宝,手机扫码支付可以使用手机网站支付方式来完成,相比电脑网站支付形式更灵活。
本项目选择手机网站支付方式。
文档:https://opendocs.alipay.com/open/02ivbt
如何开通支付宝手机网站支付接口?
进入网址:https://b.alipay.com/signing/productDetailV2.htm?productId=I1011000290000001001
点击:立即开通
上传营业执照等资料,提交审核,根据提示进行开通。
三、准备开发环境
3.1 支付宝开发环境
第三方支付接口流程大同小异,考虑开发及教学的方便性,支付宝提供支付宝沙箱环境开发支付接口,在教学中接入支付宝手机网站支付接口。
1、配置沙箱环境
沙箱环境是支付宝开放平台为开发者提供的与生产环境完全隔离的联调测试环境,开发者在沙箱环境中完成的接口调用不会对生产环境中的数据造成任何影响。
接入手机网站支付需要具备如下条件:
•申请前必须拥有经过实名认证的支付宝账户;
•企业或个体工商户可申请;
•需提供真实有效的营业执照,且支付宝账户名称需与营业执照主体一致;
•网站能正常访问且页面显示完整,网站需要明确经营内容且有完整的商品信息;
•网站必须通过ICP备案。如为个体工商户,网站备案主体需要与支付宝账户主体名称一致;
•如为个体工商户,则团购不开放,且古玩、珠宝等奢侈品、投资类行业无法申请本产品。
详细参见:https://docs.open.alipay.com/203
本文档使用支付宝沙箱进行开发测试,这里主要介绍支付宝沙箱环境配置。
详细参见:https://docs.open.alipay.com/200/105311/
2、模拟器
下载模拟器:http://mumu.163.com/
安装模拟器,安装在没有空格和中文的目录。
安装成功,启动模拟器
下一步在模拟器安装支付宝。
使用沙箱环境的买家账号登录沙箱版本的支付宝。
查看沙箱环境的账号:
3.2 支付接口测试
3.2.1 阅读接口定义
手机网站支付接入流程详细参见:https://docs.open.alipay.com/203/105285/
1、接口交互流程如下:
1)用户在商户的H5网站下单支付后,商户系统按照手机网站支付接口alipay.trade.wap.payAPI的参数规范生成订单数据
2)前端页面通过Form表单的形式请求到支付宝。此时支付宝会自动将页面跳转至支付宝H5收银台页面,如果用户手机上安装了支付宝APP,则自动唤起支付宝APP。
3)输入支付密码完成支付。
4)用户在支付宝APP或H5收银台完成支付后,会根据商户在手机网站支付API中传入的前台回跳地址return_url自动跳转回商户页面,同时在URL请求中以Query String的形式附带上支付结果参数,详细回跳参数见“手机网站支付接口alipay.trade.wap.pay”前台回跳参数。
5)支付宝还会根据原始支付API中传入的异步通知地址notify_url,通过POST请求的形式将支付结果作为参数通知到商户系统,详情见支付结果异步通知。
2、接口定义
文档:https://opendocs.alipay.com/open/203/107090
接口定义:外部商户请求支付宝创建订单并支付
公共参数
请求地址:
开发中使用沙箱地址:https://openapi.alipaydev.com/gateway.do
请求参数:
详细查阅https://opendocs.alipay.com/open/203/107090
一部分由sdk设置,一部分需要编写程序时指定。
其它扩展参数参见接口文档。
3、示例代码
public void doPost(HttpServletRequest httpRequest,
HttpServletResponse httpResponse) throws ServletException, IOException {
AlipayClient alipayClient = ... //获得初始化的AlipayClient
AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request
alipayRequest.setReturnUrl("http://domain.com/CallBack/return_url.jsp");
alipayRequest.setNotifyUrl("http://domain.com/CallBack/notify_url.jsp");//在公共参数中设置回跳和通知地址
alipayRequest.setBizContent("{" +
" \"out_trade_no\":\"20150320010101002\"," +
" \"total_amount\":88.88," +
" \"subject\":\"Iphone6 16G\"," +
" \"product_code\":\"QUICK_WAP_WAY\"" +
" }");//填充业务参数
String form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
httpResponse.setContentType("text/html;charset=" + AlipayServiceEnvConstants.CHARSET);
httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面
httpResponse.getWriter().flush();
}
3.2.2 下单执行流程
根据接口描述,支付宝下单接口的执行流程如下:
3.2.3 支付接口测试
3.2.3.1 编写下单代码
根据接口流程,首先在订单服务编写测试类请求支付宝下单的接口。
在订单服务api工程添加依赖:
<!-- 支付宝SDK -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.7.73.ALL</version>
</dependency>
<!-- 支付宝SDK依赖的日志 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
拷贝AlipayConfig.java到订单服务的service工程。
public class AlipayConfig {
// 商户appid
// public static String APPID = "";
// 私钥 pkcs8格式的
// public static String RSA_PRIVATE_KEY = "";
// 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "http://商户网关地址/alipay.trade.wap.pay-JAVA-UTF-8/notify_url.jsp";
// 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
public static String return_url = "http://商户网关地址/alipay.trade.wap.pay-JAVA-UTF-8/return_url.jsp";
// 请求网关地址
public static String URL = "https://openapi.alipaydev.com/gateway.do";
// 编码
public static String CHARSET = "UTF-8";
// 返回格式
public static String FORMAT = "json";
// 支付宝公钥
// public static String ALIPAY_PUBLIC_KEY = "";
// 日志记录目录
public static String log_path = "/log";
// RSA2
public static String SIGNTYPE = "RSA2";
}
@Controller
public class PayTestController {
@Value("${pay.alipay.APP_ID}")
String APP_ID;
@Value("${pay.alipay.APP_PRIVATE_KEY}&