Springboot Alipay sandbox payment - complete and detailed steps

1. Enter Alipay development platform sandbox environment

Sandbox environment - Alipay Document Center

1.1. Enter personal sandbox environment

Click to enter the sandbox environment and log in with Alipay

Sandbox management interface is shown in the figure

  • appid, Alipay gateway, custom key, etc

  • Here is the account number and password of sandbox Alipay (virtual), which can be used to pay

1.2. Next, generate several keys

Click to enter Key tool
Click generate

At this time, we get two keys and save them. These two keys are very important

  • Apply private key
  • Apply public key

1.3. After getting two keys, configure the user-defined key

Enter the initial sandbox management interface, click the user-defined key, click settings (view), and we choose the RSA2 key

Select the option "public key"

Fill in the application public key generated in the previous step, and you will get another key, Alipay public key. Remember and save this Alipay public key

1.4 so far, the configuration and basic parameters of our sandbox environment have been obtained.

2. Project side code configuration

2.1. First import the dependency of Alipay payment into pom.xml

Here I use the springboot+maven+themyleaf project

        <!--   Dependence of Alipay payment     -->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.16.2.ALL</version>
        </dependency>

2.2. Create payment Controller class

  • To enter Alipay payment from the Controller, you need to complete the interface provided by Alipay
  • Create the PayController class with the following code

After creating the Controller class, first set the following private properties

  • APP_ID (appId, obtained from sandbox management page)

  • APP_PRIVATE_KEY (apply the private key, which was first generated by the key tool)

  • ALIPAY_PUBLIC_KEY (Alipay public key, obtained in the previous step)

  • GATEWAY_URL (Alipay gateway address, obtained from the sandbox management page of the development platform)

  • SIGN_TYPE (signature type)

  • NOTIFY_URL (asynchronous callback address, which must be public IP, which will be explained later)

  • RETURN_URL (synchronous callback address, which can be private IP)

    @Controller
    public class PayController {
    @Autowired
    DonaItemService donaItemService;
    @Autowired
    DonaService donaService;
    //appid
    private final String APP_ID = "2021000119625133";
    //Apply private key
    private final String APP_PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCDA1Y0+IjB/z4sIhJA0sgEaNGXV9+8t0fUMhrbjHjW88tz8d7jR8ev1aFMmyDKy/cSnlsoNDLwx71GCLiNQENYTvqdcsrYLMvQkmeIYT1OWcPYSl65P0TQRDBhakVdAIXvnts7KJ/nCROGMy8qrBG8ilSlNaOkiuXgp1OPIqLe2dCkrJp1spOJ3Wfq9uyqJO5xrgx6tby3MVPLu/nJ2PtzXt62Kpcj/S9Xxxk9FXOw8cwGDStMPU471VKpEP4kMnjfpUpB9/FfQ6oDfokIaq9dehN9xSitAD6p5cFct7oG94DHai5a+ST6X+OfTv03oE2DuA7ejaJn6cDGSB4IYmZRuDGdicqmPmLEHt3Kq79+EPxBYKUcWI4zQPXlA06Kcgb8HrJntjC836svSUrewWaG32g5MlJB8e1Z+1yL75E6k6R4rBJiVW2MC5VW+p/nQiY3FLfRq4a8V+VJ9uXM1h7L8TbOHtCAQKBgQDCSljMB8VnLFMKHOrcHCZNtjnDHsRYJQYEgNhhvwx2xUIgZNhzpiDmUSwR4TOaqF+Eg5bLfC+sQboANXpP5YUyt/rqUWqQ1fmEV5US9cfiYOi5rfjETK0q6VwagYRjXe84e039Q+D8bGypY+T+uuzFcJjudfWTjBkvkOzwt57/4QKBgQCsn/BLJvO4zueqIF/A5lHdA0R3C8K9ipNjmg9LvU3/5ZXOYx//CcLk82s83C2j9rgQKBgQCNTcaW3eW3K7a6rhFzh5UPQzoX+7VFfqR0BbEFtN7Pr/spZ/X4YVqWRyvkaZbC/9frRnEAKSXLP/pN1b9F1tdMa/2iUgefi3XMJ/z4v0T4iqE58A57UEEH68JMVYuNq5kwVnnZ9FONzhpbRftJuIRAJZaqAVZ0b0PAOMoQpNSbiQKBgHtAnpTuE0QFby+7hDsnTz+qC9dyQQWH3cBOn4RQzo1DUxvyQpZjAy0Oqn/F5x6RGMQU6SrirdUQbGWcANOpp9/L3YGHUrUjlT5Ehx2nPO//yTZSTWKM+p6+XALn1DGZbTChnL/5aEZsg5R4f55wL6RYezRzhq+w4wMixTQDyFLZ";
    private final String CHARSET = "UTF-8";
    //Alipay public key
    private final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3CPgueDLkfB66s9ZsEUwyUbmkRknTFVyuBG4PkKI93OTOVC457ijEKknRYi8eKYo4Wl+7z4/nRXYCxc9XBynqtnJzronKm9Wv+7sswJI6g3Qn2SdjFxWHoQDrEqXKQALv2YVqE7R+BZqTS5TkDerQI1l+Nq3m7oemztrlx+96iAR5KxYO+tTr1u3XQZmjtjlqbty50DmxRCgEqJKYEu6CD+r1vi+2SXOUKnCJzsE8vHojS+Vk5oGbZYnX6Esw2TVeiCkmQ814CBwIDAQAB";
    //This is the sandbox interface path. The official path is https://openapi.alipay.com/gateway.do
    private final String GATEWAY_URL ="https://openapi.alipaydev.com/gateway.do";
    private final String FORMAT = "JSON";
    //Signature method
    private final String SIGN_TYPE = "RSA2";
    //Alipay asynchronous notification path. After payment, the method of this project will be called asynchronously. It must be a public network address
    private final String NOTIFY_URL = "http://127.0.0.1/notifyUrl";
    //Alipay synchronous notification path, that is, when the payment is completed, jump to the page of this project, which can not be the public network address
    private final String RETURN_URL = "http://localhost:8080/returnUrl";
    }

2.3. Create the method of clicking payment to jump to Alipay page in the Controller class

   //The ResponseBody annotation must be added, otherwise spring will look for the thymeleaf page
    @ResponseBody
    @RequestMapping("/pay/alipay")
    public String alipay(HttpSession session,Model model,
                         @RequestParam("dona_money") float dona_money,
                        @RequestParam("dona_id") int dona_id) throws AlipayApiException {
        //Put dona_id item id is placed in session
        session.setAttribute("dona_id",dona_id);

        //Generate order number (requirements of Alipay?)
        String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        String user = UUID.randomUUID().toString().replace("-","").toUpperCase();

        String OrderNum = time+user;

        //Call the encapsulated method (send a request to Alipay interface)
        return sendRequestToAlipay(OrderNum,dona_money,"ghjk");
    }
        /*
    Parameter 1: order number
    Parameter 2: order amount
    Parameter 3: order name
     */
     //Interface officially provided by Alipay
    private String sendRequestToAlipay(String outTradeNo,Float totalAmount,String subject) throws AlipayApiException {
        //Get the initialized AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL,APP_ID,APP_PRIVATE_KEY,FORMAT,CHARSET,ALIPAY_PUBLIC_KEY,SIGN_TYPE);

        //Set request parameters
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(RETURN_URL);
        alipayRequest.setNotifyUrl(NOTIFY_URL);

        //Product description (can be blank)
        String body="";
        alipayRequest.setBizContent("{"out_trade_no":"" + outTradeNo + "","
                        + ""total_amount":"" + totalAmount + "","
                        + ""subject":"" + subject + "","
                        + ""body":"" + body + "","
                        + ""product_code":"FAST_INSTANT_TRADE_PAY"}");

        //request
        String result = alipayClient.pageExecute(alipayRequest).getBody();
        return result;
    }

Explain that after clicking pay on the front page, you will jump to the Controller's = =alipay() = = method

  • The alipay method will receive some front-end parameters
  • The sendRequestToAlipay method is called in the alipay method. The sendRequestToAlipay method has the interface officially given by alipay, and only needs to provide some parameters (strictly specified parameters by alipay)

sendRequestToAlipay method

  • In addition to the previously set private properties (URL, public key, private key, gateway, etc.), you also need to provide parameters
  • outTradeNo, order number, must be String64 bits, cannot be empty and cannot be repeated
  • totalAmount, payment amount, cannot be blank
  • subject, order name, cannot be empty
  • body, product description, can be empty

The above three mandatory parameters are very important and must comply with the regulations of Alipay, which can be seen and useful when scanning the code for payment

After setting the jump to Alipay method, we can test it. First, we fill in the url in the front-end form to access the controller method just written

Figure using thymeleaf template engine

  • After setting, start the project and click Submit Form


This page accesses the page officially provided by Alipay. So far, the sandbox payment has been half completed. Next, we need to write the return () method to make us respond and jump to the page after we complete the payment.

2.4 log in to Alipay sandbox account

Because it is a sandbox environment and virtual, the Alipay scanning code above cannot be scanned with the real Alipay, but needs to download a sandbox Alipay APP

Scan the code to download

The login account and password after downloading are also the account and password of the sandbox environment, and the password used during payment is also included

2.5. Write the method of synchronous callback after payment

  • After scanning the code (or entering the password) for payment, Alipay will automatically call our previously set RETURN_URL (actually called locally), so this address can be a private network address

  • As shown in the figure, return_ The value of the URL is http://localhost:8080/returnUrl So we write this method in the project and let it call

  • Also, it is completed in the Controller

    @RequestMapping("/returnUrl")
    public String returnUrlMethod(HttpServletRequest request,HttpSession session,Model model) throws AlipayApiException, UnsupportedEncodingException {
    System.out.println("= synchronous callback ====");

        // GET feedback from Alipay GET
        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] + ",";
            }
            // Garbled code solution, this code is used in case of garbled code
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
    
        System.out.println(params);//Check the parameters
        //Verify signature (Alipay public key)
        boolean signVerified = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE); // Call SDK to verify signature
        //Verification signature passed
        if(signVerified){
            // Merchant order number
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
    
            // Alipay transaction serial number
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
    
            // Payment amount
            float money = Float.parseFloat(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));
    
            System.out.println("Merchant order number="+out_trade_no);
            System.out.println("Alipay transaction number="+trade_no);
            System.out.println("Payment amount="+money);
    
            //Write your own business code here (operation on database)
    		/*
    		################################
    		*/
            //Jump to the prompt page (successful or failed prompt page)
            model.addAttribute("flag",1);
            model.addAttribute("msg","support");
            return "common/payTips";
        }else{
            //Jump to the prompt page (successful or failed prompt page)
            model.addAttribute("flag",0);
            model.addAttribute("msg","support");
            return "common/payTips";
        }
    }
    
  • Some of the codes in the box in the figure are callback operations given by Alipay officials, so it is best not to change them, and the names of individual parameters can be changed


  • The code to operate the database can be carried out in this method or in the asynchronous callback method
  • The last part I return is the thymeleaf page. If you want to directly return String or other types of databases, you can add the @ResponseBody annotation in front of the method

2.6 asynchronous callback method

  • The above is Alipay synchronous call processing, but the official suggestion is that the operation after successful payment should be processed in the asynchronous call method. However, since the path of asynchronous call must be the public network address, Alipay can send the request to us, so the asynchronous call method is not written here. It should be noted that the asynchronous call is a post request, and the parameters passed will be more, but it is basically the same as the operation of synchronous call

  • The asynchronous callback method must be public IP, because the URL address is the official address of Alipay to call our local machine. After we complete the payment operation, Alipay needs to process some amounts (connect with the bank), so it takes a few seconds. When Alipay completes the processing, it asynchronously calls our notify method (usually in this method for database operation), and this process is asynchronous, So users generally don't feel it (what users feel is the method called synchronously).

  • There are two schemes for setting public IP: 1. Intranet penetration; 2. Deploy the project to the server, which is not mentioned here

  • The figure shows the official call of Alipay

Tags: Front-end Android Back-end Interview

Posted by Mike-2003 on Sat, 30 Jul 2022 21:14:49 +0300