Springboot简单集成支付宝沙箱
本文章只为了记录springboot集成支付宝沙箱的简单用法,至于沙箱的注册登录就不叙述了,网上百度好多好多
先导入依赖
<!--支付宝-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.9.28</version>
</dependency>
接着是支付宝的工具类
@Data
@Component
//@ConfigurationProperties(prefix = "alipay")
public class AlipayTemplate {
//在支付宝创建的应用的id
private String app_id = "";
// 商户私钥,您的PKCS8格式RSA2私钥
private String merchant_private_key = "";
// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
private String alipay_public_key = "";
// 服务器[异步通知]页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
// 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
private String notify_url="http://425q0646p1.qicp.vip/order/payed/notify";
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
//同步通知,支付成功,一般跳转到成功页
private String return_url="http://425q0646p1.qicp.vip/";
// 签名方式
private String sign_type = "RSA2";
// 字符编码格式
private String charset = "utf-8";
//超时时间,可空
String time_out = "30m";
// 支付宝网关; https://openapi.alipaydev.com/gateway.do
private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
// private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
public String pay(Order order) throws AlipayApiException {
//AlipayClient alipayClient = new DefaultAlipayClient(AlipayTemplate.gatewayUrl, AlipayTemplate.app_id, AlipayTemplate.merchant_private_key, "json", AlipayTemplate.charset, AlipayTemplate.alipay_public_key, AlipayTemplate.sign_type);
//1、根据支付宝的配置生成一个支付客户端
AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl,
app_id, merchant_private_key, "json",
charset, alipay_public_key, sign_type);
//2、创建一个支付请求 //设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(return_url);
alipayRequest.setNotifyUrl(notify_url);
//商户订单号,商户网站订单系统中唯一订单号,必填
String out_trade_no = order.getOrderNumber();
//付款金额,必填
Double total_amount = order.getPayPrice();
//订单名称,必填
String subject = order.getOrderName();
//商品描述,可空
String body = "";
alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
+ "\"total_amount\":\""+ total_amount +"\","
+ "\"subject\":\""+ subject +"\","
+ "\"body\":\""+ body +"\","
+ "\"timeout_express\":\""+ time_out +"\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
String result = alipayClient.pageExecute(alipayRequest).getBody();
//会收到支付宝的响应,响应的是一个页面,只要浏览器显示这个页面,就会自动来到支付宝的收银台页面
// System.out.println("支付宝的响应:"+result);
return result;
}
}
这里是配置类的位置。
只需将支付宝沙箱注册的APPID还有商户私钥和支付宝公钥填上就可以用了。
注意这里实现了一个Pay()方法,调用此方法时只需要传入order,然后把order的订单号,支付金额,名称等等等取出来,就可以自己生成一个支付页面了、
生成的界面如下:
接下来就是使用了,用法也非常的简单,先贴上生成订单的整个方法,只是做个参考,实际上只需要看最下面几行代码就行了。
@Autowired
private AlipayTemplate alipayTemplate;
@ResponseBody
@RequestMapping(value = "/createOrder", produces = "text/html;charset=utf-8")
public String createOrder(HttpServletRequest request, HttpServletResponse response, String address, String message) throws ServletException, IOException {
ModelAndView modelAndView = new ModelAndView();
User user = (User) request.getSession().getAttribute("user");
// http://localhost:8088/order/createOrder?address=666&&message=888
/* System.out.println(message);
System.out.println(address);*/
if (user != null) {
Order order = new Order();
Double payPrice = trolleyService.getCheckTrolleyPrice(user.getUid()); //订单总价
//时间戳拼接100以内的随机数生成订单号。
String orderNumber = getTime().replaceAll("[[\\s-:punct:]]", "") + user.getUid() + new Random().nextInt(100);
order.setUid(user.getUid()); //uid
order.setOrderNumber(orderNumber); //订单号
order.setOrderName("ll" + "deDD" + getSimpleTime().replaceAll("[[\\s-:punct:]]", "")); //订单名称
order.setPayPrice(payPrice); //订单应支付价格
order.setAddress(address); //地址
order.setMessage(message); //会员留言
Integer b = orderService.createOrder(order);
Integer oid = order.getOid();
System.out.println("订单号oid=" + oid);
if (oid != 0) {
/** 订单生成成功,
1.生成商品订单表 0默认值等待交易 1交易成功 2交易失败
2.将对应商品库存减一,同时生成商品订单表
3.将购物车对应的数据删除
4.开启计时方法,十五分钟后付款状态未成功支付执行取消订单
5.跳转支付页面
*/
List<Trolley> trolleyList = trolleyService.getCheckTrolleyByTid(user.getUid());
//将购物车查出来先减库存
for (Trolley trolley : trolleyList) {
Good good = goodService.findGoodById(trolley.getGid());
good.setCommentCount(good.getCommentCount() - trolley.getNum()); //库存更新
good.setSaleCount(good.getSaleCount() + trolley.getNum()); //销量更新
goodService.updateGood(good);
//生成商品订单表
OrdersItem ordersItem = new OrdersItem();
ordersItem.setOid(oid); //oid
ordersItem.setGid(good.getGid());
ordersItem.setGoodNum(trolley.getNum());
ordersItem.setGoodPrice(good.getNowPrice());
ordersItemService.createOrdersItem(ordersItem);
}
//删除购物车数据
trolleyService.delTroCheckByUid(user.getUid());
//开启计时方法,三十分钟后执行取消订单
Timer(String.valueOf(order.getOid()));
//跳转支付
try {
return alipayTemplate.pay(order);
} catch (AlipayApiException e) {
e.printStackTrace();
}
}
}
return null;
}
这是大三写的一个项目,贴出代码只是给个参考,代码多low咱们就不管了,重点在于最后面几行,
//跳转支付
try {
return alipayTemplate.pay(order);
} catch (AlipayApiException e) {
e.printStackTrace();
}
是的,这里传入order也就是订单相关的信息就行了,调用pay方法,就能返回到上面我们说的支付界面。
到此支付宝沙箱的集成已经完成一半了。
是的,1、导入依赖/2、支付宝配置类,3、调用。
接下来我们说说上面支付宝配置类的两个参数
好吧代码注释也说的够清楚了,上面那个是异步调用的url,当你支付成功后,支付宝就会请求这个url告诉你支付成功,所以这个方法一般就用来验签和实现支付成功后的一些逻辑
这里异步调用接口需要公网可以访问,如果经济不允许的情况下可以使用花生壳内网穿透工具:
网址:https://hsk.oray.com/
我的个人配置:开通HTTP协议需要花费6元永久域名
下面的同步通知就是支付成功后要跳转的页面。
接下来贴上异步通知的方法
/**
* 支付宝验签方法
*
* @param payAsyncVo
* @param request
* @return
* @throws AlipayApiException
* @throws UnsupportedEncodingException
*/
@ResponseBody
@PostMapping("/payed/notify")
public String handleAliPayed(PayAsyncVo payAsyncVo, HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
// 这里首先验签 验证是支付宝发来的请求
HashMap<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
params.put(name, valueStr);
}
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayTemplate.getAlipay_public_key(), alipayTemplate.getCharset(), alipayTemplate.getSign_type());
if (signVerified) {
// 收到支付宝异步通知,返回success,支付宝不再通知
// log.info("收到支付宝通知: {}",payAsyncVo);
System.out.println("支付成功");
//执行逻辑
//保存交易流水 返回success
return orderService.handlePayResult(payAsyncVo);
}
System.out.println("check失败");
// log.info("签名认证失败...");
return "false";
}
这里需要动的代码也不多,几乎都可以拿来直接用,需要改的就是下图的代码,当验签成功后,就可以走支付成功后的逻辑了,
什么更改订单状态啊 保存订单流水啊巴拉巴拉巴拉的该怎么干怎么干。
需要注意的就是 这里的返回值,如果代码执行完需要返回一个success,支付宝就会一直请求这个url,直到你告诉他成功了。
不然就会发三天三夜?(同学告诉我的我没试过)
嗯 没然后了,这里的代码几乎都是拿过来就可以直接用,需要换的地方好像都说清楚了。
生成订单的代码写的很low很low别骂了别骂了,我不听不听王八念经。
总结一下:
1.导入依赖
2.贴上支付宝配置类,修改配置类的私钥公钥和appid,还有同步回调和异步回调的url。
3.调用alipayTemplate的pay方法,往里面传入订单参数。(订单号,订单价格,订单名称等)
4.实现异步回调(支付成功)url的方法,支付宝验签。。
完。
哦对了对了,如果支付界面没出来,可以复制那个pay方法的return值,复制到记事本,然后改成html打开试试,那个就是你们想要的支付界面。