Java对接JeePay支付、转账实现以及回调函数

news2024/11/19 14:35:21

        最近公司对接了第三方支付平台JeePay,看到网上文章比较少,给大家发一篇对接微信支付的吧,支付宝也一样,更换里面的参数即可,官方文档地址:系统介绍 - 计全文档,具体的服务需要大家去搭建,并创建里面的应用,我这里只给大家展示出了代码,具体的服务搭建和创建应用大家去看下官网,下面开始实现我们的代码。

首先我们引入两个pom依赖。

<dependency>
    <groupId>com.github.wxpay</groupId>
    <artifactId>wxpay-sdk</artifactId>
    <version>0.0.3</version>
</dependency>

<dependency>
    <groupId>com.jeequan</groupId>
    <artifactId>jeepay-sdk-java</artifactId>
    <version>1.5.0</version>
</dependency>

下面我们需要在配置文件里面加上相关配置,我们可以新建一个  application-jee-pay.properties。

#这个是回调的地址,一定要能访问到我们回调的IP上面,自定义
domain-name=http://120.29.172.100:8500
#这个固定写死
api-base=https://pay.vichel.com.cn/
#商户私钥
api-key=商户的私钥,如何获取看下面截图
#商户号,看下面截图
mch-no=M1670111111
#应用ID
app-id=1111b3f0e4b05e7111111111
#转账回调地址
wx-withdrawal=${domain-name}/wxPay/result/withdrawalCallback
#支付回调地址
wx-recharge=${domain-name}/wxPay/result/wxRechargeCallback

打开jeePay运营平台,点击我们要对接的应用,点击修改,里面有应用ID和商户号,我们直接复制就可以了。随机生成出一个私钥,点击保存就可以了

基础配置类

package com.mart.web.pay;

import com.jeequan.jeepay.Jeepay;
import com.jeequan.jeepay.JeepayClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

/**
 * JeePay配置相关
 */
@Configuration
//这里指定我们要读取的配置文件
@PropertySource("classpath:application-jee-pay.properties")
public class JeePayClientConfig {

    @Autowired
    private Environment config;

    @Bean
    public JeepayClient jeePayConfig(){
        //地址
        Jeepay.setApiBase(config.getProperty("api-base"));
        //私钥
        Jeepay.apiKey = config.getProperty("api-key");
        //商户号
        Jeepay.mchNo = config.getProperty("mch-no");
        //应用ID
        Jeepay.appId = config.getProperty("app-id");
        JeepayClient jeepayClient = JeepayClient.getInstance(Jeepay.appId, Jeepay.apiKey, Jeepay.getApiBase());
        return jeepayClient;
    }
}

下面是一些支付转账操作的模块,我给大家出了一个示例,里面的参数需要结合业务需求做相应的调整,我下面只要使用的是微信小程序支付和微信零钱的转账功能。商户可以转账到用户微信的零钱。

package com.mart.web.pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.Jeepay;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.model.PayOrderCreateReqModel;
import com.jeequan.jeepay.model.TransferOrderCreateReqModel;
import com.jeequan.jeepay.model.TransferOrderCreateResModel;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.request.TransferOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.response.TransferOrderCreateResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 
 * 支付转账核心操作功能模块
 */
@Slf4j
@Service
public class JeePayService {

    @Autowired
    private JeepayClient jeepayClient;

    @Autowired
    private Environment config;

    /**
     * 转账操作,转账到微信零钱(特别注意,下面转账的时候Jeepay一定要使用微信的主商户进行转账,如果使用的是子商户就会出现   {"code":9999,"msg":"微信子商户暂不支持转账业务"})
     * @param openId   用户的openId
     * @param amount   转账金额
     * @param numberOn 转账订单号
     * @return
     */
    public Boolean withdrawal(String openId, BigDecimal amount,String numberOn) {
        // 构建请求数据
        TransferOrderCreateRequest request = new TransferOrderCreateRequest();
        TransferOrderCreateReqModel model = new TransferOrderCreateReqModel();
        // 商户号
        model.setMchNo(Jeepay.mchNo);
        // 应用ID
        model.setAppId(Jeepay.appId);
        // 商户订单号
        model.setMchOrderNo(numberOn);
        // 支付方式
        model.setIfCode("wxpay");
        // 入账方式
        model.setEntryType("WX_CASH");
        // 我们传入的是元,这里需要吧金额转成单位分
        amount = amount.multiply(new BigDecimal("100"));
        model.setAmount(amount.longValue());
        // 币种,目前只支持cny
        model.setCurrency("CNY");
        model.setAccountNo(openId);
        // 转账备注
        model.setTransferDesc("测试转账操作");
        // 异步通知地址
        model.setNotifyUrl(config.getProperty("wx-withdrawal"));
        // 商户扩展参数,回调时原样返回
        model.setExtParam(numberOn);
        request.setBizModel(model);
        log.info("jeepay下单参数处理完毕,参数:[{}]", JSON.toJSONString(request));
        try {
            TransferOrderCreateResponse response = jeepayClient.execute(request);
            // 下单成功
           if (response.isSuccess(Jeepay.apiKey)) {
               //转账成功
               log.warn("转账成功:{}");
               return true;
            }
        } catch (JeepayException e) {
            log.error(e.getMessage());
        }
        log.warn("转账失败:{}");
        return false;
    }

    /**
     * 支付操作,我下面使用的是微信支付的
     * @param Subject  商品标题
     * @param body     描述
     * @param openId   微信的OpenId或者是支付宝的用户ID
     * @param amount   支付的金额   CNY
     * @param numberOn 平台自己生成的随机订单号
     * @return
     */
    public String scanPay(String Subject,String body,String openId, BigDecimal amount,String numberOn) {
        // 构建请求数据
        PayOrderCreateRequest request = new PayOrderCreateRequest();
        PayOrderCreateReqModel model = new PayOrderCreateReqModel();
        // 商户号
        model.setMchNo(Jeepay.mchNo);
        // 应用ID
        model.setAppId(Jeepay.appId);
        // 商户订单号
        model.setMchOrderNo(numberOn);
        // 支付方式
        model.setWayCode("WX_JSAPI");
        amount = amount.multiply(new BigDecimal("100"));
        // 金额,单位分
        model.setAmount(amount.longValue());
        // 币种,目前只支持cny
        model.setCurrency("CNY");
        // 发起支付请求客户端的IP地址
        model.setClientIp(config.getProperty("ip-address"));
        // 商品标题
        model.setSubject(Subject);
        // 商品描述
        model.setBody(body);
        // 异步通知地址
        model.setNotifyUrl(config.getProperty("wx-recharge"));
        // 渠道扩展参数  传OpenId
        model.setChannelExtra("{\"openid\": \""+openId+"\"}");
        // 商户扩展参数,回调时原样返回
        model.setExtParam(numberOn);
        request.setBizModel(model);
        log.info("jeepay下单参数处理完毕,参数:[{}]", JSON.toJSONString(request));
        try {
            PayOrderCreateResponse response = jeepayClient.execute(request);
            // 下单成功
           if (response.isSuccess(Jeepay.apiKey)) {
               String result = response.getData().getString("payData");
               return result;
            }
        } catch (JeepayException e) {
            log.error(e.getMessage());
        }
        return null;
    }

}

回调函数

package com.mart.web.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.jeequan.jeepay.util.JeepayKit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * 回调接收
 * @author HayDen
 * @date 2022-11-15
 */
@RestController
@RequestMapping("/wxPay/result")
@SentinelResource(value = "CallbackController")
public class CallbackController
{
    
   
    @Autowired
    private Environment config;

    /**
     * 转账回调
     * @return
     */
    @PostMapping("/withdrawalCallback")
    public String  withdrawalCallback(HttpServletRequest req) throws Exception
    {
        String result = "failure";
        try {
            Map<String, Object> map = getParamsMap(req);
            //获取私钥
            String apikey = config.getProperty("api-key");
            //验签
            if (chackSgin(map, apikey)) {
                return result;
            }
            //提现成功
            //获取订单号
            String orderNumber = map.get("mchOrderNo").toString();
            //提现金额
            BigDecimal amount = new BigDecimal(map.get("amount").toString()).divide(new BigDecimal("100"),4,BigDecimal.ROUND_HALF_UP);
          
            }
            result = "success";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 微信支付回调
     * @return
     */
    @PostMapping("/wxRechargeCallback")
    public String  wxRechargeCallback(HttpServletRequest req) throws Exception
    {
        String result = "failure";
        try {
            Map<String, Object> map = getParamsMap(req);
            //获取私钥
            String apikey = config.getProperty("api-key");
            //验签
            if (chackSgin(map, apikey)) {
                return result;
            }
            //订单号
            String orderNumber = map.get("mchOrderNo").toString();
            //支付金额
            BigDecimal amount = new BigDecimal(map.get("amount").toString()).divide(new BigDecimal("100"),4,BigDecimal.ROUND_HALF_UP);
            //返回成功
            result = "success";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 回调验签
     * @param map
     * @param apikey
     * @return
     */
    private Boolean chackSgin(Map<String, Object> map, String apikey) {
        Object sign = map.remove("sign");
        String reSign = JeepayKit.getSign(map, apikey);

        if (!Objects.equals(reSign, sign)) {
            return true;
        }
        return false;
    }

    private Map<String, Object> getParamsMap(HttpServletRequest req) {
        Map<String, String[]> requestMap = req.getParameterMap();
        Map<String, Object> paramsMap = new HashMap<>();
        requestMap.forEach((key, values) -> {
            String strs = "";
            for (String value : values) {
                strs = strs + value;
            }
            paramsMap.put(key, strs);
        });
        return paramsMap;
    }

}

好了,到这里基本就结束了,如果大家有什么疑问可以给我留言,看到后一定会第一时间回复的,有建议那是最好的,欢迎大家提出来,如果合理我一定第一时间优化代码。

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

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

相关文章

为ABP新增手机验证模块

当前手机验证基本是标配&#xff0c;但Abp自身并没有实现这个功能&#xff0c;于是有了通过自定义模块实现的想法。 经过研究&#xff0c;发现要实现这个&#xff0c;只要重写和替换包含ReplaceEmailToUsernameOfInputIfNeeds方法的类就可以了。但要实现这个&#xff0c;首先要…

sql server提供三种常用截取字符串方法,LEFT()、RIGHT()、SUBSTRING()

一、sql server提供了三种常用截取字符串方法&#xff0c;LEFT()、RIGHT()、SUBSTRING() 1、LEFT()函数语法&#xff1a;LEFT(character,integer) 注释&#xff1a;参数1&#xff1a;要截取的字符串&#xff0c;参数2&#xff1a;截取字符个数说明&#xff1a;返回从字符串左边…

你的 VS Code 扩展值得信赖吗?

Aqua Nautilus 研究人员最近发现&#xff0c;攻击者可以轻松地冒充流行的 Visual Studio Code 扩展并诱骗不知情的开发人员下载它们。VSCode 是迄今为止最受欢迎的 IDE&#xff1b;StackOverflow 的一项调查指出&#xff0c;其目前已被 74.48% 的开发人员所使用。VSCode 的强大…

SPDK技术浅析

目录SPDK基础知识SPDK架构SPDK使用rpc后台启动基础机制分析后端vhost异步I/O写该篇的来由是因为翻阅到了TriCache: A User-Transparent Block Cache Enabling High-Performance Out-of-Core Processing with In-Memory Programs文章&#xff0c;其中对SPDK的运用的炉火纯青&…

数据结构(1)并查集

(4条消息) 第五课、Trie树、并查集、堆和堆排序_yan__kai_的博客-CSDN博客 活动 - AcWing 并查集作用&#xff1a;一群元素将可以归类到一个代表元素上。可以维护元素到根节点的距离。可以维护每个并查集的大小。 基本操作回顾基础课&#xff0c;特别是“食物链”那道题 目录…

【Django项目开发】部门管理模块的开发(八)

文章目录一、模型类设计二、视图设计1.都有哪些接口三、序列化器类设计四.分页操作1.utils工具中定义pagination.py2.视图类中使用五.路由配置一、模型类设计 一个部门下面可能会有很多子部门&#xff0c;一个子部门上面可能会有父部门&#xff1b;即部门内部之间进行关联&…

国科大模式识别与机器学习2022年期末总结

我根据本学期老师说的考试重点和我自身的情况总结的&#xff0c;希望能帮助到你&#xff0c;如有错误欢迎指正 目录第三章 判别函数Fisher线性判别感知机算法第四章 特征选择和提取K-L变换第五章 统计学习学习基础损失函数风险正则化过拟合欠拟合泛化误差第六章 有监督学习有监…

【jQuery】常用API——jQuery内容文本值

要针对元素的内容还有表单的值操作。 普通元素内容 html()&#xff08;相当于原生 inner HTML) html(); // 获取元素的内容html(内容); // 设置元素的内容<script src"../jquery.min.js"></script> </head><body><div><span>我是…

118页4万字智慧检务大数据平台解决方案

【版权声明】本资料来源网络&#xff0c;知识分享&#xff0c;仅供个人学习&#xff0c;请勿商用。【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间删除&#xff01;完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 目录 第1章 前言 1.1、 政策背…

docker-compose keep-alive mysql8 互为主从

一、准备2台物理机器master-1、master-2&#xff0c;目标虚拟VIP。   VIP:192.168.1.139   master-1:192.168.1.17   master-2:192.168.1.20    二、然后分别在2台物理机器master-1、master-2上使用docker-compose安装mysql8&#xff0c;并配置互为主从。 1&#xff09…

优先级队列、仿函数和反向迭代器

文章目录优先级队列priority_queue的模拟实现框架无参的构造(默认构造)迭代器区间构造向上调整向下调整插入删除取堆顶的数据求数据个数验满初识仿函数模拟实现仿函数更改后的向上调整仿函数更改后的向下调整反向迭代器具体实现优先级队列 1.优先队列是一种容器适配器&#xf…

微信转账api(企业付款)

企业付款介绍 提供企业向用户付款的功能&#xff0c;支持企业通过API接口付款&#xff0c;或通过微信支付商户平台网页功能操作付款。 1. 充值 登录微信支付商户平台&#xff0c;通过网页充值功能充值&#xff08;商户平台-资金管理-现金管理-充值&#xff09;。 温馨提示&a…

BreederDAO x DigiCult AMA——要点总结

问&#xff1a;为什么 BreederDAO 决定花费 200ETH 用于购买 Mythic DigiDaigaku Genesis — Ifrit&#xff1f; 答&#xff1a;除了投资之外&#xff0c;这也是为了确保这个领域中有更多的可触达性&#xff0c;尤其是随着我们 DigiDaigaku 市场工具的推出之后。这也是我们进入…

(十七)Async异步和多线程-语言进阶1

&#xff08;十七&#xff09;Async异步和多线程-语言进阶1一、进程-线程-多线程&#xff0c;同步和异步1.概念2.同步和异步3.异步与多线程异同点二、委托启动异步调用1.同步方法2.异步方法三、多线程的特点四、异步的回调和状态参数1.顺序控制2.状态参数五、异步等待三种方式1…

开学季,护眼灯什么牌子好?2023年护眼台灯推荐

2023年开始了&#xff0c;时间飞逝&#xff0c;而每个父母都越来越紧张自家娃的学业情况&#xff0c;我国近视人数超过7亿人&#xff0c;而儿童时期是视力发育的关键时期&#xff0c;为啥有那么高的近视率呢&#xff1f;主要是用眼过度&#xff0c;以及用眼习惯&#xff0c;而现…

微信小程序——模板与配置,数据绑定,事件绑定

一.数据绑定1.数据绑定的基本原则在data中定义数据在WXML中使用数据2.在data中定义页面的数据在页面对应的.js文件中&#xff0c;把数据定义到data对象中即可3. Mustache 语法的格式把 data 中的数据绑定到页面中渲染&#xff0c;使用 Mustache 语法&#xff08;双大括号&#…

想提高办公效率?可试试java开源工作流框架

在数据化管理越来越规范的当今社会&#xff0c;采用优质的办公软件平台能提高企业的办公协作效率&#xff0c;因而受到了广泛的欢迎和喜爱。那么&#xff0c;什么是java开源工作流框架&#xff1f;我们可以从它的特点、发展前景等方面来加以了解&#xff0c;一起来了解这一产品…

微信公众号运营工具有哪些?赶紧收藏

再厉害的公众号运营大神背后都有一套宝藏工具大全&#xff0c;辅助运营人一路披荆斩棘&#xff0c;堪称神器&#xff01; 我相信网上一搜也能出来很多的运营工具或是网站&#xff0c;但是这里再来给大家来一个大汇总&#xff0c;这次整理绝对是非常详细和实用的&#xff0c;纯…

Fiddler中常用的功能

Fiddler中常用的功能如下&#xff1a; 停止抓包-清空会话窗-内容过滤请求-解码-设置断点 一、 停止抓包 二、清空会话窗 方法一&#xff0c;工具栏工具&#xff1a; 方法二&#xff0c;命令行形式&#xff1a; 当然&#xff0c;命令行工具也还支持其他命令的输入&#xff0c…

word排版技巧:如何将段中文字生成标题目录

在许多Word文档里面&#xff0c;目录页是非常重要的一页内容&#xff0c;因为目录页展示的是当前文档的内容框型和结构。通过目录页&#xff0c;我们能知道这个文档主要分为哪几部分。就像看书一样&#xff0c;起到了检索的作用。今天&#xff0c;我们就来给大家分享一个偏门的…