Java开发笔记-小程序微信支付接入

步骤:

1.注册微信商户,开通小程序支付业务,获得必要接入参数。(Certificate、PrivateKey、merchantId、SerialNumbe、apiV3Key)

2.微信商户号关联小程序(需目标小程序审核)

3.java使用接入参数发起下单,获取下单参数。

4.小程序使用下单参数,调用微信支付,拉起微信支付。

5.客户支付完成后,java后台接收微信支付回调,完成最后的业务。

6.在商户平台下载微信支付账单与系统订单进行对账。

一、微信商户注册
注册地址

微信商户注册地址

通过上传企业信息,法人信息等,成为商户

开通小程序支付业务

产品中心--我的产品--JSAPI支付

merchantId获取

账户中心-商户信息-微信支付商户号

其他参数获取

Certificate、PrivateKey、SerialNumbe、apiV3Key参数获取:账户中心-API安全。具体步骤,在申请的时候官方会提醒的。

二、关联小程序

产品中心--AppID账号管理--关联APPID

三、发起下单

java使用接入参数发起下单,直接上代码

package com.ancun.netsign;import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;public class Test {private static final String appId="";private static final String merchantId="";private static final String merchantSerialNumber="";private static final String apiV3Key="";private static final String merchantPrivateKey="";public static void main(String[] args) throws Exception {payNomal();searchOrder();}public static void payNomal() throws Exception {PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(merchantPrivateKey.getBytes("utf-8")));PrivateKeySigner signer=new PrivateKeySigner(merchantSerialNumber, privateKey);byte[] bs=apiV3Key.getBytes(StandardCharsets.UTF_8);WechatPay2Credentials cred=new WechatPay2Credentials(merchantId, signer);ScheduledUpdateCertificatesVerifier   verifier = new ScheduledUpdateCertificatesVerifier(cred, bs);WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create();builder.withMerchant(merchantId, merchantSerialNumber, privateKey);builder.withValidator(new WechatPay2Validator(verifier));CloseableHttpClient httpClient = builder.build();HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");httpPost.addHeader("Accept", "application/json");httpPost.addHeader("Content-type","application/json; charset=utf-8");ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectMapper objectMapper = new ObjectMapper();ObjectNode rootNode = objectMapper.createObjectNode();rootNode.put("mchid",merchantId).put("appid", appId).put("description", "测试公司").put("notify_url", "http://回调地址").put("attach","自定义参数").put("out_trade_no", "订单id");rootNode.putObject("amount").put("total", 3);rootNode.putObject("payer").put("openid", "微信openid");objectMapper.writeValue(bos, rootNode);httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));CloseableHttpResponse response = httpClient.execute(httpPost);String bodyAsString = EntityUtils.toString(response.getEntity());JSONObject jo=JSONObject.parseObject(bodyAsString);System.out.println("prepay_id = " + jo.getString("prepay_id"));}public static void searchOrder() throws Exception {PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(merchantPrivateKey.getBytes("utf-8")));PrivateKeySigner signer=new PrivateKeySigner(merchantSerialNumber, privateKey);byte[] bs=apiV3Key.getBytes(StandardCharsets.UTF_8);WechatPay2Credentials cred=new WechatPay2Credentials(merchantId, signer);ScheduledUpdateCertificatesVerifier   verifier = new ScheduledUpdateCertificatesVerifier(cred, bs);WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create();builder.withMerchant(merchantId, merchantSerialNumber, privateKey);builder.withValidator(new WechatPay2Validator(verifier));CloseableHttpClient httpClient = builder.build();HttpGet httpget = new HttpGet("https://api.mch.weixin.qq.com/v3/pay/transactions/id/交易号?mchid=");httpget.addHeader("Accept", "application/json");httpget.addHeader("Content-type","application/json; charset=utf-8");CloseableHttpResponse response = httpClient.execute(httpget);String bodyAsString = EntityUtils.toString(response.getEntity());System.out.println(bodyAsString);JSONObject jo=JSONObject.parseObject(bodyAsString);System.out.println(jo);}}
下单接口返回:
{"prepay_id":"wx2310065247629669c55d9ec38dxxxxxx"}
//组装小程序需要的参数:packageInfo、NonceStr、AppId、PaySign、TimeStampString NonceStr= RandomUtil.enUuId();Long timeStamp = System.currentTimeMillis() / 1000;String packageInfo = "prepay_id=" + prepayId;CreateSign02 sign = new CreateSign02();String paySign = sign.getToken(appId, packageInfo, NonceStr, timeStamp, merchantPrivateKey);String signType="RSA"
package jnpf.utils;import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.util.Base64;public class CreateSign02 {public  String getToken(String appid,String prepay_id,String nonceStr,long timestamp,String privateKey) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException {//从下往上依次生成String message = buildMessage(appid, timestamp, nonceStr, prepay_id);//签名String signature = sign(message.getBytes("utf-8"),privateKey);return  signature;}String sign(byte[] message,String privateKey) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {//签名方式Signature sign = Signature.getInstance("SHA256withRSA");//私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名sign.initSign(MyPrivatekey.getPrivateKey(privateKey));sign.update(message);return Base64.getEncoder().encodeToString(sign.sign());}/***  按照前端签名文档规范进行排序,\n是换行* @param appid* @param timestamp* @param nonceStr* @param prepay_id* @return*/String buildMessage(String appid, long timestamp,String nonceStr,String prepay_id) {return appid + "\n"+ timestamp + "\n"+ nonceStr + "\n"+ prepay_id + "\n";}}
四、小程序拉起支付
//小程序拉起支付方法
uni.requestPayment({provider: 'wxpay',timeStamp: timeStamp,nonceStr: nonceStr,package: package,signType: signType,paySign: paySign,success: res => {//成功后的操作},fail: err => {},complete: () => {}})

效果

五、接收回调

业务代码就不贴了,直接上验签和解密代码

 private String checkSignAndDecrypt(HttpServletRequest request) throws Exception {StringBuffer xmlStr = new StringBuffer();BufferedReader reader = request.getReader();String line;while ((line = reader.readLine()) != null) {xmlStr.append(line);}//支付回调通知:// {// "id":"ff9ce7d0-6d60-520a-bb79-ba98aadaef58",// "create_time":"2022-01-26T10:07:46+08:00",// "resource_type":"encrypt-resource",// "event_type":"TRANSACTION.SUCCESS",// "summary":"支付成功",// "resource":{// "original_type":"transaction",// "algorithm":"AEAD_AES_256_GCM",// "ciphertext":"bHsdM/qkwb+dU0aani3s0TO+HzD4W0AbQ1TyOBL4VFKDN2IEJx9FPFWWpAwywi/5llfPkf4DoyMMc6KDSkVf3U1bk1y6rKcC+XTFg6jPpsMj/H9kqmrLTYXohtJ6PtmUijnJyEKtyjr7Z6scMEY0oRAAOMZlz3IxheXwNc1AO14zUohS3jppF7wS8lgasVTRiGnk8WRzGLyJTH7lo0bUKYtL2Asq9ARESZbDzJAUcfl8ywZTVFGIlItTXte4CT529cRl+oQtbOFXhlW4kRM7k1QVFhQ3I5FOX58+oPf5aOMaUTzh5HMbpxOAHNB6Yr0JR0QmX1qMwRbeaS45aWhd8BBYJPRFk2MuPalAK3oWqHHYTwa9lEHEJHofSRMZDdUVD3gCCEyzDJpeR0bmQlm1oxnkV4CzBQQeoPg/7Dn2VBUjyX2kKpdVMSdiCb7h1HGesl1BuFurcbZ6rayMfX1Nbq9a7C+oofGauKtdAY1tfQOkee2+NfWTKTc3cfwrWB90aYV2uV9G3tCXeD/XRS2VkXsXiU2UljeVnI1Qv7+9eHWtQDpboQ8q2G2pc4MalhXV2g==",// "associated_data":"transaction",// "nonce":"EzVTGRqlF6GM"// }// }log.info("支付回调通知接收的body参数:" + xmlStr);try {log.info("开始验签===========================");// 验签String Signature = request.getHeader("Wechatpay-Signature");String Serial = request.getHeader("Wechatpay-Serial");String Timestamp = request.getHeader("Wechatpay-Timestamp");String Nonce = request.getHeader("Wechatpay-Nonce");PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(pro.getMerchantPrivateKey().getBytes("utf-8")));//加载官方自动更新证书AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(//商户平台查看                            //不是API密钥new WechatPay2Credentials(pro.getMerchantId(), new PrivateKeySigner(pro.getMerchantSerialNumbe(), privateKey)), pro.getApiV3Key().getBytes("utf-8"));String s1 = xmlStr.toString();//按照文档要求拼接验签串String VerifySignature = Timestamp + "\n" + Nonce + "\n" + s1 + "\n";log.info("拼接后的验签串=" + VerifySignature);//使用官方验签工具进行验签boolean verify1 = verifier.verify(Serial, VerifySignature.getBytes(), Signature);log.info("验签结果=" + verify1);if (!verify1) {return "验签失败";}} catch (Exception e) {e.printStackTrace();}log.info("开始解密=========================");//解密JSONObject jo = JSONObject.parseObject(xmlStr.toString());JSONObject jodata = jo.getJSONObject("resource");String associated_data = jodata.getString("associated_data");String nonce = jodata.getString("nonce");String ciphertext = jodata.getString("ciphertext");AesUtil aesUtil = new AesUtil(pro.getApiV3Key().getBytes());String aes = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);log.info("解密结果=========================" + aes);return aes;}

回调方法定义:

  /*** 微信支付回调** @param request* @param response* @throws Exception*/@PostMapping(value = "/wxPayNotify")public String wxPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {log.info("进入微信支付回调");String aes="";try {WeCharPayProperties pro = new WeCharPayProperties();aes = this.checkSignAndDecrypt(pro, request);log.info("解密后参数:" + aes);if (aes.equals("验签失败")) {return "{" +'"' + "code" + '"' + ":" + '"' + "FAIL" + '"' + "," +'"' + "message" + '"' + ":" + '"' + "失败,验签失败" + '"' +"}";}//=============解析参数开始=======================================省略代码//============解析参数结束=======================================业务代码} catch (Exception e) {log.error("微信支付回调出错", e);}log.info("微信支付回调完成====================================================");return "{" +'"' + "code" + '"' + ":" + '"' + "SUCCESS" + '"' + "," +'"' + "message" + '"' + ":" + '"' + "成功" + '"' +"}";}

至此完成开发,后续的对账就不贴了。根据自己的业务进行对账。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式反模式:UML图示常见误用案例分析

第一章 引言 1.1 设计模式与反模式概述 在软件开发领域,设计模式与反模式是两种截然不同的概念,它们在软件设计过程中起着至关重要的作用。设计模式是经过验证的最佳实践,用于解决在特定上下文中经常出现的问题,从而提高软件的可…

使用分布式锁解决IM聊天数据重复插入的问题

导航 业务背景问题分析与定位探索可行的解决方案 数据库层面处理——唯一索引应用程序层面处理——分布式锁 分布式锁概述 分布式锁需要具备哪些特性?分布式锁有哪些实现方式? 基于数据库的实现方式基于Redisson实现方式 Redission介绍 概述可重入锁 基…

精彩!双疾病搭档孟德尔随机化,中国学者得出阴性结果照样拿下一区top!

孟德尔随机化分析领域,选题新才是王道!在之前孟德尔随机化的文章中,大多是分析暴露与疾病的关系,今天分享的这篇文章与之前不同,中国学者使用双向孟德尔随机化分析两种疾病之间的关联,还是阴性结果&#xf…

MinerU pdf文档解析markdown格式、内容提取

参考: https://github.com/opendatalab/MinerU/blob/master/README_zh-CN.md demo在线网址: https://opendatalab.com/OpenSourceTools/Extractor/PDF/detail

C语言高手参考手册:网络编程高级话题与技术细节

在上一篇文章中,我们介绍了基本的网络编程概念和操作。本文将深入探讨网络编程的一些高级话题和技术细节,包括错误处理、非阻塞I/O、多路复用(select/poll/epoll)、套接字选项以及安全编程等。 1. 错误处理 1.1 错误码 在处理网…

[数据集][目标检测]红外场景下车辆和行人检测数据集VOC+YOLO格式19069张4类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):19069 标注数量(xml文件个数):19069 标注数量(txt文件个数):19069 标…

基于B站的热门视频数据分析与情感分析【关联性、主题、情感分析】

目录 2 研究内容 2.1 主要研究内容 2.2 拟解决的关键问题 2.2.1热门视频特征的识别和提取 2.2.2情感分析与用户反馈 2.3技术路线 2.3.1数据收集 2.3.2数据预处理 2.3.3数据挖掘 2.3.4 数据可视化 2.4可行性分析 2.4.1技术可行性 2.4.2数据可行性 2.4.3经济可行性 2.5数据库设计…

[000-01-011].第2节:持久层方案的对比

我的后端学习大纲 MyBatis学习大纲 1.持久层解决方案: 1.1.面试1:请说一说持久层解决方案有哪些??? 1.jdbc JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。Java程序员使用JDB…

关于springboot的异常处理以及源码分析(一)

一、什么是异常处理 1、文档定义 首先我们先来看springboot官方对于异常处理的定义。springboot异常处理 在文档的描述中,我们首先可以看到的一个介绍如下: By default, Spring Boot provides an /error mapping that handles all errors in a sensib…

计算机网络-2-tcpip协议

1.说说 TCP/IP 四层模型? TCP/IP(Transmission Control Protocol/Internet Protocol)模型是一种用于描述互联网通信的协议层次结构。它分为四个主要层次,每个层次都定义了不同的协议来实现特定的功能。下面是TCP/IP模型各层的常用…

Android系统安全 — 1-OpenSSL支持的常用加解密算法介绍

常用加解密算法介绍 1. 哈希算法 常见的函数包含MD系列、SHA-1、SHA-2家族、SHA-3家族、SM3等。 1.1 MD5(单向散列算法) 全称是Message-Digest Algorithm 5(信息-摘要算法),经MD2、MD3和MD4发展而来。MD5算法的使用…

0基础学习Python路径(21)Python NameSpaceScope

命名空间定义了在某个作用域内变量名和绑定值之间的对应关系,命名空间是键值对的集合,变量名与值是一一对应关系。作用域定义了命名空间中的变量能够在多大范围内起作用。 命名空间在 Python 解释器中是以字典的形式存在的,是以一种可以看得…

【快速入门 LVGL】-- 1、STM32 工程移植 LVGL

目录 一、LVGL 简述 二、复制一个STM32工程 三、下载 LVGL 四、裁剪 源文件 五、工程添加 LVGL 文件 六、注册 显示 七、注册 触摸屏 八、LVGL 心跳、任务刷新 九、开跑 LVGL 十、控件的事件添加、响应处理 十 一、几个好玩小事情 十 二、显示中文 ~~ 约定 ~~ 在…

从【人工智能】到【计算机视觉】,【深度学习】引领的未来科技创新与变革

前几天偶然发现了一个超棒的人工智能学习网站,内容通俗易懂,讲解风趣幽默,简直让人欲罢不能。忍不住分享给大家,点击这里立刻跳转,开启你的AI学习之旅吧! 前言 – 人工智能教程https://www.captainbed.cn/l…

linux文件——用户缓冲区——概念深度探索、IO模拟实现

前言:本篇文章主要讲解文件缓冲区。 讲解的方式是通过抛出问题, 然后通过分析问题, 将缓冲区的概念与原理一步一步地讲解。同时, 本节内容在最后一部分还会带友友们模拟实现一下c语言的printf, fprintf接口&#xff0c…

跨境电商补单秘籍:Lazada、Shopeee、eBay、Wish等平台实战技巧

在跨境电商领域,Lazada、Shopee、eBay、Wish及速卖通等平台为商家提供了广阔的市场空间。为了有效扩大产品的曝光率和提升转化率,商家需充分利用平台活动及营销工具。平台活动不仅是获取流量的关键渠道,还能显著提升品牌知名度。此外&#xf…

Python画笔案例-006 绘制正多边形

1、绘制正多边形 通过 python 的turtle 库绘制一个正多边形的图案,如下图: 2、实现代码 绘制一个正多边形,关键两个因素,一个是边长,决定了图形的大小;另一个就是图形里每个角的角度,绘制多边形…

SSM健康生活博客小程序—计算机毕业设计源码23497

摘 要 本文设计了一种基于SSM框架的健康生活博客小程序,为人们提供了运动视频教学、博客信息分享,用户能够方便快捷地查看资讯、搜索健康方面的相关信息、还能发布个人生活博客等。健康生活博客小程序采取面对对象的开发模式进行软件的开发和硬体的架设&…

Python | Leetcode Python题解之第365题水壶问题

题目&#xff1a; 题解&#xff1a; class Solution:def canMeasureWater(self, x: int, y: int, z: int) -> bool:if x y < z:return Falseif x 0 or y 0:return z 0 or x y zreturn z % math.gcd(x, y) 0

opencv-python图像增强十一:图像强光逆光调整:

文章目录 一&#xff0c;简介&#xff1a;二&#xff0c;方案简述&#xff1a;三&#xff0c;算法实现步骤&#xff1a;3.1 获得图像的阴影区域&#xff1a;3.2 调整阴影区域的亮度和对比度 四&#xff1a;整体代码五&#xff0c;效果&#xff1a; 一&#xff0c;简介&#xff…