关于后端:自己个人拥有一个可以支付功能的网站当然可以了保姆级演示

46次阅读

共计 8766 个字符,预计需要花费 22 分钟才能阅读完成。

前提条件
这是必要条件!!!
这是必要条件!!!
这是必要条件!!!
开明当面付,集体、企业账号均可!!!

演示
获取订单点击,而后扫码领取

领取胜利后就会响应领取胜利

利用申请开明和配置
接下来介绍利用的创立和配置,肯定要认真哦!!!
利用创立
首先进入支付宝开放平台,进入控制台,创立一个利用,大略 1 个工作日内就会审核

把这几个必填项填写,而后确认创立,留神名字要清晰,利用图标要有肯定的可识别性,不然不给过,利用类型选网页利用

利用配置
创立好后,进入产品详情页面,点击产品绑定,而后去绑定

抉择领取 -> 当面付[勾选] -> 绑定, 另外你还能够找到花呗领取,这样用户扫码时就反对花呗领取了

要确认是开明状态哦,如果没有开明须要开明哦,看下面的 前提条件

而后须要配置密钥,点击下图中侧边栏中的 开发设置,须要配置的是 接口加签形式(证书 / 密钥)

接口加签形式(证书 / 密钥):配置支付宝开放平台会疏导你下载安装密钥生成工具,生成一个利用公钥和利用私钥,私钥肯定要保存好,不要泄露,保留到本地,到时候配置在服务器上,而后把利用公钥配置在开放平台上,就算配置实现了,支付宝就会给到你一个支付宝公钥,接下来你一共有三个密钥,支付宝公钥、利用公钥、利用私钥,这三个肯定要分清,接下来文章介绍的所须要用到的密钥只有这三个,清肯定要分清!!!

代码开发
接下来你能够联合着官网的开发文档看我的文章,官网文档:opendocs.alipay.com/open/02ekfg…

本文后端以 Java 的开发方式,仅供参考!
Web 前端应用原生 Html+CSS+JavaScript 简略实现,仅供参考!
安卓调用能够参考我这篇文章:myhub.blog.csdn.net/article/det…

后端实例
SDK 集成
首先获取相应的 SDK,SDK 下载页面(官网):opendocs.alipay.com/open/54/103…
我这里以 Maven 的形式集成,另外我集成了 zxing,用于生成领取二维码应用
<!–alipay SDK–>
<dependency>

<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.35.9.ALL</version>

</dependency>

<!– zxing –>
<dependency>

<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.1</version>

</dependency>
复制代码
Controller 实例

生成付款二维码,我表明了具体的正文,能够间接看!
因为波及到公钥、私钥等信息,这些局部我都用了 来示意,
记得替换哦!!!
记得替换哦!!!
记得替换哦!!!
替换成你本人的!!!

以下为简略的 Demo 演示,肯定要联合官网文档,浏览接入注意事项:opendocs.alipay.com/open/194/10…
package com.demo.pay;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;

/**

  • @author ThirdGoddess
  • @version 1.0.0
  • @time 2022/12/22 14:37
  • @desc AliPay 当面付 Demo
    */

@RestController
@RequestMapping(“pay”)
public class AliPayController {

// 模仿一个用户的领取状态
private boolean userPayState = false;

//==================================================================================================================
// 这里都是固定的

// 支付宝网关地址
private static final String SERVER_URL = "https://openapi.alipay.com/gateway.do";

//charset
private static final String CHARSET = "GBK";

//format
private static final String FORMAT = "json";

//sign type
private static final String SIGN_TYPE = "RSA2";

//==================================================================================================================
// 上面这三个是须要配置的

//APPID,即创立利用的那个 ID, 在利用详情中的左上角能够看到
private static final String APPID = "**************";

// 利用私钥,留神是利用私钥!!!利用私钥!!!利用私钥!!!private static final String APP_PRIVATE_KEY = "**************";

// 支付宝公钥,留神是支付宝公钥!!!支付宝公钥!!!支付宝公钥!!!private static final String ALIPAY_PUBLIC_KEY = "**************";

/**
 * 获取二维码
 * 获取的是用户要扫码领取的二维码
 * 创立订单,带入本人的业务逻辑
 */
@RequestMapping(value = "/getQr", produces = MediaType.IMAGE_JPEG_VALUE)
@ResponseBody
public byte[] getQr() {

    userPayState = false;

    AlipayClient alipayClient = new DefaultAlipayClient(SERVER_URL, APPID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE);
    AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();

    // 配置这是一个 url,下图我曾经配置好了,这个意思是当用户胜利后,支付宝那边会调用这个地址 url,他会给你传过来一些订单信息,// 你解决完你的业务逻辑给支付宝响应 success 就行,就代表这个订单实现交易了!//* 倡议后期开发的时候加上内网穿透调试,不然支付宝是没有方法调到你开发的接口的
    request.setNotifyUrl("http://**************.com/pay/payNotification");

    JSONObject bizContent = new JSONObject();

    // 本人生成一个订单号,我这里间接用工夫戳演示,失常状况下创立完订单须要存储到本人的业务数据库,做记录和领取实现后校验
    String orderNumber = "pay" + System.currentTimeMillis();

    bizContent.put("out_trade_no", orderNumber);// 订单号
    bizContent.put("total_amount", 0.01);// 订单金额
    bizContent.put("subject", "demo");// 领取主题,本人略微定义一下
    request.setBizContent(bizContent.toString());

    try {AlipayTradePrecreateResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {System.out.println("调用胜利");
        } else {System.out.println("调用失败");
        }

        // 获取生成的二维码,这里是一个 String 字符串,即二维码的内容;// 而后用二维码生成 SDK 生成一下二维码,弄成图片返回给前端就行, 我这里应用 Zxing 生成
        // 其实也能够间接把这个字符串信息返回,让前端去生成,一样的情理,只须要关怀这个二维码的内容就行
        String qrCode = response.getQrCode();

        // 生成领取二维码图片
        BufferedImage image = QrCodeUtil.createImage(qrCode);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(image, "jpeg", out);
        byte[] b = out.toByteArray();
        out.write(b);
        out.close();

        // 最终返回图片
        return b;
    } catch (Exception e) {e.printStackTrace();
        System.out.println("调用失败");
    }
    return null;
}

/**
 * 领取实现后支付宝会申请这个回调
 */
@PostMapping("payNotification")
public String payNotification(HttpServletRequest request) {Map<String, String> params = new HashMap<>();
    Map<String, String[]> requestParams = request.getParameterMap();
    for (String name : requestParams.keySet()) {String[] values = 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, valueStr);
    }

    for (Map.Entry<String, String> entry : params.entrySet()) {System.out.println("Key =" + entry.getKey() + ", Value =" + entry.getValue());
    }

    //==============================================================================================================
    try {
        // 执行验签,确保后果是支付宝回调的,而不是被歹意调用,肯定要做这一步
        boolean signVerified = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE);
        if (signVerified) {
            // 验签胜利,继续执行业务逻辑
            System.out.println("验签胜利");

            // 再次被动查问订单,不要只依赖支付宝回调的后果
            String orderStatus = searchOrderStatus(params.get("out_trade_no"), params.get("trade_no"));
            switch (orderStatus) {
                case "TRADE_SUCCESS":// 交易领取胜利;case "TRADE_FINISHED": // 交易完结,不可退款;//TODO 在这里继续执行用户领取胜利后的业务逻辑
                    userPayState = true;
                    break;
            }
            return "success";
        } else {
            // 验签失败(很可能接口被非法调用)System.out.println("验签失败");
            return "fail";
        }
    } catch (AlipayApiException e) {e.printStackTrace();
        return "fail";
    }
}

/**
 * 封装一个订单查问
 *
 * @param outTradeNo 商户订单号
 * @param tradeNo    支付宝交易号。支付宝交易凭证号
 * @return 订单状态:String
 * @throws AlipayApiException AlipayApiException
 * @desc "WAIT_BUYER_PAY": 交易创立,期待买家付款;"TRADE_CLOSED": 未付款交易超时敞开,或领取实现后全额退款;"TRADE_SUCCESS": 交易领取胜利;"TRADE_FINISHED": 交易完结,不可退款;*/
private String searchOrderStatus(String outTradeNo, String tradeNo) throws AlipayApiException {AlipayClient alipayClient = new DefaultAlipayClient(SERVER_URL, APPID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE); // 取得初始化的 AlipayClient
    AlipayTradeQueryRequest aliRequest = new AlipayTradeQueryRequest();// 创立 API 对应的 request 类
    JSONObject bizContent = new JSONObject();
    bizContent.put("out_trade_no", outTradeNo);
    bizContent.put("trade_no", tradeNo);
    aliRequest.setBizContent(bizContent.toString()); // 设置业务参数
    AlipayTradeQueryResponse response = alipayClient.execute(aliRequest);// 通过 alipayClient 调用 API,取得对应的 response 类
    JSONObject responseObject = JSONObject.parseObject(response.getBody());
    JSONObject alipayTradeQueryResponse = responseObject.getJSONObject("alipay_trade_query_response");
    return alipayTradeQueryResponse.getString("trade_status");
}

/**
 * 前端轮询查问这个接口,来查问订单的领取状态
 *
 * @return OrderStateEntity
 */
@CrossOrigin
@GetMapping("searchOrder")
public OrderStateEntity searchOrder() {
    //userPayState 是一个模仿值
    if (userPayState) {
        // 用户领取胜利了
        return new OrderStateEntity(200, "领取胜利了");
    } else {
        // 用户还没有领取
        return new OrderStateEntity(201, "你还没有领取哦");
    }
}

/**
 * 响应给前端的实体
 */
static class OrderStateEntity {
    private int code;
    private String msg;

    public OrderStateEntity(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {return code;}

    public void setCode(int code) {this.code = code;}

    public String getMsg() {return msg;}

    public void setMsg(String msg) {this.msg = msg;}
}

}

复制代码
用户领取后的回调
当应用 setNotifyUrl 后,用户胜利领取后,会回调其设置的 url,如 ==setNotifyUrl(“xxx.com/pay/payNoti…,那么支付宝会期待用户领取胜利后会以 POST 去申请 ==xxx.com/pay/payNoti… 这个地址来达成回调,须要响应 success 或者 fail,只有这两种值哦!

响应值形容异步是否重试发送 fail 音讯获取失败重试 success 音讯获取胜利不重试
前端代码实例
<!DOCTYPE html>
<html lang=”en”>
<head>

<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta charset="UTF-8">
<title> 支付宝当面付 Demo 演示 </title>
<style>
    * {margin: 0 auto;}
    .root {width: 260px;}
    .img_box {
        width: 260px;
        height: 260px;
        background-color: #adadad;
    }
    button {
        width: 260px;
        margin-top: 12px;
    }
</style>

</head>
<body>
<div class=”root”>

<div class="img_box"><img width="260" height="260" id="qr" src=""alt=""></div>
<button onclick="getOrderQr()"> 获取订单 </button>
<div class="response" id="response"></div>

<script>

    /**
     * 获取一个二维码
     */
    function getOrderQr() {let qrImg = document.getElementById('qr');
        qrImg.src = "http://**************.com/pay/getQr?time=" + new Date().getTime()

        // 开始轮询查问订单
        orderResponse()}

    let number = 1;
    const responseView = document.getElementById('response')

    /**
     * 循环查问订单响应
     */
    function orderResponse() {

        // 每 2 秒查问一次领取状态
        setTimeout(function () {
            // 申请接口查问领取状态
            const xhr = new XMLHttpRequest();
            xhr.open('GET', "http://**************.com/pay/searchOrder", true);
            xhr.send(null);
            xhr.onreadystatechange = function () {if (xhr.status === 200 && xhr.readyState === 4) {const json = JSON.parse(xhr.responseText);
                    if (200 === json.code) {
                        // 领取胜利
                        responseView.innerText = xhr.responseText
                    } else {
                        // 没有领取,持续下一次查问
                        responseView.innerText = '第' + number + '次查问,后果:' + xhr.responseText
                        number++
                        orderResponse()}
                }
            }
        }, 2000)
    }
</script>

</div>
</body>
</html>
复制代码

源码
Github:github.com/ThirdGoddes…

正文完
 0