微信支付功能模块

 微信支付(H5)主要流程

1、用户打开页面,点击购买按钮

2、传递商品的id和价格到createCodeController

3、获得价格并搭配商户信息,发送给微信支付系统进行下单

4、返回支付链接到createCodeController,生成支付二维码

5、返回二维码到页面窗口,用户再进行扫码支付

6、间歇查询支付状态,传递订单号给checkOrderStatusController

7、获得订单号并搭配商户信息,发送到微信支付系统查询订单状态

8、返回当前订单支付状态到checkOrderStatusController,判断当前支付状态,向前端返回json信息

9、更新页面显示的支付状态信息

 微信支付配置

public class PayConfig {
    // 企业公众号 ID
    public static String appid="wx************42e";
    // 财付通平台的商户帐号
    public static String partner="15******81";
    // 财付通平台的商户密钥
    public static String partnerKey="HJ******************gfg";
    // 回调 URL
    public static String notifyurl="你的回调地址";
}

微信支付配置模板(当前项目)

import com.github.wxpay.sdk.WXPayConfig;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

public class MyWXPayConfig implements WXPayConfig {
    private String appID;
    private String mchID;
    private String key;
    private InputStream certStream;
    private String domain;
    private int connectTimeoutMs;
    private int readTimeoutMs;
    private boolean useSandboxEnv;

    public MyWXPayConfig(String appID, String mchID, String key, String certPath,
                         String domain, int connectTimeoutMs, int readTimeoutMs, boolean useSandboxEnv) throws Exception {
        this.appID = appID;
        this.mchID = mchID;
        this.key = key;
        this.domain = domain;
        this.connectTimeoutMs = connectTimeoutMs;
        this.readTimeoutMs = readTimeoutMs;
        this.useSandboxEnv = useSandboxEnv;

        if (certPath != null) {
            this.certStream = new ByteArrayInputStream(readCertData(certPath));
        }
    }

    private byte[] readCertData(String certPath) throws Exception {
        // 根据certPath读取证书文件的内容,并返回字节数组形式
        // 这里省略具体的读取过程,请根据实际情况进行实现
        // 示例代码:
        // FileInputStream fis = new FileInputStream(certPath);
        // byte[] data = new byte[fis.available()];
        // fis.read(data);
        // fis.close();
        // return data;
        return null;
    }

    @Override
    public String getAppID() {
        return appID;
    }

    @Override
    public String getMchID() {
        return mchID;
    }

    @Override
    public String getKey() {
        return key;
    }

    @Override
    public InputStream getCertStream() {
        return certStream;
    }

    @Override
    public int getHttpConnectTimeoutMs() {
        return connectTimeoutMs;
    }

    @Override
    public int getHttpReadTimeoutMs() {
        return readTimeoutMs;
    }

//    @Override
//    public boolean useSandbox() {
//        return useSandboxEnv;
//    }
//
//    @Override
//    public WXPayConstants.SignType getSignType() {
//        return WXPayConstants.SignType.MD5;
//    }
//
//    @Override
//    public String getDomain() {
//        return domain;
//    }
}

微信支付控制层

import com.edu.api.entity.PayOrder;
import com.edu.api.vo.Result;
import com.edu.pay.config.MyWXPayConfig;
import com.edu.pay.config.PayConfig;
import com.edu.pay.service.PayOrderService;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.jfinal.kit.HttpKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

@RestController
@RequestMapping("/pay")
public class PayController {


    @Autowired
    private PayOrderService payOrderService;


    @PostMapping("/savePayOrder")
    public Result savePayOrder(@RequestBody PayOrder payOrder){
        return Result.ok(payOrderService.saveOrder(payOrder));
    }

    @PostMapping("/updatePayOrder")
    public Result updatePayOrder(@RequestBody PayOrder payOrder){
        return Result.ok(payOrderService.updateOrder(payOrder));
    }

    /**
     * 创建支付二维码
     * @param courseid
     * @param coursename
     * @param price
     * @return
     * @throws Exception
     */
    @GetMapping("/createCode")
    public Object createCode(String courseid,String coursename, String price) throws Exception {

        //1.编写商户信息
        Map<String,String> mm = new HashMap();
        mm.put("appid", PayConfig.appid); //公众账号ID
        mm.put("mch_id",PayConfig.partner);//商户号
        mm.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        mm.put("body",coursename); //商品名称
        String orderId = WXPayUtil.generateNonceStr();
        System.out.println("订单编号 = "+orderId);
        mm.put("out_trade_no",orderId); //商户订单号
        mm.put("total_fee",price+""); //订单金额,单位分
        mm.put("spbill_create_ip","127.0.0.1"); //终端IP
        mm.put("notify_url",PayConfig.notifyurl); //通知地址
        mm.put("trade_type","NATIVE"); //交易类型
        System.out.println("发送的map = "+mm.toString());
        
        //2.生成数字签名,并把上面的map转换成xml格式
        String xml = WXPayUtil.generateSignedXml(mm,PayConfig.partnerKey);
        System.out.println("转换后的xml = "+xml);

        //3.将数据发送给微信后台,并得到微信后台返回的数据
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String result = HttpKit.post(url,xml);
        System.out.println("返回的xml = "+result); //如果报错:<![CDATA[签名错误]]> 商户四要素的原因,重置商户API密钥。

        //4.后台返回的xml格式,转成map,并添加两个参数
        Map<String,String> resultMap = WXPayUtil.xmlToMap(result);
        resultMap.put("orderId",orderId);
        resultMap.put("money",price+"");

        //5.将map返回给浏览器
        return resultMap;
    }
    
    /**
     * 关闭订单
     * @param orderNo
     * @return
     * @throws Exception
     */
    @GetMapping("/closeOrder")
    public Boolean closeOrder(String orderNo) throws Exception {
        WXPayConfig wxPayConfig = new MyWXPayConfig(PayConfig.appid, PayConfig.partner, PayConfig.partnerKey, null,
                "api.mch.weixin.qq.com", 5000, 5000, false);
        WXPay wxPay = new WXPay(wxPayConfig, WXPayConstants.SignType.MD5, false);
        Map<String, String> respData;
        Map<String, String> data = new TreeMap<>();
        data.put("appid", PayConfig.appid);
        data.put("mch_id",PayConfig.partner);  // 商户号
        data.put("out_trade_no", orderNo); // 商户订单号
        data.put("nonce_str", WXPayUtil.generateNonceStr()); // 随机字符串小于32位
        String sign = WXPayUtil.generateSignature(data, PayConfig.partnerKey);
        data.put("sign", sign);
        // 调用微信关闭订单接口
        respData = wxPay.closeOrder(data);
        if (respData.get("return_code").equals("SUCCESS")) {
            System.out.println("关闭订单成功!");
            return true;
        }
        return false;
    }
    
    /**
     * 回调地址
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("wxCallback")
    public String wxCallBack(HttpServletRequest request, HttpServletResponse response) throws IOException {
        InputStream inStream = null;
        ByteArrayOutputStream outSteam = null;
        String resultxml = null;
        try {
            inStream = request.getInputStream();
            outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            resultxml = new String(outSteam.toByteArray(), "utf-8");
        } catch (Exception e) {
            System.out.println("回调处理失败");
        }finally {
            if(null != outSteam) {
                outSteam.close();
            }
            if(null != inStream) {
                inStream.close();
            }
        }
        System.out.println("wxCallback - 回调请求参数:"+ resultxml);
        return resultxml;
    }

    /**
     * 检查支付状态
     * @param orderId
     * @return
     * @throws Exception
     */
    @GetMapping("checkOrderStatus")
    public Object checkOrderStatus(String orderId) throws Exception {
        //1.编写商户信息
        Map<String,String> mm = new HashMap();
        mm.put("appid",PayConfig.appid); //公众账号ID
        mm.put("mch_id",PayConfig.partner);//商户号
        mm.put("out_trade_no",orderId);//订单编号
        mm.put("nonce_str",WXPayUtil.generateNonceStr()); //随机字符串
        System.out.println(mm);
        //2.生成数字签名,并把上面的map转换成xml格式
        String xml = WXPayUtil.generateSignedXml(mm, PayConfig.partnerKey);
        System.out.println(xml);

        //3.将数据发送给微信后台,并得到微信后台返回的数据
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";

        //第一次询问时间
        long beginTime = System.currentTimeMillis();

        while(true) { //不停的去微信后台询问是否支付
            String result = HttpKit.post(url, xml);
            System.out.println(result);//报错:<![CDATA[签名错误]]>

            //4.后台返回的xml格式,转成map,并添加两个参数
            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
            // 测试不支付
            // resultMap.put("trade_state","success");

            //5.将map转成json并返回给浏览器
            //已经成功支付,停止询问
            if(resultMap.get("trade_state").equalsIgnoreCase("success")){
                // 测试不支付
                // Thread.sleep(3000);
                return resultMap;
            }
            //超过30秒未支付,停止询问
            if(System.currentTimeMillis() - beginTime > 30000){
                return resultMap;
            }
            Thread.sleep(3000); //每隔3秒,询问一次微信后台
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

°听风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值