参考内容:
- 微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
- 微信官方demo:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
在正式敲代码之前,微信支付需要准备好应用id(appid)、appsecret、商户号(mchid)以及支付证书.
appid、appsecret在微信开放平台-管理中心-应用详情进行查看,appsecret可以重置.
mchid在微信开放平台-支付功能-已关联商户号进行查看.
支付证书则是在商户平台-账号中心-API安全进行下载.
- 先把官方demo下载下来
官方demo大概就是这些内容,其中也有对应的maven,先把这些文件复制到项目里 - 创建两个类PayAction和WXPayConfigImpl,对应代码如下
package com.solomo.sys.pay.wxpay;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSON;
import com.solomo.common.model.Orders;
import com.solomo.controller.orders.OrdersService;
import com.solomo.sys.DateUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class PayAction {
private static Logger logger = Logger.getLogger(PayAction.class);
/**
* app统一下单
* @return
* @throws Exception
*/
public static Map<String, String> pay(Map<String, String> datas) throws Exception {
String t = DateUtils.getNowTimeStamp().toString();
String timestamp = t.substring(0,t.length()-3);
Map<String, String> data = new HashMap<String, String>();
String notify_url = "http://192.168.0.107:8080/wakaka/orders/WXNotify";
String UTF8 = "UTF-8";
data.put("body", datas.get("body")); // 商品描述
data.put("out_trade_no", datas.get("out_trade_no")); // 商户订单号
data.put("device_info", "******"); // 设备号
data.put("total_fee", datas.get("total_fee")); // 总金额
data.put("mch_id", WXPayConfigImpl.getInstance().getMchID()); // 商户号
data.put("appid", WXPayConfigImpl.getInstance().getAppID()); // 应用ID
data.put("nonce_str", WXPayUtil.generateNonceStr()); // 随机字符串
data.put("fee_type", "CNY"); // 货币类型 CNY表示人民币
data.put("spbill_create_ip", "192.168.0.107"); // 终端IP
data.put("notify_url", notify_url); // 通知地址
data.put("trade_type", "APP"); // 此处指定为app支付
data.put("time_start", timestamp); // 交易起始时间
String sign = WXPayUtil.generateSignature(data, WXPayConfigImpl.getInstance().getKey());
data.put("sign", sign); // 签名
String reqBody = WXPayUtil.mapToXml(data);
boolean flag = WXPayUtil.isSignatureValid(data, WXPayConfigImpl.getInstance().getKey());
logger.debug("签名是否正确:"+flag);
URL httpUrl = new URL("https://api.mch.weixin.qq.com/pay/unifiedorder");
HttpURLConnection httpURLConnection = (HttpURLConnection) httpUrl.openConnection();
httpURLConnection.setRequestProperty("Host", "api.mch.weixin.qq.com");
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setConnectTimeout(10*1000);
httpURLConnection.setReadTimeout(10*1000);
httpURLConnection.connect();
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(reqBody.getBytes(UTF8));
//获取内容
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF8));
final StringBuffer stringBuffer = new StringBuffer();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
}
String resp = stringBuffer.toString();
if (stringBuffer!=null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream!=null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream!=null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
logger.debug(resp);
Map<String, String> result = WXPayUtil.xmlToMap(resp);
String code = result.get("return_code"); // 返回状态码
logger.debug(code);
Map<String, String> data2 = new HashMap<String, String>();
if( result.get("prepay_id") == null ){
result.put("result_code", "FAIL");
} else {
data2.put("appid", result.get("appid")); // 应用APPID
data2.put("partnerid", result.get("mch_id")); // 商户号
data2.put("prepayid", result.get("prepay_id")); // 预支付交易会话标识
data2.put("package", "Sign=WXPay");
data2.put("noncestr", result.get("nonce_str")); // 随机字符串
data2.put("timestamp", timestamp);
String secondSign = WXPayUtil.generateSignature(data2, WXPayConfigImpl.getInstance().getKey());
result.put("sign", secondSign);
result.put("timestamp", timestamp);
}
return result;
}
/**
* 接收微信支付成功通知
* @param request
* @param response
* @throws IOException
*/
public static String getNotify(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
System.out.println("微信支付回调");
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
String result = new String(outSteam.toByteArray(), "utf-8");
logger.debug("微信支付通知结果:" + result);
Map<String, String> map = null;
/**
* 解析微信通知返回的信息
*/
try {
map = WXPayUtil.xmlToMap(result);
} catch (Exception e) {
e.printStackTrace();
}
String notifyStr = null;
boolean flag = false;
try {
flag = WXPayUtil.isSignatureValid(map, WXPayConfigImpl.getInstance().getKey());
logger.debug("微信验证通知结果:"+flag);
if(!flag ){
notifyStr = WXPayUtil.setXML("FALSE", "FAIL");
return notifyStr;
}
} catch (Exception e) {
e.printStackTrace();
}
logger.debug("=========================================");
logger.info("微信支付:"+JSON.toJSONString(map));
logger.debug("=========================================");
// 若支付成功,则告知微信服务器收到通知
if (map.get("return_code").equals("SUCCESS")) {
//微信支付成功 开始业务处理
......
......
}else{
notifyStr = WXPayUtil.setXML("FALSE", "FAIL");
}
return notifyStr;
}
public static boolean orderQuery(String out_trade_no) throws Exception{
boolean flag = false;
WXPay wxpay;
WXPayConfig config;
config = WXPayConfigImpl.getInstance();
wxpay = new WXPay(config);
HashMap<String, String> map = new HashMap<String, String>();
map.put("out_trade_no", out_trade_no);
Map<String,String> result = wxpay.orderQuery(map);
System.out.println(JSON.toJSONString(result));
if( result.get("return_code").equals("SUCCESS")){
if(result.get("trade_state").equals("SUCCESS")){
flag = true;
}
}
return flag;
}
public static void main(String[] args) {
try {
orderQuery("32f8dfc373f848158804a29be008b058");
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.solomo.sys.pay.wxpay;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class WXPayConfigImpl extends WXPayConfig{
private byte[] certData;
private static WXPayConfigImpl INSTANCE;
private WXPayConfigImpl() throws Exception{
//微信支付证书
String certPath = "D://CERT/common/apiclient_cert.p12";
File file = new File(certPath);
InputStream certStream = new FileInputStream(file);
this.certData = new byte[(int) file.length()];
certStream.read(this.certData);
certStream.close();
}
public static WXPayConfigImpl getInstance() throws Exception{
if (INSTANCE == null) {
synchronized (WXPayConfigImpl.class) {
if (INSTANCE == null) {
INSTANCE = new WXPayConfigImpl();
}
}
}
return INSTANCE;
}
//appid
public String getAppID() {
return "***********************";
}
//商户id
public String getMchID() {
return "***********************";
}
//key
public String getKey() {
return "***********************";
}
public InputStream getCertStream() {
ByteArrayInputStream certBis;
certBis = new ByteArrayInputStream(this.certData);
return certBis;
}
public int getHttpConnectTimeoutMs() {
return 2000;
}
public int getHttpReadTimeoutMs() {
return 10000;
}
IWXPayDomain getWXPayDomain() {
return WXPayDomainSimpleImpl.instance();
}
public String getPrimaryDomain() {
return "api.mch.weixin.qq.com";
}
public String getAlternateDomain() {
return "api2.mch.weixin.qq.com";
}
@Override
public int getReportWorkerNum() {
return 1;
}
@Override
public int getReportBatchSize() {
return 2;
}
}
/**
* 微信支付结果异步通知
*/
public void WXNotify() {
String result = null;
try {
result = com.solomo.sys.pay.wxpay.PayAction.getnotify(getRequest(), getResponse());
} catch (IOException e) {
e.printStackTrace();
}
renderText(result);
return;
}
PayAction中主要是pay和getNotify这两个接口,pay方法中需要替换的有notify_url,对应的是第三段代码的路径;还有spbill_create_ip表示的是终端ip,需要修改成自己的ip,其他的如果需要修改可根据注释自行修改,WXPayConfigImpl中把最开始准备的信息放进去即可.
- 开始使用,代码如下
public void paymentExchange() throws Exception {
JSONObject jsonObject = new JSONObject();
String ordersId = getPara("ordersId");
String rewardId = getPara("rewardId");
String payType = getPara("payType"); // 支付类型 0微信支付 1支付宝支付
Orders orders = ordersService.findInfoById(ordersId);
orders.set("payType", payType).update();
Reward reward = rewardService.findInfoById(rewardId);
String content = "兑换"+reward.getStr("name");
double price = 0.01; // 默认价格单位:元
Map<String, String> data = new HashMap<String, String>();
data.put("body", content);
data.put("out_trade_no", orders.getStr("id"));
Map<String, String> map = new HashMap<String, String>();
if ("0".equals(payType)) { // 微信支付
String prices = price*100+"";
data.put("total_fee", prices.substring(0, prices.indexOf("."))); // 微信sdk中金额的默认单位是分
map = com.solomo.sys.pay.wxpay.PayAction.pay(data);
jsonObject.put("result", map);
} else { // 支付宝支付
data.put("total_fee", price+"");
AlipayTradeAppPayResponse response = com.solomo.sys.pay.alipay.PayAction.pay(data);
jsonObject.put("result", response.getBody());
}
String msg = map.get("return_code");
jsonObject.put("msg", msg);
jsonObject.put("code", 1);
renderJson(jsonObject.toJSONString());
return;
}
以金额和商品描述这两个参数直接调用即可,支付宝支付可查看:https://blog.csdn.net/weixin_43886319/article/details/94725850