一.获取客户资料(百度很简单)
#1.微信支付API秘钥
appsecret: d1056292feb*******439f32a0179baf918
#2.微信商户ID
mchid: 1618****679
#3.微信小程序APPID
appid: wxe7c9b******1efff47
#4. 支付成功回调地址,如果是小程序可以不配置
notifyPath: ********
#5. 微信支付v3秘钥
apiV3Key: d105629*******4439f32a0179baf918
#6. 证书序列号
merchantSerialNumber: 391CCADC***********711035E85E9D68A67
#7.证书秘钥一个叫apiclient_key.pem文件(下载的证书里有这文件)
二.获取微信支付sdk
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.3.0</version>
</dependency>
三. 解析出来apiclient_key.pem文件中的证书秘钥备用
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(ResourceUtils.getFile("classpath:apiclient_key.pem")));
四.把获取客户资料放入yml文件里写个类注入方便使用
py:
info:
#微信支付网关
gateway: https:********
#微信支付API秘钥
appsecret: *********
#微信商户ID
mchid: *******
#微信小程序APPID
appid: *********
# 支付成功回调地址,如果是小程序可以不配置
notifyPath: **********
# 微信支付v3秘钥
apiV3Key: ****************
# 证书序列号
merchantSerialNumber: ****************
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@Data
@ConfigurationProperties(prefix = "wx.py.info")
public class WeiXinPayProperties {
private String gateway;
private String appsecret;
private String mchid;
private String appid;
private String notifyPath ;
private String apiV3Key ;
private String merchantSerialNumber ;
}
五.微信支付请求获取支付id
首先拿到自动装配好客户资料的类
@Autowired
WeiXinPayProperties DD;
写一个获取openid工具类
private String getOpenid(String code) throws ParseException, IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+DD.getAppid()+"&secret="+DD.getAppsecret()+"&js_code="+code+"&grant_type=authorization_code";
HttpGet get = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute(get);
String result = EntityUtils.toString(response.getEntity(), "utf-8");
JSONObject json = JSONObject.parseObject(result);
if(!json.containsKey("errcode")) {
String openid = json.getString("openid");
return openid;
}
return "";
}
最后请求微信服务器获取支付id(我也是醉了那么多代码只是为了获取调用微信支付所需要的支付id当然微信可能有其他考虑,但这样确实对新人不友好)封装成ResultInfo发给前端,让前端调用支付
@PostMapping("pay")
public ResultInfo<Object> pay(double totaFell , String code) throws IOException {
try {
//用户openid
JSONObject order=new JSONObject();
order.put("appid",DD.getAppid());
order.put("mchid",DD.getMchid());
order.put("description","买菜");//商品描述
order.put("out_trade_no",new DateTime().toString("yyyyMMddHHmmssSSS"));//s商户服系统内部订单号
order.put("notify_url ",DD.getNotifyPath());//通知地址
JSONObject amount=new JSONObject();//支付金额js 单位分
amount.put("total",(long)(totaFell*100));//转整型
amount.put("currency","CNY");//z支付金额的货币类型
order.put("amount",amount);
JSONObject payer =new JSONObject();//支付者
payer.put("openid","CNY");//z支付金额的货币类型
payer.put("openid", this.getOpenid(code));
order.put("payer", payer);
//文件流方式获取证书私钥
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(ResourceUtils.getFile("classpath:apiclient_key.pem")));
//不需要传入微信支付证书了 签名验证器
ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
new WechatPay2Credentials("商户号", new PrivateKeySigner("商户API证书序列号", merchantPrivateKey)),
"微信支付v3秘钥".getBytes("utf-8"));// Config.getWeixinMiniApiV3Key().getBytes("utf-8") 商户v3私钥
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant("商户号", "商户API证书序列号", merchantPrivateKey)//merchantPrivateKey 证书私钥
.withValidator(new WechatPay2Validator(verifier));//微信支付平台证书
HttpClient 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");
httpPost.setEntity(new StringEntity(order.toJSONString(), "UTF-8"));
// 后面跟使用Apache HttpClient一样
HttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());//这里的返回值包含了支付id
JSONObject bodyAsJSON = JSONObject.parseObject(bodyAsString);//把返回值转js备用
//判读下微信返回值是否正确
if(bodyAsJSON.containsKey("code")) {
return new ResultInfo(1, bodyAsJSON.getString("message"));
}
final String prepay_id = bodyAsJSON.getString("prepay_id");
final String timeStamp = String.valueOf(System.currentTimeMillis());
final String nonceStr = RandomStringGenerator.getRandomStringByLength(32);
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(DD.getAppid() + "\n");
stringBuffer.append(timeStamp + "\n");
stringBuffer.append(nonceStr + "\n");
stringBuffer.append("prepay_id="+prepay_id+"\n");
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(merchantPrivateKey);
signature.update(stringBuffer.toString().getBytes("UTF-8"));
byte[] signBytes = signature.sign();
String paySign = Base64.encodeBytes(signBytes);//工具类 网上找一下
JSONObject params = new JSONObject();
params.put("appId", DD.getAppid());
params.put("timeStamp", timeStamp);
params.put("nonceStr", nonceStr);
params.put("prepay_id", prepay_id);
params.put("signType", "RSA");
params.put("paySign", paySign);
return new ResultInfo<Object>(0, params);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
封装类ResultInfo
public class ResultInfo<T> {
private int code; // 0操作成功
private T data; // 返回的数据,正确的信息或错误描述信息
public ResultInfo(){
}
public ResultInfo(T data){
this.data = data;
}
public ResultInfo(int code, T data){
this.code = code;
this.data = data;
}
public int getCode() {
return code;
}
public ResultInfo<T> setCode(int code) {
this.code = code;
return this;
}
public T getData() {
return data;
}
public ResultInfo<T> setData(T data) {
this.data = data;
return this;
}
}
工具类Base64
工具类 网上找一下
工具类 RandomStringGenerator
import java.util.Random;
/**
* 随机字符串生成
* @author zuoliangzhu
*
*/
public class RandomStringGenerator {
/**
* 获取一定长度的随机字符串
* @param length 指定字符串长度
* @return 一定长度的字符串
*/
public static String getRandomStringByLength(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();
}
}
六,请求微信支付 我们的内网是不行的,微信服务器会拒绝访问,所以我们需要内网穿透,或者把项目部署在服务器上