微信支付V3 小程序支付API Java版
Posted 俗人码农
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信支付V3 小程序支付API Java版相关的知识,希望对你有一定的参考价值。
本文目的:快速接通微信支付V3 无需关注细节,实现支付功能,修改配置即可调用
文章目录
接入准备
申请APPID,申请mchid,绑定APPID及mchid,设置APIV3密钥,下载并配置商户证书
微信支付流程整理(小程序版)
- 前端获取登录凭证(wx.login)
- 服务端换取用户openId(code2Session)
- 创建微信支付订单(/v3/pay/transactions/jsapi)
- 回调服务端
提示:以下是本篇文章正文内容,下面案例可供参考
一、导入微信支付扩展包
<!--微信支付-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.7</version>
</dependency>
二、微信支付工具类
1.签名工具类
代码如下(示例):
@Component
public class WxSignUtil
protected static final SecureRandom RANDOM = new SecureRandom();
/**
* 微信调起支付参数
* 返回参数如有不理解 请访问微信官方文档
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_4.shtml
*
* @param prepayId 微信下单返回的prepay_id
* @param appId 应用ID
* @param mch_id 商户号
* @param privateKey 私钥
* @return 当前调起支付所需的参数
* @throws Exception
*/
public static String WxAppPayTuneUp(String prepayId, String appId, String mch_id, String privateKey) throws Exception
if (StringUtils.isNotBlank(prepayId))
long timestamp = System.currentTimeMillis() / 1000;
String nonceStr = generateNonceStr();
//加载签名
String packageSign = sign(buildMessage(appId, timestamp, nonceStr, prepayId).getBytes(), privateKey);
JSONObject jsonObject = new JSONObject();
jsonObject.put("appId", appId);
jsonObject.put("prepayId", prepayId);
jsonObject.put("timeStamp", timestamp);
jsonObject.put("nonceStr", nonceStr);
jsonObject.put("package", "Sign=WXPay");
jsonObject.put("signType", "RSA");
jsonObject.put("sign", packageSign);
jsonObject.put("partnerId", mch_id);
return jsonObject.toJSONString();
return "";
public static String sign(byte[] message, String privateKey) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException
//签名方式
Signature sign = Signature.getInstance("SHA256withRSA");
//私钥
sign.initSign(PemUtil
.loadPrivateKey(privateKey));
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
//生成随机字符串 微信底层的方法,直接copy出来了
protected static String generateNonceStr()
char[] nonceChars = new char[32];
for (int index = 0; index < nonceChars.length; ++index)
nonceChars[index] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(RANDOM.nextInt("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".length()));
return new String(nonceChars);
/**
* 按照前端签名文档规范进行排序,\\n是换行
*
* @param appId appId
* @param timestamp 时间
* @param nonceStr 随机字符串
* @param prepay_id prepay_id
* @return
*/
public static String buildMessage(String appId, long timestamp, String nonceStr, String prepay_id)
return appId + "\\n"
+ timestamp + "\\n"
+ nonceStr + "\\n"
+ "prepay_id="+prepay_id + "\\n";
2.微信支付工具类
代码如下(示例):
@Slf4j
@Component
public class WxMiniPayUtils
public static CloseableHttpClient httpClient;
public static Verifier verifier;
/**
* 初始化 HttpClient
* @throws IOException
*/
public static void initWXPayClient() throws IOException
try
// 加载商户私钥(privateKey:私钥字符串)
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(微信支付私钥字符串);
// 也可使用证书 查询商户证书序列号
// X509Certificate wechatPayCert = PemUtil.loadCertificate(new ByteArrayInputStream(StaticVariable.WX_PAY_CERT.getBytes(StandardCharsets.UTF_8)));
// String serialNo = wechatPayCert.getSerialNumber().toString(16).toUpperCase();
String serialNo =微信支付商户证书序列号;
//merchantId:商户号,serialNo:商户证书序列号
// 获取证书管理器实例
CertificatesManager certificatesManager = CertificatesManager.getInstance();
// 向证书管理器增加需要自动更新平台证书的商户信息
certificatesManager.putMerchant(微信支付-商户号, new WechatPay2Credentials(微信支付-商户号,
new PrivateKeySigner(serialNo, merchantPrivateKey)), 微信支付-v3 密钥.getBytes(StandardCharsets.UTF_8));
// 从证书管理器中获取verifier
//版本>=0.4.0可使用 CertificatesManager.getVerifier(mchId) 得到的验签器替代默认的验签器。
// 它会定时下载和更新商户对应的微信支付平台证书 (默认下载间隔为UPDATE_INTERVAL_MINUTE)。
verifier = certificatesManager.getVerifier(微信支付-商户号);
//创建一个httpClient
httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(微信支付-商户号, serialNo, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier)).build();
catch (IOException e)
e.printStackTrace();
log.error("加载秘钥文件失败");
catch (GeneralSecurityException e)
e.printStackTrace();
log.error("获取平台证书失败");
catch (Exception e)
e.printStackTrace();
/**
* 关闭 HttpClient
* @throws IOException
*/
public static void closeWXClient() throws IOException
if (httpClient != null)
try
httpClient.close();
catch (IOException e)
e.printStackTrace();
/**
* 创建微信支付订单
* @param openId 用户唯一标识
* @param orderId 订单id
* @param amount 支付价格(单位分)
* @param description 订单说明
* @return
* @throws Exception
*/
public static String creatOrderJSAPI(String openId,String orderId,Integer amount,String description) throws Exception
try
initWXPayClient();
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");
String reqdata = ""
+ "\\"amount\\": "
+ "\\"total\\": "+amount+","
+ "\\"currency\\": \\"CNY\\""
+ ","
+ "\\"mchid\\": \\""+微信支付-商户号+"\\","
+ "\\"description\\": \\""+description+"\\","
+ "\\"notify_url\\": \\""+微信支付-回调地址+"\\","
+ "\\"payer\\": "
+ "\\"openid\\": \\""+openId+"\\"" + ","
+ "\\"out_trade_no\\": \\""+orderId+"\\","
+ "\\"goods_tag\\": \\"WXG\\","
+ "\\"appid\\": \\""+微信APPID+"\\"" + "";
httpPost.setEntity(new StringEntity(reqdata, "utf-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
return bodyAsString;
catch (Exception e)
e.printStackTrace();
log.error("创建微信支付订单失败");
finally
closeWXClient();
return "";
三、创建订单
代码如下(示例):
String response= WxMiniPayUtils.creatOrderJSAPI(用户openId, 订单id,订单金额,订单描述);
JSONObject jsonObject= JSONObject.fromObject(response);
if (jsonObject.containsKey("prepay_id"))
/**补充相关业务*/
创建微信支付订单,微信会返回 prepay_id (预下单id)用于前端调起支付
四、调起支付
前端通过prepay_id调起支付
五、支付回调
Controller代码如下(示例):
@ApiOperation(value = "微信支付回调", notes = "微信支付回调")
@PostMapping(value = "wxAppPayNotify.do")
public String wxAppPayNotify( @RequestHeader("Wechatpay-Serial") String wechatpaySerial,
@RequestHeader("Wechatpay-Signature") String wechatpaySignature,
@RequestHeader("Wechatpay-Timestamp") String wechatpayTimestamp,
@RequestHeader("Wechatpay-Nonce") String wechatpayNonce,
@RequestBody String callback) throws Exception
return Service.wxAppPayNotify(wechatpaySerial,wechatpaySignature,wechatpayTimestamp,wechatpayNonce,callback);
验签和解密并返回通知
Servicer代码如下(示例):
@Override
public String wxAppPayNotify(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String callback) throws Exception
//按照文档要求拼接验签串
String verifySignature = wechatpayTimestamp + "\\n"
+ wechatpayNonce + "\\n" + callback + "\\n";
//使用官方验签工具进行验签
boolean verify1 = WxMiniPayUtils.verifier.verify(wechatpaySerial, verifySignature.getBytes(), wechatpaySignature);
//判断验签的结果
if (!verify1)
//验签失败,应答接口
com.alibaba.fastjson.JSONObject jsonResponse = new com.alibaba.fastjson.JSONObject();
jsonResponse.put("code", "FAIL");
jsonResponse.put("message", "失败");
return jsonResponse.toString();
JSONObject parseObject = JSONObject.parseObject(callback);
if ("TRANSACTION.SUCCESS".equals(parseObject.getString("event_type"))
&& "encrypt-resource".equals(parseObject.getString("resource_type")))
//通知的类型,支付成功通知的类型为TRANSACTION.SUCCESS
//通知的资源数据类型,支付成功通知为encrypt-resource
JSONObject resourceJson = JSONObject.parseObject(parseObject.getString("resource"));
String associated_data = resourceJson.getString("associated_data");
String nonce = resourceJson.getString("nonce");
String ciphertext = resourceJson.getString("ciphertext");
//解密,如果这里报错,就一定是APIv3密钥错误
AesUtil aesUtil = new AesUtil(微信支付-v3 密钥.getBytes());
String resourceData = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
System.out.println("解密后=" + resourceData);
//dosomething 处理业务
JSONObject resource =JSONObject.fromObject(resourceData);
if (resource.containsKey("out_trade_no"))
/**支付成功,补充业务**/
JSONObject jsonResponse = new JSONObject();
jsonResponse.put("code", "SUCCESS");
jsonResponse.put("message", "成功");
return jsonResponse.toString();
总结
网上的微信支付V3 教程无需看太多 ,专注官方文档
参考文档:https://www.cnblogs.com/cchilei/p/16077207.html
https://blog.csdn.net/m0_59588838/article/details/127204694
微信支付--小程序版
最近应公司要求要做一个微信小程序支付功能,其实刚接到这个功能我心里是比较抵触滴。怎么说呢,如果涉及到资金的问题,应该都不是小问题。好了,废话不多说,先记录我在支付当中遇到的事情吧。
其实现在腾讯对小程序这一块已经很重视了,有完善的API开发文档,还有y用主流语言所编写的DEMO;只要按照demo修改一下一般都可以完成 DEMO下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1。
最开始花一天的时间把微信支付文档从头到尾看了一般,对支付有一个大概的映像,然后在慢慢研究demo中的代码。不难,但是编写中还是范了一些错了。
1、最普遍的错误应该会出现在签名哪儿(sign 第一次签名);提示”签名错误”;如果发现签名错误,先检查自己传递的值是否有问题,特别是商户密匙(在商户中有两个密匙 一个叫APIV3密匙,一个叫API密匙),这儿使用的是API密匙(切记,我就是在这儿调用了APIV3密匙,特别尴尬),签名的加密有MD5和HMAC-SHA256两中,一般默认的是MD5; 如果发现签名错误微信提供了签名验证:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
2、小程序的统一下单,交易的类型要是JSAPI,openid就是必须值了。
3、下单成功之后在使用小程序的支付APIwx.requestPayment(OBJECT)
支付的难点还是在于签名,一定要首先理解签名的方法。如果签名错误后续工作就没有办法了。
以上是关于微信支付V3 小程序支付API Java版的主要内容,如果未能解决你的问题,请参考以下文章