前言
記錄一下支付功能的一些方法, 僅供學習參考,不涉及商業內容,一些基本環境先說一下,後面就不再說了
jdk1.8 springBoot2.0 maven
微信支付對接流程
使用微信沙箱做演示
首先要登錄微信開放平臺-資源中心-開放平臺改爲選擇微信支付-app支付(我這裏演示使用)-API列表-統一下單
- 引入支付寶第三方jar包
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
- 編寫一個配置微信參數的類(我這裏直接下載使用的微信demo代碼, 有很多引用類方法我就不展示了)
import org.springframework.util.ResourceUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class WXConfig extends WXPayConfig {
private static byte[] certData;
// 應用ID
public static final String APP_ID = "";
// mchId
public static final String MCH_ID = "";
// 商戶密鑰
public static final String KEY = "";
// 證書
public static final String APP_CERT_PATH = "/static/CRT/apiclient_cert.p12";
private volatile static WXConfig wxConfig = null;
public static WXConfig getInstance() throws Exception {
if (wxConfig == null) {
synchronized (WXConfig.class) {
if (wxConfig == null) {
File file = new File(ResourceUtils.getURL("classpath:").getPath());
InputStream certStream = new FileInputStream(file);
certData = new byte[(int) file.length()];
certStream.read(certData);
certStream.close();
return new WXConfig();
}
}
}
return wxConfig;
}
private WXConfig() {
}
public String getAppID() {
return APP_ID;
}
public String getMchID() {
return MCH_ID;
}
public String getKey() {
return KEY;
}
public InputStream getCertStream() {
ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
return certBis;
}
public int getHttpConnectTimeoutMs() {
return 8000;
}
public int getHttpReadTimeoutMs() {
return 10000;
}
@Override
IWXPayDomain getWXPayDomain() {
return new IWXPayDomainImpl();
}
}
- 阿里支付的方法
/**
* 微信支付接口
*
* @param outTradeNo 訂單號
* @param notifyUrl 回調地址
* @param totalAmount 金額
* @param passbackParams 附加字段
*/
public static Map<String, String> wxpay(HttpServletRequest request, String outTradeNo, String totalAmount, String notifyUrl, String passbackParams) throws Exception {
WXConfig config = WXConfig.getInstance();
// 正式環境
WXPay wxpay = new WXPay(config);
// 測試環境
// WXPay wxpay = new WXPay(config, notifyUrl, false, true);
Map<String, String> data = new HashMap<>();
data.put("body", "充值");
data.put("attach", passbackParams);
data.put("out_trade_no", outTradeNo);
data.put("device_info", "");
data.put("fee_type", "CNY");
data.put("total_fee", totalAmount);
data.put("spbill_create_ip", getRemoteHost(request));
data.put("notify_url", notifyUrl);
data.put("trade_type", "APP"); // 此處指定爲APP支付
return wxpay.unifiedOrder(data);
}
- 支付完成之後,會被微信調用回調的方法,注意這個方法必須是外網能夠訪問的, 可以在阿里雲linux服務器上面,運行一個後端服務, 接受回調的方法
/**
* 獲取微信相關參數
*/
private Map<String, String> wxResponseMap(HttpServletRequest request) throws Exception {
// 獲取返回數據
StringBuilder xmlStr = new StringBuilder();
try (BufferedReader br = request.getReader()) {
String line;
while ((line = br.readLine()) != null)
xmlStr.append(line);
} catch (IOException e) {
e.printStackTrace();
throw e;
}
return WXPayUtil.xmlToMap(xmlStr.toString());
}
@PostMapping(value = "/recharge")
@ApiOperation(value = "微信回調-充值")
public String callback() throws Exception {
Map<String, String> map = wxResponseMap();
return PayUtils.notifyUrl(() -> {
//...業務邏輯
return null;
}, map);
}
/**
* @param supplier 業務邏輯
* @param data 參數
*/
public static String notifyUrl(Supplier<Void> supplier, Map<String, String> data) throws Exception {
WXConfig config = WXConfig.getInstance();
WXPay wxpay = new WXPay(config);
// WXPay wxpay = new WXPay(config, false, true);
Map<String, String> result = Maps.newHashMap();
log.debug("____________________微信返回參數start_______________________");
log.debug(JSON.toJSONString(data));
log.debug("out_trade_no: " + data.get("out_trade_no"));
log.debug("return_code: " + data.get("return_code"));
log.debug("result_code: " + data.get("result_code"));
log.debug("____________________微信返回參數end_______________________");
// 簽名驗證
if (wxpay.isPayResultNotifySignatureValid(data)) {
if ("SUCCESS".equals(data.get("return_code")) && "SUCCESS".equals(data.get("result_code"))) {
// 業務代碼
supplier.get();
result.put("return_code", "SUCCESS");
result.put("return_msg", "校驗成功");
log.debug("異步回調業務處理完畢.");
} else {
result.put("return_code", "FAIL");
result.put("return_msg", "狀態碼爲FAIL");
log.error("驗籤通過,但是狀態碼 return_code: " + data.get("return_code") + " result_code: " + data.get("result_code"));
}
} else {
result.put("return_code", "FAIL");
result.put("return_msg", "簽名失敗");
log.error("簽名失敗");
}
return WXPayUtil.mapToXml(result);
}
- 回調方法執行完成之後,再次查詢微信訂單是否生成方法
/**
* 支付寶支付訂單的查詢
*/
public static Boolean existsOrder(String outTradeNo) throws Exception {
WXConfig config = WXConfig.getInstance();
WXPay wxpay = new WXPay(config);
// WXPay wxpay = new WXPay(config, false, true);
Map<String, String> data = new HashMap<>();
data.put("out_trade_no", outTradeNo);
Map<String, String> resp = wxpay.orderQuery(data);
if (!"SUCCESS".equals(resp.get("return_code")))
throw new RuntimeException(resp.get("return_msg"));
if (!"SUCCESS".equals(resp.get("result_code"))) {
throw new RuntimeException(resp.get("return_msg"));
}
return true;
}
- 這樣微信支付流程就完成了