重庆网站建设公司下载,火车头采集wordpress,呼和浩特企业网站排名优化,图案设计网站推荐一、需要准备的资料 1.小程序AppID 如#xff1a;wx2e56f5****** 2.商户号 如#xff1a;1641****** 3.商户API私钥路径#xff1a;什么是商户API证书#xff1f;如何获取商户API证书#xff1f; 获取文件如下图#xff1a; 如#xff1a; 本地路径#xff1a;E:\Env\e…一、需要准备的资料 1.小程序AppID 如wx2e56f5****** 2.商户号 如1641****** 3.商户API私钥路径什么是商户API证书如何获取商户API证书 获取文件如下图 如 本地路径E:\Env\eladmin\cert\c2\apiclient_key.pem本地部署写入绝对路径 服务器路径/data/cert/eladmin/c2/apiclient_key.pem服务器写入相对路径 4.商户证书序列号登录商户平台【API安全】-【API证书】-【查看证书】可查看商户API证书序列号。 如4F24D009CDBC89A********************** 5.商户APIV3密钥API v3密钥 - 通用规则 | 微信支付商户文档中心 如tYsmXJrIr***************** 【商户平台】-【账户中心】-【API安全】的页面设置该密钥请求才能通过微信支付的签名校验。密钥的长度为32个字节。 6.商户平台证书路径 如 本地路径E:\Env\eladmin\cert\c2\apiclient_cert.pem本地部署写入绝对路径 服务器路径/data/cert/eladmin/c2/apiclient_cert.pem服务器写入相对路径 7.商户平台证书路径p12 如 本地路径E:\Env\eladmin\cert\c2\apiclient_cert.p12本地部署写入绝对路径 服务器路径/data/cert/eladmin/c2/apiclient_cert.p12服务器写入相对路径
二、代码部分
1.pom.xml内加入微信支付扩展
!-- 微信支付 --dependencygroupIdcom.github.wechatpay-apiv3/groupIdartifactIdwechatpay-java/artifactIdversion0.2.7/version/dependency
2.在resources的dev和prod内加入微信支付必填字段#微信支付字段
wx:merchantId: 164*******privateKeyPath: E:\Env\eladmin\cert\c2\apiclient_key.pemcertPath: E:\Env\eladmin\cert\c2\apiclient_cert.pemcertP12Path: E:\Env\eladmin\cert\c2\apiclient_cert.p12merchantSerialNumber: 4F24D009CDBC**********************apiV3key: tYsmXJr******************appId: wx2e56f5******
3.微信支付测试接口3-1测试下单接口/api/weChatPay/ceshiJSAPI3-2测试微信支付结果回调地址当微信支付后微信方返回支付信息在回调接口内触发业务逻辑注测试回调接口必须为线上接口线下无法实现可先在线上将微信返回数据打印到txt文件内然后在本地测试回调接口触发业务逻辑/api/weChatPay/ceshiPayNotify放入线上的测试回调接口/api/weChatPay/payNotify本地测试回调接口--可在postman内测试测试时在Headers内Wechatpay-Serial、Wechatpay-Nonce、Wechatpay-Timestamp、Wechatpay-Signature必填上微信返回的json直接放入raw-json内进行测试4.退款测试接口/api/weChatPay/ceshiRefund回调接口不是必填项可用可不用
WeChatPayService.java:可放在Service内
----------------------------------------------------package me.zhengjie.modules.api.service;import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Random;Service
RequiredArgsConstructor
public class WeChatPayService {/** 商户API私钥路径 */Value(${wx.privateKeyPath}) //可自己写死路径public String privateKeyPath;//生成签名开始/*** 作用使用字段appId、timeStamp、nonceStr、package计算得出的签名值* 场景根据微信统一下单接口返回的 prepay_id 生成调启支付所需的签名值* param appId* param timestamp* param nonceStr* param pack package* return* throws Exception*/public String getSign(String appId, long timestamp, String nonceStr, String pack) throws Exception{String message buildMessage(appId, timestamp, nonceStr, pack);String paySign sign(message.getBytes(utf-8));return paySign;}private String buildMessage(String appId, long timestamp, String nonceStr, String pack) {return appId \n timestamp \n nonceStr \n pack \n;}private String sign(byte[] message) throws Exception{Signature sign Signature.getInstance(SHA256withRSA);//这里需要一个PrivateKey类型的参数就是商户的私钥。sign.initSign(getPrivateKey(privateKeyPath));sign.update(message);return Base64.getEncoder().encodeToString(sign.sign());}/*** 获取私钥。** param filename 私钥文件路径 (required)* return 私钥对象*/public static PrivateKey getPrivateKey(String filename) throws IOException {String content new String(Files.readAllBytes(Paths.get(filename)), utf-8);try {String privateKey content.replace(-----BEGIN PRIVATE KEY-----, ).replace(-----END PRIVATE KEY-----, ).replaceAll(\\s, );KeyFactory kf KeyFactory.getInstance(RSA);return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));} catch (NoSuchAlgorithmException e) {throw new RuntimeException(当前Java环境不支持RSA, e);} catch (InvalidKeySpecException e) {throw new RuntimeException(无效的密钥格式);}}/*** 获取随机位数的字符串* param length* return*/public static String getRandomString(int length) {String base abcdefghijklmnopqrstuvwxyz0123456789;Random random new Random();StringBuffer sb new StringBuffer();for (int i 0; i length; i) {int number random.nextInt(base.length());sb.append(base.charAt(number));}return sb.toString();}//生成签名结束/*** 获取请求文体* param request* return* throws IOException*/public static String getRequestBody(HttpServletRequest request) throws IOException {ServletInputStream stream null;BufferedReader reader null;StringBuffer sb new StringBuffer();try {stream request.getInputStream();// 获取响应reader new BufferedReader(new InputStreamReader(stream));String line;while ((line reader.readLine()) ! null) {sb.append(line);}} catch (IOException e) {throw new IOException(读取返回支付接口数据流出现异常);} finally {reader.close();}return sb.toString();}
}Controller代码如下package me.zhengjie.modules.api.rest;import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.annotation.Log;
import me.zhengjie.config.FileProperties;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.api.service.WeChatPayService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;Slf4j
RestController
RequiredArgsConstructor
Api(tags 1.微信小程序)
RequestMapping(/api/weChatPay)
public class WeChatPayContoller {private final WeChatPayService weChatPayService;private final FileProperties fileProperties;/*** appID*/Value(${wx.appId}) // 可自己写死--我引用的是自己写的配置内写死的方式如appIdwx12345678910public String appId;/*** 商户号*/Value(${wx.merchantId}) // 可自己写死public String merchantId;/*** 商户API私钥路径*/Value(${wx.privateKeyPath}) //可自己写死public String privateKeyPath;/*** 商户证书序列号*/Value(${wx.merchantSerialNumber}) // 可自己写死public String merchantSerialNumber;/*** 商户APIV3密钥*/Value(${wx.apiV3key}) //可自己写死public String apiV3key;/*** 商户平台证书路径*/Value(${wx.certPath}) // 可自己写死public String certPath;/*** 商户平台证书路径p12*/Value(${wx.certP12Path}) //可自己写死public String certP12Path;private static MapString, Config configMap new HashMap();private static Config config null;private static JsapiService service null;private static RefundService refundService null;/*** JSAPI 测试下单接口*/PostMapping(value /ceshiJSAPI)Log(JSAPI 测试下单接口)ApiOperation(JSAPI 测试下单接口)AnonymousAccessTransactional(rollbackFor Exception.class)public JSONObject ceshiJSAPI() throws Exception {if (config null) {config new RSAAutoCertificateConfig.Builder().merchantId(merchantId).privateKeyFromPath(privateKeyPath).merchantSerialNumber(merchantSerialNumber).apiV3Key(apiV3key).build();}if (service null) {service new JsapiService.Builder().config(config).build();}// request.setXxx(val)设置所需参数具体参数可见Request定义PrepayRequest request new PrepayRequest();Amount amount new Amount();amount.setTotal(1);//金额1为0.01元request.setAmount(amount);request.setAppid(appId);request.setMchid(merchantId);request.setDescription(测试商品标题);//下单标题request.setNotifyUrl(https://www.ceshi123.com/api/weChatPay/ceshiPayNotify);//要求必须为线上接口String ddh weChatPayService.getRandomString(20);request.setOutTradeNo(ddh);//订单号Payer payer new Payer();payer.setOpenid(oMr**********);//openidrequest.setPayer(payer);PrepayResponse response service.prepay(request);JSONObject result new JSONObject();Long date new Date().getTime();//获取当前时间戳String nonceStr weChatPayService.getRandomString(28);//随机字符串长度为32个字符以下result.put(timeStamp, date.toString());//时间戳result.put(nonceStr, nonceStr);//随机字符串长度为32个字符以下result.put(package, prepay_id response.getPrepayId());//PrepayIdresult.put(signType, RSA);//签名类型result.put(paySign, weChatPayService.getSign(appId, date, nonceStr, prepay_id response.getPrepayId()));//签名return result;}/*** 测试微信支付结果回调地址放入线上测试** param*/PostMapping(value /ceshiPayNotify)Log(ceshiPayNotify方法)ApiOperation(ceshiPayNotify方法)AnonymousAccesspublic void ceshi_payNotify(HttpServletRequest request) throws IOException {//微信返回的证书序列号String serialNo request.getHeader(Wechatpay-Serial);//微信返回的随机字符串String nonceStr request.getHeader(Wechatpay-Nonce);//微信返回的时间戳String timestamp request.getHeader(Wechatpay-Timestamp);//微信返回的签名String wechatSign request.getHeader(Wechatpay-Signature);String singType request.getHeader(Wechatpay-Signature-Type);String collect request.getReader().lines().collect(Collectors.joining());try {FileUtil.writeUtf8String(collect, fileProperties.getPath().getPath() /huidiao-collect.txt);//打印看效果FileUtil.writeUtf8String(serialNo, fileProperties.getPath().getPath() /huidiao-serialNo.txt);//打印看效果FileUtil.writeUtf8String(singType, fileProperties.getPath().getPath() /huidiao-Signature-Type.txt);//打印看效果FileUtil.writeUtf8String(nonceStr, fileProperties.getPath().getPath() /huidiao-nonceStr.txt);//打印看效果FileUtil.writeUtf8String(timestamp, fileProperties.getPath().getPath() /huidiao-timestamp.txt);//打印看效果FileUtil.writeUtf8String(wechatSign, fileProperties.getPath().getPath() /huidiao-wechatSign.txt);//打印看效果//TODO 业务校验---可以写入自己的业务逻辑} catch (Exception e) {System.out.println(e e);FileUtil.writeUtf8String(22222222222222222222, fileProperties.getPath().getPath() /huidiao22.txt);//打印看效果}}/*** 微信支付结果回调地址(本地** param request* return*/PostMapping(value /payNotify)AnonymousAccessTransactional(rollbackFor Exception.class)public ResponseEntityObject wxCallback(HttpServletRequest request) throws Exception {//获取报文String body weChatPayService.getRequestBody(request);//随机串String nonce request.getHeader(Wechatpay-Nonce);//微信传递过来的签名String signature request.getHeader(Wechatpay-Signature);//证书序列号微信平台String wechatPaySerial request.getHeader(Wechatpay-Serial);String singType request.getHeader(Wechatpay-Signature-Type);//时间戳String timestamp request.getHeader(Wechatpay-Timestamp);if (configMap.get(config) null) {config new RSAAutoCertificateConfig.Builder().merchantId(merchantId).privateKeyFromPath(privateKeyPath).merchantSerialNumber(merchantSerialNumber).apiV3Key(apiV3key).build();configMap.put(config, config);}else {config configMap.get(config);}NotificationParser parser new NotificationParser((NotificationConfig) config);RequestParam.Builder builder new RequestParam.Builder();builder.body(body);builder.signature(signature);builder.nonce(nonce);builder.timestamp(timestamp);builder.serialNumber(wechatPaySerial);builder.signType(singType);RequestParam requestParam builder.build();Transaction parse parser.parse(requestParam, Transaction.class);if (SUCCESS.equals(parse.getTradeState().toString())) {//支付成功你的业务逻辑return new ResponseEntity(HttpStatus.OK);} else {throw new BadRequestException( 支付失败);}}/** 测试退款申请* return*/PostMapping(value /ceshiRefund)Log(JSAPI 测试退款接口)ApiOperation(JSAPI 测试退款接口)AnonymousAccessTransactional(rollbackFor Exception.class)public JSONObject ceshiRefund(String No) throws Exception {if (config null) {config new RSAAutoCertificateConfig.Builder().merchantId(merchantId).privateKeyFromPath(privateKeyPath).merchantSerialNumber(merchantSerialNumber).apiV3Key(apiV3key).build();}if (refundService null) {// 初始化服务refundService new RefundService.Builder().config(config).build();}CreateRequest request new CreateRequest();request.setOutTradeNo(No);//商户订单号request.setOutRefundNo(weChatPayService.getRandomString(16));//商户退款单号随机生成request.setReason(取消订单的退款);//退款原因AmountReq amount new AmountReq();//金额信息amount.setRefund(Long.parseLong(1));//退款金额0.01元amount.setTotal(Long.parseLong(1));//原订单退款金额0.01元amount.setCurrency(CNY);//人民币request.setAmount(amount);// request.setNotifyUrl(https://https://www.ceshi123.com/api/weChatPay/ceshiRefundNotify);//回调接口退款时非必填--这里我就没写接口JSONObject result new JSONObject();try {Refund response refundService.create(request);result.put(code, SUCCESS);result.put(message, 退款成功);return result;} catch (ServiceException e) { // 服务返回状态小于200或大于等于300例如500// 调用e.getResponseBody()获取返回体打印日志或上报监控更多方法见ServiceException定义return JSONObject.parseObject(e.getResponseBody());}}}
文章转载自: http://www.morning.gswfs.cn.gov.cn.gswfs.cn http://www.morning.ckxd.cn.gov.cn.ckxd.cn http://www.morning.knsmh.cn.gov.cn.knsmh.cn http://www.morning.dfkmz.cn.gov.cn.dfkmz.cn http://www.morning.sgwr.cn.gov.cn.sgwr.cn http://www.morning.fhwfk.cn.gov.cn.fhwfk.cn http://www.morning.cthrb.cn.gov.cn.cthrb.cn http://www.morning.wmnpm.cn.gov.cn.wmnpm.cn http://www.morning.qkqpy.cn.gov.cn.qkqpy.cn http://www.morning.wrlxt.cn.gov.cn.wrlxt.cn http://www.morning.tqqfj.cn.gov.cn.tqqfj.cn http://www.morning.mhlsx.cn.gov.cn.mhlsx.cn http://www.morning.gjcdr.cn.gov.cn.gjcdr.cn http://www.morning.bsjpd.cn.gov.cn.bsjpd.cn http://www.morning.rxzcl.cn.gov.cn.rxzcl.cn http://www.morning.blfgh.cn.gov.cn.blfgh.cn http://www.morning.xrksf.cn.gov.cn.xrksf.cn http://www.morning.nzxdz.cn.gov.cn.nzxdz.cn http://www.morning.pccqr.cn.gov.cn.pccqr.cn http://www.morning.yprnp.cn.gov.cn.yprnp.cn http://www.morning.gmztd.cn.gov.cn.gmztd.cn http://www.morning.sgrdp.cn.gov.cn.sgrdp.cn http://www.morning.lsnhs.cn.gov.cn.lsnhs.cn http://www.morning.qrmyd.cn.gov.cn.qrmyd.cn http://www.morning.wpspf.cn.gov.cn.wpspf.cn http://www.morning.ptdzm.cn.gov.cn.ptdzm.cn http://www.morning.gyjld.cn.gov.cn.gyjld.cn http://www.morning.sxjmz.cn.gov.cn.sxjmz.cn http://www.morning.rfgc.cn.gov.cn.rfgc.cn http://www.morning.bynf.cn.gov.cn.bynf.cn http://www.morning.gwmny.cn.gov.cn.gwmny.cn http://www.morning.sbjbs.cn.gov.cn.sbjbs.cn http://www.morning.ryxgk.cn.gov.cn.ryxgk.cn http://www.morning.zqzhd.cn.gov.cn.zqzhd.cn http://www.morning.qzsmz.cn.gov.cn.qzsmz.cn http://www.morning.zlrrj.cn.gov.cn.zlrrj.cn http://www.morning.fqtzn.cn.gov.cn.fqtzn.cn http://www.morning.jsrnf.cn.gov.cn.jsrnf.cn http://www.morning.thzwj.cn.gov.cn.thzwj.cn http://www.morning.dwmtk.cn.gov.cn.dwmtk.cn http://www.morning.ktlxk.cn.gov.cn.ktlxk.cn http://www.morning.rpkl.cn.gov.cn.rpkl.cn http://www.morning.gfnsh.cn.gov.cn.gfnsh.cn http://www.morning.qwdlj.cn.gov.cn.qwdlj.cn http://www.morning.clbgy.cn.gov.cn.clbgy.cn http://www.morning.yrcxg.cn.gov.cn.yrcxg.cn http://www.morning.sgbsr.cn.gov.cn.sgbsr.cn http://www.morning.qhydkj.com.gov.cn.qhydkj.com http://www.morning.hkshy.cn.gov.cn.hkshy.cn http://www.morning.qggm.cn.gov.cn.qggm.cn http://www.morning.lxyyp.cn.gov.cn.lxyyp.cn http://www.morning.kjmcq.cn.gov.cn.kjmcq.cn http://www.morning.gnfkl.cn.gov.cn.gnfkl.cn http://www.morning.cdlewan.com.gov.cn.cdlewan.com http://www.morning.hnrls.cn.gov.cn.hnrls.cn http://www.morning.lwlnw.cn.gov.cn.lwlnw.cn http://www.morning.mhxlb.cn.gov.cn.mhxlb.cn http://www.morning.lhhdy.cn.gov.cn.lhhdy.cn http://www.morning.wtsr.cn.gov.cn.wtsr.cn http://www.morning.qyhcm.cn.gov.cn.qyhcm.cn http://www.morning.glwyn.cn.gov.cn.glwyn.cn http://www.morning.sxlrg.cn.gov.cn.sxlrg.cn http://www.morning.fhbhr.cn.gov.cn.fhbhr.cn http://www.morning.tbzcl.cn.gov.cn.tbzcl.cn http://www.morning.hrnrx.cn.gov.cn.hrnrx.cn http://www.morning.hypng.cn.gov.cn.hypng.cn http://www.morning.brcdf.cn.gov.cn.brcdf.cn http://www.morning.mfcbk.cn.gov.cn.mfcbk.cn http://www.morning.mwnch.cn.gov.cn.mwnch.cn http://www.morning.qxmys.cn.gov.cn.qxmys.cn http://www.morning.wpcfm.cn.gov.cn.wpcfm.cn http://www.morning.fddfn.cn.gov.cn.fddfn.cn http://www.morning.srkqs.cn.gov.cn.srkqs.cn http://www.morning.lnsnyc.com.gov.cn.lnsnyc.com http://www.morning.fnpyk.cn.gov.cn.fnpyk.cn http://www.morning.mnyzz.cn.gov.cn.mnyzz.cn http://www.morning.srjgz.cn.gov.cn.srjgz.cn http://www.morning.lgznc.cn.gov.cn.lgznc.cn http://www.morning.gtxrw.cn.gov.cn.gtxrw.cn http://www.morning.rqkk.cn.gov.cn.rqkk.cn