springboot集成微信app支付

一、准备工作(以下信息需要自行开通和申请):

    public static final String APP_ID = "";//app的id 需要app应用
    public static final String KEY = "";//api密钥 商户账户信息里面去获取
    public static final String MCH_ID = "";//商户的id,需要开通商户

maven项目添加依赖:

		<!-- 微信支付 -->
		<dependency>
			<groupId>com.github.wxpay</groupId>
			<artifactId>wxpay-sdk</artifactId>
			<version>0.0.3</version>
		</dependency>

二、开发流程:

整个流程我们只需要两个接口即可:

1.微信支付的统一下单接口(本地项目请求微信):

接口api请点击这里

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

2.微信支付后的通知接口,是我们向外提供的(微信请求本地项目):接口地址自行定义

三、代码:我使用的springboot restful接口方式,详解请看注释

service层:


import java.util.Map;

/**
 * 
 * @类名称 WeixinService.java
 * @类描述 <pre>微信相关</pre>
 * @作者  yw  xingsfdz@163.com
 * @创建时间 2020年4月29日 下午4:25:10
 * @版本 5.0.0
 *
 * @修改记录
 * <pre>
 *     版本                       修改人 		修改日期 		 修改内容描述
 *     ----------------------------------------------
 *     5.0.0 	yw 	2020年4月29日             
 *     ----------------------------------------------
 * </pre>
 */
public interface WeixinService {

	/**
	 * 
	 * @方法名称 payBack
	 * @功能描述 <pre>回调接口</pre>
	 * @作者    yw
	 * @创建时间 2020年5月22日 下午12:50:15
	 * @param resXml
	 * @return
	 */
    String payBack(String resXml);

    /**
     * 
     * @param order 
     * @方法名称 doUnifiedOrder
     * @功能描述 <pre>统一下单</pre>
     * @作者    yw
     * @创建时间 2020年5月22日 下午12:50:26
     * @return
     * @throws Exception
     */
    Map<String, String> doUnifiedOrder(Order order) throws Exception;
    
}

service层实现(以下代码已删除了业务处理部分,需要自己添加自己项目的业务处理):


import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 
 * @类名称 WeixinServiceImpl.java
 * @类描述 <pre>微信 支付</pre>
 * @作者  yw  xingsfdz@163.com
 * @创建时间 2020年5月22日 下午12:51:13
 * @版本 5.0.0
 *
 * @修改记录
 * <pre>
 *     版本                       修改人 		修改日期 		 修改内容描述
 *     ----------------------------------------------
 *     5.0.0 	yw 	2020年5月22日             
 *     ----------------------------------------------
 * </pre>
 */
@Service
@Slf4j
public class WeixinServiceImpl implements WeixinService {
	
    public static final String HOST_IP = "";//回调的服务器ip
    public static final String NOTIFY_URL = "";//回调的地址,注意:外网可以访问
    public static final String TRADE_TYPE_APP = "APP";

    @Autowired
    OrderService orderService;//自己业务的处理服务
   
    @Override
    public String payBack(String resXml) {
        WXConfigUtil config = null;
        try {
            config = new WXConfigUtil();
        } catch (Exception e) {
            e.printStackTrace();
        }
        WXPay wxpay = new WXPay(config);
        String xmlBack = "";
        Map<String, String> notifyMap = null;
        try {
            notifyMap = WXPayUtil.xmlToMap(resXml);         // 调用官方SDK转换成map类型数据
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {//验证签名是否有效,有效则进一步处理

                String return_code = notifyMap.get("return_code");//状态
                String out_trade_no = notifyMap.get("out_trade_no");//商户订单号
                if (return_code.equals("SUCCESS")) {
                    if (out_trade_no != null) {
                        // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户的订单状态从退款改成支付成功
                        // 注意特殊情况:微信服务端同样的通知可能会多次发送给商户系统,所以数据持久化之前需要检查是否已经处理过了,处理了直接返回成功标志
                    	//业务处理 以下进行业务处理(比如修改订单状态信息等)
                        log.info("微信手机支付回调成功订单号:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                    } else {
                        log.info("微信手机支付回调失败订单号:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                    }
                }
                return xmlBack;
            } else {
                // 签名错误,如果数据里没有sign字段,也认为是签名错误
                //失败的数据要不要存储?
                log.error("手机支付回调通知签名错误");
                xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                return xmlBack;
            }
        } catch (Exception e) {
            log.error("手机支付回调通知失败", e);
            xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        return xmlBack;
    }

    /**
     * 
     * @方法名称 doUnifiedOrder
     * @功能描述 <pre>统一下单接口具体实现</pre>
     * @作者    yw
     * @创建时间 2020年5月22日 下午4:30:44
     * @param order 参数可以根据自己定义
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> doUnifiedOrder(Order order) throws Exception {
        try {
            WXConfigUtil config = new WXConfigUtil();
            WXPay wxpay = new WXPay(config);
            Map<String, String> data = new HashMap<>();
            //生成商户订单号,不可重复
            data.put("appid", WXConfigUtil.APP_ID);
            data.put("mch_id", WXConfigUtil.MCH_ID);
            data.put("nonce_str", WXPayUtil.generateNonceStr());
            String body = "手机支付";
            data.put("body", body);
            data.put("out_trade_no", order.getOrderNo());//订单号
            data.put("total_fee", "1");//设置金额1分
            //自己的服务器IP地址
            data.put("spbill_create_ip", HOST_IP);
            //异步通知地址(请注意必须是外网)
            data.put("notify_url", NOTIFY_URL);
            //交易类型
            data.put("trade_type", TRADE_TYPE_APP);
            //附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
            data.put("attach", "");
            data.put("sign", WXPayUtil.generateSignature(data, WXConfigUtil.KEY,
                    WXPayConstants.SignType.MD5));
            //使用官方API请求预付订单
            Map<String, String> response = wxpay.unifiedOrder(data);
            if ("SUCCESS".equals(response.get("return_code"))) {//主要返回以下5个参数
                Map<String, String> param = new HashMap<>();
                param.put("appid", WXConfigUtil.APP_ID);
                param.put("partnerid",response.get("mch_id"));
                param.put("prepayid",response.get("prepay_id"));
                param.put("package","Sign=WXPay");
                param.put("noncestr",WXPayUtil.generateNonceStr());
                param.put("timestamp",System.currentTimeMillis()/1000+"");
                param.put("sign",WXPayUtil.generateSignature(param, WXConfigUtil.KEY,
                        WXPayConstants.SignType.MD5));
                return param;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("下单失败");
        }
        throw new Exception("下单失败");
    }
}

controller层:



import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;



import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @类名称 WeixinRestController.java
 * @类描述 <pre>微信app支付</pre>
 * @作者  yw  xingsfdz@163.com
 * @创建时间 2020年5月22日 下午4:04:19
 * @版本 5.0.0
 *
 * @修改记录
 * <pre>
 *     版本                       修改人 		修改日期 		 修改内容描述
 *     ----------------------------------------------
 *     5.0.0 	yw 	2020年5月22日             
 *     ----------------------------------------------
 * </pre>
 */
@Slf4j
@Api(value="微信",tags={"微信"})
@RequestMapping("/weixin/")
@RestController
public class WeixinRestController{
	
	@Autowired
	WeixinService weixinService;
	
	/**
	 * 
	 * @方法名称 wxAdd
	 * @功能描述 <pre>微信统一下单- 前端发起下单 比如web ios android</pre>
	 * @作者    yw
	 * @创建时间 2020年5月22日 下午12:56:59
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value={"app/wxpay"}, method={RequestMethod.POST})
    public ResponseMsg wxpay(HttpServletRequest request, Order order) throws Exception {
        return new ResponseMsg(weixinService.doUnifiedOrder(order));
    }
	
	/**
	 * 
	 * @方法名称 wxPayNotify
	 * @功能描述 <pre>给微信回调的接口</pre>
	 * @作者    yw
	 * @创建时间 2020年5月22日 下午4:04:55
	 * @param request
	 * @return
	 */
    @PostMapping("order/wxnotify")
    @ApiOperation("微信回调")
    public String wxPayNotify(HttpServletRequest request) {
        String resXml = "";
        try {
            InputStream inputStream = request.getInputStream();
            //将InputStream转换成xmlString
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder sb = new StringBuilder();
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
            } catch (IOException e) {
            	log.info(e.getMessage());
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            resXml = sb.toString();
            String result = weixinService.payBack(resXml);
            return result;
        } catch (Exception e) {
            log.info("微信手机支付失败:" + e.getMessage());
            String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
            return result;
        }
    }
}

四、测试:

安卓端发起请求,并请求支付成功:

SpringBoot 集成 App 微信支付是一个过程,它涉及到使用 SpringBoot 框架构建的后端服务与微信支付 API 进行交互,从而允许应用通过微信平台完成支付功能。以下是集成步骤: ### 1. 注册并获取微信支付相关证书 首先,您需要在微信公众平台上注册并创建一个应用,然后申请微信支付所需的API密钥和其他信息,例如商户号、支付密钥等。 ### 2. 添加依赖到项目中 在您的 SpringBoot 项目的 `pom.xml` 文件中添加微信支付 SDK 的 Maven 依赖。可以使用微信提供的官方 Java SDK 或第三方库如 `wechat-pay`。 ```xml <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-pay</artifactId> <version>1.x.y</version> </dependency> ``` ### 3. 配置微信支付参数 配置您的微信支付环境信息,包括 appid、mch_id(商户号)、key 和合作伙伴证书路径等。通常在应用启动时读取这些参数,并存储在应用程序上下文中供后续使用。 ### 4. 创建支付请求 编写代码生成支付请求,包括设置商品描述、订单金额等数据,并使用微信支付 SDK 发送请求。 ```java String appId = "your_appid"; String mchId = "your_mch_id"; String api_key = "your_api_key"; String notifyUrl = "http://yourdomain.com/pay_notify"; double total_fee = 100.0; // 单位为分 // 根据实际情况选择合适的构造函数,一般会提供商品ID、数量、订单总金额等参数 WechatPay wechatPay = new WechatPay(appId, mchId, api_key); JSONObject result = wechatPay.sendOrderRequest(notifyUrl, total_fee); // 处理返回结果,判断是否支付成功以及获取支付单号 if (result.containsKey("code") && "SUCCESS".equals(result.getString("code"))) { String tradeNo = result.getString("trade_no"); } else { throw new RuntimeException("Payment failed."); } ``` ### 5. 处理回调通知 当用户在微信支付完成后,微信服务器会发送一个 HTTP POST 请求至您预先设定的通知 URL。您需要监听这个请求,解析其中的数据,确认支付状态。 ### 6. 错误处理及安全性考虑 在实际应用中,需要对异常情况做出处理,比如网络错误、密钥验证失败等。同时,注意保护敏感信息的安全,避免直接将密钥等重要信息硬编码在代码中。 ### 相关问题 - SpringBoot 集成微信支付: 1. **如何保证支付安全**:除了加密传输外,还需要定期更新 API 密钥,防止泄露;对敏感信息进行混淆处理;使用HTTPS协议保障通信安全。 2. **如何处理异步通知**:微信支付的异步通知可能会因为各种原因延迟到达,需要设计合理的机制去处理这些通知,包括重新触发支付流程或调整业务逻辑,以减少用户不必要的等待或操作。 3. **性能优化**:对于频繁使用的支付功能,可以考虑缓存支付结果或采用队列系统处理异步任务,提高系统的响应速度和稳定性。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值