Springboot는 Alipay 지불을 실현합니다.

1. Ant Financial Open Platform 진입

https://open.alipay.com/platform/home.htm

2. 공식 Alipay 데모 다운로드, 구성 및 테스트

문서 주소 :

https://openhome.alipay.com/docCenter/docCenter.htm 애플리케이션 해당 문서 생성

https://opendocs.alipay.com/open/200/105304 웹 모바일 애플리케이션 문서

https://opendocs.alipay.com/open/54/cyz7do 관련 데모
여기에 사진 설명 삽입
여기에 사진 설명 삽입
여기에 사진 설명 삽입

3. 테스트에 샌드 박스 사용

https://openhome.alipay.com/platform/appDaily.htm?tab=info
여기에 사진 설명 삽입

4. 공개 키, 개인 키, 암호화, 서명 및 확인이란 무엇입니까?

1. 공개 키, 개인 키, 공개 키 및 개인 키는 상대적인 개념입니다.

그들의 공적 및 사적 성격은 발전기에 상대적입니다.

한 쌍의 키가 생성 된 후 개인 키는 생성기의 손에 보관되고 생성기가 게시하는 공개 키는 공개 키입니다.

여기에 사진 설명 삽입

Alipay 개발 플랫폼 개발 도우미 다운로드여기에 사진 설명 삽입

5. Alipay 결제 프로세스

https://opendocs.alipay.com/open/270/105898

1. 사용자를 Alipay 페이지로 안내

1, pom.xml

<!--支付宝模块-->
 <dependency>
     <groupId>com.alipay.sdk</groupId>
     <artifactId>alipay-sdk-java</artifactId>
     <version>4.9.28.ALL</version>
 </dependency>

2. 자료에서 제공하는 파일을 프로젝트에 도입

AlipayTemplate 、 PayVo 、 PaySyncVo

AlipayTemplate
application.yml 에 추가되었습니다.

#配置支付宝
alipay:
  app_id: 2016101800718205

여기에 사진 설명 삽입

package com.atguigu.gulimall.order.config;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.atguigu.gulimall.order.vo.PayVo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@ConfigurationProperties(prefix = "alipay")
@Component
@Data
public class AlipayTemplate {
    
    

    //在支付宝创建的应用的id
    private   String app_id = "2016092200568607";

    // 商户私钥,您的PKCS8格式RSA2私钥
    private  String merchant_private_key = "XXX";
    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    private  String alipay_public_key = "XXX";
    // 服务器[异步通知]页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    // 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
    private  String notify_url="http://eaact93of6.52http.tech/payed/notify";

    // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    //同步通知,支付成功,一般跳转到成功页
    //在本地开发的时候可以使用内网穿透的生成的域名来做测试。
    private  String return_url = "http://member.gulimall.com/memberOrder.html";

    // 签名方式
    private  String sign_type = "RSA2";

    // 字符编码格式
    private  String charset = "utf-8";
    // 订单超时时间,到达超时时间后自动关闭订单不能再继续支付
    private String timeout = "30m";

    // 支付宝网关; https://openapi.alipaydev.com/gateway.do
    private  String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

    public  String pay(PayVo vo) 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 = vo.getOut_trade_no();
        //付款金额,必填
        String total_amount = vo.getTotal_amount();
        //订单名称,必填
        String subject = vo.getSubject();
        //商品描述,可空
        String body = vo.getBody();

        // timeout_express 订单支付超时时间
        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"timeout_express\":\"" + timeout + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        String result = alipayClient.pageExecute(alipayRequest).getBody();

        //会收到支付宝的响应,响应的是一个页面,只要浏览器显示这个页面,就会自动来到支付宝的收银台页面
        System.out.println("支付宝的响应:"+result);

        return result;
    }
}

PayVo

package com.atguigu.gulimall.order.vo;

import lombok.Data;

/**
 * 支付使用Vo
 */
@Data
public class PayVo {
    
    
    private String out_trade_no; // 商户订单号 必填
    private String subject; // 订单名称 必填
    private String total_amount;  // 付款金额 必填
    private String body; // 商品描述 可空
}

3. 결제 페이지로 이동하는 업체 작성

제어 장치

/**
 * @author gcq
 * @Create 2021-01-08
 */
@Controller
public class PayWebController {
    
    

    @Autowired
    AlipayTemplate alipayTemplate;

    @Autowired
    OrderService orderService;

    /**
     * 1、跳转到支付页面
     * 2、用户支付成功后,我们要跳转到用户的订单列表页
     * produces 明确方法会返回什么类型,这里返回的是html页面
     * @param orderSn
     * @return
     * @throws AlipayApiException
     */
    @ResponseBody
    @GetMapping(value = "/payOrder",produces = "text/html")
    public String payOrder(@RequestParam("orderSn") String orderSn) throws AlipayApiException {
    
    
//        PayVo payVo = new PayVo();
//        payVo.setBody(); // 商品描述
//        payVo.setSubject(); //订单名称
//        payVo.setOut_trade_no(); // 订单号
//        payVo.setTotal_amount(); //总金额
        PayVo payvo = orderService.payOrder(orderSn);
        // 将返回支付宝的支付页面,需要将这个页面进行显示
        String pay = alipayTemplate.pay(payvo);
        System.out.println(pay);
        return pay;
    }
}

서비스

 /**
     * 计算商品支付需要的信息
     * @param orderSn
     * @return
     */
    @Override
    public PayVo payOrder(String orderSn) {
    
    
        PayVo payVo = new PayVo();
        OrderEntity orderEntity = this.getOrderByOrderSn(orderSn); // 根据订单号查询到商品
        // 数据库中付款金额小数有4位,但是支付宝只接受2位,所以向上取整两位数
        BigDecimal decimal = orderEntity.getPayAmount().setScale(2, BigDecimal.ROUND_UP);
        payVo.setTotal_amount(decimal.toString());
        // 商户订单号
        payVo.setOut_trade_no(orderSn);
        // 查询出订单项,用来设置商品的描述和商品名称
        List<OrderItemEntity> itemEntities = orderItemService.list(new QueryWrapper<OrderItemEntity>()
                .eq("order_sn", orderSn));
        OrderItemEntity itemEntity = itemEntities.get(0);
        // 订单名称使用商品项的名字
        payVo.setSubject(itemEntity.getSkuName());
        // 商品的描述使用商品项的属性
        payVo.setBody(itemEntity.getSkuAttrsVals());
        return payVo;
    }

마지막으로 Alipay의 결제 페이지가 생성됩니다.

3. 결제 완료 후 성공 페이지로 이동

점프 된 페이지는 AlipayTemplate에서 정의한 콜백 주소에 따라 점프됩니다.

  • notify_url : 성공적인 결제를위한 비동기 콜백, 성공적인 결제에 대한 정보를 반환하며, 매개 변수 형식으로 주소 뒤에 연결됩니다.
  • return_url : 결제 성공 후 페이지로 이동하는 동기 알림
   // 服务器[异步通知]页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    // 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
    private  String notify_url = "http://eaact93of6.52http.tech/payed/notify";

 // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
 //同步通知,支付成功,一般跳转到成功页,这里跳转到我的订单页。
    private  String return_url = "http://member.gulimall.com/memberOrder.html";

1. 결제 성공 후 비동기 콜백 인터페이스 처리

이 방법을 수신하려면 서버가 있거나 인트라넷 침투를 구성해야합니다. nginx 구성 파일에서 구성 정보를 수정합니다.
여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입
Alipay는 컨트롤러를 비동기 적으로 호출합니다. 여기서 Alipay는 분산 트랜잭션에서 최선의 알림을 사용하여이 주소를 다시 호출합니다. 때때로이 주소로 다시 호출하며이 주소가 그에게 성공을 반환 할 때만 끝입니다. .


/**
 * 支付宝成功异步回调
 * @author gcq
 * @Create 2021-01-08
 */
@RestController
public class OrderPayedListenerController {
    
    
    @Autowired
    AlipayTemplate alipayTemplate;

    @Autowired
    OrderService orderService;

    /**
     * 支付宝异步通知回调接口,需要拥有内网穿透或服务器
     * @param request
     * @return
     */
    @PostMapping("/payed/notify")
    public String handleAlipayed(PayAsyncVo vo, HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException {
    
    
        /**
         * 重要一步验签名
         *  防止别人通过postman给我们发送一个请求,告诉我们请求成功,为了防止这种效果通过验签
         */
        Map<String,String> params = new HashMap<String,String>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> 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] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        // 支付宝验签 防止恶意提交
        boolean signVerified = AlipaySignature.rsaCheckV1(params
                , alipayTemplate.getAlipay_public_key()
                , alipayTemplate.getCharset()
                , alipayTemplate.getSign_type());
        if (signVerified) {
    
    
            String result = orderService.handlePayResult(vo);
            return result;
        } else {
    
    
            return "error";
        }
    }
}

서비스

 @Override
    public String handlePayResult(PayAsyncVo vo) {
    
    
        // 保存交易流水信息,每个月和支付宝进行对账
        PaymentInfoEntity infoEntity = new PaymentInfoEntity();
        // 设置核心字段
        infoEntity.setOrderSn(vo.getOut_trade_no());
        infoEntity.setAlipayTradeNo(vo.getTrade_no());
        infoEntity.setPaymentStatus(vo.getTrade_status());
        infoEntity.setCallbackTime(vo.getNotify_time());
        // 保存订单流水
        paymentInfoService.save(infoEntity);
        /**
         * 支付宝交易状态说明
         *      https://opendocs.alipay.com/open/270/105902
         */
        // TRADE_FINISHED 交易结束、不可退款
        // TRADE_SUCCESS 交易支付成功
        if (vo.getTrade_status().equals("TRADE_SUCCESS") || vo.getTrade_status().equals("TRADE_FINISHED")) {
    
    
            String outTradeNo = vo.getOut_trade_no();
            // 支付宝回调成功后,更改订单的支付状态位已支付
            this.baseMapper.updateOrderStatus(outTradeNo,OrderStatusEnum.PAYED.getCode());
        }
        return "success";
    }

문제 획득 :
여기에 사진 설명 삽입
질문 1. 제한 시간을 설정할 수 있으며 해당 기간이 만료 된 후에는 결제를 시작할 수 없습니다.
여기에 사진 설명 삽입여기에 사진 설명 삽입

질문 2 :
통합 획득 트랜잭션 종료 인터페이스 로직 또는 다운로드 한 데모 종료 코드를 참조하고 시간 초과 모니터링 순서에서 수동으로 종료를 호출합니다.

추천

출처blog.csdn.net/u014496893/article/details/114292481