前言

本文使用SpringBoot+SpringMVC对接支付宝电脑网站支付接口。接下来将详细讲解开发步骤及一些常见问题。

1.首先打开支付宝开放平台,

2.点击研发服务。因为正式接入需要企业签约,所以我们这里先用沙盒模式进行模拟接入,完成签约后将程序中的部分参数替换即可。

3.点击沙盒应用,查看APPID等参数

4.设置RSA2密钥

使用官方密钥生成工具生成密钥,将生成的密钥填入

时序图

正式开发

依赖pom.xml

org.springframework.boot

spring-boot-starter-parent

2.2.4.RELEASE

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-devtools

runtime

true

org.projectlombok

lombok

true

org.springframework.boot

spring-boot-starter-thymeleaf

2.2.4.RELEASE

org.springframework.boot

spring-boot-starter-test

test

org.junit.vintage

junit-vintage-engine

com.alipay.sdk

alipay-sdk-java

4.10.124.ALL

目录层级

关键代码

AlipayConfig类

创建DefaultAlipayClient所需参数,文档中提及DefaultAlipayClient只需要创建一次,后续可直接调用,所以这里使用了双重校验锁方式创建单例对象。

如果不清楚双重校验锁的朋友可以看这篇博客:双重校验锁

package online.xybh.pay_demo.pay.alipay;

import com.alipay.api.AlipayClient;

import com.alipay.api.DefaultAlipayClient;

import org.springframework.stereotype.Component;

@Component

public class AlipayConfig {

/**

* 支付宝网关(https://openapi.alipay.com/gateway.do)

* 沙盒网关(https://openapi.alipaydev.com/gateway.do)

*/

public static String URL = "https://openapi.alipaydev.com/gateway.do";

/**

* 创建应用时产生的应用号

*/

public static String APP_ID = "你的APPID";

/**

* 开发者私钥

*/

public static String APP_PRIVATE_KEY = "你的开发者私钥";

/**

* 参数返回格式, 只支持json

*/

public static String FORMAT = "json";

/**

* 编码集,支持GBK/UTF-8,根据自己工程编码进行调整

*/

public static String CHARSET = "UTF-8";

/**

* 支付宝公钥

*/

public static String ALIPAY_PUBLIC_KEY = "你的支付宝公钥";

/**

* 签名算法类型

*/

public static String SIGN_TYPE = "RSA2";

/**

* 回调地址

*/

public static String RETURN_URL = "你的回调地址";

/**

* 异步通知地址

*/

public static String NOTIFY_URL;

/**

* 私有化构造方法

*/

private AlipayConfig(){}

private volatile static AlipayClient instance = null;

/**

* 双重校验锁,单例模式

* @return 支付宝请求客户端实例

*/

public static AlipayClient getInstance(){

if(instance == null){

synchronized (AlipayConfig.class){

if(instance == null){

instance = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE);

}

}

}

return instance;

}

}

AlipayTrade类

这个类主要完成与支付宝的常用对接,如支付,退款,查询是否成功支付等。这里我们只完成支付功能。

package online.xybh.pay_demo.pay.alipay;

import com.alibaba.fastjson.JSON;

import com.alipay.api.AlipayApiException;

import com.alipay.api.request.AlipayTradePagePayRequest;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

import java.util.Map;

@Slf4j

@Component

public class AlipayTrade {

public String trade(Map content){

AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();

alipayRequest.setReturnUrl(AlipayConfig.RETURN_URL);

alipayRequest.setBizContent(JSON.toJSONString(content));

String form = "";

try {

form = AlipayConfig.getInstance().pageExecute(alipayRequest).getBody();

} catch (AlipayApiException e) {

log.error("支付宝构建表单失败", e);

}

log.debug("支付宝构建表单"+form);

return form;

}

}

这里用来lombok中的Slf4j注解,如果不需要的话可以与下面的log.error,log.debug一同删除。

Service

PayService接口

package online.xybh.pay_demo.service;

public interface PayService {

/**

* @param total 订单总金额

* @param subject 订单标题

* @param body 订单详情

* @param goodsId 商品id

* @param goodsName 商品名

* @param quantity 数量

* @param price 单价

* @return 支付表单

*/

String pay(double total, String subject, String body, String goodsId, String goodsName, int quantity, double price);

}

这里只写了一部分常用参数,如需其他参数可看alipay.trade.page.pay

PayServiceImpl实现类

package online.xybh.pay_demo.service.impl;

import online.xybh.pay_demo.pay.alipay.AlipayTrade;

import online.xybh.pay_demo.service.PayService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.HashMap;

import java.util.UUID;

@Service

public class PayServiceImpl implements PayService {

@Autowired

private AlipayTrade alipayTrade;

@Override

public String pay(double total, String subject, String body, String goodsId, String goodsName, int quantity, double price){

HashMap content = new HashMap<>();

content.put("out_trade_no", UUID.randomUUID().toString());

content.put("product_code", "FAST_INSTANT_TRADE_PAY");

content.put("total_amount", String.valueOf(total));

content.put("subject", subject);

content.put("body", body);

content.put("goods_id", goodsId);

content.put("goods_name", goodsName);

content.put("quantity", String.valueOf(quantity));

content.put("price", String.valueOf(price));

return alipayTrade.trade(content);

}

}

测试

首页 IndexController

package online.xybh.pay_demo.controller;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

public class IndexController {

@RequestMapping({"/", "/index"})

public String index(Model model){

return "index";

}

}

支付 PayController

package online.xybh.pay_demo.controller;

import online.xybh.pay_demo.service.PayService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@Controller

public class PayController {

@Autowired

private PayService payService;

@PostMapping("/pay")

public String pay(@RequestParam String subject,

@RequestParam String body,

@RequestParam String goodsId,

@RequestParam String goodsName,

@RequestParam int quantity,

@RequestParam double price,

HttpServletResponse response){

String form = payService.pay(quantity*price, subject, body, goodsId, goodsName, quantity, price);

response.setContentType("text/html;charset=" + "UTF8");

try {

response.getWriter().write(form);

response.getWriter().flush();

response.getWriter().close();

} catch (IOException e) {

e.printStackTrace();

}

return "callback";

}

}

回调 CallBackController

package online.xybh.pay_demo.controller;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.GetMapping;

@Controller

public class CallBackController {

@GetMapping("CallBack/alipay_back")

public String callback(){

return "/callback";

}

}

index.html

Title

订单标题:
订单描述:
商品编号:
商品名称:
商品数量:
商品单价:

实现效果

1.商品详情

2.支付页面

支付宝客户端java版_支付宝对接支付-JAVA版相关推荐

  1. java支付宝当面付接口_支付宝当面付秘钥生成教程(加对接案例)

    总是有小伙伴犯愁支付宝当面付的秘钥生成,看着挺高大上,实际上不是很麻烦,给大家分享一下生成过程,以及对接我们伟大的sspanel的方法 准备 开通了支付宝当面付的账号一枚(本人代开,50大洋,地址:联 ...

  2. app支付宝支付java后台_支付宝app支付java后台流程demo

    支付宝app支付java后台流程demo 使用ssm框架实现支付宝支付功能. 支付宝测试环境代码测试 源代码 https://github.com/OUYANGSIHAI/sihai-maven-ss ...

  3. 支付宝java代码_支付宝回调JAVA版代码

    支付宝回调: 1 //这个是支付宝回调的信息 2 @RequestMapping("alipay_callback.do") 3 @ResponseBody 4 public Ob ...

  4. 支付宝服务商子商户_支付宝推广数字化经营服务商应该怎么做?

    数字化经营无疑是今年最大的热点,那么什么叫数字化经营呢? 早在去年支付宝行业支付事业部总经理叶国晖认为,移动支付是线下数字经济的重要入口,以支付为起点的全域.全链路数字化经营是必然趋势.支付宝希望帮助 ...

  5. 来电通java版_还在玩JAVA版《我的世界》?教你怎么转换存档玩光追!

    简介 如果你一直在花时间扩展和开发"我的世界 (Minecraft)" Java 版世界,那下面为你公布一则好消息:此版本现可转换为"我的世界 (Minecraft)&q ...

  6. 来电通java版_我的世界基岩版1.19正式版下载-我的世界基岩版1.19下载手机版v1.19...

    我的世界基岩版是我的世界手游的特殊版本,在这个特殊版本中玩家可以体验到特殊的游戏玩法,特殊的版本加入了特殊的元素,带给玩家的特殊的游戏体验,还有很多的新的游戏道具以及新的玩法,游戏以像素的风格为玩家进 ...

  7. 我的世界java版_我的世界Java版1.16.5

    我的世界Java版1.16.5终于经历多次测试终于推出了全新的正式版本哦,在这款游戏中修复了大量的bug确保玩家在游戏中可以尽情的创造玩耍,另外游戏中玩家可以利用各种资源组件来打造一场令人惊叹的奇迹建 ...

  8. 我的世界java版_我的世界Java版1.16.4-pre2

    我的世界Java版1.16.4-pre2是一款可以让玩家自由发挥自己创造力的像素沙盒类游戏,在这款游戏中玩家就是一片天地的造物主,玩家可以把现实中一切的建筑都完美的复刻在这款游戏里,如此好玩的游戏,玩 ...

  9. 我的世界java凋零_我的世界JAVA版发布1.14快照 加入全新植物凋零玫瑰

    原标题:我的世界JAVA版发布1.14快照 加入全新植物凋零玫瑰 <我的世界>JAVA版在沉默了很久后终于发布了1.14版的快照.全新加入了多种生物,包括凋零玫瑰,掠夺兽,织布机等,再次加 ...

  10. s数据结构替换子表java版_数据结构与算法分析Java语言描述(第3版) PDF和源码免费 下载...

    <数据结构与算法分析Java语言描述(第3版)>PDF和源码免费 下载 免积分下载 用户下载说明: 图书简介: 数据结构:Java语言描述(原书第3版)是国外数据结构与算法分析方面的经典教 ...

最新文章

  1. win7中安装mysql_windows7下安装Mysql5.6数据库图文教程(压缩包安装)
  2. java自动生成数据库代码
  3. [PHP] Laravel常见报错总结(持续更新)
  4. Python 技术篇-百度语音合成SDK接口调用演示
  5. 【Android】Android程序自己主动更新
  6. 微信终端跨平台组件 mars 系列(二) - 信令传输超时设计
  7. 什么是类加载器?类加载器有哪些
  8. 回答知乎问题:你写过什么自认为惊艳的诗?
  9. 编写一个函数func(),将此函数的输入参数(int型)逆序输出显示,如54321 – 12345,要求使用递归,并且函数体代码不超过8行...
  10. 笨办法学 Python · 续 练习 20:二叉搜索树
  11. [LeetCode] 342. Power of Four(位操作)
  12. Rockwell AB PLC 控制器EDS 更新下载更新方法
  13. 何凯明最新成果PointRend解析
  14. uniapp实现微信公众号支付
  15. 使用pm2部署vue项目
  16. pycharm ssh interpreter 搭建
  17. 压缩winsxs文件夹的正确姿势
  18. 2018 拼多多 校招真题 最大乘积
  19. c#调用TSC条码打印出现中文乱码
  20. 自定义安装Office 365(适用于个人版订阅等)

热门文章

  1. 大象的崛起!Hadoop七年发展风雨录
  2. 众信金融获“2015最佳绿色贡献奖”
  3. 涨姿势,原来程序员喝酒都是这样的呀
  4. 纯CSS实现下拉菜单导航
  5. 网页设计制作CSS实现隔行换色两种方法
  6. poj3984(经典dfs)
  7. 磁盘类型 GetDriveType
  8. 面向对象技术之系统分析:类图
  9. 三星t959手机sim卡网络解锁pin码处理方法
  10. Android -- TabHost