springboot 整合当面付接口+异步回调通知
下面使用沙箱环境来测试
首先导入支付宝的依赖再开始工作:
<!-- 引入支付宝-->
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-easysdk -->
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.4.27.ALL</version>
</dependency>
1.填支付宝商户配置,直接创建类来测,也可以获取application配置,这里就用配置类读取
下面的配置密钥等经过处理,不能直接使用。
*/
public class AliPayConfig {
// 商户APPID
public static String APPID="2021000118697085";//
// 应用私钥pkcs8
public static String RSA_PRIVATE_KEY="MIIEvwIBADANBgkqtvyqkneOovUGnE0Q8KK5wwQQkw0zsjwvKn7MRbZJZmAUDavC6zEzHHyeJvuIkMtJIlE4eiwUAc2GT8/Kp/Fzs/CWWoWhecrdB2xDm/KsJFZ22cxpFvpeDKrAh+E2SAsqwEWXSSobTeyTUqpPFyiHQh5kw53is543nAWMQ6J02ls7RiHjn8uZkaPEodrzRSw4ScFe80kfktZ+77pqrTdJId2bvQ1gvF2AILBanBFB4RsVQxZ8SIvceaC6rvFolf6639cHWzMPZ43hqG63UwCcShTnWa7cdB2nQDWOHZW6lKDaQMk05AgMBAAECggEAW3p+yfYD0G9whDQddoizm+wOYG6iJirmggwIOz0Qwb6j0HxTzVzKsk58ZAOl0IluD51fttn2G7XtBI+TIoqYyXpRttx1J6k2Hj0HLpza7z1PAuqJ2PY4SYNE+QwCKfLZxNr7Vk9+hr+phzDwR803gh3sFwCvJfhR+jEtYu60KUfDxvUDdhqETwx16iZSaZA7FHpdiwoQtTNWSnontOJ7Vb0+9R+bsiDzVpINFUyp0aRffxqImjA6rtUE7qeGNlZMQw4OKF7qd3J4SKRgBgEt4UQW+LMupo9pPUulN7Xbd4RjUrerefywyVp2NTR67JP1eKMzOlN/sW/C66IWvmomwQKBgQDK8bopRwXD8h6pVa8hagcvOfZ0SNWo3gaHmXW7bHcK/x7QtVfN0A/NEFKT+VBOBKTJ1kpWJhZSHFCwLH6Qh5IJx/QPBbs0593wmV/kUE2XfQx4gfv09pviQd0HkPcXuUU01SAqfr/KAc0WZL8DIBVO67q7tGz6lp/2/a+YeY6KWwKBgQC1BsL6TwEbqAjH23HVgp6RMLoVXmTRDFN0PgVpx6QCAflQTSCGwQnbUGFEObcJCyLleWy1/v6wGgVYmcmlsF3aQhxyHCWpn/1kgkSoEjU8aiGfFYvZdsfu8CfI9TecNXQtUg3t0swWYQxdKERmKQ8dTkSqZbVttu1YgOh5anbS+wKBgQC8K5Hu//lqi66+V8JAey0aLuZDP91L7EGlrTaqh5GBUrfh0KMPJCHig4XtyjcZf9jDhLv8UOhVTgfKshbQL8PK6elznF7OWUdB9RQigArRsZLEkdFqetZi3arxfwp8pr5ylEJ05H0z8qOUZeluHmtjd9L2g/6gAtVjkCkmeV8fDQKBgQCqgJ7eodD6Wo9CpocWQbvWJp3uCIVOfJyR7OSuWBI6rd9D6hELuv/sqE2ks/OYuft5RZ/F31HFTgzhAaByxaXwL7qZI7e5h25j32qJHvUzXQcjzmh1P7Jac6oVVhm1sIcnNJTX/mapYWkCyS17R4rr4E8+ayOyHcx5Qpkz2rnmRwKBgQC3/0/yAJgUy8J7oe7PLNokAtIYH+2FzIML5aMF6azvjn/vyl/dkBfaMQ8bLzlwrLBV6SzO4ZtBtVoGI1iPZQfE7zs30i1Mk4A/wa5fEigQDnJPpvEvLQR5zc79mrXjUQ4hAU02yU5YKdm4VPvGWky5sLCzZO6o2xbq8AB8n9/w+A==";//真实
// 服务器异步通知页面 http://或者https://完整路径 必须外网可以访问
public static String notify_url="http://127.0.0.1:9090/alipaynotify";
// 同步通知路径,支付后页面跳转
public static String return_url="https://www.baidu.com";
// 请求网关地址
public static String server_URL="https://openapi.alipaydev.com/gateway.do";//
// 编码
public static String CHARSET="UTF-8";
// 返回格式
public static String FORMAT="json";
// 支付宝公钥
public static String ALIPAY_PUBLIC_KEY="MIIBIjANBg+ZYyU4gE0CByQFxVkHsXtA5xDSqVydqPER9f5Pz+fEnkqU48njGCQvSWxpOdDTArgq5ub9r+rIEYyzPedpcV3Y5yEY+8WKFr+HRdsax7LtuXOC7aws7mu6k4EfaqWs+zYKQJ8P/t+anPRF673o+MvWh/DK4L0vGM5BW7vY5FAf0NrGDMfbyDqh2Cp0HUXGImnuBp1+s3FpCb/1BHgTITHITwijKZZlWVUxTFenwcXGFC5aDA5ep0d9sR0Vif7Nn/JpjjCtda0CgmYBhqAHKLk9eH6hhIbQAowcMVDGNYFETVV20OxWwIDAQAB";//真实
// RSA2
public static String SIGNTYPE="RSA2";
}
2.接口接收参数
@Data
@AllArgsConstructor
@NoArgsConstructor
public class QrPayParam {
// @NotNull(message = "流水单号不能空")
// String out_trade_no;
@NotNull(message = "商品名称不能空")
String subject;
@NotNull(message = "付款金额不能空")
String total_amount;
String body;
// @NotNull(message = "二维码过期时间不能空")
// String timeout_express;
// @NotNull(message = "产品码不能空")
// String product_code;
}
3.controller
下面是简单的接口
@ResponseBody
@PostMapping("/pay")
public HashMap<String, Object> pay(@RequestBody QrPayParam param) throws AlipayApiException {
Integer uid = LocalUser.getUid();
AliPayConfig aliPayConfig = new AliPayConfig();
AlipayClient alipayClient = new DefaultAlipayClient(aliPayConfig.server_URL,
aliPayConfig.APPID,aliPayConfig.RSA_PRIVATE_KEY,aliPayConfig.FORMAT,aliPayConfig.CHARSET,
aliPayConfig.ALIPAY_PUBLIC_KEY,aliPayConfig.SIGNTYPE);
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
String idStr = IdUtil.getSnowflakeNextIdStr();//生成的流水号
model.setOutTradeNo(idStr);//设置商家这边的流水单号 后台写
model.setSubject(param.getSubject());//设置商品名称
model.setTotalAmount(param.getTotal_amount());//设置付款金额
model.setBody(param.getBody());//设置商品描述
model.setTimeoutExpress("10m");//设置过期时间 格式:xxm 后台写
// model.setProductCode(qrPayParam.getProduct_code());//设置产品码 - 二维码支付的话没有该功能
request.setBizModel(model);//存入请求信息
request.setNotifyUrl(aliPayConfig.notify_url);//设置通知地址
request.setReturnUrl(aliPayConfig.return_url);//设置返回地址,二维码支付此功能无效
// 生成表单,二维码支付无表单
// String form = alipayClient.pageExecute(request).getBody();
// 封装生成请求对象
AlipayTradePrecreateResponse response = alipayClient.execute(request);
// 发送请求,获取返回信息
System.out.println(response.getBody());
HashMap<String, Object> map = new HashMap<>();
// 成功
if (response.isSuccess()){
System.out.println("调用成功");
JSONObject responJson = JSONUtil.parseObj(response.getBody());
JSONObject rsj = (JSONObject)responJson.get("alipay_trade_precreate_response");
String qr_code = (String) rsj.get("qr_code");//获取二维码地址
map.put("qrcode",qr_code);
map.put("out_trade_no",idStr);
return map;
}else {
JSONObject responJson = JSONUtil.parseObj(response.getBody());
JSONObject rsj = (JSONObject)responJson.get("alipay_trade_precreate_response");
String res = (String) rsj.get("sub_msg");//获取返回错误的信息
map.put("sub_msg",res);
return map;
}
}
4.异步通知接口
用户支付成功后(当面付只有成功支付后支付宝才向该地址发送通知,所以当有请求给这个地址,就表明有用户扫码支付了),支付宝会向该地址发送请求,下面只接收处理两个参数,
还有更多的参数可以看:https://opendocs.alipay.com/open/194/103296
按照自己需求接收处理。下面的代码只是简单调用,没有进行二次校验密钥,可能存在安全性问题,请查看支付宝的开发文档接收参数验证增加安全性。
// 接收异步消息并同步订单状态
@PostMapping("/alipaynotify")
public ApiRequest getnotify(String trade_no, String out_trade_no){
LambdaQueryWrapper<QrPay> wr = new LambdaQueryWrapper<QrPay>().eq(QrPay::getOutTradeNo, out_trade_no);
QrPay order = payService.getOne(wr);
System.out.println(order);
order.setState(1);
order.setPaytime(new DateTime().toString());
order.setTradeNo(trade_no);
System.out.println(order.getOutTradeNo());
boolean update = payService.update(order, wr);//提交修改订单状态
Integer uid = order.getUid();
LambdaQueryWrapper<User> userwr = new LambdaQueryWrapper<User>().eq(User::getId, uid);
User user = userService.getOne(userwr);
BigDecimal money = user.getMoney();//现在余额
System.out.println("现在余额:" +money);
System.out.println("开始加鱼儿---"+ order.getTotalAmount().toString());
BigDecimal newmonry = new BigDecimal( money.add(order.getTotalAmount()).toString());//现在余额加上充值金额
System.out.println("新余额:"+newmonry);
user.setMoney(newmonry);
userService.update(user,userwr);
return ApiRequest.ok(update);
}
当发送请求成功后,支付宝会返回一个成功信息,里面含有当面付二维码地址,需要获取后返回给前端,前端页面生成二维码,用户扫码支付成功后,支付宝会异步回调你设置的接口地址。