**
微信小程序-授权登录-支付-退款
**
简单的写一下,第一次写小程序支付退款的项目,纪念一下自己一路的学习过程。
微信小程序支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1
/**
* 微信授权时录入用户数据-需要前端发送一个code值,拿到code获取微信openid返回给前端换取用户信息。
*/
@RequestMapping(value = "wxLogin")
@ResponseBody
@Transactional
public Map<String,Object> insert(@RequestParam("code")String code, HttpSession session) throws ClientProtocolException, IOException {
//返回map
System.err.println("微信授权登录");
System.err.println("code值: "+code);
Map<String,Object> resultMap = new HashMap<>();
String appid = WXPayConstants.APP_ID;
String secret = WXPayConstants.SECRET;
String loginUrl="https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code";
try {
CloseableHttpClient client = null;
CloseableHttpResponse response = null;
try {
// 创建http GET请求
HttpGet httpGet = new HttpGet(loginUrl);
client = HttpClients.createDefault();
// 执行请求
response = client.execute(httpGet);
HttpEntity entity = response.getEntity();//得到返回数据
String result = EntityUtils.toString(entity);
System.err.println("微信返回的结果"+result);
resultMap.put("data", result);//进行封装
System.err.println(resultMap);
JSONObject json_test = JSONObject.parseObject(result);
String wxOpenid = json_test.getString("openid");
String sessionKey = json_test.getString("session_key");
System.err.println("openid值: "+wxOpenid);//得到微信openID
System.err.println("sessionKey值: "+sessionKey);
WxUser user = wxUserService.selectByid(wxOpenid);//根据id数据库数据查询
System.err.println("用户信息: "+user);
if (user == null){//如果user等于null说明该用户第一次登录,数据库没有该用户信息。
resultMap.put("state", 2000);
resultMap.put("data", wxOpenid);
resultMap.put("sessionKey", sessionKey);
resultMap.put("message", "未查询到用户信息");
}else {
resultMap.put("state", 2000);
resultMap.put("data", wxOpenid);//查找的用户信息进行封装返回
resultMap.put("sessionKey", sessionKey);
resultMap.put("user", user);//查找的用户信息进行封装返回
resultMap.put("message", "该用户已存在");
return resultMap;
}
if(StringUtils.isEmpty(wxOpenid)){
resultMap.put("state", 2000);
resultMap.put("message", "未获取到openid");
return resultMap;
}
} finally {
if (response != null) {
response.close();
}
if (client != null) {
client.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return resultMap;
}
调用支付接口时需要注意的是需要:必须要开通微信小程序支付功能,拿到商户id和密钥。还需要小程序APPID和密钥。
/*调用支付接口*/
@RequestMapping("prePay")
@ResponseBody
public Map<String, Object> prePay(Integer id, HttpServletRequest request){
// 返回参数
Map<String, Object> resMap = new HashMap<>();
//获取请求ip地址
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getRemoteAddr();
}
if(ip.indexOf(",")!=-1){
String[] ips = ip.split(",");
ip = ips[0].trim();
}
try {
// 拼接统一下单地址参数
Map<String, String> paraMap = new HashMap<>();
Order order = orderMapper.selectByPrimaryKey(id);
String body = order.getHeader();//商品名称
String orderNum = order.getOrdernum();//订单号
String openId = order.getOpenid();
// String price = order.getMoney();
String price = "1";//支付金额,单位:分,这边需要转成字符串类型,否则后面的签名会失败
// 封装11个必需的参数
paraMap.put("appid", WXPayConstants.APP_ID);
paraMap.put("mch_id", WXPayConstants.MCH_ID);//商家ID
paraMap.put("nonce_str", WXPayUtil.generateNonceStr());//获取随机字符串 Nonce Str
paraMap.put("body", body); //商品名称
paraMap.put("out_trade_no", orderNum);//订单号
paraMap.put("total_fee",price); //测试改为固定金额
paraMap.put("spbill_create_ip", ip);
paraMap.put("notify_url",WXPayConstants.CALLBACK_URL);// 此路径是微信服务器调用支付结果通知路径
paraMap.put("trade_type", "JSAPI");
paraMap.put("openid", openId);
String sign = WXPayUtil.generateSignature(paraMap, WXPayConstants.PATERNER_KEY);//商户密码
//生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
paraMap.put("sign", sign);
//将所有参数(map)转xml格式
String xml = WXPayUtil.mapToXml(paraMap);
System.out.println("xml:"+xml);
// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
String unifiedorder_url = WXPayConstants.UNIFIEDORDER_URL;//统一下单接口
System.out.println("unifiedorder_url:"+unifiedorder_url);
//发送post请求"统一下单接口"返回预支付id:prepay_id
String xmlStr = HttpClientUtil.sendPost(unifiedorder_url, xml);
System.out.println("xmlStr:"+xmlStr);
//以下内容是返回前端页面的json数据
//预支付id
String prepay_id = "";
if (xmlStr.indexOf("SUCCESS") != -1) {
Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);//XML格式字符串转换为Map
prepay_id = map.get("prepay_id");
}
Map<String, String> payMap = new HashMap<String, String>();
// 封装所需6个参数调支付页面
payMap.put("appId", WXPayConstants.APP_ID);
payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");//获取当前时间戳,单位秒
payMap.put("nonceStr", WXPayUtil.generateNonceStr());//获取随机字符串 Nonce Str
payMap.put("signType", "MD5");
payMap.put("package", "prepay_id=" + prepay_id);
//生成带有 sign 的 XML 格式字符串
String paySign = WXPayUtil.generateSignature(payMap, WXPayConstants.PATERNER_KEY);
payMap.put("paySign", paySign);
// 封装正常情况返回数据
resMap.put("success",true);
resMap.put("payMap",payMap);
} catch (Exception e) {
// 封装异常情况返回数据
resMap.put("success",false);
resMap.put("message","调用统一订单接口错误");
e.printStackTrace();
}
return resMap;
}
/*支付成功回调*/
@RequestMapping("callBack")
public JsonResult callBack(HttpServletRequest request, HttpServletResponse response){
JsonResult result = new JsonResult();
System.err.println("微信支付成功,微信发送的callback信息,请注意修改订单信息");
InputStream is = null;
try {
is = request.getInputStream();//获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
String xml = WXPayUtil.inputStream2String(is);
Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//将微信发的xml转map
if(notifyMap.get("return_code").equals("SUCCESS")){
result.setData(SUCCESS);
result.setData("支付回调成功,修改订单状态为支付成功");
String ordersNum = notifyMap.get("out_trade_no");//商户订单号
//处理订单状态
// String openid = notifyMap.get("openid");
Date zhifutime = new Date();
Integer ordertype = 1;//1支付完成
String complete = "待服务";
try {
orderMapper.updateByOrdersNum(ordersNum,ordertype,zhifutime,complete);
//告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
is.close();
}catch (Exception e){
result.setMessage("订单状态修改失败");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
这些参数大家自己补把
public static final String APP_ID = "";//appid
public static final String MCH_ID = "";//商家ID
public static final String SECRET = "";//APP KEY
public static final String OPENID_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
public static final String NOTIFY_URL = "";//回调ip
public static final String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//统一下单接口
public static final String CALLBACK_URL = "";//微信服务器调用支付结果通知路径
public static final String PATERNER_KEY = "";//商户key秘钥
/*退款*/
public static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";//申请退款路径接口
public static final String notify_url = "";//微信服务器调用退款结果通知路径
退款和支付类似就不写了。
如果又不懂得可以私聊我。或者加QQ群:1126420499
关注公众号:获取更多资源