首页 > 其他分享 >微服务对接沙箱支付宝支付,并实现回调数据修改

微服务对接沙箱支付宝支付,并实现回调数据修改

时间:2024-10-11 14:13:25浏览次数:1  
标签:支付宝 return String orderVip 对接 支付 沙箱 config public

在前文中,我们完成了vip题目与权限的设计,于是自然而然的引出了我们怎么成为vip这个问题,传统的c端系统以及游戏,往往采用对接支付接口的方式,本文选取了对接支付宝接口的形式进行支付并获取vip权限。

扫码付款的接入流程

 

 支付宝支付的逻辑过程

 支付成功后的消息回调

 有了此处基础上,通过研究支付宝沙箱支付原内容,我们可以很好的上手

进入支付宝沙箱系统网站(沙箱应用 - 开放平台 (alipay.com)

 

 拿到这些信息

由于测试环境是本地运行,我们通过内网穿透获得一个公网地址,这里我用的内网穿透工具为natapp工具

 配置页

 

          <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.9.9</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

        <!--方式二 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>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.5</version>
        </dependency>

 

/**
 * @Description:
 * @Version: V1.0
 */
@Configuration
@Data
@ConfigurationProperties(prefix = "alipay.easy")
public class AliPayProperties {
    //请求协议
    private String protocol;
    // 请求网关
    private String gatewayHost;
    // 签名类型 RSA2
    private String signType;
    // 应用ID
    private String appId;
    // 应用私钥
    private String merchantPrivateKey;
    // 支付宝公钥
    private String alipayPublicKey;
    // 异步通知接收服务地址
    private String notifyUrl;
    // 设置AES密钥
    private String encryptKey;
}
@Configuration
@Data
public class AlipayConfig {

    @Bean
    public Config config(AliPayProperties payProperties) {
        Config config = new Config();
        config.protocol = payProperties.getProtocol();
        config.gatewayHost = payProperties.getGatewayHost();
        config.signType = payProperties.getSignType();
        config.appId = payProperties.getAppId();
        config.merchantPrivateKey = payProperties.getMerchantPrivateKey();
        config.alipayPublicKey = payProperties.getAlipayPublicKey();
        //可设置异步通知接收服务地址(可选)
        config.notifyUrl = payProperties.getNotifyUrl();
        config.encryptKey = "";
        return config;
    }


}
@RestController
@Slf4j
@AllArgsConstructor
public class EasyPayController {

    private final Config config;

    @GetMapping("pay")
    public String pay() throws Exception {
        Factory.setOptions(config);
        //调用支付宝接口
        AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace().preCreate("iphone15 promax 1T", "12138881313134", "12999");
        //解析结果
        String httpBody = response.getHttpBody();
        System.out.println(httpBody);
        //转JSON对象
        JSONObject jsonObject = JSONObject.parseObject(httpBody);
       try {
           String qrUrl = jsonObject.getJSONObject("alipay_trade_precreate_response").get("qr_code").toString();
           QrCodeUtil.generate(qrUrl,300,300,new File("E://qr2.jpg"));
       }catch (Exception e){
           return "支付失败";
       }
        //生成二维码
        return httpBody;
    }

    @PostMapping("/notify")
    public String notify(HttpServletRequest request){
        log.info("收到支付成功通知");
        System.out.println("支付成功");
        String out_trade_no = request.getParameter("out_trade_no");
        log.info("流水号:{}",out_trade_no);
        System.out.println("流水号"+out_trade_no);
        //TODO 后续业务流程 发货
        //回调了多次怎么办?  考虑接口的幂等性    分布式锁 乐观锁  先判断再处理
        return "success";
    }

    @GetMapping("/query")
    public String query() throws Exception {
        Factory.setOptions(config);
        AlipayTradeQueryResponse response = Factory.Payment.Common().query("1213131313131");
        return response.getHttpBody();
    }

}

上述代码实现了一个简单的模拟支付的流程,下面引出我们刷题系统的支付流程管理。

问题:

系统是微服务,支付功能放在哪里?

系统怎么确定某个用户是否支付?

怎么提升系统复用性?

一开始的设计之初,笔者是想把支付接口与微信服务写在一起,因为二者都需要内网穿透映射在公网,同时都是对外对接的服务,但是尝试过后笔者发现设计之初时,我们的微信服务是无业务关联的,他只负责登陆,这就导致了我们将支付系统引入微信服务会导致原代码大量重构,后面笔者又想将支付接口写入auth用户微服务中,但是因为支付接口异步消息回调的原因,将用户服务暴露在公网对系统安全也是不利的,同时内网穿透本身网速就慢,这样对系统而言影响较大。

考虑到系统后期可能不止一种服务支持方式,也不止仅仅充值vip这一个服务,为了更好的服务于其他功能,我们决定将支付服务单独独立部署出来。

新建订单表

 

 @Override
    public String created(Orders order) throws Exception {
        // 创建订单预支付请求
        AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace().preCreate(order.getOrderName(), order.getOrderId(), order.getOrderPrice());
        // 解析结果
        String httpBody = response.getHttpBody();
        System.out.println(httpBody);
        // 转JSON对象
        JSONObject jsonObject = JSONObject.parseObject(httpBody);
        try {
            // 检查是否订单已支付
            if ("40004".equals(jsonObject.getJSONObject("alipay_trade_precreate_response").getString("code"))) {
                return "订单已支付,请勿重复支付";
            }
            // 获取二维码URL
            String qrUrl = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
            // 生成二维码并保存到本地文件
            String filePath = "codeimg.png";
            qrCodeGenerator.generateQRCode(qrUrl, filePath);
            // 构建MinIO中的对象名称
            String uniqueObjectName = OBJECT_NAME + "/" + Paths.get(filePath).getFileName();
            // 将生成的二维码上传到MinIO
            Path path = Paths.get(filePath);
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(BUCKET_NAME)
                            .object(uniqueObjectName) // 使用唯一的对象名称
                            .stream(Files.newInputStream(path), Files.size(path), -1)
                            .contentType("image/png")
                            .build()
            );

            // 生成预签名URL
            String url = URL + "/" + BUCKET_NAME + "/" + uniqueObjectName;
            // 删除本地文件
            Files.delete(path);
            OrderVip orderVip = new OrderVip();
            orderVip.setOrderId(Integer.valueOf(order.getOrderId()));
            orderVip.setOrderName(order.getOrderName());
            orderVip.setOrderPrice(order.getOrderPrice());
            orderVip.setStatus(0L);
            String loginId = LoginUtil.getLoginId();
            orderVip.setUserId(loginId);
            orderVip.setIsDeleted(0);
            orderVipService.insert(orderVip);
            return url;
        } catch (Exception e) {
            // 记录异常信息
            e.printStackTrace();
            return "上传失败";
        }
    }

业务分析:用户调用支付接口传入订单id,订单名称,订单金额字段

 

通过阿里云面对面支付生成预创建订单

// 创建订单预支付请求
AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace().preCreate(order.getOrderName(), order.getOrderId(), order.getOrderPrice()); 订单数据传入订单表

 

订单创建成功后调用zxing生成二维码传入minio然后将图片url返还给前端

 用户打开支付宝扫码完成支付

异步消息回调这里有个问题我们要主要下,由于消息是异步回调通知,所以我们回调的消息内容在threadlocal中是不包含用户数据信息的,所以我们需要回调消息的订单id去订单库中提取用户信息

 public AuthUserRoleDTO updated(String out_trade_no,String loginId) throws Exception {
        AuthUserRoleDTO authUserRoleDTO = new AuthUserRoleDTO();
      //获取用户信息 OrderVip orderVip =orderVipService.queryByOrderId(Integer.valueOf(out_trade_no)); orderVip.setStatus(1L); orderVipService.update(orderVip); //改为vip角色 authUserRoleDTO.setRoleId(4L); // Long userId = Long.valueOf(loginId); authUserRoleDTO.setUserId(orderVip.getUserId()); AuthUserRoleDTO authUserRole=userRpc.updateRole(authUserRoleDTO); return authUserRole; }

feign传送数据至下文修改用户角色为vip角色

   public AuthUserRoleDTO updateRole(AuthUserRoleDTO authUserRole) {
        AuthUserRoleDTO result = userFeignService.updateRole(authUserRole).getData();
        return result;
    }
 @RequestMapping("updateRole")
    public Result<AuthUserRole> updateRole(@RequestBody AuthUserRoleDTO authUserRoleDTO) {
        try {
            if (log.isInfoEnabled()) {
                log.info("RoleController.update.dto:{}", JSON.toJSONString(authUserRoleDTO));
            }
           // Preconditions.checkNotNull(authUserRole.getUserId(), "用户id不能为空");
            Preconditions.checkNotNull(authUserRoleDTO.getRoleId(), "角色id不能为空");
            String loginId = authUserRoleDTO.getUserId();
            log.info("loginId:{}",loginId);
            AuthUserBO authUserBO = new AuthUserBO();
            authUserBO.setUserName(loginId);
            AuthUserBO userInfo =authUserDomainService.getUserInfo(authUserBO);
            AuthUserRole authrole = new  AuthUserRole();
            authrole.setUserId(userInfo.getId());
            authrole.setRoleId(authUserRoleDTO.getRoleId());
            AuthUserRole authUserRole1 =authUserRoleService.updateUserId(authrole);
            return Result.ok(authUserRole1);
        } catch (Exception e) {
            log.error("RoleController.update.error:{}", e.getMessage(), e);
            return Result.fail("更新角色信息失败");
        }
    }

整体效果:

 

 

 

 

 

 

标签:支付宝,return,String,orderVip,对接,支付,沙箱,config,public
From: https://www.cnblogs.com/azwz/p/18458235

相关文章

  • Odoo18.0 支付宝
    odoo16.0官方将支付宝模块弃用了,但是需求还在,我们也不太可能去使用推荐的asipay,因此,我们决定,自己手动实现它。安装与配置首先,我们在应用中安装我们的支付宝模块:  安装好之后,我们在销售-配置-在线支付-支付提供商菜单进入支付宝配置界面: 这里对各个参数简单介绍一下:......
  • 淘宝图片搜索商品数据api接口对接详细的描述和解释
    淘宝图片搜索商品数据接口是一项高级的API服务,它允许用户通过上传图片来搜索淘宝上的商品。这一功能依托于先进的图像识别技术,通过复杂的算法对上传的图片进行分析和处理,从而找到与图片相似的商品。以下是对该接口的详细描述和解释:主要功能、特点、优势主要功能:以图搜图......
  • 支付宝公匙 私匙 APPID 配置方法
    相信很多站长都给自己的网站开通了网上支付功能,而网上支付最方便的要属支付宝与微信了,我们抛开微信支付不谈,说一说支付宝支付的公匙,私匙以及APPID的获取方法!使用支付宝支付需要创建应用后进行签约,比如当付面(不强制使用营业执照),手机支付,网站支付,转账等,这里的签约自己根据支付宝......
  • 7天毕设速成9小程序接口封装及对接
    1.接口封装1.1.请求接口封装新建文件夹request,新建index.js,封装接口接口调用对应此系列,springboot后端搭建笔记https://blog.csdn.net/PoofeeDong/article/details/140695913代码如下:constcommoneUrl="http://locahost:9999";//对应前面接口//get请求封装functi......
  • 研讨会/对接会/发布会等座位查询怎么查?扫码查座位小程序怎么用?
    签到入座是各种活动的第一步,扫码查座位系统允许参与者扫描二维码完成签到,并扫码查询显示其座位信息,这种方式减少了排队时间,提高了入场的效率,确保活动能够按时高效开始。点击下方链接前往工具查座位-会议/宴会/年会扫码签到查座位系统​​​​​​​实施扫码查询系统的步骤很......
  • glance对接cephA5
    目录*glance对接ceph1.上传镜像2.对接ceph2.1创建池2.2创建用户:西部世界官网2.3下发ceph文件2.4修改globals文件2.5更新glance配置3.上传镜像到cephglance对接ceph基于前面的openstack环境glance的镜像默认情况下是存储在本地的,如果glance节点挂掉了,那......
  • 全国电影票优惠充值接口对接需要遵循哪些步骤?
    要进行全国电影票优惠充值接口的对接,你需要遵循以下步骤:需求分析:确定你需要的API功能,比如电影信息查询、影院信息、座位预订、在线支付等。选择API服务提供商:根据你的需求,选择一个合适的电影票API接口服务提供商。注册和申请:在选定的服务提供商平台注册开发者账号,并申请API......
  • 全国外卖霸王餐系统对接详细步骤操作?
    对接全国外卖霸王餐系统并选择适合的系统时,你可以考虑以下几个步骤和标准:明确业务需求:首先确定你的平台需要哪些功能,如展示霸王餐选项、下单、支付、订单跟踪等。选择信誉良好的服务提供商:选择提供稳定服务的API提供商,并确保其提供的接口能满足你的业务需求。了解API文档和......
  • glance对接ceph
    目录glance对接ceph1.上传镜像2.对接ceph2.1创建池2.2创建用户2.3下发ceph文件2.4修改globals文件2.5更新glance配置3.上传镜像到cephglance对接ceph基于前面的openstack环境glance的镜像默认情况下是存储在本地的,如果glance节点挂掉了,那么镜像也就不存在了,所以现在我......
  • Go语言对接微信支付与退款全流程指南
    目录:一、准备工作二、初始化微信支付客户端三、实现支付功能1.付款时序图2.实现不同场景下的支付WAP端支付PC端支付Android端支付3.解析支付回调四、实现退款功能退款时序图发起退款解析退款回调五、总结在互联网技术日益发展的今天,线上支付已成为不可或缺的一......