【微信支付】微信APP支付
程序员文章站
2024-01-22 11:11:22
...
官方文档
微信支付-APP支付文档
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
APP端开发步骤
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
后端代码实现
引入依赖
<!-- 微信支付 -->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
配置参数
application.yml
# 微信相关配置
wx:
#商户 ID(微信支付平台-账户中心-个人信息)
MCH_ID:
# APP_ID(微信开放平台查找)
A_APP_ID:
# 秘钥(微信开放平台查找)
A_APP_SECRET:
# 支付秘钥KEY(微信支付平台-账户中心-api安全-api秘钥)
A_KEY:
# 支付商户证书所载目录(微信支付平台-账户中心-api安全-API证书)
A_CERT_PATH:
#支付成功回调地址
WX_CALLBACK_URL:
YmlParament
@Component
@Data
public class YmlParament {
/*微信相关字段*/
@Value("${wx.A_APP_ID}")
private String a_app_id;
@Value("${wx.A_APP_SECRET}")
private String a_app_secret;
@Value("${wx.MCH_ID}")
private String mch_id;
@Value("${wx.A_KEY}")
private String a_key;
@Value("${wx.A_CERT_PATH}")
private String a_cert_path;
@Value("${wx.WX_CALLBACK_URL}")
private String wx_callback_url;
微信统一下单
微信统一下单接口文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
-
初始化微信支付配置
@Component
public class WxConfig {
@Autowired
private YmlParament ymlParament;
@Bean(autowire = Autowire.BY_NAME,value = WxParament.APP_WX_PAY)
public WXPay setAppWXPay() throws Exception {
return new WXPay(new WxPayConfig(
ymlParament.getA_cert_path(),
ymlParament.getA_app_id(),
ymlParament.getMch_id(),
ymlParament.getA_key()));
}
WxPayConfig
public class WxPayConfig implements WXPayConfig {
private byte[] certData;
private String appID;
private String mchID;
private String key;
public WxPayConfig(String certPath, String appID,String mchID,String key) throws Exception {
File file = new File(certPath);
InputStream certStream = new FileInputStream(file);
this.certData = new byte[(int) file.length()];
certStream.read(this.certData);
certStream.close();
this.appID = appID;
this.mchID = mchID;
this.key = key;
}
}
-
微信下单接口,关键代码(服务层)
@Resource(name = WxParament.APP_WX_PAY)
private WXPay wxAppPay;
/* 微信统一下单 */
private Map<String, String> wxUnifiedOrder(String orderNo, String orderFee, String requestIp) throws RuntimeException {
Map<String, String> data = new HashMap<String, String>();
data.put("nonce_str", WXPayUtil.generateNonceStr());
data.put("body", "我来下单啦");
data.put("out_trade_no", orderNo);
data.put("sign_type", "MD5");
data.put("total_fee", orderFee);
data.put("spbill_create_ip", requestIp);
data.put("notify_url",ymlParament.getWx_callback_url());
data.put("trade_type", "APP"); // 此处指定为APP支付
Map<String, String> wxOrderResult = WxPay.unifiedorder(data,wxAppPay);
if("FAIL".equals(wxOrderResult.get("return_code"))){
throw new RuntimeException(wxOrderResult.get("return_msg"));
}
/* IsNull自定义,主要判断非空 */
if (IsNull.isNull(wxOrderResult.get("prepay_id"))) {
throw new RuntimeException("微信支付下单成功后,返回的prepay_id为空");
}
return wxOrderResult;
}
@Override
public Map<String, String> insertWxAppPay(String orderNo,String orderFee, String requestIp, String openid) {
try {
/* 微信下单 */
Map<String, String> wxOrderResult = wxUnifiedOrder(orderNo, orderFee, requestIp, openid);
Map<String, String> chooseWXPay = new HashMap<>();
/* 这里的key值都是小写的,而JSAPI是驼峰式写法 */
chooseWXPay.put("appid", ymlParament.getA_app_id());
chooseWXPay.put("partnerid", ymlParament.getMch_id());
chooseWXPay.put("prepayid", wxOrderResult.get("prepay_id"));
chooseWXPay.put("package", "Sign=WXPay");
chooseWXPay.put("noncestr", wxOrderResult.get("nonce_str"));
chooseWXPay.put("timestamp", WxUtils.create_timestamp());
String signature = WXPayUtil.generateSignature(chooseWXPay, ymlParament.getA_key());
chooseWXPay.put("sign", signature);
return chooseWXPay;
} catch (Exception e) {
e.printStackTrace();
}
}
-
controller层(略)
微信支付成功回调
-
关键代码
@Resource(name = WxParament.APP_WX_PAY)
private WXPay wxAppPay;
@ApiOperation("微信支付回调")
@PostMapping("callback")
public String callback(HttpServletRequest request) throws Exception {
try {
// 1、获取参数
Map<String, String> params = getMapByRequest(request);
log.info("微信回调回来啦!!!!" + params);
// 2、校验
checkCallbackWxPay(params);
//业务逻辑
return wxPaySuccess();
} catch (Exception e) {
e.printStackTrace();
return wxPayFail(e.getMessage());
}
}
/**
* 获取微信过来的请求参数
* @param request
* @return
* @throws Exception
*/
private static Map<String, String> getMapByRequest(HttpServletRequest request) throws Exception{
InputStream 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);
}
Map<String, String> ret= WXPayUtil.xmlToMap(new String(outSteam.toByteArray(), "utf-8"));
outSteam.close();
inStream.close();
return ret;
}
/*校验 */
private void checkCallbackWxPay(Map<String, String> params)
throws Exception {
if ("FAIL".equals(params.get("result_code"))) {
throw new Exception("微信支付失败");
}
if (!checkWxCallbackSing(params, wxH5Pay)) {
throw new Exception("微信支付回调签名认证失败");
}
//校验金额
//判断订单是否重复
//....业务逻辑
}
/**
* 检查微信回调签名 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
*
* @param wp 传入:@Autowired WXPay
*/
private static boolean checkWxCallbackSing(Map<String, String> notifyMap, WXPay wp) throws Exception {
return wp.isPayResultNotifySignatureValid(notifyMap);
}
/**
* 微信支付返回参数结果封装
*/
private static String wxPaySuccess() throws Exception {
Map<String, String> succResult = new HashMap<String, String>();
succResult.put("return_code", "SUCCESS");
succResult.put("return_msg", "OK");
return WXPayUtil.mapToXml(succResult);
}
/**
* @param mess 错误消息提示
* @return 微信返回错我的提示
* @throws Exception
*/
private static String wxPayFail(String mess) throws Exception {
Map<String, String> succResult = new HashMap<String, String>();
succResult.put("return_code", "FAIL");
succResult.put("return_msg", IsNull.isNull(mess)?"自定义异常错误!":mess);
return WXPayUtil.mapToXml(succResult);
}
补充
如果不想验证签名,还有一种方式判断是否支付成功,就是调用微信查询订单接口查看是否支付成功
-
关键代码
/*调用微信查询订单接口*/
Map<String, String> orderqueryRes = orderquery(wXH5Pay,params.get("out_trade_no"));
/*交易成功*/
if (!"SUCCESS".equals(orderqueryRes.get("trade_state"))){
throw new Exception("<===微信支付失败====>订单号为【"+ params.get("out_trade_no")+ "】的订单");
}
/**
* 查询支付结果 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
*/
private static Map<String, String> orderquery(WXPay wxpay, String outTradeNo) throws Exception {
Map<String, String> parament = new HashMap<String, String>();
parament.put("out_trade_no", outTradeNo);
return wxpay.orderQuery(parament);
}