SpringBoot + 微信公众号JSAPI支付

一、pom.xml依赖配置

<!-- 微信支付 -->
<dependency>
    <groupId>com.egzosn</groupId>
    <artifactId>pay-java-wx</artifactId>
    <version>2.12.4</version>
</dependency>

二、application.yml文件配置微信公众号的基础信息

#微信公众号支付配置
wechatpay:
  mchId:  # 商户Id
  appId:  #应用id
  storePassword:  #秘钥支付密码
  secretKey:  # 密钥
  notifyUrl:  #微信支付回调
  keyStore:   # 证书所在位置

三、设置配置文件 WechatPayConfig.java

package com.example.emoticon.wechat;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @ClassName WechatPayConfig
 * @Description 微信支付配置
 * @Author WangJing
 * @Date 2021/3/23 4:38 下午
 * @Version V1.1.0
 */

@Data
@Component
@ConfigurationProperties(prefix = "wechatpay")
public class WechatPayConfig {

    private String mchId;//合作者id(商户号

    private String appId;//应用id

    private String secretKey;//密钥

    private String notifyUrl;
    private String keyStore;// 支付密钥存放位置 文件是以.p12为后缀名字
    private String storePassword;

}

四、controller 逻辑代码

package com.example.emoticon.controller;

import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.PayOrder;
import com.egzosn.pay.common.bean.RefundOrder;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.wx.api.WxPayConfigStorage;
import com.egzosn.pay.wx.api.WxPayService;
import com.egzosn.pay.wx.bean.WxTransactionType;
import com.example.emoticon.wechat.WechatPayConfig;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

/**
 * @ClassName WechatPayController
 * @Description 微信支付Controller
 * @Author WangJing
 * @Date 2021/3/23 4:35 下午
 * @Version V1.1.0
 */
@RestController
@RequestMapping("/wechatPay")
@Slf4j
public class WechatPayController {


    @Autowired
    WechatPayConfig wechatPayConfig;

    private PayService service = null;

    @PostConstruct
    public void init() {
        WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
        wxPayConfigStorage.setMchId(wechatPayConfig.getMchId()); // 合作者id(商户号
        wxPayConfigStorage.setAppid(wechatPayConfig.getAppId()); // 应用id
        wxPayConfigStorage.setSecretKey(wechatPayConfig.getSecretKey()); // 密钥
        wxPayConfigStorage.setNotifyUrl(wechatPayConfig.getNotifyUrl()); // 异步回调地址 http://域名:端口号/项目名/回调接口名称
        wxPayConfigStorage.setSignType(SignUtils.MD5.name());
        wxPayConfigStorage.setInputCharset("utf-8");
        // 支付api证书设置,退款必须 方式一
        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
        httpConfigStorage.setKeystore(wechatPayConfig.getKeyStore());// 支付密钥存放位置 文件是以.p12为后缀名字
        httpConfigStorage.setStorePassword(wechatPayConfig.getStorePassword());
        // 是否为证书地址
        httpConfigStorage.setPath(true);
        service = new WxPayService(wxPayConfigStorage, httpConfigStorage);
        // 请求连接池配置
        // 最大连接数
        httpConfigStorage.setMaxTotal(20);
        // 默认的每个路由的最大连接数
        httpConfigStorage.setDefaultMaxPerRoute(10);
        service.setRequestTemplateConfigStorage(httpConfigStorage);
    }

    @ApiOperation("返回订单信息")
    @RequestMapping(value = "weixinpay", method = RequestMethod.POST)
    public Map<String, Object> weixinpay(HttpServletRequest request) {
        //备注:这个可以获取预支付的订单,根据需要调用这个接口,可有前台向后台传递参数。然后后台根据需要进行处理。
        init();
        // 在这一步,可以传入一个订单Id,自行去搜索订单信息,并填写以下内容
        PayOrder payOrder = new PayOrder();// 这个就是支付成功后,在微信支付里面返回的信息(支付订单信息)
        // 一下内容需要分情况而定,自行填写。
        payOrder.setSubject("商品名称");
        payOrder.setBody("商品描述");
        payOrder.setAddition("附加信息");
        payOrder.setPrice(new BigDecimal(0.2));// 价格
        payOrder.setOutTradeNo("商户订单号");
        payOrder.setBankType("银行卡类型");
        payOrder.setDeviceInfo("设备信息");
        payOrder.setSpbillCreateIp("支付创建ip");// 可用IPUtils.getIpAddr(request)
        payOrder.setOpenid("用户微信openid");
        payOrder.setTransactionType(WxTransactionType.JSAPI);// 支付方式
        Map orderInfo = service.orderInfo(payOrder);// 返回创建的订单信息
        log.debug("获取预支付订单信息回参" + orderInfo.toString());
        // 可自行选择 ,是否将支付的流水插入到数据库中。返回的信息由:signType appId timeStamp nonceStr package sign
        return orderInfo;
    }

    /**
     * 这就是支付回调地址
     *
     * @param request
     * @return
     * @throws IOException
     */
    @ApiOperation("回调地址")
    @RequestMapping(value = "weixinpayBack")
    public String payBack(HttpServletRequest request) throws IOException {
        init();
        // 获取支付方返回的对应参数
        Map<String, Object> params = service.getParameter2Map(request.getParameterMap(), request.getInputStream());
        if (null == params) {
            log.debug("通知失败");
            return service.getPayOutMessage("failed", "通知失败").toMessage();
        }
        log.debug("微信公众号支付结果通知:" + params.toString());
        // 校验
        if (service.verify(params)) {
            // 这里处理业务逻辑 支付成功后的代码逻辑块
            // ......业务逻辑处理块........
            log.debug("通知支付成功");
            return service.getPayOutMessage("success", "支付成功").toMessage();
        }
        log.debug("通知支付失败");
        return service.getPayOutMessage("fail", "支付失败").toMessage();
    }


    @ApiOperation("微信公众号退款")
    @RequestMapping(value = "weixinAccRefund")
    public String weixinRefund() {
        init();
        RefundOrder refundOrder = new RefundOrder();//退款订单信息
        refundOrder.setRefundNo("退款单号,每次进行退款的单号,此处唯一");
        refundOrder.setTradeNo("支付平台订单号,交易号");
        refundOrder.setOutTradeNo("商户单号");
        refundOrder.setRefundAmount(new BigDecimal(0.2));//退款金额
        refundOrder.setTotalAmount(new BigDecimal(0.5));//订单总金额
        refundOrder.setOrderDate(new Date());//退款交易日期
        refundOrder.setDescription("退款说明");
        Map<String, Object> refund = service.refund(refundOrder);//微信退款
        //退款成功后,写其他的逻辑
        log.debug("微信公众号退款结果:=" + refund.toString());

        return "Success";

    }
}

注:以上内容仅提供参考和交流,请勿用于商业用途,如有侵权联系本人删除!

让你真正做到一行代码实现支付聚合,让你可以不用理解支付怎么对接,只需要专注你的业务 全能第三方支付对接pay-spring-boot-starter开发工具包 开发工具在软件开发生命周期中扮演着至关重要的角色,它们旨在简化和加速从概念设计到产品部署的各个环节。以下是开发工具的主要作用: 代码编写与编辑: 提供集成开发环境(IDE),如Visual Studio、Eclipse、Android Studio和Sublime Text等,这些工具集成了文本编辑器,支持语法高亮、自动补全、代码片段管理和版本控制等功能,有助于开发者高效编写和维护代码。 项目管理: 支持项目创建、组织、构建自动化以及依赖管理,确保不同模块和组件之间的协调一致。 编译与构建: 包括编译器、构建工具(如Make、Gradle、Maven)等,用于将源代码转换为可执行文件或库,并进行资源打包、优化等处理。 调试与测试: 集成调试器允许开发者逐行执行代码,设置断点、查看变量值、跟踪调用堆栈等,帮助定位并修复代码中的错误。 测试框架和工具则协助开发者编写和运行单元测试、集成测试及性能测试,确保软件质量。 版本控制与协作: 通过集成Git、SVN等版本控制系统,支持团队成员间的代码共享、分支管理、合并请求和冲突解决。 可视化设计与原型制作: 对于UI/UX设计,有界面设计工具,如Sketch、Adobe XD,可以帮助设计师快速构建应用程序界面模型,并生成规范的设计稿供开发人员参考实现。 跨平台支持: 跨平台开发工具如Xamarin、React Native和Flutter,让开发者使用一种语言或框架编写可以在多个操作系统上运行的应用程序。 文档编写与API管理: 文档生成工具可以自动生成代码注释文档,便于团队内外理解和使用项目代码。 API管理工具则方便开发者创建、测试、发布和维护API接口。 持续集成与持续部署(CI/CD): Jenkins、Travis CI、GitHub Actions等工具负责自动化构建、测试和部署流程,提高交付效率和可靠性。 数据库管理与ORM工具: 数据库客户端工具用于连接、查询、更新数据库,ORM(对象关系映射)工具简化了数据操作和持久化层的开发工作。 总之,开发工具极大地提升了软件工程师的工作效率,保证了开发过程中的准确性与一致性,同时也促进了团队合作,使得软件开发更系统化、规范化和工业化。
以下是一个简单的示例代码,演示如何使用Vue和Spring Boot实现微信支付: 前端Vue代码: ```vue <template> <div> <button @click="pay">微信支付</button> </div> </template> <script> import axios from 'axios' export default { methods: { pay() { axios.post('/api/wechat/pay').then(response => { const data = response.data WeixinJSBridge.invoke( 'getBrandWCPayRequest', { 'appId': data.appId, //公众号名称,由商户传入 'timeStamp': data.timeStamp, //时间戳,自1970年以来的秒数 'nonceStr': data.nonceStr, //随机串 'package': data.packageValue, 'signType': data.signType, //微信签名方式: 'paySign': data.paySign //微信签名 }, function (res) { if (res.err_msg == 'get_brand_wcpay_request:ok') { alert('支付成功') } else if (res.err_msg == 'get_brand_wcpay_request:cancel') { alert('取消支付') } else { alert('支付失败') } } ) }) } } } </script> ``` 后端Spring Boot代码: ```java @RestController @RequestMapping("/api/wechat") public class WechatController { @Autowired private WechatPayService wechatPayService; @PostMapping("/pay") public Map<String, String> pay() throws Exception { return wechatPayService.unifiedOrder(); } } @Service public class WechatPayServiceImpl implements WechatPayService { @Autowired private WechatPayConfig wechatPayConfig; @Override public Map<String, String> unifiedOrder() throws Exception { //生成微信支付参数 Map<String, String> parameters = new HashMap<>(); parameters.put("appid", wechatPayConfig.getAppId()); parameters.put("mch_id", wechatPayConfig.getMchId()); parameters.put("nonce_str", UUID.randomUUID().toString().replace("-", "")); parameters.put("body", "测试商品"); parameters.put("out_trade_no", UUID.randomUUID().toString().replace("-", "")); parameters.put("total_fee", "1"); parameters.put("spbill_create_ip", "127.0.0.1"); parameters.put("notify_url", wechatPayConfig.getNotifyUrl()); parameters.put("trade_type", "JSAPI"); parameters.put("openid", "openid"); String sign = WechatPayUtil.generateSignature(parameters, wechatPayConfig.getKey()); parameters.put("sign", sign); //调用微信支付统一下单API String xml = WechatPayUtil.mapToXml(parameters); String result = HttpUtil.post(wechatPayConfig.getUnifiedOrderUrl(), xml); Map<String, String> resultMap = WechatPayUtil.xmlToMap(result); //生成前端需要的支付参数 Map<String, String> payParameters = new HashMap<>(); payParameters.put("appId", wechatPayConfig.getAppId()); payParameters.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); payParameters.put("nonceStr", UUID.randomUUID().toString().replace("-", "")); payParameters.put("packageValue", "prepay_id=" + resultMap.get("prepay_id")); payParameters.put("signType", "MD5"); String paySign = WechatPayUtil.generateSignature(payParameters, wechatPayConfig.getKey()); payParameters.put("paySign", paySign); return payParameters; } } @Configuration @ConfigurationProperties(prefix = "wechat.pay") public class WechatPayConfig { private String appId; //公众账号ID private String mchId; //商户号 private String key; //商户密钥 private String unifiedOrderUrl; //统一下单地址 private String notifyUrl; //支付结果通知地址 //省略getter和setter方法 } ``` 以上代码示例中,前端Vue代码中使用axios发送POST请求到后端的`/api/wechat/pay`接口,后端Spring Boot代码中生成微信支付参数,调用微信支付统一下单API,然后将生成的前端需要的支付参数返回给前端。前端再将支付参数传给微信客户端进行支付
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JAVA·D·WangJing

您的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值