技术汇总:第十四章:电脑端生成支付宝二维码支付

简介: 技术汇总:第十四章:电脑端生成支付宝二维码支付

支付宝支付

第一步:alipay.properties

alipay_url=https://openapi.alipay.com/gateway.do
#app的id
app_id=2018020102122556
#私钥
app_private_key=MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCdQeknhM2rhiGAH6V0ljxn3rAWIdzduTEQuteTfwjnZtvMhQPuuN1b/88D5yMuaZhZNFeUdWb+SmtP9DAzAWWgnT13T0YhJcxP6txm7JBRrjadCRt+LOFxPiPQk5t9fH7yXjw9i4uMDsNJeTncrVZ/AZYrk0ESC9anJR8XeuBc3HE8T4fqlKKl35jlumIWrPbPNQhKGXaGcOnpiaXO9qYYUSP/tnrjNYXHOso0yBs4YTl+LLX2TJ12p3n/oX6HnL4zQgtN5k4QasHP7CIig1ngcVQGfWsMm4djI9KXNXvGLQPfMQEmyb71mM5OCdl1MtAc6OaIAymhSv2hOLNIuyodAgMBAAECggEAe05/P5mGm4QlKI2n8u8KlneqovASe1kG/BNFjkYB+VBR8OAr4TfbepPvAyRuFap+5xN/yMz14VcBJkRWtufVhEdHNxJV7w/wUIncIGhGEYYFFMVbZWhTrbQH6TiUp6TC9dCmc6vD1CKPRkFj+YGBXT0lPy3LzBa0TYNyCbszyhthrgkpuFYbB0R93IPvvBh5NJFXQytwNb2oVopC9AQWviqnZUZcT0eJ087dQ1WLPa6blBD8DP1PUq0Ldr6pgKfObFxIj8+87DlJznRfdEsbqZlS7jagdw5tLr71WJpctIGPqKpgvajfePP/lj3eY82BKQB+aTw0zmAiB05Yes4LgQKBgQDq3EiQR8J1MEN2rpiLt1WvDYYvKVUgOY7Od//fRPgaMBstbe4TzGBpR8E+z267bHAWLaWtHkfX6muFHn1x68ozEUWk/nZq0smWnuPdcy4E7Itbk36W2FF/rOZB7j5ddlC9byrxDSNgcf9/FA/CU+i5KVQpLYfsk2dvwomvu0aFVQKBgQCraXpxzMmsBx4127LsZDO5bxfxb6nqzyK4NPe0VaGiRg8oaCWczcLz1J5iRqC9QeEwsSt4XU1sYBMTcsFpA0apZpm3prH2HJRx/isNENesaHcihF0mMd0WxU3xyRvWSDeZV5A1Zy1ZEJ+p17DGwb2j+yo2uBrDNXBgBWEzXwiRqQKBgBdXFvsHtqKQzlOQHGbeLGy+KlSrheMy9Sc9s7cLkqB/oWPNZfifugEceW71jGqh5y29EZb3yGoDyPWsxwi4Rxr2H3a7Nyd8lT4bwkdyt+MTYvIR4WW6T7chhqyMsbP2GyYIUzsrdBWUnrCRXNOSJTGpksyY0sZHC+OGcMp/EQ4VAoGBAIISSVL/pm1+/UK7U1ukcced8JpKNLM0uVD1CJ50eHHOHgR4e0owrWYfioxisejLjBlJ6AWvL2g0w2T3qKKKVN2JOM4ulU5/w3l4+KwygqaWowizTogEQJPd5ta52ADTzjTzSD/t6nByd+YHAWLhc4lyt0bMj6pf68VBb8/upm75AoGAGAYz79IVHp9eppykufjNcWu6okkG8tZnzuyaWKW/CuKKBWMaTk0vcyQlfJfxIBccoQrBuYyXBdcpPuZ/ys2C25pNrkACuhIKNgnMc0floJoYEfJzetw/3cIimWu4NJzVQOaojaGA58oo2+fub43Xn25Jq4rvSVe3oLdb5xWkw5Q=
#公钥
alipay_public_key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhkZi6W0wn/prX+NIIF9ATb5Z8ReKK4hFYtBrweDfGHD1mNW7YIZY4G5hE7S2Sry8eFXlFgSlBWlJ4fVnDaK9MkVThpwE2H65ooVlK/wLuyPqovIVpMt/utva5Ayuzv7eQOWK45FdLDNDlK8QLoBko6SS+YbnWnf7a+mrf4NAS4UFClpfe8Byqe8XIraO2Cg4Ko5Y5schX39rOAH8GlLdgqQRYVQ2dCnkIQ+L+I4Cy9Mvw3rIkTwt3MBU+AqREXY4r5Bn6cmmX/9MAJbFqrofGiUAqG+qbjTcZAzgNPfuiD0zXgt/YYjMQMzck75BOmwnYOam2ajODUSQn8Xybsa7wQIDAQAB
#回调地址
return_payment_url=http://localhost:8085/member/pay/alipay/callback/return
#异步地址需要外网可以访问(暂时没有写)
notify_payment_url=http://60.205.215.91/alipay/callback/notify

第二步:PayController

package com.macro.mall.portal.controller;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.macro.mall.common.api.CommonResult;
import com.macro.mall.model.OmsOrderItem;
import com.macro.mall.model.PaymentInfo;
import com.macro.mall.portal.config.AlipayConfig;
import com.macro.mall.portal.service.OmsPortalOrderService;
import com.macro.mall.portal.service.PaymentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
 * 支付管理
 */
@Controller
@Api(tags = "PayController", description = "支付管理")
@RequestMapping("/member/pay")
public class PayController {
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private OmsPortalOrderService omsPortalOrderService;
    @Autowired
    AlipayClient alipayClient;
    @ApiOperation("去支付")
    @RequestMapping(value = "/alipay/submit", method = RequestMethod.GET)
    @ResponseBody
    public String goToPay( String orderSn, BigDecimal totalAmount) {
        //根据订单编号获取订单详情信息
        OmsOrderItem omsOrderItem =omsPortalOrderService.getOrderByOrderSn(orderSn);
        //获取商品名称
        String productName = omsOrderItem.getProductName();
        //创建PC场景下单并支付请求对象
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//创建API对应的request
        //设置同步返回地址,HTTP/HTTPS开头字符串
        alipayRequest.setReturnUrl(AlipayConfig.return_payment_url);
        //支付宝服务器主动通知商户服务器里指定的页面http/https路径。
        alipayRequest.setNotifyUrl(AlipayConfig.notify_payment_url);//在公共参数中设置回跳和通知地址
        Map<String,String> requestMap = new HashMap<>();
        requestMap.put("out_trade_no",orderSn);//订单编号
        requestMap.put("product_code","FAST_INSTANT_TRADE_PAY");//产品交易码
        requestMap.put("total_amount","0.01");//实际付款金额
        requestMap.put("subject",productName);//商品名称
        //填充业务参数
        alipayRequest.setBizContent(JSON.toJSONString(requestMap));
        String form="";
        try {
            //调用SDK生成表单
            form = alipayClient.pageExecute(alipayRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        // 生成(保存)支付信息
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setOutTradeNo(orderSn);
        paymentInfo.setPaymentStatus("未支付");
        paymentInfo.setOrderId(String.valueOf(omsOrderItem.getOrderId()));
        paymentInfo.setTotalAmount(totalAmount);
        paymentInfo.setSubject(productName);
        paymentInfo.setCreateTime(new Date());
        paymentService.save(paymentInfo);
        // 发送检查支付结果的消息队列,
        paymentService.sendDelayPaymentCheck(orderSn,5);
        return form;
    }
    @ApiOperation("支付成功后同步回调转支付成功页面")
    @ResponseBody
    @RequestMapping(value = "/alipay/callback/return",method = RequestMethod.GET)
    public CommonResult callBackReturn(HttpServletRequest request){// 页面同步反转的回调
        Map<String,String> paramsMap = new HashMap<String, String>();
        Map parameterMap = request.getParameterMap();
        for(Iterator<String> iter = parameterMap.keySet().iterator(); iter.hasNext();){
            String name = iter.next();
            String[] values = (String [])parameterMap.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1 ) ? valueStr + values [i] : valueStr + values[i] + ",";
            }
            paramsMap.put(name,valueStr);
        }
        String outTradeNo = request.getParameter("out_trade_no");
        String tradeNo = request.getParameter("trade_no");
        String sign = request.getParameter("sign");
        try {
            boolean b = AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key,AlipayConfig.charset,AlipayConfig.sign_type);// 对支付宝回调签名的校验
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //修改支付信息,幂等性检查
/*        boolean b = paymentService.checkPaymentStatus(outTradeNo);
        if(!b){
            PaymentInfo paymentInfo = paymentService.checkPaymentResult(outTradeNo);
            paymentService.updatePayment(request.getQueryString(),outTradeNo,tradeNo);
            //发送系统消息,出发并发商品支付业务消息队列
            paymentService.sendPaymentSuccess(outTradeNo,paymentInfo.getPaymentStatus(),tradeNo);
        }*/
        return CommonResult.success("支付成功");
    }
}

第三步:发送检查支付结果的消息队列

    @Autowired
    private OmsOrderSettingMapper orderSettingMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;
    /**
     * 发送检查支付结果的消息队列
     * @param orderSn
     * @param count
     */
    @Override
    public void sendDelayPaymentCheck(String orderSn, int count) {
        //获取订单超时时间
        OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
        long delayTimes = orderSetting.getNormalOrderOvertime() * 60 * 1000;
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put("out_trade_no",orderSn);
        hashMap.put("count",count);
        //给延迟队列发送消息
        amqpTemplate.convertAndSend(QueueEnum.QUEUE_PAY_CANCEL.getExchange(), QueueEnum.QUEUE_PAY_CANCEL.getRouteKey(), hashMap, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //给消息设置延迟毫秒值
                message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
                return message;
            }
        });
    }

第四步:处理发送检查支付结果的消息队列

package com.macro.mall.portal.component;
import com.macro.mall.model.PaymentInfo;
import com.macro.mall.portal.service.PaymentService;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
/**
 * 支付的处理者
 */
@Component
@RabbitListener(queues = "mall.pay.cancel")
public class PayReceiver {
    @Autowired
    PaymentService paymentService;
    @RabbitHandler
    public void handle(HashMap mapMessage){
        try {
            String outTradeNo = mapMessage.get("out_trade_no").toString();
            int count = Integer.parseInt(mapMessage.get("count").toString());
            // 如果没有支付成功,再次发送延迟检查队列
            if (count > 0) {
                // 进行支付状态检查
                System.out.println("正在进行第" + (6 - count) + "支付结果次检查");
                //调用alipayClient接口,根据out_trade_no查询支付信息
                PaymentInfo paymentInfo = paymentService.checkPaymentResult(outTradeNo);
                Thread thread = new Thread();
                thread.start();
                Thread.sleep(10000);
                //判断是否已经支付成功
                if (paymentInfo.getPaymentStatus()!=null&&(paymentInfo.getPaymentStatus().equals("TRADE_SUCCESS") || paymentInfo.getPaymentStatus().equals("TRADE_FINISHED"))) {
                    // 交易成功或者失败,记录交易状态
                    System.out.println("检查交易结果成功,记录交易状态。。。");// 修改支付的状态信息
                    // 修改支付信息
                    boolean b = paymentService.checkPaymentStatus(outTradeNo);
                    if(!b){
                        //修改为已支付
                        paymentService.updatePayment(paymentInfo.getCallbackContent(),outTradeNo,paymentInfo.getAlipayTradeNo());
                        // 发送系统消息,出发并发商品支付业务消息队列
                        paymentService.sendPaymentSuccess(paymentInfo.getOutTradeNo(),paymentInfo.getPaymentStatus(),paymentInfo.getAlipayTradeNo());
                    }
                } else {//未支付
                    // 再次进行延迟检查
                    System.out.println("正在进行第" + (6 - count) + "支付结果次检查,检查用户尚未付款成功,继续巡检");
                    paymentService.sendDelayPaymentCheck(outTradeNo, count - 1);
                }
            } else {
                System.out.println("支付结果次检查次数耗尽,支付未果。。。");
            }
        } catch (Exception e) {
        }
    }
}

第五步:调用alipayClient接口,根据out_trade_no查询支付信息

    @Autowired
    AlipayClient alipayClient;
/**
     * 进行支付状态检查
     * @param outTradeNo
     * @return
     */
    @Override
    public PaymentInfo checkPaymentResult(String outTradeNo) {
        PaymentInfo paymentInfo = new PaymentInfo();
        // 调用alipayClient接口,根据out_trade_no查询支付状态
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        Map<String,Object> mapString = new HashMap<String,Object>();
        mapString.put("out_trade_no",outTradeNo);
        String s = JSON.toJSONString(mapString);
        request.setBizContent(s);
        AlipayTradeQueryResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        // 等待付款、付款成功、付款失败、已经结束
        paymentInfo.setCallbackTime(new Date());
        paymentInfo.setOutTradeNo(outTradeNo);
        paymentInfo.setCallbackContent(response.getMsg());
        if(response.isSuccess()){
            System.out.println("交易已经创建");
            paymentInfo.setPaymentStatus(response.getTradeStatus());
            paymentInfo.setAlipayTradeNo(response.getTradeNo());
        } else {
            System.out.println("交易未创建");
        }
        return paymentInfo;
    }

第六步:发送系统消息,出发并发商品支付业务消息队列

    @Autowired
    private OmsOrderSettingMapper orderSettingMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;
  /**
     * 发送系统消息,出发并发商品支付业务消息队列
     * @param outTradeNo
     * @param paymentStatus
     * @param tradeNo
     */
    @Override
    public void sendPaymentSuccess(String outTradeNo, String paymentStatus, String tradeNo) {
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("outTradeNo",outTradeNo);
        hashMap.put("paymentStatus",paymentStatus);
        hashMap.put("tradeNo",tradeNo);
        OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
        long delayTimes = orderSetting.getNormalOrderOvertime() * 60 * 1000;
        //给延迟队列发送消息
        amqpTemplate.convertAndSend(QueueEnum.QUEUE_PAYMENT_SUCCESS_CANCEL.getExchange(), QueueEnum.QUEUE_PAYMENT_SUCCESS_CANCEL.getRouteKey(), hashMap, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //给消息设置延迟毫秒值
                message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
                return message;
            }
        });
    }

第七步:处理发送系统消息,出发并发商品支付业务消息队列

package com.macro.mall.portal.component;
import com.macro.mall.portal.service.OmsOrderService;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
/**
 * 支付成功的处理者
 */
@Component
@RabbitListener(queues = "mall.paysuccess.cancel")
public class PaySuccessReceiver {
    @Autowired
    private OmsOrderService orderService;
    @RabbitHandler
    public void handle(HashMap mapMessage){
        String outTradeNo = mapMessage.get("outTradeNo").toString();
        String trackingNo = mapMessage.get("tradeNo").toString();
        String paymentStatus = mapMessage.get("paymentStatus").toString();
        // 消费代码
        orderService.updateOrder(outTradeNo,paymentStatus,trackingNo);
        // 发送一个订单成功的消息队列,由库存系统消费(或者调用库存接口)
        orderService.sendOrderResult(outTradeNo);
    }
}

第八步:发送一个订单成功的消息队列,由库存系统消费(或者调用库存接口)

    @Autowired
    private OmsOrderItemMapper omsOrderItemMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;
/**
     * 发送一个订单成功的消息队列,由库存系统消费(或者调用库存接口)
     * @param outTradeNo
     */
    @Override
    public void sendOrderResult(String outTradeNo) {
        OmsOrderItemExample omsOrderItemExample = new OmsOrderItemExample();
        OmsOrderItemExample.Criteria criteria = omsOrderItemExample.createCriteria();
        criteria.andOrderSnEqualTo(outTradeNo);
        List<OmsOrderItem> omsOrderItems = omsOrderItemMapper.selectByExample(omsOrderItemExample);
        OmsOrderItem omsOrder = omsOrderItems.get(0);
        Long productId = omsOrder.getProductId();
        HashMap<String, Long> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("productId",productId);
        //给延迟队列发送消息
        amqpTemplate.convertAndSend(QueueEnum.QUEUE_STOCK_QUEUE.getExchange(), QueueEnum.QUEUE_STOCK_QUEUE.getRouteKey(),objectObjectHashMap, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //给消息设置延迟毫秒值
                message.getMessageProperties().setExpiration(String.valueOf(0));
                return message;
            }
        });
    }

第九步:处理发送一个订单成功的消息队列,由库存系统消费(或者调用库存接口)

package com.macro.mall.portal.component;
import com.macro.mall.portal.service.PmsSkuStockService;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
@Component
@RabbitListener(queues = "mall.stock.cancel")
public class StockReserve {
    @Autowired
    private PmsSkuStockService pmsSkuStockService;
    @RabbitHandler
    public void handle(HashMap<String, Long> productId){
        //根据订单编号查询该订单的商品数量
        Integer productQuantity = pmsSkuStockService.getProductQuantity(productId);
        //根据商品id减卖家库存表的库存
        pmsSkuStockService.updateOrderStock(productQuantity,productId.get("productId"));
    }
}

如果对rabbitmq不熟悉的话可以查看https://blog.csdn.net/java_wxid/article/category/8663217

相关文章
|
11月前
|
JSON 小程序 数据可视化
手把手带你开发一款云开发版点餐小程序,微信扫码点餐,用户端和后厨端都有
手把手带你开发一款云开发版点餐小程序,微信扫码点餐,用户端和后厨端都有
271 0
|
6月前
|
网络安全 开发工具 Android开发
微信刷脸支付插件
微信刷脸支付插件
94 0
|
存储 传感器 文字识别
二维码支付功能设计【系列文章,本章1】
扫一扫已经是我们生活中非常熟悉的功能,而扫一扫离不开二维码,那么二维码扫码原理是什么,如何实现的,如果企业要上自己的扫码功能如何实现? 本章将从二维码原理讲起。
364 0
二维码支付功能设计【系列文章,本章1】
|
双11 开发者
有奖反馈 | 支付宝使用demo在线调试,小白也能轻松接入当面付
刚到公司一段时间就赶上双十一,大促在即,当面付的功能开发不知道怎么搞,奈何功能包接口太多,组合效果啥样子不清楚!能不能满足老板的“想象”还不知道!商家资质也没申请下来,环境搭建又很繁琐,文档写的还和教科书一样复杂,啊啊啊~有个demo可以让我先试试,学习一把就好了。开箱即用的当面付在线调试Demo玩起来,效果一目了然,这次我们还提供了大礼相送,学+实践+好礼,能力这趴不再是问题!
2219 0
有奖反馈 | 支付宝使用demo在线调试,小白也能轻松接入当面付
为什么第三方应用内无法找到当面付快捷版功能
为什么第三方应用内无法找到当面付快捷版功能
1149 0
为什么第三方应用内无法找到当面付快捷版功能
如何开发创建微信、支付宝、百度等多合一小程序?
那么要是能有一个平台,能一下子生成多个平台的小程序就好了,那么小编告诉你,阿里云已经帮你实现了。
9173 0
|
iOS开发
iPhone 手机中支付宝钱包页面电话带 +86问题解决方案
说明:   这个问题只会出现在iPhone手机系统大于11.2以上的版本,由于 UIWebview 的问题导致 电话号码(如下图) 解决方案:   一般我们写的代码如下:  拨打电话  修改成代码参考如下:  拨打电话 如果您对这个方案有任何疑问欢迎在帖子下方追问吐槽
532 0
小程序快速接入支付宝卡包
[font=微软雅黑] [size=2] 企业或者个人开发者可以通过支付宝提供的开放接口,把卡券添加到支付宝卡包,用户可以通过小程序查看卡券,同时支持跳转到支付宝卡包页面,在卡包中查看并使用商户同步进来的卡券。
776 0