支付宝支付

  1. 支付宝加密方式:非对称加密(RSA)

支付宝支付_第1张图片
  1. 支付宝支付过程(如图 1234 流程)

1-商户私钥加签,发送数据和公钥公钥到支付宝 ,

2-支付宝用商户告诉的公钥验签

3-支付宝私钥加签,发送数据和公钥告诉客户支付成功,

4-客户拿支付宝公钥验证。

支付宝支付_第2张图片

  1. 支付流程(示列 : 电脑网站支付)

3-1支付宝开放平台 (alipay.com) 进入API文档

支付宝支付_第3张图片

3-2下载对应语言的用例

支付宝支付_第4张图片

3-3支付宝沙箱环境(控制台 沙箱应用中,沙箱环境是支付宝的测试环境)

生成私钥 以及公钥

支付宝支付_第5张图片

3-4引入依赖

   
        
        
            com.alipay.sdk
            alipay-sdk-java
            4.9.28.ALL
        

3-5抽取支付宝配置

@ConfigurationProperties(prefix = "alipay") 配置的值写在application.properties中,

如下付宝相关的配置

@ConfigurationProperties(prefix = "alipay")
@Component
@Data
public class AlipayTemplate {
   // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
    public String app_id;
    // 商户私钥,您的PKCS8格式RSA2私钥
    public String merchant_private_key;
    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public String alipay_public_key;
    // 服务器[异步通知]页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    // 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
    public String notify_url;
    // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    //同步通知,支付成功,一般跳转到成功页
    public String return_url;
    // 签名方式
    private  String sign_type;
    // 字符编码格式
    private  String charset;
    //订单超时时间
    private String timeout = "1m";
    // 支付宝网关; https://openapi.alipaydev.com/gateway.do
    public String gatewayUrl;
    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();

    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;

    }
}
#支付宝相关的配置
alipay.app_id=
alipay.merchant_private_key=
alipay.alipay_public_key=
alipay.notify_url=http://hjl.mynatapp.cc/payed/notify
alipay.return_url=http://member.gulimall.com/memberOrder.html
alipay.sign_type=RSA2
alipay.charset=utf-8
alipay.gatewayUrl=https://openapi.alipaydev.com/gateway.do

3-6前置 安装内网穿透工具(我们的地址映射到外网),用于外部访问支付宝支付页(自行安装:花生壳等)

支付宝支付_第6张图片

3-7操作流程:页面点击跳转支付宝支付页面,链接如下,以及接口

支付宝支付_第7张图片
支付宝

跳转接口:alipayTemplate.pay(payVo) 调用支付宝接口,返回页面

  /**
     * 用户下单:支付宝支付
     * 1、让支付页让浏览器展示
     * 2、支付成功以后,跳转到用户的订单列表页
     * @param orderSn
     * @return
     * @throws AlipayApiException
     */
    @ResponseBody
    //produces 告诉产生html 页面
    @GetMapping(value = "/aliPayOrder",produces = "text/html")
    public String aliPayOrder(@RequestParam("orderSn") String orderSn) throws AlipayApiException {

        PayVo payVo = orderService.getOrderPay(orderSn);
        //返回的是一个页面 直接交给浏览器就行
        String pay = alipayTemplate.pay(payVo);
        System.out.println(pay);
        return pay;
    }

3-8 return_url支付成功跳转,同步跳转路径回调页面,一般支付成功展示列表页

支付宝支付_第8张图片

3-9 notify_url 支付宝异步回调地址,验签同时修改我们数据状态

异步回调地址规则,具体可以看官方文档

内网穿透工具转到我的电脑,通过host文件访问nginx时,请求头为外网的请求头

所以需要拦击支付请求替换请求头

   #支付宝外网穿透拦击支付请求转到订单服务
    location /payed/notify {
     proxy_pass http://gulimall;
     proxy_set_header Host order.gulimall.com;
  }
支付宝支付_第9张图片

@RestController
public class OrderPayedListener {

    @Autowired
    private OrderService orderService;

    @Autowired
    private AlipayTemplate alipayTemplate;

    @PostMapping(value = "/payed/notify")
    public String handleAlipayed(PayAsyncVo asyncVo, HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
        // 只要收到支付宝的异步通知,返回 success 支付宝便不再通知
        // 获取支付宝POST过来反馈信息
        //TODO 需要验签
        Map params = new HashMap<>();
        Map 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] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        /**
         *调用SDK验证签名
         */
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayTemplate.getAlipay_public_key(),
                alipayTemplate.getCharset(), alipayTemplate.getSign_type());

        if (signVerified) {
            System.out.println("签名验证成功...");
            //去修改订单状态
            String result = orderService.handlePayResult(asyncVo);
            return result;
        } else {
            System.out.println("签名验证失败...");
            return "error";
        }
    }

    @PostMapping(value = "/pay/notify")
    public String asyncNotify(@RequestBody String notifyData) {
        //异步通知结果
        return orderService.asyncNotify(notifyData);
    }

}

你可能感兴趣的:(java)