IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> SpringBoot微信支付 -> 正文阅读

[移动开发]SpringBoot微信支付

本地模拟微信支付回调

  • 因微信支付回调是由拉起支付时的notify_url属性设置,notify_url 是由微信服务器请求自己项目暴露出的指定的接口地址(公网IP);在生产环境中项目接口地址微信服务器请求必须可达;
  • 则在本地服务支付回调接口需要测试时,可以通过从线上服务器中获取微信回调XML数据,在本地使用Postman模拟支付回调进行接口测试。

示例代码:

1.微信支付SDK

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

2.微信支付小程序配置

public class OurWxPayConfig implements WXPayConfig {
    private final static String APP_KEY = "APPId";
    private final static String MCH_ID = "商户ID";
    private final static String KEY = "小程序Key";
    private final static String SECRET = "小程序密钥";

    /**
     * 加载证书  这里证书需要到微信商户平台进行下载
     */
    private byte[] certData;

    public OurWxPayConfig() throws Exception {
        InputStream certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("apiclient_cert.p12");
        this.certData = IOUtils.toByteArray(certStream);
        certStream.close();
    }

    /**
     * 设置我们自己的appid
     * 商户号
     * 秘钥
     */

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

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


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

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

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

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

    public String getSecret() {
        return SECRET;
    }
}

2.1.支付POJO

@ToString
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class PayOrderInfo implements Serializable {

    private static final long serialVersionUID = -3133004352432358931L;

    /**
     * 商户订单Id = 微信回调 out_trade_no
     */
    @TableId(type = IdType.INPUT)
    private String id;

    /**
     * 金额
     */
    private Float money;

    /**
     * 订单创建时间
     */
    private Date createTime;

    /**
     * 订单结束时间
     */
    private Date endTime;

    /**
     * 实际付款金额
     */
    private Float payMoney;

    /**
     * 支付商户订单号
     */
    private String payOrder;

    /**
     * 订单付款时间
     */
    private Date orderPayTime;

}

2.2.支付后台关键业务方法

	/**
	* 执行支付关键方法拉起
	*/
	@Override
    public JSONObject execPay(JSONObject requestParam, HttpServletRequest request) throws Exception {
        JSONObject attach = new JSONObject();
        String spbill_create_ip = request.getRemoteAddr();
        String out_trade_no = requestParam.getString("order_id");
        String openid = requestParam.getString("openid");

        PayOrderInfo orderById = payOrderInfoService.getById(out_trade_no);
        Float total_fee = orderById.getPayMoney();
        String body = "订单实付金额:" + orderById.getPayMoney();
        OurWxPayConfig ourWxPayConfig = new OurWxPayConfig();
        WXPay wxPay = new WXPay(ourWxPayConfig);
        //根据微信支付api来设置
        Map<String, String> data = new HashMap<>();
        data.put("appid", ourWxPayConfig.getAppID());
        data.put("mch_id", ourWxPayConfig.getMchID());
        data.put("spbill_create_ip", spbill_create_ip);//终端ip
        data.put("trade_type", "JSAPI");//支付场景 APP 微信app支付 JSAPI 公众号支付  NATIVE 扫码支付
        data.put("notify_url", notifyUrl);//回调地址
        //total_fee提交内容:金额*100
        data.put("total_fee", String.valueOf(Math.round(total_fee * 100)));//订单总金额
        data.put("fee_type", "CNY");//默认人民币
        data.put("out_trade_no", out_trade_no);//商户id
        data.put("body", body);//订单信息描述
        data.put("openid", openid);   // openId
        data.put("sign_type", "MD5");   // 签名类型

        //生成首次签名
        String sign = WXPayUtil.generateSignature(data, ourWxPayConfig.getKey());
        data.put("sign", sign); // sign

        //调用微信统一下单接口
        Map<String, String> wxRespData = wxPay.unifiedOrder(data);
        if (wxRespData.get("return_code").equals("SUCCESS")) {
            try {
                //根据统一下单数据包装获取二次签名
                String timeStamp =
                			String.valueOf(System.currentTimeMillis() / 1000);//注意该单位一定得是秒
                String nonceStr = WXPayUtil.generateNonceStr();
                Map<String, String> sign2Map = new HashMap<>();
                sign2Map.put("appId", ourWxPayConfig.getAppID());
                sign2Map.put("nonceStr", nonceStr);
                sign2Map.put("package", "prepay_id=" + wxRespData.get("prepay_id"));
                sign2Map.put("signType", "MD5");
                sign2Map.put("timeStamp", timeStamp);
                //获取二次签名并封装前端拉起的时需要的数据
                String paySign = WXPayUtil.generateSignature(sign2Map, ourWxPayConfig.getKey());
                attach.put("paySign", paySign);
                attach.put("prepay_id", wxRespData.get("prepay_id"));
                attach.put("appId", ourWxPayConfig.getAppID());
                attach.put("key", ourWxPayConfig.getKey());
                attach.put("signType", "MD5");
                attach.put("nonceStr", nonceStr);
                attach.put("timeStamp", timeStamp);
                return attach;//返回前端拉去数据
            } catch (RuntimeException e) {
                log.error(" --- 订单拉起支付失败");
            }
        }
        throw new JeecgBootException("微信支付订单出现错误");
    }

2.3.前端获取签名进行支付窗口拉起

pay(res){
    const packages='wxpay'
    //前端拉起支付当前时间(单位必须得是秒)
    let timeStamp = String(Date.now()/1000).substr(0,10)
    let nonceStr = res.data.result.nonceStr
    let packageStr = 'prepay_id='+res.data.result.prepay_id
    let signTypeStr = 'MD5'
    let key=res.data.result.key
    let sign = res.data.result.paySign
    wx.requestPayment({
        timeStamp: res.data.result.timeStamp,
        nonceStr: nonceStr ,
        package: packageStr,
        signType: signTypeStr,
        paySign: sign,
        success:  (res) =>{  
      uni.redirectTo({
       url:'***'
      })
        },
        fail:  (errs)=> {
         this.$u.toast('支付失败')
        }
    });
   },

3.微信支付回调接口

 @ApiOperation("blogDemo")
    @RequestMapping(value = "/blogDemo")
    public void blogDemo(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Lock lock = this.lock;
        lock.lock();
        try {
            OurWxPayConfig ourWxPayConfig = new OurWxPayConfig();
            WXPay wxpay = new WXPay(ourWxPayConfig);
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            response.setHeader("Access-Control-Allow-Origin", "*");

            DataInputStream in;
            String wxNotifyXml = "";
            try {
                in = new DataInputStream(request.getInputStream());
                byte[] dataOrigin = new byte[request.getContentLength()];
                in.readFully(dataOrigin); // 根据长度,将消息实体的内容读入字节数组dataOrigin中

                in.close(); // 关闭数据流
                wxNotifyXml = new String(dataOrigin); // 从字节数组中得到表示实体的字符串
                //可通过这行代码获取微信回调xml数据
               	log.error(" --- wxNotifyXml->[{}]", wxNotifyXml);
            } catch (IOException e) {
                e.printStackTrace();
            }

            Map<String, String> wxResponse = wxpay.processResponseXml(wxNotifyXml);
            // 解析各种数据
            if (wxResponse.get("result_code").equalsIgnoreCase("SUCCESS") && wxResponse.get("return_code").equalsIgnoreCase("SUCCESS")) {
                String out_trade_no = wxResponse.get("out_trade_no");//商户保存订单号(自身业务保存订单好)
                String transaction_id = wxResponse.get("transaction_id");//微信支付订单号(微信生成的订单号)
            }
        } finally {
            lock.unlock();
        }
    }

3.1.从公网服务器中获取接口微信回调的xml数据

在这里插入图片描述

3.2Postman接口请求配置

Postman接口请求配置
在这里插入图片描述
本地请求成功!注:服务器行获取的xml数据内容不可改变,如果订单内容有变动,得从服务器上获取新的xml数据

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-29 13:09:42  更:2021-10-29 13:11:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:09:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码