第三方支付之微信支付(扫码支付)
第一步:注册微信支付账户,开通扫码支付
具体流程请参照官方说明
第二步:创建Maven项目
1. 添加微信支付SDK依赖、二维码工具依赖(微信支付需要自己通过二维码工具生成支付二维码)
<!-- 微信支付 -->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<!-- google二维码工具 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
2. 实现SDK微信配置类官网:www.fhadmin.org,创建商户自己的配置类
public class WxPayConfig implements WXPayConfig{
private byte[] certData;
//初始化退款、撤销时的商户证书
public WxPayConfig() throws Exception {
String certPath = "D://第三方开放平台/wx_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 String getAppID() {
return "";
}
/** 微信支付商户号 */
public String getMchID() {
return "";
}
public String getKey() {
return "";
}
public int getHttpConnectTimeoutMs() {
return 8000;
}
public int getHttpReadTimeoutMs() {
return 10000;
}
@Override
public InputStream getCertStream() {
ByteArrayInputStream certBis;
certBis = new ByteArrayInputStream(this.certData);
return certBis;
}
}
3. 创建微信支付的控制器类 3.1 初始化微信支付的SDK客户端
private WxPayConfig config;
private WXPay wxpay;
public WxPayController() {
try {
//初始化微信支付客户端
config = new WxPayConfig();
wxpay = new WXPay(config);
} catch (Exception e) {
e.printStackTrace();
}
}
3.2 创建预支付接口,生成支付二维码(可以在页面添加img标签,让它的url指向这里就能直接在页面特定区域显示二维码了)
/**
* 预支付接口,生成支付二维码
* @param order
* @return
* @throws Exception
*/
@RequestMapping("/wxpay/pay")
public void pay(HttpServletResponse response) throws Exception {
//TODO:这里执行商户系统创建新的订单操作
WxPayOrder order = new WxPayOrder();
order.setOut_trade_no(System.currentTimeMillis() + "");
wxPayService.createOrder(order);
//设置请求参数
Map<String, String> data = new HashMap<String, String>();
data.put("body", "微信支付测试");
data.put("out_trade_no", order.getOut_trade_no());
data.put("device_info", "");
data.put("fee_type", "CNY");
data.put("total_fee", "1");
data.put("spbill_create_ip", "192.168.0.119");
data.put("notify_url", notify_url);
data.put("trade_type", "NATIVE"); // 此处指定为扫码支付
data.put("product_id", "12");
try {
//发起支付
Map<String, String> resp = wxpay.unifiedOrder(data);
//获取二维码URL
String code_url = resp.get("code_url");
//根据url生成二维码
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
// 设置二维码参数
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
BitMatrix bitMatrix = multiFormatWriter.encode(code_url, BarcodeFormat.QR_CODE, 300, 300, hints);
//返回二维码
MatrixToImageWriter.writeToStream(bitMatrix, "jpg", response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
3.3 创建支付结果回调接口官网:www.fhadmin.org(回调的URL必须公网可以访问,测试时可以使用花生壳等工具映射一个公网地址
/**
* 支付结果回调
* @return
* @throws Exception
*/
@PostMapping("/wxpay/notify_url")
public void notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 读取回调内容
InputStream inputStream;
StringBuffer sb = new StringBuffer();
inputStream = request.getInputStream();
String s;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while ((s = in.readLine()) != null) {
sb.append(s);
}
in.close();
inputStream.close();
// 支付结果通知的xml格式数据
String notifyData = sb.toString();
// 转换成map
Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);
//支付确认内容
String resXml = "";
//验证签名
if (wxpay.isPayResultNotifySignatureValid(notifyMap)) { // 签名正确
WxPayOrder order = wxPayService.getOrder(notifyMap.get("out_trade_no"));
if(order != null) {
if("SUCCESS".equals(notifyMap.get("result_code"))) { //交易成功
// TODO:更新订单
System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付成功");
} else { //交易失败
System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付失败");
}
}
// 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
//设置成功确认内容
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
}
else { // 签名错误,如果数据里没有sign字段,也认为是签名错误
//设置失败确认内容
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg></return_msg>" + "</xml> ";
System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付失败");
}
//发送通知
response.getWriter().println(resXml);
}
3.4 创建申请退款接口官网:www.fhadmin.org(这里一定要注意先要下载并配置证书,否则会报错;证书下载请参考官方文档,证书配置见商户微信配置类)
/**
* 微信申请退款接口
* @param out_trade_no 订单号
* @throws Exception
*/
@RequestMapping("/wxpay/refund")
public void refund(String out_trade_no) throws Exception {
//设置请求参数
HashMap<String, String> data = new HashMap<String, String>();
data.put("out_trade_no", out_trade_no);
data.put("out_refund_no", out_trade_no);
data.put("total_fee", "1");
data.put("refund_fee", "1");
data.put("refund_fee_type", "CNY");
data.put("op_user_id", config.getMchID());
try {
//调用sdk发起退款
Map<String, String> result = wxpay.refund(data);
if("SUCCESS".equals(result.get("result_code"))) {
//TODO:更新订单
System.out.println("订单" + out_trade_no + "微信退款成功");
}
} catch (Exception e) {
e.printStackTrace();
}
}
第三步:测试支付、退款 1. 运行项目 mvn jetty:run 2. 测试支付接口:http://localhost:8080/wxpay/pay 3. 测试退款接口:http://localhost:8080/wxpay/refund
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
- 上一篇:没有了
- 下一篇: Spring MVC 中获取session的几种方法
