支付宝调用流程

开发前的准备工作

配置应用网关
应用网关里面填写的值就是商户后台的异步回调地址.也就是在支付宝付完款之后,由支付宝调用商户,便于商户验证订单各信息和更新订单状态
授权回调地址
授权回调地址的值是指用户在使用支付宝付款成功后从支付宝跳转到商户自己的页面.
接口加密方式
这个用于商户的签名加密,有RSA2和RSA两种算法类型,默认是RSA2.开发人员可以使用支付宝提供的生成方式自己生成,然后将公钥上传到支付宝开放平台.这里提供支付宝生成密钥的教程和下载地址
现在提供一张的截图,显示配置的位置.到达方式:蚂蚁金服开放文档—> 右上角账户中的账号管理—>开发者中心—>我的应用(应用) —> 选择自己将要配置的应用名称点击右边的查看—>应用信息(就是截图看到的页面了)

支付宝支付流程:

前端调用商户后台支付接口
商户后台支付接口进行一些必要的业务逻辑上的处理之后调用支付宝的支付接口(原始支付API).需要的参数详见支付宝支付接口的参数说明.支付宝会返回一个form表单.商户后台支付接口将表单返回给前台.
前台将表单提交给支付宝,唤起支付宝客户端进行支付.
支付成功后支付宝会根据原始支付API中传入的异步通知地址notify_url,通过POST请求的方式将支付结果作为参数通知到商户后台系统.
商户后台系统在接到支付宝的异步通知后要在验证自己本身业务逻辑之外严格验证通知数据的正确性.
商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额)
校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
验证app_id是否为该商户本身
上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略.详情参见https://docs.open.alipay.com/203/105286/ 异步返回的验签
判断没有任何错误,打印success.否则支付宝服务器会不断重发通知,直至超过24小时22分钟.

开发需要准备的物料
pom.xml添加支付宝依赖

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.alipay</groupId>
<artifactId>alipay-sdk</artifactId>
<version>java20170307171631</version>
</dependency>

支付宝方面的参数

代码展示
商户后台支付接口

/**
* 支付宝支付
* @param req
* @param response
* @throws OperationFailedException
*/
@RequestMapping("alipay/Prepay")
@ResponseBody
public void aliPrepay(@RequestBody AliPrepayReq req, HttpServletResponse response) throws OperationFailedException {
Set<ConstraintViolation<AliPrepayReq>> constraintViolationSet = validator.validate(req);
if (constraintViolationSet.size() > 0) {
throw new OperationFailedException(constraintViolationSet.iterator().next().getMessage());
}

LibraOrder libraOrder = libraService.findLibraOrderByHashCode(req.getOutTradeNo());

Product product = productRepository.findOne(Long.valueOf(libraOrder.getProduct().getId()));
if(product == null) { throw new OperationFailedException("该商品不存在"); }

try{
String form = aliPayService.generateAliPay(req);

if(!"err".equals(form)){
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(form);// 直接将完整的表单html输出到页面
response.getWriter().flush();
}
}catch (Exception e){
throw new OperationFailedException("支付失败");
}

}

/**
* 支付宝方面订单号获取
* @param aliPrepayReq
* @return
* @throws OperationFailedException
*/
public String generateAliPay(AliPrepayReq aliPrepayReq) throws OperationFailedException {
AlipayClient alipayClient = new DefaultAlipayClient(aliPayUrl,
appId, rsaPrivateKey, "json", "UTF-8", rsaPublicKey, "RSA2"); //获得初始化的AlipayClient
Map<String, String> param = new HashMap<>();

AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

// 封装请求支付信息
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(aliPrepayReq.getOutTradeNo());
model.setSubject(aliPrepayReq.getSubject());
Integer totalAmount = aliPrepayReq.getTotalAmount();
model.setTotalAmount(String.valueOf(totalAmount / 100.0));
// model.setBody(aliPrepayReq.getBody());
model.setProductCode(aliPrepayReq.getProductCode());
alipay_request.setBizModel(model);
// 设置异步通知地址
alipay_request.setNotifyUrl(notifyUrl);
// 设置同步地址
alipay_request.setReturnUrl(returnUrl);

String form = "";
try {
LOGGER.info("alipay_request = "+jsonService.toJson(alipay_request));
// 调用SDK生成表单
form = alipayClient.pageExecute(alipay_request).getBody();
LOGGER.info("form = "+form);
} catch (Exception e) {
throw new OperationFailedException("支付出错");
}
return form;
}

异步回调接口

/**
* 支付宝方面异步回调
* @param request
* @return
* @throws OperationFailedException
*/
@RequestMapping("alipay/notifyCallback")
public String AlipayCallBack(HttpServletRequest request) throws OperationFailedException {
//获取支付宝POST过来反馈信息
Map<String,String> params = new HashMap<String,String>();

Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
LOGGER.info("params = "+jsonService.toJson(params));
boolean verify_result = aliPayService.rsaCheck(params);
if(verify_result && aliPayService.dealWithAliPayChargeOrder(params)){
return "success";
}
return "false";
}

/**
* 订单验证
* @param params
* @return
*/
@Transactional
public boolean dealWithAliPayChargeOrder(Map<String, String> params) {
String outTradeNo = params.get("out_trade_no");
LibraOrder libraOrder = libraOrderRepository.findByHashCode(outTradeNo);
if (libraOrder == null) {
LOGGER.info("订单" + outTradeNo + "不存在");
return false;
}

boolean locked = distributeLocker.lock(USER_ALIPAY_DEAL_LOCK_KEY);
try {
if (locked) {
String totalAmount = params.get("total_amount");
double totalPrice = Double.parseDouble(totalAmount) * 100;
if(libraOrder.getTotalPrice() != Math.round(totalPrice)){
LOGGER.info("alipay和订单金额不一致");
return false;
}

if(totalPrice < 0 || libraOrder.getTotalPrice() < 0){
LOGGER.info("alipay或订单金额为负");
return false;
}
//set done
libraOrder.setPayAt(new Date());
libraOrder.setUpdateAt(new Date());
libraOrder.setStatus(ClientOrderStatus.PAYED);

//后台订单状态初始化为 等待接待
libraOrder.setServiceStatus(ServiceStatus.SERVICE_WAIT);
libraOrderRepository.save(libraOrder);
}
} finally {
if (locked) {
//TODO + order.getUserId()
distributeLocker.unlock(USER_ALIPAY_DEAL_LOCK_KEY);
}
}
return false;
}

/**
* 验证RSA签名
* @param params
* @return
* @throws OperationFailedException
*/
public boolean rsaCheck(Map<String, String> params) throws OperationFailedException {
try {
boolean verify_result = AlipaySignature.rsaCheckV1(params, rsaPublicKey, charset, signType);
LOGGER.info("verify_result = "+verify_result);
return verify_result;
} catch (AlipayApiException e) {
throw new OperationFailedException("验证签名失败");
}
}
---------------------

支付宝支付Java代码的更多相关文章

  1. (转载)Android支付宝支付封装代码

    Android支付宝支付封装代码 投稿:lijiao 字体:[增加 减小] 类型:转载 时间:2015-12-22我要评论 这篇文章主要介绍了Android支付宝支付封装代码,Android支付的时候 ...

  2. app支付宝支付java服务端代码

    app支付java服务端生成支付单文档 public String aliPay(String amount,Map<String,Object> body){ //实例化客户端 Alip ...

  3. 手把手教你完成App支付JAVA后台-支付宝支付JAVA

    接着上一篇博客,我们暂时完成了手机端的部分支付代码,接下来,我们继续写后台的代码. 后台基本需要到以下几个参数,我都将他们写在了properties文件中: 支付宝参数 AliPay.payURL = ...

  4. 支付宝支付Java后台总结

    这个支付的流程是前端H5(APP等)需要支付时调用后台的接口拿到我们加密的签名去调起支付宝的支付界面(支付宝APP)进行支付操作,并且前端在支付成功后,支付宝后台会回调一个我们在签名时写入的一个接口地 ...

  5. uni-app支付宝支付成功代码处理,获取trade_no数据

    uni-app支付宝支付成功以后返回很多代码,我简单梳理一下,提出trade_no数据 uni.requestPayment({ provider: 'alipay', orderInfo: orde ...

  6. 微信支付与支付宝支付java开发注意事项

    说明:这里只涉及到微信支付和淘宝支付 以官网的接口为准,主要关注[网关].[接口].[参数][加密方式][签名][回调] 第一步,了解自己的项目要集成的支付方式 常见的有扫码支付.网页支付.APP支付 ...

  7. MUI 支付宝支付接入

    沙箱测试地址:https://openhome.alipay.com/platform/appDaily.htm 1资源下载地址:https://docs.open.alipay.com/54/106 ...

  8. 移动应用端的支付宝支付php开发流程

    1.https://openhome.alipay.com/ 支付宝开放平台并创建应用,审核通过后并签约app支付拿到pid 2.按照官方文档用 [RSA签名验签工具.bat]生成应用公钥和私钥 3. ...

  9. spring_boot_pay支付宝,微信,银联支付详细代码案例

    spring-boot-pay 支付服务:支付宝,微信,银联详细代码案例(除银联支付可以测试以外,支付宝和微信支付测试均需要企业认证,个人无法完成测试),项目启动前请仔细阅读 注意事项  . 友情提示 ...

随机推荐

  1. 浏览器预览office文件(word,Excel,等)

    提示:预览是通过后台转pdf到前台展示的过程,当然网上也有购买的api 举个栗子:(http://www.officeweb365.com/) <!DOCTYPE html> <ht ...

  2. 【其他】SAS key 获得办法【转载】

    小弟偶然得到了一个利用google得到SID的方法,经本人测试(9.4 64位)得到的SID可以用到2015年12月,从此之后再也不用改时间了.为了让更多的人看见,设定了回复可见.所有内容免费.路过的 ...

  3. 代码: html 页面小效果 (集合,待补充)

    标签切换(下部内容区跟着切换): 2016-6-2 <script type="text/javascript" src="http://cdn.bootcss.c ...

  4. [转] 常用的CSS命名规则

    (一)常用的CSS命名规则  头:header  内容:content/container  尾:footer  导航:nav  侧栏:sidebar  栏目:column  页面外围控制整体布局宽度 ...

  5. 37.如何把握好 transition 和 animation 的时序,创作描边按钮特效

    原文地址:https://segmentfault.com/a/1190000015089396 拓展地址:https://scrimba.com/c/cWqNNnC2 HTML code: < ...

  6. python中的clear

    1 a = { 2 "name":"dlrb", 3 "age":25, 4 "height":168 5 } 6 a. ...

  7. 用递归方法计算斐波那契数列第n项的和

    参考: https://blog.csdn.net/xuzhangze/article/details/78568702 波那契数列数列从第3项开始,每一项都等于前两项之和.即 第n项的值为  (n- ...

  8. TFDStoredProc执行sql server的部分存储过程报错,有的是好的。

    TFDStoredProc执行sql server的部分存储过程报错,有的是好的. Invalid character value for cast specification 暂时无解.用fdque ...

  9. 分布式 session

    分布式session的实现方式: 一.Session Replication 方式管理 (即session复制) 简介:将一台机器上的Session数据广播复制到集群中其余机器上 使用场景:机器较少, ...

  10. JEECG-P3首个开源插件诞生!CMS网站插件 Jeecg-p3-biz-cms1.0版本发布!

    Jeecg-P3-Biz-Cms   ( JEECG 首个微服务插件,支持小程序的CMS系统) 是基于JEECG-P3 微服务框架开发的CMS建站系统,可轻量级集成进jeecg系统,定制各类网站模板, ...