微信小程序支付 和支付结果处理(Java+微信小程序)
小程序前端 因为微信支付需要openid所有这需要code去后端还换取openid
join :function(){
wx.login({
timeout: 3000,
success(res){
if(res.code){
wx.request({
url: '自己的后端路径',
header: { 'Content-Type': 'application/json;charset=utf-8'},
data:{
code:res.code
},
success:function(res){
console.log("服务端返回订单号");
console.log(res.data);
wx.requestPayment({
nonceStr: res.data.data.nonceStr,
package: res.data.data.package,
paySign: res.data.data.paySign,
timeStamp: res.data.data.timeStamp,
signType:'MD5',
success(res){
wx.showToast({
title: '成功',
icon: 'success',
duration: 2000
})
console.log("统一下单接口成功");
},
fail(res) {
wx.showToast({
title: '用户取消支付',
icon: 'fail',
duration: 2000
})
wx.navigateTo({
url: '../success/success',
})
console.log("统一下单接口失败");
}
});
}
})
}else{
console.log('登录失败!' + res.errMsg)
}
}
})
后端
WXPayConfigImpl`
package com.example.xcxynbwkfptdemo.serverimpl;
import com.github.wxpay.sdk.WXPayConfig;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class WXPayConfigImpl implements WXPayConfig {
private byte[] certData;
@Override
public String getAppID() {
return "小程序appid";
}
@Override
public String getMchID() {
return "商品号";
}
@Override
public String getKey() {
return "自己的key";
}
@Override
public InputStream getCertStream() {
ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
return certBis;
}
@Override
public int getHttpConnectTimeoutMs() {
return 8000;
}
@Override
public int getHttpReadTimeoutMs() {
return 10000;
}
}
controller (notify_url )接收微信支付完成的结果通知接口路径
package com.example.xcxynbwkfptdemo.controller;
import com.alibaba.fastjson.JSONObject;
import com.example.xcxynbwkfptdemo.bean.WeChatSession;
import com.example.xcxynbwkfptdemo.serverimpl.WXPayConfigImpl;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.gson.Gson;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.wxpay.sdk.WXPay;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.InetAddress;
import java.util.*;
/**
* @author admin
* 小程序登录支付
*/
@Controller
@RequestMapping("/kjpfxcx")
public class LoginController {
private static final String AppSecret = "小程序AppSecret ";
private static final String notify_url = "必须是发布在服务器上的接口路径 xcx/kjpfxcx/informed.do";
private static Log logger = LogFactory.getLog(LoginController.class);
@RequestMapping("/Login")
@ResponseBody
public JSONObject login(String code) throws Exception {
JSONObject jsonObject = new JSONObject();
WXPayConfigImpl wxPayConfig = new WXPayConfigImpl();
//正式环境
WXPay wxpay = new WXPay(wxPayConfig);
Map resultMap = new HashMap();
//请求微信服务器获取
System.out.println(code);
//微信的接口
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wxPayConfig.getAppID() +
"&secret=" + AppSecret + "&js_code=" + code + "&grant_type=authorization_code";
//进行网络请求
RestTemplate restTemplate = new RestTemplate();
//进行网络请求,访问url接口
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
String sessionData = responseEntity.getBody();
System.out.println(sessionData);
Gson gson = new Gson();
//解析从微信服务器获得的openid和session——key;
WeChatSession weChatSession = gson.fromJson(sessionData, WeChatSession.class);
//获取用户的唯一标识
String openid = weChatSession.getOpenid();
String session_key = weChatSession.getSession_key();
//生成随机字符串
String nonce_str = WXPayUtil.generateNonceStr();
//获得IP地址
InetAddress addr = InetAddress.getLocalHost();
String spbill_create_ip = addr.getHostAddress();
//支付金额
int total_fee = 1;
//商品描述
String body = "测试";
//商品订单号
String out_trade_no = WXPayUtil.generateNonceStr();
//统一下单接口参数
Map<String, String> data = new HashMap<String, String>();
data.put("appid", wxPayConfig.getAppID());
data.put("mch_id", wxPayConfig.getMchID());
data.put("nonce_str", nonce_str);
data.put("body", body);
data.put("out_trade_no", out_trade_no);
data.put("total_fee", String.valueOf(total_fee));
data.put("spbill_create_ip", spbill_create_ip);
data.put("notify_url", notify_url);
data.put("trade_type", "JSAPI");
data.put("openid", openid);
//正式环境统一下单
Map<String, String> rMap = wxpay.unifiedOrder(data);
logger.info("统一下单接口返回" + rMap);
String return_code = (String) rMap.get("return_code");
String result_code = (String) rMap.get("result_code");
String nonceStr = WXPayUtil.generateNonceStr();
resultMap.put("nonceStr", nonceStr);
Long timeStamp = System.currentTimeMillis();
if ("SUCCESS".equals(return_code) && result_code.equals(result_code)) {
String prepayid = rMap.get("prepay_id");
resultMap.put("package", "prepay_id=" + prepayid);
resultMap.put("signType", "MD5");
//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误
resultMap.put("timeStamp", timeStamp + "");
//再次签名
resultMap.put("appId", wxPayConfig.getAppID());
String sign = WXPayUtil.generateSignature(resultMap, wxPayConfig.getKey());
resultMap.put("paySign", sign);
System.out.println("生成的签名paySign :" + sign);
jsonObject.put("msg", "成功");
jsonObject.put("data", resultMap);
logger.info("返回的数据" + jsonObject);
return jsonObject;
}
}
return null;
}
/**
* 支付结果处理
*
* @return
*/
@RequestMapping("/informed.do")
@ResponseBody
public String informed(HttpServletRequest request, HttpServletResponse response) {
/**
* 返回成功xml
*/
String resSuccessXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
/**
* 返回失败xml
*/
String resFailXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";
String resXml = "";
InputStream inStream;
try {
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);
}
logger.info("wxnotify:微信支付----start----");
//获取微信调用我们notify_url的返回信息
String result = new String(outSteam.toByteArray(), "UTF-8");
//关闭流
outSteam.close();
inStream.close();
//xml转map
Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
logger.info("支付结果数据: " + resultMap);
boolean isSuccess = false;
if (resultMap != null) {
// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
return resSuccessXml;
}
} catch (Exception e) {
e.printStackTrace();
logger.error("wxnotify:支付回调发布异常:out:", e);
return resFailXml;
}
return resFailXml;
}
}
maven
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>xcx-ynbwkfptdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>xcx-ynbwkfptdemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.cedarsoft.commons/lang -->
<dependency>
<groupId>com.cedarsoft.commons</groupId>
<artifactId>lang</artifactId>
<version>6.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.wxpay/wxpay-sdk -->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>