关于初次对接微信支付(JSAPI支付)

前期准备:

  • 微信公众号APPID
  • 商户号
  • 支付密钥
  • 支付证书
  • 微信支付SDK

微信支付SDK下载链接

开发:

微信支付整体流程:

  1. 前端发起支付请求,后端统一下单
  2. 前端调起支付
  3. 后端接收支付通知

创建IWxPayConfig, 继承微信支付SDK中的WXPayConfig,用于读取各种配置

public class IWxPayConfig extends WXPayConfig { // 继承sdk WXPayConfig
	// 实现sdk中部分抽象方法
	private byte[] certData;
	
	public IWxPayConfig() throws Exception { // 构造方法读取证书, 通过getCertStream可以使sdk获取到证书
		String certPath = Config.CERTIFICATE_ADDRESS;//证书地址
		File file = new File(certPath);
		InputStream certStream = new FileInputStream(file);
		this.certData = new byte[(int) file.length()];
		certStream.read(this.certData);
		certStream.close();
	}

	@Override
	public String getAppID() {
		return Config.APP_ID;//公众号APPID
	}
	
	@Override
	public String getMchID() {
		return Config.MCH_ID;//商户号
	}

	@Override
	public String getKey() {
		return Config.PAY_KEY;//支付密钥
	}

	@Override
	public InputStream getCertStream() {
		return new ByteArrayInputStream(this.certData);
	}

	@Override
	public IWXPayDomain getWXPayDomain() { // 这个方法需要这样实现, 否则无法正常初始化WXPay
		IWXPayDomain iwxPayDomain = new IWXPayDomain() {
			@Override
			public void report(String domain, long elapsedTimeMillis, Exception ex) {

			}
			@Override
			public DomainInfo getDomain(WXPayConfig config) {
				return new IWXPayDomain.DomainInfo(WXPayConstants.DOMAIN_API, true);
			}
		};
		return iwxPayDomain;
	}
}

统一下单

	// 发起微信支付
	Map<String, String> result = new HashMap<>();
	try {
		IWxPayConfig iWxPayConfig = new IWxPayConfig();
	    // ******************************************
	    //  统一下单
	    // ******************************************
	   	WXPay wxpay = new WXPay(iWxPayConfig); // 注入自己实现的微信配置类, 创建WXPay核心类, WXPay 包括统一下单接口
	    Map<String, String> data = new HashMap<String, String>();
	    data.put("appid", iWxPayConfig.getAppID());// 微信公众号统一标示
	    data.put("body", "商品");//商品描述 body
	    data.put("mch_id", iWxPayConfig.getMchID());//商户macId
	    data.put("detail", "报名费");//商品详情
	    data.put("nonce_str", UUID.randomUUID().toString());   // 随机字符串小于32位
	    data.put("notify_url", "接口地址"); // 订单结果通知, 微信主动回调此接口
	    data.put("openid", openId);// 微信用户唯一表示
	    data.put("out_trade_no", orderNO); // 订单唯一编号, 不允许重复
	    data.put("spbill_create_ip", IP); // 下单ip
		data.put("total_fee", "1");//订单总金额, 单位分
	    data.put("trade_type", "JSAPI"); // 固定填写 支付场景 APP 微信app支付 JSAPI 公众号支付  NATIVE 扫码支付
	    data.put("fee_type","CNY"); // 固定填写 支付场景 APP 微信app支付 JSAPI 公众号支付  NATIVE 扫码支付
	    String s = WXPayUtil.generateSignature(data, iWxPayConfig.getKey());//签名
	    data.put("sign", s);
	    //System.out.println("发起微信支付下单接口, request={"+data.toString()+"}");
	    Map<String, String> response = wxpay.unifiedOrder(data); // 微信sdk集成方法, 统一下单接口unifiedOrder, 此处请求   MD5加密   加密方式
	    //System.out.println("微信支付下单成功, 返回值 response={"+response.toString()+"}");
	    String returnCode = response.get("return_code");
	    if (!"SUCCESS".equals(returnCode)) {
	        return null;
	    }
	    String resultCode = response.get("result_code");
	    if (!"SUCCESS".equals(resultCode)) {
	        return null;
	    }
	    String prepay_id = response.get("prepay_id");
	    if (prepay_id == null) {
	        return null;
	    }

	    // ******************************************
	    //  前端调起微信支付必要参数
	    // ******************************************
	    String packages = "prepay_id=" + prepay_id;
	    Map<String, String> wxPayMap = new HashMap<String, String>();
	    //返回给APP端的参数,APP端再调起支付接口
	    wxPayMap.put("appId", iWxPayConfig.getAppID());
	    wxPayMap.put("package", packages);
	    wxPayMap.put("signType", "MD5");
	    wxPayMap.put("nonceStr", response.get("nonce_str"));
	    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
	    wxPayMap.put("timeStamp",  formatter.format(new Date()));
		//System.out.println("加密前的参数:" + wxPayMap);
		String sign = WXPayUtil.generateSignature(wxPayMap, iWxPayConfig.getKey()); //签名
		wxPayMap.put("sign", sign);
		wxPayMap.put("timestamp", response.get("timeStamp"));
		//System.out.println("加密后:" + wxPayMap);
		result.putAll(wxPayMap);
	} catch (Exception e) {
	
	}
	

前端调起微信JSAPI支付

	var wxDaye = json.businessData;
	WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
         "appId":wxDaye.appId,     //公众号名称,由商户传入     
         "timeStamp":wxDaye.timeStamp,         //时间戳,自1970年以来的秒数     
         "nonceStr":wxDaye.nonceStr, //随机串     
         "package":wxDaye.package,     
         "signType":"MD5",         //微信签名方式:     
         "paySign":wxDaye.sign //微信签名 
      },
      function(res){
	  	if(res.err_msg == "get_brand_wcpay_request:ok" ){
		  	$.toast("支付成功!");
	  	}
   	});

微信支付结果通知

 	//System.out.println("进入微信支付异步通知");
    String resXml="";
    try{
       InputStream is = request.getInputStream();
        //将InputStream转换成String
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        resXml=sb.toString();
        //System.out.println("微信支付异步通知请求包: {"+resXml+"}");
        return weixinpayService.payBack(resXml);
    }catch (Exception e){
        System.out.println("微信支付回调通知失败");
        System.out.println(e);
        String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        return result;
    }

@Override
	public String payBack(String notifyData,int type) {
	    String xmlBack="";
	    Map<String, String> notifyMap = null;
	    try {
	    	IWxPayConfig iWxPayConfig = new IWxPayConfig();
	        WXPay wxpay = new WXPay(iWxPayConfig);
	        notifyMap = WXPayUtil.xmlToMap(notifyData);// 转换成map
	        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {// 判断签名是否正确
	            // 进行处理。
	            // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
	            String return_code = notifyMap.get("return_code");//状态
	            String out_trade_no = notifyMap.get("out_trade_no");//订单号
	            System.out.println("return_code = "+return_code+"out_trade_no = "+out_trade_no);
	            if (out_trade_no == null || !"SUCCESS".equals(return_code)) {//当订单号为空或支付状态失败时
	                System.out.println("微信支付回调失败订单号:{"+notifyMap+"}");
	                xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
	                return xmlBack;
	            }
	            // ******************************************
			    // 此处添加执行业务逻辑处理代码
			    // ******************************************    
	            System.out.println("微信支付回调成功订单号: {"+notifyMap+"}");
	            xmlBack = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[SUCCESS]]></return_msg>" + "</xml> ";
	            return xmlBack;
	        } else {
	            System.out.println("微信支付回调通知签名错误");
	            xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
	            return xmlBack;
	        }
	    } catch (Exception e) {
	    	System.out.println("微信支付回调通知失败");
	        System.out.println(e);
	        xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
	    }
	    return xmlBack;
	}

结束语

初次接触微信支付可能会一头雾水,但是逻辑清晰了之后就会发现很简单。
写的不好的欢迎大佬们指点
最后再说一个坑点

支付签名生成统一下单和返回至前端的签名参数必须一致,支付签名错误请检查签名生成参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值