基于spring boot 的 app微信支付
微信申请支付平台
-
根据需求提供材料,完成账户注册流程
wx011.jpg
wx022.jpg
wx03.png
wx055.jpg
- 在当前账户下申请支付功能
- JSAPI支付
- Native支付
-
H5支付
wx04.png
相关所有支付类型
wx_config04.png
-
查看对应的支付配置
wx_config011.jpg -
AppId账户管理,核心配置参数
app应用
wx_config022.jpg
小程序应用
wx_config033.jpg
- 接入文档
https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml -
流程图
wx_pay.png
springboot 接入app支付
controller
@Log4j2
@RequestMapping("/api/ocs/we-chat/pay")
@RestController
public class ApiOcsWeChatPayController extends BaseController {
@Autowired
private IApiWeChatPayService apiWeChatPayService;
/**
* 微信APP支付 获取预支付id
* @param request
* @param response
* @return
* @throws Exception
*/
@PostMapping("/prepay")
public AjaxResult prepayOrder(HttpServletRequest request, HttpServletResponse response )throws Exception{
TenPayRes tenPayRes = apiWeChatPayService.prepayOrder(request, response);
if (tenPayRes==null) {
return AjaxResult.error("失败,请重试");
}
return AjaxResult.success("成功",tenPayRes);
}
/** app 微信支付校验 */
@PostMapping("/notify")
public void notifyRechargeOrder(HttpServletRequest request, HttpServletResponse response)throws Exception{
boolean b = apiWeChatPayService.notifyRechargeOrder(request, response);
}
}
//app端需要的参数
public class TenPayRes implements Serializable {
/** appid */
private String appId;
/** 签名 */
private String sign;
/** 预支付交易会话标识 */
private String prepayId;
/** 商户id */
private String partnerId;
/** 随机字符串 */
private String nonceStr;
/** 时间戳 */
private String timeStamp;
/** 支付方式 */
private String packageValue;
}
service
@Service
public class ApiWeChatPayServiceImpl implements IApiWeChatPayService {
@Autowired
private IOcsRechargeOrderService rechargeOrderService;
/**
* app 微信支付 获取预支付id
* @param request
* @param response
* @return
*/
@Override
public TenPayRes prepayOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
//1. 微信支付工具类
PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
//2. 获取该业务相关信息
// 2.1 用户id
String userId = request.getParameter("userId");
// 2.2 订单总金额
String totalFee =request.getParameter("orderAmount");
BigDecimal total_fees = new BigDecimal(totalFee).multiply(new BigDecimal(100));
int total_fee = total_fees.intValue();
// 2.3 订单编号
String out_trade_no = request.getParameter("orderCode");
Long aLong = Long.valueOf(out_trade_no);
QueryWrapper<OcsRechargeOrder> wrapper = new QueryWrapper<>();
wrapper.eq("code", aLong).eq("user_id", userId);
//3. 自己业务 可以省略不写
OcsRechargeOrder one = rechargeOrderService.getOne(wrapper);
Integer userType = one.getUserType();
String appId=null;
String appSecrrt=null;
if (userType==0){
appId=WeChatPayStatic.APP_IDS;
appSecrrt=WeChatPayStatic.APP_SECRETS;
}else if(userType==1){
appId=WeChatPayStatic.APP_ID;
appSecrrt=WeChatPayStatic.APP_SECRET;
}
//4.关键 ----------------- 微信支付 参数封装 生成签名-------------
//微信开发平台应用ID
prepayReqHandler.setParameter("appid", appId);
//商品描述
prepayReqHandler.setParameter("body", WeChatPayStatic.BODY);
//微信支付商户号
prepayReqHandler.setParameter("mch_id", WeChatPayStatic.MCH_ID);
String nonce_str = WXUtil.getNonceStr();
//随机字符串
prepayReqHandler.setParameter("nonce_str", nonce_str);
//微信服务器回调通知url :目的就是微信那边支付成功或者失败后的回调地址,在这里 可以进行自己业务操作(异步的)
prepayReqHandler.setParameter("notify_url", WeChatPayStatic.NOTIFY_URLS);
prepayReqHandler.setParameter("out_trade_no", out_trade_no);
//获取到客户端IP地址
prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr());
String timestamp = WXUtil.getTimeStamp();
//时间戳
prepayReqHandler.setParameter("time_start", timestamp);
// System.out.println(String.valueOf(total_fee));
//订单总金额
prepayReqHandler.setParameter("total_fee", String.valueOf(total_fee));
prepayReqHandler.setParameter("trade_type", "APP");
/**
* 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
*/
String signsss=prepayReqHandler.createMD5Sign(WeChatPayStatic.APP_KEY);
prepayReqHandler.setParameter("sign", signsss);//签名
prepayReqHandler.setGateUrl(WeChatPayStatic.GATEURL);//支付入口参数
//获取prepayid
String prepayid = prepayReqHandler.sendPrepay().get("prepay_id");
if (prepayid != null && !prepayid.equals("")) {
String signs = "appid=" + appId + "&noncestr=" + nonce_str + "&package=Sign=WXPay&partnerid="
+ WeChatPayStatic.PARTNER_ID + "&prepayid=" + prepayid + "×tamp=" + timestamp
+ "&key="+WeChatPayStatic.APP_KEY;
TenPayRes tenPayRes = new TenPayRes();
tenPayRes.setAppId(appId);
tenPayRes.setSign(Md5Encrypt.MD5Encode(signs, "utf8").toUpperCase());
tenPayRes.setPartnerId(WeChatPayStatic.PARTNER_ID);
tenPayRes.setPrepayId(prepayid);
tenPayRes.setNonceStr(nonce_str);
tenPayRes.setTimeStamp(timestamp);
tenPayRes.setPackageValue("Sign=WXPay");
return tenPayRes;
}
return null;
}
/**
* 验签
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
public boolean notifyRechargeOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
//获取信息流
response.reset();
PrintWriter writer = response.getWriter();
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);
}
outSteam.close();
inStream.close();
String result = new String(outSteam.toByteArray(), "utf-8");
Map<String, String> map = null;
try {
/**
* 解析微信通知返回的信息
*/
map = XMLUtil.doXMLParse(result);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String rnc = map.get("return_code");
String rtc = map.get("result_code");
if ("SUCCESS".equals(rnc)) {
SortedMap<String,String> sort=new TreeMap<String,String>(map);
String signss=sort.get("sign");
String signs= XMLUtil.createSign(sort);
if(!signs.equals(signss)){
throw new Exception("微信回调参数签名不合法");
}
if ("SUCCESS".equals(rtc)){
//业务校验
// 订单编号
String orderCode = map.get("out_trade_no");
Long orderCodes = Long.valueOf(orderCode);
// 支付编号
String payCode = map.get("transaction_id");
// 支付金额
String total_fee = map.get("total_fee");
boolean b = rechargeOrderService.checkRecharge(orderCodes, total_fee, 2);
if(!b){
throw new Exception("金额不符");
}
// 支付完成 更新订单状态
int payType=2;
BigDecimal money = new BigDecimal(total_fee).divide(new BigDecimal("100"));
String paymentAmount = money.toString();
boolean flag = rechargeOrderService.updateRechargeOrder(orderCodes, payType, payCode, paymentAmount,new Date());
String notifyStr = XMLUtil.setXML("SUCCESS", "OK");
writer.write(notifyStr);
writer.flush();
}
}
return false;
}
}
dao
utils
public class PrepayIdRequestHandler extends RequestHandler {
public PrepayIdRequestHandler(HttpServletRequest request,
HttpServletResponse response) {
super( request, response );
}
public String createMD5Sign(String Appkeys) {
StringBuffer sb = new StringBuffer();
Set es = super.getAllParameters().entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append( k + "=" + v + "&" );
}
String params = sb.append( "key=" + Appkeys ).substring( 0 );
String sign = Md5Encrypt.MD5Encode( params, "utf8" );
return sign.toUpperCase();
}
/**
* 提交预支付
*
* @return
* @throws Exception
*/
public Map<String,String> sendPrepay() throws Exception {
TenpayHttpClient httpClient = this.callHP();
Map<String, String> map = new HashMap<>();
String prepayid = "";
String resContent = "";
if (httpClient != null) {
resContent = httpClient.getResContent();
System.out.println( "获取prepayid的返回值:" + resContent );
map= XMLUtil.doXMLParse( resContent );
}
return map;
}
//获取沙箱密钥
public String getShaKey() throws Exception {
TenpayHttpClient httpClient = this.callHP();
String SignKey = "";
String resContent = "";
if (httpClient != null) {
resContent = httpClient.getResContent();
System.out.println( "获取SignKey的返回值:" + resContent );
Map<String, String> map = XMLUtil.doXMLParse( resContent );
if (map.containsKey( "sandbox_signkey" )) {
SignKey = map.get( "sandbox_signkey" );
}
}
return SignKey;
}
public TenpayHttpClient callHP() {
String SignKey = "";
Set es = super.getAllParameters().entrySet();
Iterator it = es.iterator();
StringBuffer sb = new StringBuffer( "<xml>" );
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
sb.append( "<" + k + ">" + v + "</" + k + ">" );
}
sb.append( "</xml>" );
String params = sb.substring( 0 );//截取字符串
System.out.println( "请求参数:" + params );
String requestUrl = super.getGateUrl();
System.out.println( "请求url:" + requestUrl );
TenpayHttpClient httpClient = new TenpayHttpClient();
httpClient.setReqContent( requestUrl );
Boolean b = httpClient.callHttpPost( requestUrl, params );
if (b) {
return httpClient;
} else {
return null;
}
}
}
参考文献
https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_5_2.shtml
https://blog.csdn.net/xiaxl/article/details/108851372
网友评论