微信APP支付-Android+springboot搭建后端
Posted hequnwang10
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信APP支付-Android+springboot搭建后端相关的知识,希望对你有一定的参考价值。
在微信APP支付-Android+springboot搭建后端(一)和微信APP支付-Android+springboot搭建后端(二)这两篇中基本介绍完了微信APP支付的流程,本篇主要补充一点——对于支付通知的处理和查单。
Springboot后端
一、支付通知
这里主要是后端在处理,android端在支付完后继续处理Android端的业务,但是后端需要接收微信服务器端发来的支付通知消息。
WxPayController
@Resource
private Verifier verifier;
/**
* 支付通知
* 微信支付通过支付通知接口将用户支付成功消息通知给商户
*/
@ApiOperation("支付通知")
@PostMapping("/app/notify")
public String nativeNotify(HttpServletRequest request, HttpServletResponse response)
Gson gson = new Gson();
Map<String, String> map = new HashMap<>();//应答对象
try
//处理通知参数
String body = HttpUtils.readData(request);
Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
String requestId = (String)bodyMap.get("id");
log.info("支付通知的id ===> ", requestId);
log.info("支付通知的完整数据 ===> ", body);
//签名的验证
WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
= new WechatPay2ValidatorForRequest(verifier, requestId, body);
if(!wechatPay2ValidatorForRequest.validate(request))
log.error("通知验签失败");
//失败应答
response.setStatus(500);
map.put("code", "ERROR");
map.put("message", "通知验签失败");
return gson.toJson(map);
log.info("通知验签成功");
//处理订单,在这里主要讲支付通知的数据中的密文转为明文,将信息保存到数据库中
wxPayService.processOrder(bodyMap);
//应答超时
//模拟接收微信端的重复通知
TimeUnit.SECONDS.sleep(5);
//成功应答
response.setStatus(200);
map.put("code", "SUCCESS");
map.put("message", "成功");
return gson.toJson(map);
catch (Exception e)
e.printStackTrace();
//失败应答
response.setStatus(500);
map.put("code", "ERROR");
map.put("message", "失败");
return gson.toJson(map);
WxPayService
/**
* 处理订单
* @param bodyMap
*/
void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException;
WxPayServiceImpl
@Override
public void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException
log.info("处理订单");
//解密报文
String plainText = decryptFromResource(bodyMap);
//将明文转换成map
Gson gson = new Gson();
HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);
String orderNo = (String)plainTextMap.get("out_trade_no");
String transactionId = (String)plainTextMap.get("transaction_id");
log.info("处理订单 获取商户订单号 ===> ", orderNo);
log.info("处理订单 获取微信支付订单号 ===> ", transactionId);
//TODO 将订单信息保存至数据库中
/**
* 对称解密
* @param bodyMap
* @return
*/
private String decryptFromResource(Map<String, Object> bodyMap) throws GeneralSecurityException
log.info("密文解密");
//通知数据
Map<String, String> resourceMap = (Map) bodyMap.get("resource");
//数据密文
String ciphertext = resourceMap.get("ciphertext");
//随机串
String nonce = resourceMap.get("nonce");
//附加数据
String associatedData = resourceMap.get("associated_data");
log.info("密文 ===> ", ciphertext);
AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
nonce.getBytes(StandardCharsets.UTF_8),
ciphertext);
log.info("明文 ===> ", plainText);
return plainText;
这样就将微信支付通知的密文转为明文,在TODO中完成相应的数据库操作。
下面就是转为明文的消息。
需要注意,这里需要严格使用微信官方文档操作!
二、查单
WxPayController
@Resource
private Verifier verifier;
/**
* 查询订单
* @param orderNo
* @return
* @throws Exception
*/
@ApiOperation("查询订单:测试订单状态用")
@GetMapping("/query/orderNo")//也可以用微信的订单号查询
public R queryOrder(@PathVariable String orderNo) throws Exception
log.info("查询订单");
String result = wxPayService.queryOrder(orderNo);
return R.ok().setMessage("查询成功").data("result", result);
WxPayService
/**
* 查询订单
* @param orderNo
* @return
* @throws Exception
*/
String queryOrder(String orderNo) throws Exception;
WxPayServiceImpl
/**
* 查询订单
* @param orderNo
* @return
* @throws Exception
*/
@Override
public String queryOrder(String orderNo) throws Exception
log.info("查单接口调用 ===> ", orderNo);
String url = String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo);
url = wxPayConfig.getDomain().concat(url).concat("?mchid=").concat(wxPayConfig.getMchId());
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Accept", "application/json");
//完成签名并执行请求
CloseableHttpResponse response = wxPayClient.execute(httpGet);
try
String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
int statusCode = response.getStatusLine().getStatusCode();//响应状态码
if (statusCode == 200) //处理成功
log.info("成功, 返回结果 = " + bodyAsString);
else if (statusCode == 204) //处理成功,无返回Body
log.info("成功");
else
log.info("查单接口调用,响应码 = " + statusCode+ ",返回结果 = " + bodyAsString);
throw new IOException("request failed");
return bodyAsString;
finally
response.close();
这里就是查单之后的数据,当然根据查单之后的数据继续其他操作,完善后端的代码,比如使用定时器、更新订单记录等等。
以上是关于微信APP支付-Android+springboot搭建后端的主要内容,如果未能解决你的问题,请参考以下文章
本人现在开发一款android应用要app,想请教业内人士,在安卓app中怎样嵌入支付宝、微信支付
微信APP支付-Android+springboot搭建后端