在线支付系列【22】微信支付实战篇之集成服务商API

news2024/11/26 13:48:31

有道无术,术尚可求,有术无道,止于术。

文章目录

    • 前言
    • 1. 环境搭建
    • 2. 特约商户进件
    • 3. 统一下单
    • 总结

前言

在上篇文档中,我们做好了接入前准备工作,接下来使用开源框架集成服务商相关API

一个简单的支付系统完成支付流程图如下所示:
在这里插入图片描述

1. 环境搭建

引入开源微信支付框架。

        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>wx-java-pay-spring-boot-starter</artifactId>
            <version>4.4.8.B</version>
        </dependency>

配置上篇文档中我们获取到的参数、秘钥、证书

wx:
  pay:
    appId: wx7xxxxx # 服务商应用ID(公众号)
    mchId: xxxxx # 服务商收款账号
    apiV3Key: UDuLFDcmy5Eb6o0xxxxx # 服务商API V3密钥
    certSerialNo: 34345964330B66427E0D3D2882xxxxx # 服务商商户证书序列
    privateKeyPath: classpath:cert/apiclient_key.pem # 服务商apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径
    privateCertPath: classpath:cert/apiclient_cert.pem # 服务商apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径

新建商户管理表、支付订单表等~

2. 特约商户进件

官方API文档

该支付系统,首先需要入驻子商户,可以集成微信提供的进件接口,这样自由度和管理更方便。

该框架的Applyment4SubService接口实现类已经集成微信特约商户进件API,我们只需要设置对应的请求参数对象即可,如果是直接集成微信SDK,还需要封装参数、解析响应比较麻烦。

public interface Applyment4SubService {
  /**
   * 提交申请单API
   */
  WxPayApplymentCreateResult createApply(WxPayApplyment4SubCreateRequest request) throws WxPayException;

  /**
   * 通过业务申请编号查询申请状态
   *
   * @param businessCode 业务申请编号
   *  1、只能由数字、字母或下划线组成,建议前缀为服务商商户号。
   *  2、服务商自定义的唯一编号。
   *  3、每个编号对应一个申请单,每个申请单审核通过后生成一个微信支付商户号。
   *  4、若申请单被驳回,可填写相同的“业务申请编号”,即可覆盖修改原申请单信息。
   *  示例值:1900013511_10000
   */
  ApplymentStateQueryResult queryApplyStatusByBusinessCode(String businessCode) throws WxPayException;

  /**
   * 通过申请单号查询申请状态
   */
  ApplymentStateQueryResult queryApplyStatusByApplymentId(String applymentId) throws WxPayException;

  /**
   * 根据特约子商户ID查询结算账户
   */
  SettlementInfoResult querySettlementBySubMchid(String subMchid) throws WxPayException;

  /**
   * 修改结算帐号
   */
  String modifySettlement(String subMchid, ModifySettlementRequest request) throws WxPayException;

}

示例代码如下:

  @Operation(summary = "提交申请单")
    @GetMapping("/createApply")
    public R<String> createApply(@RequestParam(required = false) String applymentId) throws WxPayException {
        WxPayApplyment4SubCreateRequest request = new WxPayApplyment4SubCreateRequest();
        // 主体资料:主体类型、是否是金融机构、营业执照、登记证书、组织机构代码证、单位证明函照片、经营者/法人身份证件、最终受益人信息列表(UBO)、小微辅助证明材料(subjectType为小微商户时必填)
        WxPayApplyment4SubCreateRequest.SubjectInfo subjectInfo = WxPayApplyment4SubCreateRequest.SubjectInfo.builder().build()
                .setFinanceInstitution(false)
                .setBusinessLicenseInfo(null);// 省略.......
        request.setSubjectInfo(subjectInfo);
        // 补充材料
        WxPayApplyment4SubCreateRequest.AdditionInfo additionInfo=new WxPayApplyment4SubCreateRequest.AdditionInfo();
        additionInfo.setBusinessAdditionMsg("补充说明");
        additionInfo.setBusinessAdditionPics(null) ;// 补充材料
        additionInfo.setLegalPersonCommitment("法人开户承诺函");
        additionInfo.setLegalPersonVideo("法人开户意愿视频");
        request.setAdditionInfo(additionInfo);
        // 结算银行账户
        WxPayApplyment4SubCreateRequest.BankAccountInfo bankAccountInfo=new WxPayApplyment4SubCreateRequest.BankAccountInfo();
        bankAccountInfo.setBankAccountType(BankAccountTypeEnum.BANK_ACCOUNT_TYPE_CORPORATE); // 账户类型:对公银行账户
        bankAccountInfo.setAccountName("开户名称");  // 开户名称
        bankAccountInfo.setAccountBank("开户银行");
        bankAccountInfo.setBankAddressCode("开户银行省市编码");
        bankAccountInfo.setBankBranchId("开户银行联行号");
        bankAccountInfo.setBankName("开户银行全称(含支行)");
        bankAccountInfo.setAccountNumber("银行账号");
        request.setBankAccountInfo(bankAccountInfo);
        // 业务申请编号
        request.setBusinessCode("业务申请编号");
        // 经营资料
        request.setBusinessInfo(null); // 省略.......
        // 超级管理员信息
        request.setContactInfo(null);// 省略.......
        // 结算规则
        request.setSettlementInfo(null);// 省略.......

        // 调用微信API
        Applyment4SubService applyment4SubService=new Applyment4SubServiceImpl(wxPayService);
        WxPayApplymentCreateResult apply = applyment4SubService.createApply(request);
        String applyMentId = apply.getApplymentId(); // 返回申请单ID
        return R.success(applyMentId);
    }
    
    @Operation(summary = "通过申请单号查询申请状态")
    @GetMapping("/queryApply")
    public R<ApplymentStateQueryResult> queryApply(@RequestParam(required = true) String applymentId) throws WxPayException {
        // 调用API 查询申请状态
        Applyment4SubService applyment4SubService=new Applyment4SubServiceImpl(wxPayService);
        ApplymentStateQueryResult result = applyment4SubService.queryApplyStatusByApplymentId(applymentId);
        return R.success(result);
    }

3. 统一下单

EcommerceService接口实现类中,集成了服务商下单API。多种支付方式时,使用同一个方法即可。

public interface EcommerceService {
  /**
   * <pre>
   *  服务商模式普通支付API(APP支付、JSAPI支付、H5支付、NATIVE支付).
   *  请求URL:https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi
   *  文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/transactions_sl.shtml
   *  </pre>
   *
   * @param tradeType 支付方式
   * @param request   请求对象
   * @return 调起支付需要的参数 transactions result
   * @throws WxPayException the wx pay exception
   */
  TransactionsResult partner(TradeTypeEnum tradeType, PartnerTransactionsRequest request) throws WxPayException;
  /**
   * <pre>
   * 普通查询订单API
   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/e_transactions/chapter3_5.shtml
   * </pre>
   *
   * @param request 商户订单信息
   * @return 支付订单信息
   * @throws WxPayException the wx pay exception
   */
  PartnerTransactionsResult queryPartnerTransactions(PartnerTransactionsQueryRequest request) throws WxPayException;
  /**
   * <pre>
   * 关闭普通订单API
   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/e_transactions/chapter3_6.shtml
   * </pre>
   *
   * @param request 关闭普通订单请求
   * @throws WxPayException the wx pay exception
   * @return
   */
  String closePartnerTransactions(PartnerTransactionsCloseRequest request) throws WxPayException;
}

示例代码如下:

    @Operation(summary = "统一下单/(V3)")
    @PostMapping("/ecommerceNative")
    public R<?> ecommerceNative(OrderEntity mchOrder,String subMchId) throws Exception {
        try {
            // 1. 创建请求对象
            PartnerTransactionsRequest orderRequest=new PartnerTransactionsRequest();
            // 2. 根据订单系统传过来的订单信息组装支付参数,创建支付订单
            orderRequest.setSpMchid(subMchId); // 子商户号
            orderRequest.setDescription("示例值:Image形象店-深圳腾大-QQ公仔"); // 商品描述:示例值:Image形象店-深圳腾大-QQ公仔
            PartnerTransactionsRequest.Amount amount = new PartnerTransactionsRequest.Amount();
            amount.setTotal(1); // 订单金额信息
            orderRequest.setAmount(amount);
            orderRequest.setOutTradeNo(mchOrder.getOutTradeNo()); // 商户订单号,商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
            orderRequest.setNotifyUrl("https://8da1-120-227-23-190.jp.ngrok.io/pay/wechat/notify"); // 通知地址
            // 3. 发起V3 服务商发起NATIVE支付
            EcommerceServiceImpl ecommerceService=new EcommerceServiceImpl(wxPayService);
            TransactionsResult result = ecommerceService.partner(com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum.NATIVE, orderRequest);
            log.info("NATIVE支付成功,返回二维码URL" + result.getCodeUrl());
            // 4. 省略后续操作
            return R.success(result);
        } catch (Exception e) {
            log.error("微信支付失败!,原因:{}", e.getMessage());
            e.printStackTrace();
            return R.fail();
        }
    }

总结

weixin-java-pay框架中,几乎所有的微信API都帮我们集成好了,我们只需要设置对应的参数即可,甚至每个方法对应的官网API文档也贴上去了,好像实在也没什么可讲的~
在这里插入图片描述

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

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

相关文章

火爆全网的ChatGPT使用教程

最近&#xff0c;大家有没有被ChatGPT所刷屏呢&#xff1f;记得之前元宇宙刚出来的时候&#xff0c;也是极其火爆&#xff0c;虽说这二者是不同的性质&#xff0c;但是都是代表着当下互联网发展之迅速。 一、什么是ChatGPT 百度百科中给出的解释&#xff1a;ChatGPT&#xff0…

【Explain详解与索引优化最佳实践】

摘要 explain命令是查看MySQL查询优化器如何执行查询的主要方法&#xff0c;可以很好的分析SQL语句的执行情况。每当遇到执行慢&#xff08;在业务角度&#xff09;的SQL&#xff0c;都可以使用explain检查SQL的执行情况&#xff0c;并根据explain的结果相应的去调优SQL等。 …

LabVIEW中加载.NET 2.0,3.0和3.5程序集

LabVIEW中加载.NET 2.0,3.0和3.5程序集已使用.NETFramework 2.0,3.0或3.5创建了.NET程序集&#xff0c;但是当尝试在构造函数节点中加载这些程序集时&#xff0c;却收到LabVIEW消息显示: 所选文件不是.NET程序集&#xff0c;所属类型库或自动化可执行文件。所以想确认是否可以在…

多线程环境下的伪共享

今天和大家聊一聊伪共享 1.什么是伪共享&#xff1f; 缓存一致性协议在计算机中针对的最小单元&#xff1a;缓存行&#xff0c;每个缓存行的大小是64字节&#xff0c;一串连续的64字节数据都会存储到缓存行中。 假设数据A和数据B在同一缓存行中&#xff0c;CPU1修改了数据A&am…

你每天所做的工作,让你产生了成就感吗?

我们是为了什么而工作&#xff1f;金钱&#xff1f;理想&#xff1f;生活&#xff1f; 似乎这一切都没有标准答案&#xff0c;你自己问你自己&#xff0c;问问你自己&#xff0c;每天踏入公司&#xff0c;坐到工位面前&#xff0c;你最真实的感受是什么&#xff1f; “成就感…

OpenHarmony 3.2 Beta多媒体系列——视频录制

一、简介媒体子系统为开发者提供了媒体相关的很多功能&#xff0c;本文针对其中的视频录制功能做个详细的介绍。首先&#xff0c;我将通过媒体子系统提供的视频录制Test代码作为切入点&#xff0c;给大家梳理一下整个录制的流程。二、目录foundation/multimedia/camera_framewo…

今天面了个字节拿 38K 出来的测试,让我见识到了基础的天花板

前言 人人都有大厂梦&#xff0c;对于软件测试人员来说&#xff0c;BAT 为首的一线互联网公司肯定是自己的心仪对象&#xff0c;毕竟能到这些大厂工作&#xff0c;不仅薪资高待遇好&#xff0c;而且能力技术都能够得到提升&#xff0c;最关键的是还能够给自己镀上一层金&#…

webpack新手入门

前言&#xff1a; 如何配置webpack呢&#xff1f; webpack概念有哪些呢&#xff1f; 怎么快速理解并使用webpack呢&#xff1f; 文章目录一. 什么是webpack二. 安装webpack三. webpack的五个核心概念四. webpack配置五. loader加载器1. css处理2. 处理文件&#xff08;图片&…

内网渗透(十二)之内网信息收集-内网端口扫描和发现

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…

FOXCONN的第一天 记录 转型的前奏

2023年春&#xff0c;我来到美丽富饶的威海小城&#xff0c;开始了我的foxconn之旅&#xff0c;刚毕业那阵来过之后&#xff0c;再一次参与这个价值10个亿的项目&#xff0c;首先要致敬郭老板&#xff0c;好久不见。然后致敬一下曾经的工友们&#xff0c;再次致敬一下逝去的SAP…

2023年全国数据治理DAMA-CDGA/CDGP考试报名到弘博创新

弘博创新是DAMA中国授权的数据治理人才培养基地&#xff0c;贴合市场需求定制教学体系&#xff0c;采用行业资深名师授课&#xff0c;理论与实践案例相结合&#xff0c;快速全面提升个人/企业数据治理专业知识与实践经验&#xff0c;通过考试还能获得数据专业领域证书。 DAMA认…

分布式高级篇4 —— 商城业务(2)

一、订单服务1、订单基本概念2、订单基本构成3、订单状态4、订单流程5、配置拦截器拦截订单请求6、订单确认页模型抽取7、订单确认页vo封装8、Feign 远程调用请求头丢失问题\*\*\*\*\* 惨痛教训9、Feign 异步调用请求头丢失问题10、查看库存状态11、模拟计算运费12、接口幂等性…

智能优化算法——粒子群优化算法(PSO)(小白也能看懂)

前言&#xff1a; 暑假期间&#xff0c;因科研需要&#xff0c;经常在论文中看到各种优化算法&#xff0c;所以自己学习了一些智能优化的算法&#xff0c;做了一些相关的纸质性笔记&#xff0c;寒假一看感觉又有点遗忘了&#xff0c;并且笔记不方便随时查看&#xff0c;所以希…

受ChatGPT影响,唐磊数字签名照经和合国际提升100倍

如果有人问二十年前什么最火&#xff0c;相信很多人会说唐磊的《丁香花》&#xff0c;如果有人问去年什么最火&#xff0c;很多人会把目光投向袁树雄的《早安隆回》。这也充分说明一个问题&#xff0c;世间的万事万物&#xff0c;都不会永远火爆下去&#xff0c;总有一天会被新…

网络安全实验室4.注入关

4.注入关 1.最简单的SQL注入 url:http://lab1.xseclab.com/sqli2_3265b4852c13383560327d1c31550b60/index.php 查看源代码&#xff0c;登录名为admin 最简单的SQL注入&#xff0c;登录名写入一个常规的注入语句&#xff1a; admin’ or ‘1’1 密码随便填&#xff0c;验证…

社区人员管理系统项目测试

项目测试: 目录 项目测试: 项目分析 项目介绍 1.对项目进行冒烟测试 2.测试 2.1注册功能测试 2.1.1需求分析&#xff1a; 2.1.2 编写测试用例 2.2登录功能测试 2.2.1需求分析&#xff1a; 2.2.2 编写测试用例 2.3针对用户管理功能进项测试&#xff1a; 2.3.1需求…

如何预测机组设备健康状态?你可能需要这套解决方案

1. 应用场景随机振动[注1]会发生在工业物联网的各个场景中&#xff0c;包括产线机组设备的运行、运输设备的移动、试验仪器的运行等等。通过分析采集到的振动信号可以预估设备的疲劳年限、及时知晓设备已发生的异常以及预测未来仪器可能发生的异常等等。本篇教程会提供给有该方…

访问学者初到加拿大需要怎么做?

新报到的访问学者在刚刚到达加拿大的一段时间里由于环境陌生、语言障碍等会遇到一些问题。有的在解决住房问题上有不少困难&#xff0c;有的在与外国人打交道时有不少困惑。这些困难使有的学者在经济上和精神上吃了不少苦头。这也是最需要帮助的时候。我们希望这些信息能够帮助…

RocketMQ5.0.0消息存储<二>_消息存储流程

目录 一、消息存储概览 二、Broker接收消息 三、消息存储流程 1. DefaultMessageStore类 2. 存储流程 1)&#xff1a;同步与异步存储 2)&#xff1a;CommitLog异步存储消息 3)&#xff1a;提交消息&#xff08;Commit&#xff09; 四、参考资料 一、消息存储概览 如下图所…

【MySQL】MySQL 8.0 新特性之 - 公用表表达式(CTE)

MySQL 8.0 新特性之 - 公用表表达式&#xff08;CTE&#xff09;1. 公用表表达式&#xff08;CTE&#xff09; - WITH 介绍1.1 公用表表表达式1.1.1 什么是公用表表达式1.1.2 CTE 语法1.1.3 CTE示例1.3 递归 CTE1.3.1 递归 CTE 简介1.3.2 递归成员限制1.3.3 递归 CTE 示例1.3.4…