支付宝沙箱环境 支付

news2024/12/23 6:26:01

一 什么是沙箱:

沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境

支付宝正式和沙箱环境的区别 :

AI:

  • 从沙箱到正式环境

  • 当应用程序开发完成后,需要将应用程序从沙箱环境迁移到正式环境。

  • 这通常涉及到更新应用程序中的配置文件,更换正式的 AppID 和密钥等凭证

二 注册使用

网址:登录 - 支付宝 点击 进行注册

查看信息:appid

点击查看 应用密钥与支付宝公钥 :appPrivateKey 与 publiceKey

​ 记录一下卖家信息:

三 实现

支付实现的步骤:1.导入依赖 2.配置参数 3.调用方法(API调用) 4.处理响应或异常

具体实现可查看官网文档: 小程序文档 - 支付宝文档中心

小程序文档 - 支付宝文档中心

简易版概述小程序文档 - 支付宝文档中心

小程序文档 - 支付宝文档中心

​​​查看api使用规范 根据需求选择对应的接口方法

比如下面我们要实现的电脑网站的支付功能

对应的就是 Factory.Payment.Page.pay()

Easy 版

有拦截器的 注意放开路径

3.1 导入项目依赖

<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-easysdk -->
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-easysdk</artifactId>
    <version>2.2.0</version>
</dependency>

3.2 编写配置信息:

其中关于//@PostConstruct 是一个 Java 注解,用于标记需要在依赖注入完成后执行的方法。它表示该方法应该在对象创建和属性注入完毕后由容器自动调用,以完成初始化工作。

@Component
@ConfigurationProperties(prefix = "alipay")
@Data
	public class AlipayConfig {
    // 应用Id
    private String appId;
    // 应用私钥
    private String appPrivateKey;
    // 支付宝公钥
    private String publiceKey;
    // 回调接口路径
    private String notifyUrl;
    // 支付宝网关地址
    private String gatewayHost;
    @PostConstruct
    //@PostConstruct 是一个 Java 注解,用于标记需要在依赖注入完成后执行的方法。
    // 它表示该方法应该在对象创建和属性注入完毕后由容器自动调用,以完成初始化工作。
    // 此注解的方法无参数,返回类型可为空或其他类型。主要用于确保对象完全初始化。
    public void init(){
        Config config = new Config();
        // 基础配置
        config.protocol = "https";
        config.gatewayHost = this.gatewayHost;// 支付宝网关地址
        config.signType = "RSA2";

        // 业务配置
        config.appId = this.appId;
        config.merchantPrivateKey = this.appPrivateKey;
        config.alipayPublicKey = this.publiceKey;
        config.notifyUrl = this.notifyUrl;

        // 将配置信息, 添加到相应的工厂类
        Factory.setOptions(config);
        System.out.println("支付宝初始化配置完成");
    }
}

application.properties

其中 appid appPrivateKey publiceKey 在开发者平台获取

gatewayHost 大家都一样 无需更改

notifyUrl 是内网穿透这里使用不到 现在随便写都可以

alipay.appid=9021000139682312
alipay.appPrivateKey=MIIEvwIBADANBgkqhkiG9w0BAQEFAAS...
alipay.publiceKey=MIIBIjANBgkqhkiG9w0BAQEFAAOC.......
alipay.notifyUrl=http://xxxxxxx/api/alipay/notify
alipay.gatewayHost=openapi-sandbox.dl.alipaydev.com

3.3 调用支付方法

我这里直接在cotroller层编写

@RestController
@RequestMapping("/api/alipay")
public class PayController {

    /**
     * 订单支付接口, 核心是调用支付宝的 Factory.Payment.Page().pay() 方法
     * @param subject  支付对象信息
     * @param outTradeNo  订单号
     * @param totalAmount 订单金额
     * @param returnUrl   支付成功以后返回的页面地址
     * @return
     */

    @GetMapping("/pay")
    public void pay(String subject, String outTradeNo, String totalAmount, String returnUrl, HttpServletResponse httpResponse) throws Exception {
        // 使用支付宝支付页面接口进行支付
        AlipayTradePagePayResponse response = Factory.Payment.Page().pay(subject, outTradeNo, totalAmount, returnUrl);
        System.out.println(response);
        // response.getBody();
        // 设置HTTP响应内容类型为HTML,编码为UTF-8
         httpResponse.setContentType("text/html;charset=utf-8");
        // 向HTTP响应写入支付宝支付页面接口返回的响应体
        httpResponse.getWriter().write(response.getBody());
        // 刷新HTTP响应输出流,确保数据立即发送到客户端
        httpResponse.getWriter().flush();
        // 关闭HTTP响应输出流,释放资源
        httpResponse.getWriter().close();
    }

}

Java

可以进行测试后端了!!!!!!!!

可以进行测试后端了!!!!!!!!

可以进行测试后端了!!!!!!!!

http://localhost:8080/api/alipay/pay?subject=%E7%81%AB%E8%BD%A6%E7%A5%A8%E6%94%AF%E4%BB%98&outTradeNo=63172637&totalAmount=16.8&returnUrl=http%3A%2F%2Flocalhost%3A8080%2Fpayok.html%3ForderId%3D312323

3.4 回调方法 配合内网穿透使用

回调就是支付宝在进行扣款操作之后 调用我们的后端 告诉我们支付结果

回调方法如下:

回调中有个验证操作来源于:调用官方给我们提供的方法来验证数据的真实性。

    @PostMapping("/notify")
    public String notify(@RequestParam Map parameterMap) throws Exception {
        String tradeStatus = parameterMap.getOrDefault("trade_status","").toString();
        if (tradeStatus.trim().equals("TRADE_SUCCESS")) {
            // 验证请求的有效性
            if (Factory.Payment.Common().verifyNotify(parameterMap)) {
                System.out.println("通过支付宝的验证");
                System.out.println("订单id:" + parameterMap.get("out_trade_no"));
            }else {
                System.out.println("支付验证不通过");
            }
        }
        return "success";
    }

需要先开启内网穿透

服务器为localhost:8080 支付宝无法调用:

注意:如果是部署云服务器就不需要内网穿透了 只不过需要我我们对回调的参数进行相对应的修改!!!!

3.5 内网穿透工具

1.路由侠-局域网变公网

​ 设置 信息 主机号

查看内网映射:

测试: 说明映射是没有问题的 成功调用了后端

修改 alipay.notifyUrl 的 配置信息

alipay.notifyUrl=http://xxxk.w1.luyouxia.net/api/alipay/notify

再次进行支付测试:s

这里加上vue进行测试:

前端 vue:

3.6 前端

<template>
  <h2>支付</h2>
  <el-form :inline="true" :model="form" class="demo-form-inline">
    <el-form-item label="支付对象信息">
      <el-input v-model="form.subject" placeholder="请输入" clearable />
    </el-form-item>
    <el-form-item label="订单号">
      <el-input v-model="form.outTradeNo" placeholder="请输入" clearable />
    </el-form-item>
    <el-form-item label="订单金额">
      <el-input-number v-model="form.totalAmount" placeholder="请输入" clearable />
    </el-form-item>
    <el-form-item label="支付成功以后返回的页面地址">
      <el-input v-model="form.returnUrl" placeholder="请输入" clearable />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">提交</el-button>
    </el-form-item>
  </el-form>
  <br>
  <h2>退款</h2>
  <el-form :inline="true" :model="form2" class="demo-form-inline">
    <el-form-item label="退款单号">
      <el-input v-model="form2.outTradeNo" placeholder="请输入" clearable />
    </el-form-item>
    <el-form-item label="退款金额">
      <el-input-number v-model="form2.refundAmount" placeholder="请输入" clearable />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit2">提交</el-button>
    </el-form-item>
  </el-form>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import dayjs from 'dayjs';
import router from '@/router';
import { ElNotification } from 'element-plus'
import { alipayApi } from '@/api';
const form = ref({
  subject: '小米su8',
  outTradeNo: dayjs().format('YYYYMMDDHHmmss'),
  totalAmount: 188888,
  returnUrl: 'http://localhost:5000/paysuccess'
})

const form2 = ref({
  outTradeNo: '20220422164101',
  refundAmount: 18888,
})
const onSubmit = () => {
  let returnUrl = encodeURIComponent(form.value.returnUrl)
  window.location.href = "http://localhost:8080/api/alipay/pay?subject=" + `${form.value.subject}` + "&outTradeNo=" + `${form.value.outTradeNo}`
    + "&totalAmount=" + `${form.value.totalAmount}` + "&returnUrl=" + `${returnUrl}`
}
const onSubmit2 = () => {
  alipayApi.refund.call({
    outTradeNo: form2.value.outTradeNo,
    refundAmount: form2.value.refundAmount
  }).then(_res => {
    ElNotification({
      title: '提示',
      message: '退款成功',
      type: 'success',
    })
  })
}

</script>


测试结果

一方面 : 前端返回我们设置的 returnUrl 界面

另一方: 后端执行 配置的 alipay.notifyUrl=http://xxxk.w1.luyouxia.net/api/alipay/notify

成功

3.7 退款

调用 refund 交易退款方法

    @GetMapping("/refund")
    public String refund( String outTradeNo,Float refundAmount) {
        try {
com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse response = Factory.Payment.Common().refund(outTradeNo, String.valueOf(refundAmount));
            System.out.println(response);
            if (response.msg.equals("Success")){
                return "退款成功";
            }else {
                throw new BizException(777, "退款失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            throw  new BizException(777, "退款失败");
        }
    }

通用版

​小程序文档 - 支付宝文档中心​

通用版

导入依赖

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

配置

@Component
@ConfigurationProperties(prefix = "alipay2")
@Data
public class Alipay2Config extends com.alipay.api.AlipayConfig {
    // 网关地址
    private String serverUrl;
    // 应用Id
    private String appId;
    // 应用私钥
    private String appPrivateKey;
    //请求格式
    private String format;
    //字符集编码
    private String charset;
    //签名类型
    private String signType;
    // 支付宝公钥
    private String publiceKey;
    // 回调接口路径
    private String notifyUrl;

}

支付

    @GetMapping("/pay2")
    public void pay2(String subject, String outTradeNo, String totalAmount, String returnUrl, HttpServletResponse httpResponse) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(alipay2Config.getServerUrl(), alipay2Config.getAppId(),
       alipay2Config.getAppPrivateKey(), alipay2Config.getFormat(), alipay2Config.getCharset(), alipay2Config.getAlipayPublicKey(), alipay2Config.getSignType());
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setNotifyUrl(alipay2Config.getNotifyUrl());
        request.setReturnUrl(returnUrl);
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", outTradeNo);
        bizContent.put("total_amount", totalAmount);
        bizContent.put("subject", subject);
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        request.setBizContent(bizContent.toString());
        String form = "";
        try {
            // 调用SDK生成表单
            form = alipayClient.pageExecute(request).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        httpResponse.setContentType("text/html;charset=UTF-8");
        // 直接将完整的表单html输出到页面
        httpResponse.getWriter().write(form);
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }

退款

        /**
         * 退款接口
         *
         * @return
         */
        @GetMapping("/refund2")
        public String refund2 (String outTradeNo, Float refundAmount){
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi-sandbox.dl.alipaydev.com/gateway.do",
                    alipayConfig.getAppId(),
                    alipayConfig.getAppPrivateKey(),
                    "JSON",
                    "utf-8",
                    alipayConfig.getPubliceKey(),
                    "RSA2");
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            // 获取获取对应订单信息
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", outTradeNo);
            bizContent.put("refund_amount", refundAmount);
            bizContent.put("out_request_no", "HZ01RF002"); //退款标识,用于查询状态是操作
            request.setBizContent(bizContent.toString());
            // 使用支付宝支付页面接口进行支付
            try {
                AlipayTradeRefundResponse response = alipayClient.execute(request);
                System.out.println(response);
                if (response.isSuccess()) {
                    System.out.println("退款成功");
                    return "退款成功";
                } else {
                    System.out.println("退款失败");
                    throw new BizException(777, "退款失败");
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("退款失败");
                throw new BizException(777, "退款失败");
            }
        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2164640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

opencv图像增强十四:opencv两种白平衡介绍及实现

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、白平衡介绍二、灰度世界法三、完美反射法 前言 在摄影与影像领域&#xff0c;白平衡是一个至关重要的概念。它直接影响着画面的色彩表现&#xff0c;关系到…

构建网络遇到的问题-AlexNet

1.对模型进行初始化采用的一般代码 def _initialize_weights(self):for m in self.modules(): # 遍历模型每一层if isinstance(m, nn.Conv2d): # 判定m层是否属于nn.Conv2d类型nn.init.kaiming_normal_(m.weight, modefan_out, nonlinearityrelu)if m.bias is not None:nn.in…

从自动化到智能化:AI如何推动业务流程自动化

引言&#xff1a;从自动化到智能化的必然趋势 在当今数字化时代&#xff0c;企业为了提升效率、降低成本&#xff0c;纷纷采用自动化技术来简化重复性任务。然而&#xff0c;传统自动化仅限于标准化操作&#xff0c;无法应对复杂的决策和多变的市场环境。随着人工智能&#xff…

基于springboot垃圾分类网站

基于springboot垃圾分类网站 摘 要 本论文主要论述了如何使用JAVA语言开发一个垃圾分类网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述垃圾分类网站的当…

Android开发拍身份证带人像框和国徽框效果

Android开发拍身份证带人像框和国徽框效果 拍身份证时往往要带上外框辅助用户拍照&#xff0c;这也是很常见的需求。 一、思路 自定义Camera和自定义拍照的界面&#xff0c;把外框画上去&#xff0c;做个遮罩 二、效果图&#xff1a; Android开发教程实战案例源码分享-拍身…

深入理解计算机系统-Bomb Lab

使用 头歌 平台 GDB 调试器 反汇编函数

动力锂电池电芯壳体市场前景:预计2030年全球市场规模将达到49.2亿美元

动力锂电池罐起着传输能量、承载电解液、保护安全等重要作用&#xff0c;是锂电池的重要组成部分。 据QYResearch调研团队最新报告“全球动力锂电池电芯壳体市场报告2024-2030”显示&#xff0c;预计2030年全球动力锂电池电芯壳体市场规模将达到49.2亿美元&#xff0c;未来几年…

分布式算法

分布式场景下的核心问题 分布式场景下困扰我们的3个核心问题&#xff08;CAP&#xff09;&#xff1a;一致性、可用性、分区容错性。 1、一致性&#xff08;Consistency&#xff09;&#xff1a;无论服务如何拆分&#xff0c;所有实例节点同一时间看到是相同的数据。 2、可用性…

开源链动 2+1 模式 S2B2C 商城小程序:社交电商团队为王的新引擎

摘要&#xff1a;本文深入探讨在社交电商领域中&#xff0c;团队的重要性以及如何借助开源链动 21 模式 S2B2C 商城小程序&#xff0c;打造具有强大竞争力的团队&#xff0c;实现个人价值与影响力的放大&#xff0c;创造被动收入&#xff0c;迈向财富自由之路&#xff0c;同时为…

从汽车高速线束角度浅谈中控屏黑屏、闪屏及信号阈值低故障-之AEM线束测试仪应用案例

故障成因和解决方案 随着车载信息娱乐技术的迅速发展&#xff0c;中控屏已经成为现代汽车的标配。然而&#xff0c;许多主机厂和消费者在车辆使用过程中常常遇到中控屏出现黑屏、闪屏以及信号阈值低等问题&#xff0c;给使用带来了诸多困扰。本文将从汽车高速线束的角度&#…

GPU服务器本地搭建Dify+xinference实现大模型应用

文章目录 前言一、显卡驱动配置1.检测显卡2.安装驱动 二、安装nvidia-docker二、安装Xinference1.拉取镜像2.运行Xinference3.模型部署 三、安装Dify1.下载源代码2.启动 Dify3.访问 Dify 四、Dify构建应用1.配置模型供应商2.聊天助手3.Agent 前言 本文使用的GPU服务器为UCloud…

MySQL: 数据类型介绍

文章目录 数据类型数值类型字符串类型日期类型 数据类型 数值类型 分为整型和浮点型: BIT类似于数据结构中的位图,BIT可以认为是一组二进制bit位. BIT(10)表示这个类型里就存最多10个bit位. 虽然TINYINT和SMALLINT更节省空间,但是还是更推荐使用INT或者BIGINT. 如果存储空间…

MySql语言操作数据库---增删改查数据库,表,数据

思维导图 SQL语言共分为四大类&#xff1a; 数据定义语言DDL:数据定义语言DDL用来创建数据库中的各种对象-----[库]、[表]、[视图]、[索引]、 数据操纵语言DML:(1) 插入&#xff1a;INSERT (2) 更新&#xff1a;UPDATE (3) 删除&#xff1a;DELETE 数据查询语言DQL:数据查询语…

Android 深层链接利用

为了能够从我们的应用程序打开另一个应用程序&#xff0c;我们通常通过声明我们想要访问的 Activity 类的名称来实现这一功能。但是&#xff0c;如果我们要打开的 Activity 在其清单文件中设置了android:exported"false" &#xff0c;则无法使用此方法。而其中一种替…

人工智能有助于解决 IT/OT 集成安全挑战

思科的一项研究表明&#xff0c;信息技术 (IT) 和运营技术 (OT) 融合所带来的安全问题可以通过人工智能 (AI) 解决&#xff0c;尽管该技术也可能被恶意行为者利用。 该报告由思科和 Sapio Research 联合发布&#xff0c;对 17 个国家的 1,000 名行业专业人士进行了调查&#x…

基于Java,SpringBoot和Vue的仓库管理商品管理电商后台管理系统

摘要 基于Java、Spring Boot和Vue的仓库管理系统是一个现代化的库存管理解决方案&#xff0c;旨在提高仓库运营效率和准确性。系统采用Java作为后端开发语言&#xff0c;结合Spring Boot框架简化配置和部署过程&#xff0c;实现业务逻辑和数据处理。前端使用Vue.js构建用户界面…

2024.9.25 数据分析学习

资料&#xff1a; 【开课吧哩堂】数据挖掘项目之用户流失预警系统_哔哩哔哩_bilibili 五万字 | Spark吐血整理&#xff0c;学习与面试收藏这篇就够了&#xff01;-腾讯云开发者社区-腾讯云 (tencent.com) 黑马程序员Spark全套视频教程&#xff0c;4天spark3.2快速入门到精通…

**CentOS7安装配置mysql**

CentOS7安装配置mysql 首先先将mysql57-community-release-el7.rpm解压出来 rpm -ivh mysql57-community-release-el7.rpmls /etc/yum.repos.d/ -l // 检查是否解压成功安装mysql yum install -y mysql-community-server可能会出现 GPG 密钥过期 rpm --import https://r…

一个可以免费上传样本图册的网站

在数字化时代&#xff0c;图像和样本图册的重要性不言而喻。无论是设计师、摄影师、艺术家还是普通用户&#xff0c;都需要一个可靠的平台来上传、分享和存储自己的作品。今天&#xff0c;给大家推荐一个可以免费上传样本图册的网站——【FLBOOK】&#xff0c;它为用户提供了无…

UE学习篇ContentExample解读------Blueprint_Communication-上

文章目录 总览描述批次阅览1.1 Basic communication with a target blueprint1.2 Basic communication via actor casting1.3 Blueprint communication via actor casting to child Blueprint1.4 Communicating with all actors of a specific class 概念总结致谢&#xff1a; …