文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

springboot整合IJPay实现微信支付-V3---微信小程序

2023-09-23 16:16

关注

前言

微信支付适用于许多场合,如小程序、网页支付、但微信支付相对于其他支付方式略显麻烦,我们使用IJpay框架进行整合

一、IJpay是什么?

JPay 让支付触手可及,封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。

二、使用步骤

1.准备小程序必要信息

1.1 要在小程序端关联商户号

1.2在application.yml文件中配置相关信息

这是微信平台下载的证书

1.3导入IJpay依赖

                com.github.javen205            IJPay-WxPay            2.9.6        

2.具体操作

2.1新建控制器WxPayApiContoller

2.2控制器代码:

package cn.cnvp.web.api.wechart;import cn.cnvp.web.token.message.JsonResult;import cn.cnvp.web.utils.WxUtils;import cn.hutool.core.date.DatePattern;import cn.hutool.core.date.DateUtil;import cn.hutool.core.io.file.FileWriter;import cn.hutool.core.util.StrUtil;import cn.hutool.http.ContentType;import cn.hutool.http.HttpStatus;import cn.hutool.json.JSONArray;import cn.hutool.json.JSONObject;import cn.hutool.json.JSONUtil;import com.ijpay.core.IJPayHttpResponse;import com.ijpay.core.enums.RequestMethodEnum;import com.ijpay.core.kit.AesUtil;import com.ijpay.core.kit.HttpKit;import com.ijpay.core.kit.PayKit;import com.ijpay.core.kit.WxPayKit;import com.ijpay.core.utils.DateTimeZoneUtil;import com.ijpay.wxpay.WxPayApi;import com.ijpay.wxpay.enums.WxDomainEnum;import com.ijpay.wxpay.enums.v3.BasePayApiEnum;import com.ijpay.wxpay.enums.v3.OtherApiEnum;import com.ijpay.wxpay.model.v3.Amount;import com.ijpay.wxpay.model.v3.Payer;import com.ijpay.wxpay.model.v3.UnifiedOrderModel;import io.swagger.annotations.Api;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Scope;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.ByteArrayInputStream;import java.nio.charset.StandardCharsets;import java.security.cert.X509Certificate;import java.util.HashMap;import java.util.Map;@Slf4j@Api(tags = "微信支付控制器")@RestController@RequestMapping("/api/wx/pay/v1")@Scope("prototype")public class WxPayApiController {        @Value("${wechat.ma.appId}")    String appid;        @Value("${wechat.ma.secret}")    String secret;        @Value("${wechat.ma.mchid}")    String mchid;        @Value("${wechat.ma.mchKey}")    String mchKey;        @Value("${wechat.ma.notifyUrl}")    String notifyUrl;        @Value("${wechat.ma.certPath}")    String certPath;        @Value("${wechat.ma.certKeyPath}")    String certKeyPath;        @Value("${wechat.ma.platFormPath}")    String platFormPath;        @RequestMapping("/jsApiPay")    @ResponseBody    public JsonResult jsApiPay(@RequestParam(value = "openId", required = false, defaultValue = "o-_-itxuXeGW3O1cxJ7FXNmq8Wf8") String openId) {        try {            String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()                    // APPID                    .setAppid(appid)                    // 商户号                    .setMchid(mchid)                    .setDescription("IJPay 让支付触手可及")                    .setOut_trade_no(PayKit.generateStr())                    .setTime_expire(timeExpire)                    .setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX")                    .setNotify_url(notifyUrl)                    .setAmount(new Amount().setTotal(1))                    .setPayer(new Payer().setOpenid(openId));            log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));            IJPayHttpResponse response = WxPayApi.v3(                    RequestMethodEnum.POST,                    WxDomainEnum.CHINA.toString(),                    BasePayApiEnum.JS_API_PAY.toString(),                    mchid,                    getSerialNumber(),                    null,                    certKeyPath,                    JSONUtil.toJsonStr(unifiedOrderModel)            );            log.info("统一下单响应 {}", response);            // 根据证书序列号查询对应的证书来验证签名结果            boolean verifySignature = WxPayKit.verifySignature(response, platFormPath);            log.info("verifySignature: {}", verifySignature);            if (response.getStatus() == HttpStatus.HTTP_OK && verifySignature) {                String body = response.getBody();                JSONObject jsonObject = JSONUtil.parseObj(body);                String prepayId = jsonObject.getStr("prepay_id");                Map map = WxPayKit.jsApiCreateSign(appid, prepayId, certKeyPath);                log.info("唤起支付参数:{}", map);                return JsonResult.success("获取成功",JSONUtil.toJsonStr(map));            }        } catch (Exception e) {            e.printStackTrace();        }        return JsonResult.error("唤起失败");    }        @RequestMapping(value = "/payNotify", method = {org.springframework.web.bind.annotation.RequestMethod.POST, org.springframework.web.bind.annotation.RequestMethod.GET})    public void payNotify(HttpServletRequest request, HttpServletResponse response) {        Map map = new HashMap<>(12);        try {            String timestamp = request.getHeader("Wechatpay-Timestamp");            String nonce = request.getHeader("Wechatpay-Nonce");            String serialNo = request.getHeader("Wechatpay-Serial");            String signature = request.getHeader("Wechatpay-Signature");            log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);            String result = HttpKit.readData(request);            log.info("支付通知密文 {}", result);            // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号            String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp,                    mchKey, platFormPath);            log.info("支付通知明文 {}", plainText);            if (StrUtil.isNotEmpty(plainText)) {                response.setStatus(200);                map.put("code", "SUCCESS");                map.put("message", "SUCCESS");            } else {                response.setStatus(500);                map.put("code", "ERROR");                map.put("message", "签名错误");            }            response.setHeader("Content-type", ContentType.JSON.toString());            response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));            response.flushBuffer();        } catch (Exception e) {            e.printStackTrace();        }    }    private String getSerialNumber() {        // 获取证书序列号        X509Certificate certificate = PayKit.getCertificate(certPath);        if (null != certificate) {            String serialNo = certificate.getSerialNumber().toString(16).toUpperCase();            // 提前两天检查证书是否有效            boolean isValid = PayKit.checkCertificateIsValid(certificate, mchid, -2);            log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN));            System.out.println("serialNo:" + serialNo);            return serialNo;        }        return null;    }    @RequestMapping("/get")    @ResponseBody    public String v3Get() {        // 获取平台证书列表        try {            IJPayHttpResponse response = WxPayApi.v3(                    RequestMethodEnum.GET,                    WxDomainEnum.CHINA.toString(),                    OtherApiEnum.GET_CERTIFICATES.toString(),                    mchid,                    getSerialNumber(),                    null,                    certKeyPath,                    ""            );            String serialNumber = response.getHeader("Wechatpay-Serial");            String body = response.getBody();            int status = response.getStatus();            log.info("serialNumber: {}", serialNumber);            log.info("status: {}", status);            log.info("body: {}", body);            int isOk = 200;            if (status == isOk) {                JSONObject jsonObject = JSONUtil.parseObj(body);                JSONArray dataArray = jsonObject.getJSONArray("data");                // 默认认为只有一个平台证书                JSONObject encryptObject = dataArray.getJSONObject(0);                JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");                String associatedData = encryptCertificate.getStr("associated_data");                String cipherText = encryptCertificate.getStr("ciphertext");                String nonce = encryptCertificate.getStr("nonce");                String serialNo = encryptObject.getStr("serial_no");                final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, platFormPath);                log.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo);            }            // 根据证书序列号查询对应的证书来验证签名结果            boolean verifySignature = WxPayKit.verifySignature(response, platFormPath);            System.out.println("verifySignature:" + verifySignature);            return body;        } catch (Exception e) {            e.printStackTrace();            return null;        }    }        private String savePlatformCert(String associatedData, String nonce, String cipherText, String certPath) {        try {            AesUtil aesUtil = new AesUtil(mchKey.getBytes(StandardCharsets.UTF_8));            // 平台证书密文解密            // encrypt_certificate 中的  associated_data nonce  ciphertext            String publicKey = aesUtil.decryptToString(                    associatedData.getBytes(StandardCharsets.UTF_8),                    nonce.getBytes(StandardCharsets.UTF_8),                    cipherText            );            // 保存证书            cn.hutool.core.io.file.FileWriter writer = new FileWriter(certPath);            writer.write(publicKey);            // 获取平台证书序列号            X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));            return certificate.getSerialNumber().toString(16).toUpperCase();        } catch (Exception e) {            e.printStackTrace();            return e.getMessage();        }    }}

2.3下载平台证书platForm.pem

调用上面get方法下载证书下载完成后会在yml配置的路径生成platForm.pem证书

2.4启动测试

接口传入openID(后续可换其他方式),返回如下json字符串表示成功

2.5小程序唤起微信支付

2.5.1uniapp代码

2.6异步回调

在yml配置的异步回调地址(需要外网访问)

总结

以上就是今天要讲的内容,本文仅仅简单介绍了springboot整合IJpay进行微信支付的使用,关于调用支付jspi缺少参数:total_fee主要是因为1.金额为空 2.订单号重复 3.订单号为空

来源地址:https://blog.csdn.net/qq_37612049/article/details/129589510

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯