支付宝支付 第十集:支付回调
一、注意
-
这里的支付回调最好是自己有一个服务器(阿里云服务器一年70多也不是很贵),博主自己尝试了一下,本机和使用虚拟机模拟服务器的话,支付宝的授权回调信息是传不过来的,无法进行支付回调!!!
-
怎样使用阿里云服务器运行Java项目?
-
为什么接收不到回调信息?
一定要注意在沙盒设置中的授权回调地址,一般自己的服务器都是http不是https!!!写错了的话是接收不到回调信息的!!!
-
为什么接收到了支付宝回调信息,写不到数据库中?
检查自己传给支付宝的参数的名称,与传回来的解析名称是否一致,我传过去的时候是ID,接受回调信息进行解析的时候,写的是Id,导致一直无法识别回调信息。。。。
二、代码
-
目录结构
-
更新AlipayController.java
package com.dzy.alipay.web; import com.alibaba.fastjson.JSONObject; import com.alipay.api.internal.util.StringUtils; import com.dzy.alipay.service.AlipayService; import com.dzy.alipay.service.pay.PayCommonService; import com.dzy.alipay.vo.PayVo; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @Controller @Log4j2 public class AlipayController { private final AlipayService alipayService; private final PayCommonService payCommonService; public AlipayController(AlipayService alipayService, PayCommonService payCommonService) { this.alipayService = alipayService; this.payCommonService = payCommonService; } @GetMapping("/alipay/pay") @ResponseBody public byte[] alipay(String courseID) { PayVo payVo = new PayVo(); payVo.setCourseid(courseID); payVo.setUserId("1"); return alipayService.alipay(payVo); } /** * 定义支付回调的地址 */ @ResponseBody @RequestMapping("/aliPayNotifyUr") public String notify_url(HttpServletRequest request) throws Exception { boolean result = alipayCallback(request); if (result) { System.out.println("success"); return "success"; // 请不要修改或删除 } else { // 验证失败 System.out.println("fail"); return "fail"; } } /** * 支付宝回调 */ private boolean alipayCallback(HttpServletRequest request) throws Exception { // 获取支付宝GET过来反馈信息 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] + ","; } params.put(name, new String(valueStr.getBytes("ISO-8859-1"), "UTF-8")); } // 计算得出通知验证结果 log.info("1:---->获取支付宝回传的参数---------------------------------->" + params); // 支付宝返回的请求参数body String extparamString = request.getParameter("extra_common_param"); log.info("2---->:支付宝交易返回的参数:{}", extparamString); String tradeno = params.get("trade_no");; //交易完成 String body = params.get("body"); if (StringUtils.isEmpty(tradeno)) { tradeno = params.get("trade_no"); } log.info("3---->:【支付宝】交易的参数信息是:{},流水号是:{}", body, tradeno); try { JSONObject bodyJson = JSONObject.parseObject(body); String userId = bodyJson.getString("userId"); String ptype = bodyJson.getString("ptype"); String orderNumber = bodyJson.getString("orderNumber"); log.info("4---->:【支付宝】交易的参数信息是:ptype:{},orderNumber是:{}", ptype,orderNumber); // 课程支付成功,保存的订单交易明细 if (ptype != null && ptype.equalsIgnoreCase("productcourse")) { payCommonService.payproductcourse(bodyJson, userId, orderNumber, tradeno, "1"); } } catch (Exception ex) { log.info("支付宝支付出现了异常....."); ex.printStackTrace(); return false; } return true; } }
-
更新PayCommonService.java
package com.dzy.alipay.service.pay; import com.alibaba.fastjson.JSONObject; import com.dzy.alipay.entity.OrderDetail; import com.dzy.alipay.entity.ProductCourse; import com.dzy.alipay.mapper.OrderDetailMapper; import com.dzy.alipay.mapper.ProductCourseMapper; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Component; @Component @Log4j2 public class PayCommonService { private final OrderDetailMapper orderDetailMapper; private final ProductCourseMapper productCourseMapper; public PayCommonService(OrderDetailMapper orderDetailMapper, ProductCourseMapper productCourseMapper) { this.orderDetailMapper = orderDetailMapper; this.productCourseMapper = productCourseMapper; } /** * 支付课程回调封装 */ public void payproductcourse(JSONObject jsonObject, String userId, String orderNumber, String transaction_id, String paymethod) { String courseId = jsonObject.getString("courseID"); String money = jsonObject.getString("money"); ProductCourse productCourse = productCourseMapper.selectById(courseId); if (productCourse == null) { log.info("【" + (paymethod.equals("2") ? "微信" : "支付宝") + "】你支付的课程被删除了:{}", courseId); return; } OrderDetail orderDetail = new OrderDetail(); orderDetail.setUserid(userId); orderDetail.setCourseid(courseId); orderDetail.setUsername("飞哥"); orderDetail.setPaymethod(paymethod); orderDetail.setCoursetitle(productCourse.getTitle()); orderDetail.setCourseimg(productCourse.getImg()); orderDetail.setOrdernumber(orderNumber); orderDetail.setTradeno(transaction_id); orderDetail.setPrice(money == null ? "0.01" : money); orderDetailMapper.insert(orderDetail); } }
-
更新AlipayServiceImpl.java
package com.dzy.alipay.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradePrecreateModel; import com.alipay.api.request.AlipayTradePrecreateRequest; import com.alipay.api.response.AlipayTradePrecreateResponse; import com.dzy.alipay.config.AlipayConfig; import com.dzy.alipay.entity.ProductCourse; import com.dzy.alipay.qrcode.QRCodeUtil; import com.dzy.alipay.qrcode.QrCodeResponse; import com.dzy.alipay.qrcode.QrResponse; import com.dzy.alipay.service.course.ProductCourseService; import com.dzy.alipay.util.GenerateNum; import com.dzy.alipay.vo.PayVo; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Service; import org.springframework.util.FileCopyUtils; import org.springframework.util.ResourceUtils; import javax.imageio.ImageIO; import javax.imageio.stream.ImageOutputStream; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @Service @Log4j2 public class AlipayServiceImpl implements AlipayService { private final ProductCourseService productCourseService; private final AlipayConfig alipayConfig; public AlipayServiceImpl(AlipayConfig alipayConfig, ProductCourseService productCourseService) { this.alipayConfig = alipayConfig; this.productCourseService = productCourseService; } /* * @Author * @Description 阿里支付 -打赏 * @Date 23:59 2020/9/8 * @Param [payVo] * @return byte[] **/ @Override public byte[] alipay(PayVo payVo) { try { ProductCourse productCourse = productCourseService.getById(payVo.getCourseid()); if(productCourse==null){ return null; } // 1:支付的用户 String userId = payVo.getUserId(); // 2: 支付金额 String money = productCourse.getPrice().toString(); // 3: 支付的产品 String title = productCourse.getTitle(); // 4: 支付的订单编号 String orderNumber = GenerateNum.generateOrder(); // 5:支付宝携带的参数在回调中可以通过request获取 JSONObject json = new JSONObject(); json.put("userId", userId); json.put("orderNumber", orderNumber); json.put("money", money); json.put("ptype","productcourse"); json.put("courseID",payVo.getCourseid()); String params = json.toString(); // 6:设置支付相关的信息 AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); model.setOutTradeNo(orderNumber); // 自定义订单号 model.setTotalAmount(money);// 支付金额 model.setSubject(title);// 支付的产品名称 model.setBody(params);// 支付的请求体参数 model.setTimeoutExpress("30m");// 支付的超时时间 model.setStoreId(userId + "");// 支付的库存id QrCodeResponse qrCodeResponse = qrcodePay(model); ByteArrayOutputStream output = new ByteArrayOutputStream(); String logoPath =""; try { logoPath = ResourceUtils.getFile("classpath:favicon.png").getAbsolutePath(); }catch (Exception ex){ logoPath = new File("/www/wwwroot/aliPay/favicon.png").getAbsolutePath(); } BufferedImage buffImg = QRCodeUtil.encode(qrCodeResponse.getQr_code(), logoPath, false);//获取二维码 ImageOutputStream imageOut = ImageIO.createImageOutputStream(output); ImageIO.write(buffImg, "JPEG", imageOut); imageOut.close(); ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); return FileCopyUtils.copyToByteArray(input); } catch (Exception ex) { ex.printStackTrace(); return null; } } /** * 扫码运行代码 * 验签通过返回QrResponse * 失败打印日志信息 * 参考地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.app.pay */ public QrCodeResponse qrcodePay(AlipayTradePrecreateModel model) { // 1: 获取阿里请求客户端 AlipayClient alipayClient = getAlipayClient(); // 2: 获取阿里请求对象 AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); // 3:设置请求参数的集合,最大长度不限 request.setBizModel(model); // 设置异步回调地址 request.setNotifyUrl(alipayConfig.getNotify_url()); // 设置同步回调地址 request.setReturnUrl(alipayConfig.getReturn_url()); AlipayTradePrecreateResponse alipayTradePrecreateResponse = null; try { alipayTradePrecreateResponse = alipayClient.execute(request); } catch (AlipayApiException e) { e.printStackTrace(); } assert alipayTradePrecreateResponse != null; QrResponse qrResponse = JSON.parseObject(alipayTradePrecreateResponse.getBody(), QrResponse.class); return qrResponse.getAlipay_trade_precreate_response(); } /** * 获取AlipayClient对象 */ private AlipayClient getAlipayClient() { return new DefaultAlipayClient(alipayConfig.getGatewayUrl(), alipayConfig.getApp_id(), alipayConfig.getMerchant_private_key(), "JSON", alipayConfig.getCharset(), alipayConfig.getAlipay_public_key(), alipayConfig.getSign_type()); } }
-
更新OrderDetail.java
package com.dzy.alipay.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.Accessors; import java.util.Date; @Data @ToString @AllArgsConstructor @NoArgsConstructor @Accessors(chain = true) @TableName("kss_order_detail") public class OrderDetail { // 主键 @TableId(value = "id", type = IdType.ASSIGN_ID) private Long id; // 支付课程id private String courseid; // 支付课程标题 private String coursetitle; // 支付课程封面 private String courseimg; // 支付价格 private String price; // 支付用户 private String userid; // 支付用户昵称 private String username; // 支付流水订单号 private String ordernumber; // 支付交易号 private String tradeno; // 1 alipay 2 weixin private String paymethod; // 课程创建时间 @TableField(fill = FieldFill.INSERT) private Date createTime; // 课程更新时间 @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; }
-
更新OrderDetailMapper.java
package com.dzy.alipay.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dzy.alipay.entity.OrderDetail; import org.springframework.stereotype.Repository; @Repository public interface OrderDetailMapper extends BaseMapper<OrderDetail> { }
-
更新OrderDetailServiceImpl.java
package com.dzy.alipay.service.order; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dzy.alipay.entity.OrderDetail; import com.dzy.alipay.mapper.OrderDetailMapper; import org.springframework.stereotype.Service; @Service public class OrderDetailServiceImpl extends ServiceImpl<OrderDetailMapper, OrderDetail> implements OrderDetailService { }
-
然后将Java项目打jar包,上传至服务器中,以下是Linux操作命令
nohup java -jar aliPay.jar >>1.txt & # 后台运行jar包 tail -f 1.txt # 查看日志 netstat -anp | grep 8989 # 利用管道查看端口号8989有没有被占用 sudo lsof -i:8989 # 查看端口号8989的进程的PID sudo kill -9 9851 # 利用PID杀死进程
-
扫描二维码进行支付