內容來自:https://www.jianshu.com/p/0a0ccc15cb80
pom.xml 文件
需要在 pom.xml 加入以下依賴!
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>3.0.0</version>
</dependency>
application.yml 文件
將 application.yml 中修改自己商戶平臺的信息,以下 keyPath 是證書,可以在微信支付後臺下載,指定相關目錄即可。
wx:
pay:
appId: #微信公衆號或者小程序等的appid
mchId: #微信支付商戶號
mchKey: #微信支付商戶密鑰
keyPath: # p12證書的位置,可以指定絕對路徑,也可以指定類路徑(以classpath:開頭)
tradeType: JSAPI #JSAPI--公衆號支付 NATIVE--原生掃碼支付 APP--app支付
假設我們將證書放到 resources 目錄下,那寫成以下形式即可。
keyPath: classpath:證書名
還需要準備兩個配置文件
WechatPayConfig 文件
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* @author Gentle
* @date 2019/05/05
* 微信支付信息注入bean 中
*/
@Component
public class WeChatPayConfig {
@Autowired
private WeChatPayProperties properties;
@Bean
@ConditionalOnMissingBean
public WxPayConfig payConfig() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(this.properties.getAppId());
payConfig.setMchId(this.properties.getMchId());
payConfig.setMchKey(this.properties.getMchKey());
payConfig.setKeyPath(this.properties.getKeyPath());
payConfig.setTradeType(this.properties.getTradeType());
payConfig.setNotifyUrl(this.properties.getNotifyUrl());
return payConfig;
}
@Bean
public WxPayService wxPayService(WxPayConfig payConfig) {
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}
微信支付接口的 Controller
import com.gentle.config.WeChatPayProperties;
import com.gentle.entity.ReturnPayInfoVO;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
/**
* @author : Gentle
* @date : 2019/5/17 12:11
* @description:
*/
@RestController
@RequestMapping(value = "/api/client/pay/")
public class WeChatPayController {
@Autowired
private WxPayService wxPayService;
@Autowired
WeChatPayProperties weChatPayProperties;
/**
* 此處處理訂單信息,構建訂單數據。
*
* 將構建好的支付參數返回到前端,前端調起微信支付
* @return
*/
@GetMapping(value = "weChatPay")
public ReturnPayInfoVO weChatPay() {
/**
* 處理內部業務,校驗訂單等
*/
final WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
//調起支付的人的 openId
.openid("openId")
//訂單編號
.outTradeNo("我們系統內部訂單號")
//訂單金額
.totalFee(yuanToFee(new BigDecimal(100)))
//商品描述
.body("訂單信息")
//獲取本地IP
.spbillCreateIp(InetAddress.getLoopbackAddress().getHostAddress())
//回調的 URL 地址
.notifyUrl("http://我們的域名/api/client/pay/weChatPayNotify")
.build();
WxPayUnifiedOrderResult wxPayUnifiedOrderResult =null;
try {
wxPayUnifiedOrderResult = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);
} catch (WxPayException e) {
e.printStackTrace();
throw new RuntimeException("微信支付調起失敗!");
}
//組合參數構建支付
Map<String, String> paySignInfo = new HashMap<>(5);
String timeStamp = createTimestamp();
String nonceStr = String.valueOf(System.currentTimeMillis());
paySignInfo.put("appId", weChatPayProperties.getAppId());
paySignInfo.put("nonceStr", nonceStr);
paySignInfo.put("timeStamp", timeStamp);
paySignInfo.put("signType", "MD5");
paySignInfo.put("package", "prepay_id=" + wxPayUnifiedOrderResult.getPrepayId());
String paySign = SignUtils.createSign(paySignInfo, "MD5", weChatPayProperties.getMchKey(), false);
//組合支付參數
ReturnPayInfoVO returnPayInfoVO = new ReturnPayInfoVO();
returnPayInfoVO.setAppId(weChatPayProperties.getAppId());
returnPayInfoVO.setNonceStr(nonceStr);
returnPayInfoVO.setPaySign(paySign);
returnPayInfoVO.setSignType("MD5");
returnPayInfoVO.setPrepayId(wxPayUnifiedOrderResult.getPrepayId());
returnPayInfoVO.setTimeStamp(timeStamp);
return returnPayInfoVO;
}
/**
*
* @param xmlData 微信返回的流
* @return
*/
@RequestMapping(value = "weChatPayNotify",method = {RequestMethod.GET,RequestMethod.POST})
public String weChatNotify(@RequestBody String xmlData){
try {
final WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
//這裏是存儲我們發起支付時訂單號的信息,所以取出來
notifyResult.getOutTradeNo();
/**
* 系統內部業務,修改訂單狀態之類的
*/
//成功後回調微信信息
return WxPayNotifyResponse.success("回調成功!");
} catch (WxPayException e) {
e.printStackTrace();
return WxPayNotifyResponse.fail("回調有誤!");
}
}
/**
* 1 塊錢轉爲 100 分
* 元轉分
*
* @param bigDecimal 錢數目
* @return 分
*/
private int yuanToFee(BigDecimal bigDecimal) {
return bigDecimal.multiply(new BigDecimal(100)).intValue();
}
/**
* 時間
*
* @return 時間戳
*/
private String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
上述代碼便是位置支付的調起信息和支付成功後回調的處理邏輯了,可以對代碼進行適當的修改,便可使用。
微信退款實現:
以下便是微信退款的實現,代碼也相對簡單,修改以下便可使用,當然要各種參數校驗等,否則可能會出現被人惡意調起的可能!
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
/**
* @author : Gentle
* @date : 2019/5/17 12:38
* @description:
*/
@RestController
@RequestMapping(value = "/api/client/refund/")
@Slf4j
public class WeChatRefundController {
private static final String REFUND_SUCCESS = "SUCCESS";
@Autowired
private WxPayService wxPayService;
@PostMapping(value = "weChatRefund")
public String refund() {
//申請退款
WxPayRefundRequest refundInfo = WxPayRefundRequest.newBuilder()
//訂單號
.outTradeNo("自己系統訂單號")
//退款訂單號
.outRefundNo("自己系統訂單號")
//金額
.totalFee(yuanToFee(new BigDecimal(100)))
//退款金額
.refundFee(yuanToFee(new BigDecimal(100)))
//todo 回調地址
.notifyUrl("http://我們系統的域名/api/client/refund/refundNotify")
.build();
WxPayRefundResult wxPayRefundResult;
try {
wxPayRefundResult = wxPayService.refund(refundInfo);
//判斷退款信息是否正確
if (REFUND_SUCCESS.equals(wxPayRefundResult.getReturnCode())
&& REFUND_SUCCESS.equals(wxPayRefundResult.getResultCode())) {
/**
* 系統內部業務邏輯
*/
return "正在退款中。。";
}
} catch (WxPayException e) {
log.error("微信退款接口錯誤信息= {}", e);
}
return "退款失敗";
}
/**
* 僅支持一次性退款,多次退款需要修改邏輯
* @param xmlData 微信返回的流數據
* @return
*/
@RequestMapping(value = "refundNotify",method = {RequestMethod.GET,RequestMethod.POST})
public String refundNotify(@RequestBody String xmlData) {
WxPayRefundNotifyResult wxPayRefundNotifyResult;
try {
wxPayRefundNotifyResult = wxPayService.parseRefundNotifyResult(xmlData);
} catch (WxPayException e) {
log.error("退款失敗,失敗信息:{}", e);
return WxPayNotifyResponse.fail("退款失敗");
}
//判斷你返回狀態信息是否正確
if (REFUND_SUCCESS.equals(wxPayRefundNotifyResult.getReturnCode())) {
WxPayRefundNotifyResult.ReqInfo reqInfo = wxPayRefundNotifyResult.getReqInfo();
//判斷退款狀態
if (REFUND_SUCCESS.equals(reqInfo.getRefundStatus())) {
//內部訂單號
String outTradeNo = reqInfo.getOutTradeNo();
/**
* 一、可能會重複回調,需要做防重判斷
* 二、處理我們系統內部業務,做修改訂單狀態,釋放資源等!
*/
return WxPayNotifyResponse.success("退款成功!");
}
}
return WxPayNotifyResponse.fail("回調有誤!");
}
/**
* 1 塊錢轉爲 100 分
* 元轉分
*
* @param bigDecimal 錢數目
* @return 分
*/
private int yuanToFee(BigDecimal bigDecimal) {
return bigDecimal.multiply(new BigDecimal(100)).intValue();
}
/**
* 時間
*
* @return 時間戳
*/
private String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
案例相關代碼已經發布到 GitHub 和碼雲上,如有興趣可以下載學習!
GitHub:
https://github.com/LuckyToMeet-Dian-N/WeChat-Demo/tree/master/wechat-pay-demo
碼雲:
https://gitee.com/reway_wen/WeChat-Demo/tree/master/wechat-pay-demo
總結:
上述便是微信支付和微信退款的實現!代碼不難,只是開發資質倒是個問題。如果有資質的話,那這篇文章可能給到您一些幫助。
作者:LuckToMeetDian葉
鏈接:https://www.jianshu.com/p/0a0ccc15cb80
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。