700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > springboot实现微信小程序V3微信支付功能

springboot实现微信小程序V3微信支付功能

时间:2023-10-25 15:03:17

相关推荐

springboot实现微信小程序V3微信支付功能

springboot对接微信小程序V3微信支付功能(支付、退款、查询)

1. 程序开发前的准备工作,获取微信支付相关的参数1.1 在application.yml文件中填写配置信息1.2 获取配置文件中的参数 2. 在pom.xml中引入相关依赖3. 实现微信支付相关方法3.1 获取平台证书3.2 微信支付3.3 微信支付回调3.4 微信退款3.5 订单查询

1. 程序开发前的准备工作,获取微信支付相关的参数

appId:小程序appidappSecret:小程序的secretmchId:商户号keyPath:商户私钥路径(apiclient_key.pem)certPath:证书路径(apiclient_cert.pem)platFormPath:平台证书(cert.pem)

注 : 需要通过写程序生成平台证书(见v3Get()方法)apiKey3:apiv3密钥serialnumber:商户证书序列号notifyUrl:回调地址

注 : 回调地址需要是线上能访问到的地址,本地的地址是无效的

1.1 在application.yml文件中填写配置信息

# 微信支付pay:wechat:appId: xxxappSecret: xxxmchId: xxx# 商户私钥路径keyPath: D:\xx\xx\WxPay\apiclient_key.pem# 证书路径certPath: D:\xx\xx\\WxPay\apiclient_cert.pemplatFormPath: D:\xx\xx\\WxPay\cert.pem # 后续生成的平台证书路径# apiv3秘钥apiKey3: xxx# 商户证书序列号serialnumber: xxx# 回调地址notifyUrl: http://xxx:xx/wx/pay/payNotify # 线上地址

1.2 获取配置文件中的参数

/**微信小程序appid**/@Value("${pay.wechat.appId}")String appid;/**微信小程序secretId**/@Value("${pay.wechat.appSecret}")String secret;/**商户号**/@Value("${pay.wechat.mchId}")String mchid;/**商户密钥**/@Value("${pay.wechat.apiKey3}")String mchKey;/**回调地址**/@Value("${pay.wechat.notifyUrl}")String notifyUrl;/**证书地址**/@Value("${pay.wechat.certPath}")String certPath;/**证书密钥地址**/@Value("${pay.wechat.keyPath}")String certKeyPath;/**微信平台证书**/@Value("${pay.wechat.platFormPath}")String platFormPath;/**证书序列号**/@Value("${pay.wechat.serialnumber}")String serialNumber;

2. 在pom.xml中引入相关依赖

<!-- /artifact/com.github.javen205/IJPay-WxPay --><dependency><groupId>com.github.javen205</groupId><artifactId>IJPay-WxPay</artifactId><version>2.7.4</version></dependency><!-- /artifact/cn.hutool/hutool-core --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId><version>5.8.16</version></dependency><dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-apache-httpclient</artifactId><version>0.4.7</version></dependency>

3. 实现微信支付相关方法

3.1 获取平台证书

public String v3Get() {// 获取平台证书列表try {IJPayHttpResponse response = WxPayApi.v3(RequestMethod.GET,WxDomain.CHINA.toString(),WxApiType.GET_CERTIFICATES.toString(),mchid,serialNumber,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 ciphertextString 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();}}

3.2 微信支付

public String wxPay(String openId, String payId, int amount) {//商户订单号(随机字符串)// String orderSn = PayKit.generateStr();try {String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()// APPID.setAppid(appid)// 商户号.setMchid(mchid).setDescription("门票账单支付").setOut_trade_no(payId).setTime_expire(timeExpire).setNotify_url(notifyUrl).setAmount(new Amount().setTotal(amount)).setPayer(new Payer().setOpenid(openId));log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));IJPayHttpResponse response = WxPayApi.v3(RequestMethod.POST,WxDomain.CHINA.toString(),WxApiType.JS_API_PAY.toString(),mchid,serialNumber,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<String, String> map = WxPayKit.jsApiCreateSign(appid, prepayId, certKeyPath);log.info("唤起支付参数:{}", map);String jsonStr = JSONUtil.toJsonStr(map);return jsonStr;}} catch (Exception e) {e.printStackTrace();}return null;}

3.3 微信支付回调

public void payNotify(HttpServletRequest request, HttpServletResponse response) {Map<String, String> 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();}}

3.4 微信退款

public String payRefund(int amount, int qty, String outTradeNo, String outRefundNo) {log.info("进入退款接口------>" );log.info("执行操作的 原支付交易对应的商户订单号:{}", outTradeNo );try {// String outRefundNo = PayKit.generateStr();log.info("商户退款单号: {}", outRefundNo);List<RefundGoodsDetail> list = new ArrayList<>();RefundGoodsDetail refundGoodsDetail = new RefundGoodsDetail().setMerchant_goods_id(outRefundNo).setGoods_name("取消订单").setUnit_price(amount)//金额,单位为分.setRefund_amount(amount).setRefund_quantity(qty);list.add(refundGoodsDetail);RefundModel refundModel = new RefundModel().setOut_refund_no(outRefundNo).setReason("取消订单")//.setNotify_url(wechatPayV3Bean.getDomain().concat("/wechat/operation/pay/refundNotify")) //退款异步回调通知.setAmount(new RefundAmount().setRefund(1).setTotal(1).setCurrency("CNY")).setGoods_detail(list);if (outTradeNo != null && !outTradeNo.equals("")) {refundModel.setOut_trade_no( outTradeNo );}log.info("退款参数: {}", JSONUtil.toJsonStr(refundModel));IJPayHttpResponse response = WxPayApi.v3(RequestMethod.POST,WxDomain.CHINA.toString(),WxApiType.DOMESTIC_REFUNDS.toString(),mchid,serialNumber,null,certKeyPath,JSONUtil.toJsonStr(refundModel));log.info("退款响应 {}", response);// 根据证书序列号查询对应的证书来验证签名结果boolean verifySignature = WxPayKit.verifySignature(response, platFormPath);log.info("verifySignature: {}", verifySignature);String body = response.getBody();JSONObject jsonObject = JSONUtil.parseObj(body); //转换为JSONlog.info("响应数据:" + body);if(response.getStatus()==200){//退款成功,处理业务逻辑System.out.println("==================================");System.out.println("退款成功!");}if (verifySignature) {return response.getBody();}} catch (Exception e) {e.printStackTrace();return e.getMessage();}return null;}

3.5 订单查询

public String queryPayResult(String payId) throws Exception{WechatPayHttpClientBuilder builder = getWechatPayHttpClientBuilder();CloseableHttpClient httpClient = builder.build();String result = "";try {URIBuilder uriBuilder = new URIBuilder("https://api.mch./v3/pay/transactions/out-trade-no/"+ payId +"?mchid=" + mchid);HttpGet httpGet = new HttpGet(uriBuilder.build());httpGet.addHeader("Accept", "application/json");CloseableHttpResponse response = httpClient.execute(httpGet);result = EntityUtils.toString(response.getEntity());log.info("支付信息:" + result);JSONObject jsonObject = JSONUtil.parseObj(result);String code = jsonObject.getStr("trade_state");log.info("支付结果:" + code);} catch (Exception e) {e.printStackTrace();}return result;}private WechatPayHttpClientBuilder getWechatPayHttpClientBuilder() throws Exception{PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(certKeyPath));// 获取证书管理器实例CertificatesManager certificatesManager = CertificatesManager.getInstance();// 向证书管理器增加需要自动更新平台证书的商户信息certificatesManager.putMerchant(mchid, new WechatPay2Credentials(mchid,new PrivateKeySigner(serialNumber, merchantPrivateKey)), mchKey.getBytes(StandardCharsets.UTF_8));// ... 若有多个商户号,可继续调用putMerchant添加商户信息// 从证书管理器中获取verifierVerifier verifier = certificatesManager.getVerifier(mchid);X509Certificate certificate = verifier.getValidCertificate();List<X509Certificate> certificates = new ArrayList<>();certificates.add(certificate);WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create().withMerchant(mchid, serialNumber, merchantPrivateKey).withWechatPay(certificates);// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签return builder;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。