支付宝为普通商户提供如下支付产品:
产品介绍详见:https://b.alipay.com/signing/productSetV2.htm
在国内线下场景,商家可通过以下任一方式进行收款。提升商家收银效率,资金实时到账。
(1)商家通过扫描线下买家支付宝钱包中的条码、二维码等方式完成支付;
(2)线下买家通过使用支付宝钱包扫一扫,扫描商家的二维码等方式完成支付。
商家APP集成支付宝提供的支付能力,在线上轻松收款:
用户在商家APP消费,自动跳转支付宝完成付款,付款后自动跳回。 轻松享受更全面、更安全的支付服务。
无需手机,刷脸支付:
当不便使用手机或没有手机时,用户亦可“刷脸”完成——通过线下支付机具读取脸部完成自助结账等支付行为,快捷安全方便。 商家多一种方案,用户多一种选择,同样方便安全。
无需开发APP,手机网站同样能轻松收款:
用户在商家手机网站消费,通过浏览器自动跳转支付宝APP或支付宝网页完成付款。 轻松实现和APP支付相同的支付体验。
PC网站轻松收款,资金马上到账:
用户在商家PC网站消费,自动跳转支付宝PC网站收银台完成付款。 交易资金直接打入商家支付宝账户,实时到账。
下边列出接入聚合支付平台且应用于线下场所的支付方式。
线下场所泛指商超、便利店、餐饮、医院、学校、电影院和旅游景区等具有明确经营地址的实体场所。
商家通过扫描线下买家支付宝钱包中的条码、二维码等方式完成支付;
条码支付应用于B扫C的场景,即商户扫客户。
买家用支付宝客户端打开H5网页,点击支付,打开支付宝客户端支付界面,完成支付。
手机网站支付应用于C扫B场景,即客户扫商户。
闪聚支付接入“支付宝手机网站支付”完成C扫B自由输入金额的支付,原因如下:
聚合支付对C扫B的一个需求是用户可自由输入金额,且向用户展示订单信息,存在手机网页交互,所以使用手机网站支付可以满足需求。
接入手机网站支付需要具备如下条件:
详细参见:https://docs.open.alipay.com/203
本文档使用支付宝沙箱进行开发测试,这里主要介绍支付宝沙箱环境配置。
详细参见:https://docs.open.alipay.com/200/105311/
首先需要注册一个支付宝账号:
注册地址:https://developers.alipay.com/developmentAccess/developmentAccess.htm
注册成功,登录支付宝开放平台
登录成功,点击“研发服务”进入研发服务查看沙箱配置
进入研发服务,左侧菜单列出了沙箱环境的配置菜单
使用支付沙箱需要配置密钥,密钥作为与支付宝接口对接的必要参数。
下载密钥生成工具:AlipayDevelopmentAssistant-1.0.2.exe,执行安装,注意不要安装在有空格的目录中。
下载网址:https://ideservice.alipay.com/ide/getPluginUrl.htm?clientType=assistant&platform=win&channelType=WEB
安装成功,进入安装目录:
安装成功,进入安装目录,双击“支付宝开放平台开发助手.exe”,使用工具生成密钥(应用私钥和应用公钥),如下图,点击“生成密钥”:
复制应用公钥,进行设置,点击下图中的“设置”,将应用公钥粘贴进去,点击“保存设置”:
填入应用公钥,点击保存设置。
此时,再查看RSA2密钥
注意:需要保存好支付宝公钥和使用“支付宝开放平台开发助手.exe”生成的私钥,在开发中要使用两者。
获取沙箱账号作为支付宝客户端(沙箱版本)的登录账号。
点击研发服务进入,点击“沙箱账号”列出商家账号和买家账号。
注意:C扫B测试需要使用买家账号,请保证账号余额不为0,否则会影响付款,测试前进行充值(假数据,充值不要钱)。
我们在测试支付宝下单接口时需要使用支付宝扫描二维码,需要在手机安装支付宝客户端(沙箱版本),用沙箱账号登录支付宝,扫二维码,二维码的地址即为下单接口的地址。
本项目使用模拟器进行测试,使用模拟器和使用手机测试效果一致。
下载模拟器:http://mumu.163.com/,也可以使用资料文件夹中的MuMuInstaller,如下:
MuMuInstaller_1.1.0.4_nochannel_zh‐Hans_1573633675.exe
安装模拟器,安装在没有空格和中文的目录。
选择资料文件夹提供的支付宝安装包wallet_101521226_client_release_201812261416.apk(沙箱版本)
使用沙箱环境的买家账号登录沙箱版本的支付宝。
ZXing是一个开源的,用Java编写的多格式的1D / 2D条码图像处理库,使用ZXing可以生成、识别QR Code(二维码)。常用的二维码处理库还有zbar,近几年已经不再更新代码,下边介绍ZXing生成二维码的方法。
<dependency>
<groupId>com.google.zxinggroupId>
<artifactId>coreartifactId>
<version>3.3.3version>
dependency>
<dependency>
<groupId>com.google.zxinggroupId>
<artifactId>javaseartifactId>
<version>3.3.3version>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
dependency>
复制二维码工具类QRCodeUtil.java到项目中
测试根据内容生成二维码方法,在QRCodeUtil中添加main方法如下:
public static void main(String[] args) throws IOException {
QRCodeUtil qrCodeUtil = new QRCodeUtil();
System.out.println(qrCodeUtil.createQRCode("http://www.itcast.cn/", 200, 200));
}
运行main方法,将输出的内容复制到浏览器地址后回车
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAQAAAACFI5MzAAABO0lEQVR42u2YMQ7DIAxFHTF0zBF6lBwtHI2j5AgZM1S4/t8kUVu1UwcjhSEI3mT0/8dE9NuQi/wkq2Dc1rutHjYVru/Ryb6lmXWU2T5rfFJkMCIy17SNRry6LogudvaJ9XREVpl0oHY6IdSOLlNu9bypKibZfVrm4YuDA5J9mHao+M+0jEgQK6wAEpJxgYSOTAxLTC0sxLaMj5CQTRqeWISzApW0oayaXPGRCSIcW0gXGjTX0wthCeqBT21ZadEjXSITZOKgNKhLva2CE148NKj6dKZlYGIabw2Vb2UGeg/k4ZmoGyCq0+CkDSjepX5oJzLZ73qEjF/5kl47lJCkvRdkyhVJri0aoxPvYXnxUDu8hrohPH5he9UL8W5Q0YCfHVdk0t4LPP6xF3L8c8g0aJnrm4MjkutP1n/JExXRT2sic1M+AAAAAElFTkSuQmCC
本章节介绍支付宝手机网站支付接入方法,详细参见:https://docs.open.alipay.com/203/
支付宝手机网站支付适用于商家在移动端网页应用中集成支付宝支付功能。
商家在网页应用中调用支付宝提供的网页支付接口,接口会调起支付宝客户端内的支付模块,此时会从商家网页应用跳转到支付宝客户端中并开始支付;支付完成后会跳转回商家网页应用内,最后商家展示支付结果。
步骤1:用户在浏览器中访问商家网页应用,选择商品下单、确认购买,进入支付环节,选择支付宝付款,用户点击去支付,如下图1;
步骤2:进入到支付宝支付路由页面,支付宝处理支付请求,并尝试唤起支付宝客户端,如下图2;
步骤3:进入到支付宝页面,调起支付宝客户端支付,出现确认支付界面,如下图3;
步骤4:用户确认收款方和金额,点击立即支付后出现输入密码界面,如下图4;
步骤5:输入正确密码后,支付宝端显示支付结果,如下图5;
步骤6:自动回跳到浏览器中,商家根据付款结果个性化展示订单处理结果,如下图6。
手机网站支付接入详细参见:https://docs.open.alipay.com/203/105285/
接口交互流程如下:
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请求的形式将支付结果作为参数通知到商户系统,详情见支付结果异步通知。
接口定义:外部商户请求支付宝创建订单并支付
公共参数
请求地址:
开发中使用沙箱地址:https://openapi.alipaydev.com/gateway.do
环境 | HTTPS请求地址 |
---|---|
正式环境 | https://openapi.alipay.com/gateway.do |
公共请求参数:
详细参数参见:https://docs.open.alipay.com/203/107090/,https://docs.open.alipay.com/api_1/alipay.trade.wap.pay
标记蓝色的由支付宝sdk(开发工具包)设置、标记红色的已在支付渠道参数中配置,标记绿色的需程序来设置。
业务参数如下:
本节测试支付宝下单接口,使用支付宝提供sdk(开发工具包)调用支付宝的接口。
sdk是一个方便调用支付宝接口的开发工具包,提供方便接口调用的api方法。
下图展现在sdk的位置,闪聚平台微服务需要引入sdk依赖(jar包),即可使用sdk的api
1、在交易服务shanjupay-transaction-service中引入支付宝的sdk作为测试战场,在交易服务pom.xml中添加如下坐标:
<dependency>
<groupId>com.alipay.sdkgroupId>
<artifactId>alipay-sdk-javaartifactId>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.2version>
dependency>
2、必要的参数
如下参数是支付宝接口交互中的必要参数:appId、应用私钥、支付宝公钥,以下参数请学习者自行申请。
//沙箱应用APPID
String APP_ID = "2021000118620802";
//沙箱应用私钥
String APP_PRIVATE_KEY ="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCWIa5n7rnlTYpgC7AUXC5n1I9CtFfK40wBkQoPea8dpsuMWcOFOM7TDzD1ImQXO01oak5VGdpRKj4WIOH3o/n2VYwaFipBldGLfFOQhPZbqbFEI2I7vWf0r716SuN5cG4mny8ZbhP56S4ccNpCsLsd7ZExjDPMR30loc0sBYkwomBk3To9HzD+xvYB0Ld2orhjFTB7/VCPYblDYZkwfRiZ/BoJY5cpyt3hgF9uVa0KQq6whhrvnX0HzzTNtYClCrOemLu0BqTzX6g5mFxGJwfF7hhwvbgHqTS8Gonn9+ha3VTEMikPHjVCg03PmtBoJyaMhQwhATELNe2UWOMmlRJLAgMBAAECggEADw/b/oNd1Rp9anths/k3kqUppkiPkkRRiMqzVrAfmHr2auNKkWAMp/IbOEy1+/qwHmyj5TfNxlzVk8TCxuSFnGgiwS8+GAxe1H6pp5MfYDzbEvn1zgaHmm3TNaSzw6g69Nb9k7COgoEZZjMQQqaWbz85VN47CCCX9qGQAv2fMOjBnYXz9/5cexEYFM5n881ocWh4CbmRwn3S5M2EqVXMvxkYP27STtv808GvrozrODzR+D4k3yubkLC7/U9HDnazY5sAN0YNCf3sBudAgeU42HyBHq2sxIUWyZy9UaxTnqNoYo+8lldGS3QbdrXIHZM40V6tWKYbGMA2BrYAFNCRCQKBgQDnvFjmxEZRQOt9f9u5fF4wL2TRYPQajsajBm5bXq2MF+YQnNnUzh1n+Lh/GLSCND+97mNftaM0zYgGxj241KaLF83w9KqFTl1RCT1CSMN4+PRhsMfzU/Hpx/13ZYtvOb+qLnczjkTYa4wx79n5I54ib9noQcKGsEtRyHygU+tqLwKBgQCl2fFTb2l2IdwgeopRkE+Ak+bTIBzks/VS8+4pbFPFKb94VI0eJCTtLaMun9ElB01WfnYqVfQaCeieRzHWnpo00XR6r4qtmeoBV91JDpHmpnRqHjEMr5gr5RBhzgLUgxOA2O2RtX68Pe8Dd/siSEKHGz9gyw8Eus1gdj2RjrH+pQKBgQC9MO8f0ARcl/Tqa/V2VMwM6NSVgGMqP4B6XmjAneZwJp7E11mcPH6TgOMXmJLebkvQA40L+Z36IQa6CSUg/jPOASw4WXfSB6112GYz9HXqEM5r50kHJnStWYJc9QFGWE5bYT4eUDtyuTMnHdvGZEbZdJnh3bY0AkArz9O3jWv4LwKBgC793oO+eIoxM9a8Ab70faI3xdoiKi2e067KULvJ5r5hgs/MXSOiKBhPqwHF5JNySzZrpH2AVyadkhxuna9qxtSaWD9+x3NCvevdgmR1zV8l4KxEm681fY9KWubrYR/nd7o1PLLhUuRxQ+yerThccwUm8kExp7K2XwSq2+0HGmXFAoGBAIxgJ57Pcmix0HO/xnEcHYhADrSDGDyKDCmNdoW/rxI5JKq6/SucPvDGwWv9/1bwp46y7CSWUM5UqCOqcnsbTDmoOz1oO3Lm7ESKydv7/IXQdrmDXUPzrXVGwne4JpCKkuwhYaCeT6uICJWOs4ZFv0kw9l9n9nYQBrQB06Hc4mzd";
1、首先参考sdk代码示例如下:
详细见:https://docs.open.alipay.com/203/105285/
package com.shanjupay.transaction.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 支付宝接口对接测试类
*/
@Slf4j
@Controller
//@RestController//请求方法响应统一json格式
public class PayTestController {
//沙箱应用APPID
String APP_ID = "2021000118620802";
//沙箱应用私钥
String APP_PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCWIa5n7rnlTYpgC7AUXC5n1I9CtFfK40wBkQoPea8dpsuMWcOFOM7TDzD1ImQXO01oak5VGdpRKj4WIOH3o/n2VYwaFipBldGLfFOQhPZbqbFEI2I7vWf0r716SuN5cG4mny8ZbhP56S4ccNpCsLsd7ZExjDPMR30loc0sBYkwomBk3To9HzD+xvYB0Ld2orhjFTB7/VCPYblDYZkwfRiZ/BoJY5cpyt3hgF9uVa0KQq6whhrvnX0HzzTNtYClCrOemLu0BqTzX6g5mFxGJwfF7hhwvbgHqTS8Gonn9+ha3VTEMikPHjVCg03PmtBoJyaMhQwhATELNe2UWOMmlRJLAgMBAAECggEADw/b/oNd1Rp9anths/k3kqUppkiPkkRRiMqzVrAfmHr2auNKkWAMp/IbOEy1+/qwHmyj5TfNxlzVk8TCxuSFnGgiwS8+GAxe1H6pp5MfYDzbEvn1zgaHmm3TNaSzw6g69Nb9k7COgoEZZjMQQqaWbz85VN47CCCX9qGQAv2fMOjBnYXz9/5cexEYFM5n881ocWh4CbmRwn3S5M2EqVXMvxkYP27STtv808GvrozrODzR+D4k3yubkLC7/U9HDnazY5sAN0YNCf3sBudAgeU42HyBHq2sxIUWyZy9UaxTnqNoYo+8lldGS3QbdrXIHZM40V6tWKYbGMA2BrYAFNCRCQKBgQDnvFjmxEZRQOt9f9u5fF4wL2TRYPQajsajBm5bXq2MF+YQnNnUzh1n+Lh/GLSCND+97mNftaM0zYgGxj241KaLF83w9KqFTl1RCT1CSMN4+PRhsMfzU/Hpx/13ZYtvOb+qLnczjkTYa4wx79n5I54ib9noQcKGsEtRyHygU+tqLwKBgQCl2fFTb2l2IdwgeopRkE+Ak+bTIBzks/VS8+4pbFPFKb94VI0eJCTtLaMun9ElB01WfnYqVfQaCeieRzHWnpo00XR6r4qtmeoBV91JDpHmpnRqHjEMr5gr5RBhzgLUgxOA2O2RtX68Pe8Dd/siSEKHGz9gyw8Eus1gdj2RjrH+pQKBgQC9MO8f0ARcl/Tqa/V2VMwM6NSVgGMqP4B6XmjAneZwJp7E11mcPH6TgOMXmJLebkvQA40L+Z36IQa6CSUg/jPOASw4WXfSB6112GYz9HXqEM5r50kHJnStWYJc9QFGWE5bYT4eUDtyuTMnHdvGZEbZdJnh3bY0AkArz9O3jWv4LwKBgC793oO+eIoxM9a8Ab70faI3xdoiKi2e067KULvJ5r5hgs/MXSOiKBhPqwHF5JNySzZrpH2AVyadkhxuna9qxtSaWD9+x3NCvevdgmR1zV8l4KxEm681fY9KWubrYR/nd7o1PLLhUuRxQ+yerThccwUm8kExp7K2XwSq2+0HGmXFAoGBAIxgJ57Pcmix0HO/xnEcHYhADrSDGDyKDCmNdoW/rxI5JKq6/SucPvDGwWv9/1bwp46y7CSWUM5UqCOqcnsbTDmoOz1oO3Lm7ESKydv7/IXQdrmDXUPzrXVGwne4JpCKkuwhYaCeT6uICJWOs4ZFv0kw9l9n9nYQBrQB06Hc4mzd";
//支付宝公钥
String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZsrdXBmfuatiXIQWT84KNAirI9XrGnFNFmXpoZUaU9kC40fFZiamPoCaHASs3gsuJka3gezE+rMoZHPNzHIoWsHnE6kPgv2n2AdBFW7Bo4BL8fkiNj+2iNPfF2Cn9CgpsplTWCBygJCdf6QoRblQRyQzpnMT8aqcid/5cXxUNTsXqtcunCmQyZMqN+KJcgskk46RFIvdgkQMNuiTKJI3Pg+pPRDFXoxpY4YcWiJNDRbzc7UC4jr+sR6qAYkd7mDiMSSK8t8ybtltbfyvIIYnTG87HCl/atMCGYWUcyohjWxduX1PDQP3IxxgKpRSDDujVb8s/Le4LZ4LEZocasUgQIDAQAB";
//签名算法类型
String CHARSET = "utf-8";
//支付宝接口的网关地址,正式"https://openapi.alipay.com/gateway.do"
String serverUrl = "https://openapi.alipaydev.com/gateway.do";
//签名算法类型
String sign_type = "RSA2";
@GetMapping("/alipaytest")
public void alipaytest(HttpServletRequest httpRequest,
HttpServletResponse httpResponse) throws ServletException, IOException {
//构造sdk的客户端对象
AlipayClient alipayClient = new DefaultAlipayClient(serverUrl, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, sign_type); //获得初始化的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\":\"20150420010101017\"," + " \"total_amount\":\"88.88\"," + " \"subject\":\"Iphone6 16G\"," + " \"product_code\":\"QUICK_WAP_PAY\"" + " }");//填充业务参数
String form = "";
try {
//请求支付宝下单接口,发起http请求
form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
} catch (AlipayApiException e) {
e.printStackTrace();
}
httpResponse.setContentType("text/html;charset=" + CHARSET);
httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面
httpResponse.getWriter().flush();
httpResponse.getWriter().close();
}
}
指定二维码的URL,模拟器必须可以访问到此地址,由于模拟器在开发机安装,URL使用局域网ip即可。
进入cmd命令状态,输入以下命令查看ip地址:ipconfig ‐all
二维码的URL为:http://192.168.159.1:56050/transaction/alipaytest
执行下边的代码生成二维码:
public static void main(String[] args) throws IOException {
QRCodeUtil qrCodeUtil = new QRCodeUtil();
String qrCode = qrCodeUtil.createQRCode("http://192.168.70.1:56050/transaction/alipaytest", 200, 200);
System.out.println(qrCode);
}
进入模拟器打开浏览器,输入生成的二维码,并截屏(稍后使用支付宝客户端扫相册中的图片)
启动shanjupay-transaction-service交易服务,使用支付宝沙箱买家账号登录支付宝客户端(沙箱版)
点击扫一扫
选择相册中的二维码图片:
打开支付宝客户端,进行支付
支付成功,到此下单测试完成。
注意:再次测试需要修改下单请求的订单号,因为此订单号在支付宝已存在,实际开发中的订单号是每次支付都生成,无需此操作。