Java 微信jsapi支付

话不多说,撸起袖子就是干,下面上源码

pom.xml

<dependency>
     <groupId>com.github.wxpay</groupId>
     <artifactId>wxpay-sdk</artifactId>
     <version>0.0.3</version>
</dependency>

配置文件 resources/wx.properties

#未知是否再支付的时候必传
pay.appSecret=你自己的appSecret
pay.appID=你自己的appID
#必传
pay.mchID=你自己的mchID
#必传,但不参与签名
pay.key=自己的key
#随机数 必传
pay.nonceStr=
#必传,支付成功后的通知地址,通知url必须为外网可访问的url,不能携带参数。
pay.notifyUrl=http://***********/pay/hasOrder
#必传,终端IP支持IPV4和IPV6两种格式的IP地址。用户的客户端IP,这里测试就写死 
pay.spbillCreateIp= 127.0.0.1
#支付方式
pay.tradeType=JSAPI
#设备信息,非必须
pay.deviceInfo=WEB
#JSAPI方式必传,只是这里用测试测试就写死
pay.openid=oPgg30mSXJTvd372-pgnyb1M9aEI
#HTTP(S) 连接超时时间,单位毫秒
pay.httpConnectTimeoutMs=180000
#HTTP(S) 读数据超时时间,单位毫秒
pay.httpReadTimeoutMs=180000
#证书路径 非必传
pay.certPath=E:/******

配置类

import com.github.wxpay.sdk.WXPayConfig;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

@Data
@Component
@PropertySource(value = "classpath:wx.properties")
@ConfigurationProperties(prefix = "pay")
public class Pay  implements WXPayConfig{
    private String appSecret;
    // 公众账号ID
    private String appID;
    // 商户号
    private String mchID;
    // 设备号
    private String deviceInfo;
    // 商户的key【API密匙】
    private String key;
    // api请求地址
    //private String url;
    // 服务器异步通知页面路径
    private String notifyUrl;

    private String spbillCreateIp;

    private String tradeType;

    private String openid;
    /**
     * HTTP(S) 连接超时时间,单位毫秒
     */
    private int httpConnectTimeoutMs;

    /**
     * HTTP(S) 读数据超时时间,单位毫秒
     */
    private int httpReadTimeoutMs;

    /**
     * API证书绝对路径
     */
    private String certPath;

    private String weChatRedirectUrl;
     @Override
    public InputStream getCertStream() {
        File certFile = new File(certPath);
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(certFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return inputStream;
    }

    @Override
    public String getKey() {
//        if (useSandbox) {
//            return sandboxKey;
//        }

        return key;
    }
    }

service(WechatPayService)

public interface WechatPayService {
   ResResult goWeChatPay(String money,String des, HttpServletRequest request) throws Exception;
   String reply(HttpServletRequest request, HttpServletResponse response) throws IOException;
}

上impl(WechatPayServiceImpl)之前还是先上一个获取IP的工具类和返回工具类( ResResult)

ResResult

@Data
public  class ResResult {
    private int code=200;
    private Object data;
    private String description="请求成功!";

    public  ResResult() {
    }
    public  ResResult ok(){
        return this;
    }
    public ResResult data(Object data){
        this.data=data;
        return this;
    }
    public ResResult err(int code,Object data,String des){
        this.code=code;
        this.data=data;
        this.description=des;
        return this;
    }
    public ResResult err(int code,Object data){
        this.code=code;
        this.data=data;
        this.description="请求失败!";
        return this;
    }
    public ResResult err(Object data,String des){
        this.code=500;
        this.data=data;
        this.description=des;
        return this;
    }
    static class Nei{
        private static ResResult resResult=new ResResult();


    }
}

GetRealyIp


import javax.servlet.http.HttpServletRequest;

public class GetRealyIp {
    public static String getIPAddress(HttpServletRequest request) {
        String ip = null;

        //X-Forwarded-For:Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //Proxy-Client-IP:apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //WL-Proxy-Client-IP:weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //HTTP_CLIENT_IP:有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //X-Real-IP:nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }

        //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }

        //还是不能获取到,最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}

impl(WechatPayServiceImpl)


@Service
public class WechatPayServiceImpl implements WechatPayService {
    @Autowired
    private Pay pay;

//这个是你你们本地的订单service,你们可以删除
    @Autowired
    private Orderservice orderservice;
    //这个是你你们本地的订单service,你们可以删除
        @Autowired
    private CoreUserService userService;
    
    public ResResult goWeChatPay(String money,String des, HttpServletRequest request) throws Exception {
        //new一个微信支付,实际开发中最好使用单例模式
        WXPay wxPay = new WXPay(pay);
        //订单实体,和你们的不同,你们自己换,我使用的是jpa,id是uaa自增长,我这样写的目的是
        //在下边能使用订单的id做一些事
        Orders order=new Orders();
        order.setCoreUser(user);
        order=orderservice.save(order);
        String outTradeNo= order.getId()
                .replaceAll("-","0")
                .substring(5);
        LocalDateTime time_start= LocalDateTime.now();
        String substring = time_start
                .toString()
                .substring(0, time_start.toString().lastIndexOf("."));
        substring=substring
                .replaceAll("-","")
                .replaceAll("T","")
                .replaceAll(":","")
                .substring(0,14);

        Map<String, String> params = new HashMap<String, String>();
        params.put("notify_url", pay.getNotifyUrl());
        params.put("device_info",pay.getDeviceInfo());
        params.put("total_fee", String.valueOf(money));
        params.put("trade_type",pay.getTradeType());
        params.put("body", des);//商品描述
        params.put("openid", user.getOpenId());
        params.put("out_trade_no", outTradeNo);
        params.put("spbill_create_ip", GetRealyIp.getIPAddress(request));
        params.put("time_start",String.valueOf(Long.parseLong(substring)));
        //加上下边这个东西好像报错,报一个啥啥一分钟,啥啥其他不能低于5分钟,忘记了,你们自行研究,
        //这里我是没搞好的,你们谁搞好了帮忙通知一哈我(微信:gdc1997i),谢谢
//        long expire = Long.parseLong(substring)+240;
//        params.put("time_expire", String.valueOf(expire));

//这下边也是我的订单实体的,你们自己换成你们自己的
        order.setWxOutTradeNo(outTradeNo);
        order.setOrderName(des);
        orderservice.save(order);

        System.out.println("out_trade_no:"+ outTradeNo);
        System.out.println("time_start:"+Long.parseLong(substring));
        Map<String, String> resultMap = null;
        try {
            resultMap = wxPay.unifiedOrder(params);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("--------------------------------------------------------------------------------");
        System.out.println("return_code:"+resultMap.get("result_code"));
        System.out.println("result_code:"+resultMap.get("result_code"));
        System.out.println("appid:"+resultMap.get("appid"));
        System.out.println("mch_id:"+resultMap.get("mch_id"));
        System.out.println("device_info:"+resultMap.get("device_info"));
        System.out.println("nonce_str:"+resultMap.get("nonce_str"));
        System.out.println("sign:"+resultMap.get("sign"));
        System.out.println("err_code:"+resultMap.get("err_code"));
        System.out.println("err_code_des:"+resultMap.get("err_code_des"));
        System.out.println("--------------------------------------------------------------------------------");
        if ("FAIL".equals(resultMap.get("return_code"))) {
        //这里,我是如果预下单不成功,就删除刚才新建的order
            orderservice.delete(order);
            System.out.println("FAIL");
            return new ResResult().err(500,resultMap);
        }else if ("SUCCESS".equals(resultMap.get("result_code"))) {
            System.out.println("trade_type:"+resultMap.get("trade_type"));
            System.out.println("prepay_id:"+resultMap.get("prepay_id"));
            System.out.println("code_url:"+resultMap.get("code_url"));
            Map<String,String> map=new HashMap<>();
            map.put("appId",resultMap.get("appid"));
            //微信那边要求时间戳只能是十位,我这样干估计有问题,但现在还没遇到,哈哈哈!
            String time = String.valueOf(System.currentTimeMillis()).substring(0,10);
            System.out.println("timeStamp:"+time);
            map.put("timeStamp",new Date().toString());
            map.put("nonceStr",WXPayUtil.generateNonceStr());
            map.put("package","prepay_id="+resultMap.get("prepay_id"));
            //加密方式和之前预下单的一样,预下单没看见传这个是因为它封装好了的,
            //可以从下单的那个方法跟着代码就能看见
            map.put("signType","MD5");
            String sing=WXPayUtil.generateSignature(map,pay.getKey());
            map.put("paySign",sing);
            //这里返回给前端
            return new ResResult().ok().data(map);
        }

        return null;
    }

//这个支付成功是返回通知
    @Override
    public String reply(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String res = "";
        InputStream inputStream = request.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF8));
        StringBuffer stringBuffer = new StringBuffer();
        String line = null;

        while((line = bufferedReader.readLine()) != null) {
            stringBuffer.append(line);
        }
        String xml = stringBuffer.toString();
        //System.out.println("微信支付成功,微信发送的callback信息,请注意修改订单信息");
        InputStream is = null;
        try {
            is = request.getInputStream();
            //获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
            String RETURN_CODE = "return_code";
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//将微信发的xml转map
            if(notifyMap.get("return_code").equals("SUCCESS")){
                if(notifyMap.get("result_code").equals("SUCCESS")){
               		 //商户订单号
                    String ordersSn = notifyMap.get("out_trade_no");
                    //实际支付的订单金额:单位 分
                    String amountpaid = notifyMap.get("total_fee");
                    //将分转换成元-实际支付金额:元
                    BigDecimal amountPay = (new BigDecimal(amountpaid).divide(new BigDecimal("100"))).setScale(2);
                     //如果有需要可以获取
                    String openid = notifyMap.get("openid");
                    String trade_type = notifyMap.get("trade_type");
                    /*以下是自己的业务处理------仅做参考
                     * 更新order对应字段/已支付金额/状态码
                     */
                 
                }
            }
            //告诉微信服务器收到信息了,不要在调用回调action了
            //========这里很重要回复微信服务器信息用流发送一个xml即可
            res= "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
			 response.getWriter().write(res);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return res;
    }
}

controller(WeichatPayController )

@RestController
@RequestMapping("pay")
public class WeichatPayController {
    @Autowired
    private WechatPayService wechatPayService;

    @RequestMapping("/wechatpay")
    public ResResult wxUnifiedorder(@RequestParam("money") String money,@RequestParam("des") String des, HttpServletRequest request) throws Exception {
      return wechatPayService.goWeChatPay(money,des, request) ;
    }

    @RequestMapping("hasOrder")
    public String  reply(HttpServletRequest request,HttpServletResponse response) throws Exception {

        response.getWriter().write( wechatPayService.reply(request, response));
        return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
    }
}

前端(我这里是没有前后端分离,引擎使用的是thymeleaf)

终于到最后一步了html,新建一个pay.html

pay.html的位置不必和我的一样,但方式一定一样,内容我就不全写了,把重要的部分干出来
immediateRecharge()这个函数就是你点击需要支付产品的时候出发的函数,它就会调起微信的h5支付页面

//这个必须要加载你的html那
    <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js" type="text/javascript"></script>
 

<script type="text/javascript">
    function addMoney(money) {
        $("#money").text(money);
    }
    var appId,timeStamp,nonceStr,package,signType,paySign;

    function immediateRecharge(){
    //money=9990不能是小数必须是整数,它那边还要化成元,基本单位是分,这个只是题外的话,不管他了
        var url="/pay/wechatpay?money=9990&des=佐良科技-会员"
        $.get(url,function(result) {
            if (result.data.code==200){
                appId = result.data.appId;
                timeStamp = result.data.timeStamp;
                nonceStr = result.data.nonceStr;
                package = result.data.package;
                signType = result.data.signType;
                paySign = result.data.paySign;
                if (typeof WeixinJSBridge == "undefined") {
                    if (document.addEventListener) {
                        document.addEventListener('WeixinJSBridgeReady',
                            onBridgeReady, false);
                    } else if (document.attachEvent) {
                        document.attachEvent('WeixinJSBridgeReady',
                            onBridgeReady);
                        document.attachEvent('onWeixinJSBridgeReady',
                            onBridgeReady);
                    }
                } else {
                    onBridgeReady();
                }
            }else {
                alert("服务器错误")
            }
        });
    }
    function onBridgeReady(){
        WeixinJSBridge.invoke( 'getBrandWCPayRequest', {
                "appId":appId, //公众号名称,由商户传入
                "timeStamp":timeStamp, //时间戳,自1970年以来的秒数
                "nonceStr":nonceStr, //随机串
                "package":package,
                "signType":signType, //微信签名方式:
                "paySign":paySign //微信签名
            },
            function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                    console.log('支付成功');
                    //支付成功后跳转的页面
                }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                    console.log('支付取消');
                }else if(res.err_msg == "get_brand_wcpay_request:fail"){
                    console.log('支付失败');
                    WeixinJSBridge.call('closeWindow');
                }
 //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
            });
    }
</script>

spring boot微信支付到此结束!

我也是第一次写这个csdn论坛的文章,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值