微信小程序的支付/退款

官网

我的代码百度云盘:

链接:https://pan.baidu.com/s/1hs-1HScGBGy4NpaHVenZ1g
提取码:jhfv

验证签名是否成功的网址

自己的经验

1.不要先去网上查找,先看官方的demo
2.尽量使用官方的demo里面的方法
3.注意入参的大小写的区分

支付

下载官网的demo,在idea打开

https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3

给的demo里面有很多api的调用(下单,查单,撤单,退单,退款等)

然后把这些类都复制到自己的项目中,然后再使用
注意点:
①appid和appID的区分,统一下单接口入参是appid,得到结果封装的时候是appId
② wxpay.unifiedOrder(data)这个统一下单的官方方法需要确认前后的编码一致(我遇到的坑,我使用md5,但是这个方法不是是另一个)
③ 前后的随机字符串nonce_str要保持一致
④注意支付的时候就会调用接口了,此时应该是待支付状态,输完密码后才会走回调然后在回调里面修改订单状态到已支付
⑤不输入密码是不会走回调的

支付回调的真是环境需要是https的,而且端口后的是开放给外部使用的

/**
     * 微信小程序支付
     */
    @PostMapping("/wx/pay02")
    public R wxPay02(String openid) throws Exception {

        Map resultMap=new HashMap();

        MyConfig config = null;
        WXPay wxpay =null;
        try {
            config = new MyConfig();
            wxpay= new WXPay(config);
        } catch (Exception e) {
            e.printStackTrace();
			logger.error("===new MyConfig();错误提示===", e);
        }
        //生成的随机字符串
        String nonce_str = WXPayUtil.generateNonceStr();
        
        //支付金额,需要转成字符串类型,否则后面的签名会失败
        int  total_fee=1;
        //商品描述
        String body = "车费支付";
        //商户订单号
        String out_trade_no= WXPayUtil.generateNonceStr();
        //统一下单接口参数
        HashMap<String, String> data = new HashMap<String, String>();
        data.put("appid", config.getAppID());
        data.put("mch_id", config.getMchID());
        data.put("nonce_str", nonce_str);
        data.put("body", body);
        data.put("out_trade_no",out_trade_no);
        data.put("total_fee", String.valueOf(total_fee));
        data.put("notify_url", "https://xxxxxx/wxapi/notice");
        data.put("trade_type","JSAPI");
          data.put("sign_type", "MD5");
        data.put("openid", openid);
        try {
            Map<String, String> rMap = wxpay.unifiedOrder(data); // 这个官网给的demo方法一定要注意编码方式要一致
            System.out.println("统一下单接口返回: " + rMap);
            String return_code = (String) rMap.get("return_code");
            String result_code = (String) rMap.get("result_code");
            resultMap.put("nonceStr", nonce_str);
            Long timeStamp = System.currentTimeMillis() / 1000;
            if ("SUCCESS".equals(return_code) && return_code.equals(result_code)) {
                String prepayid = rMap.get("prepay_id");
                resultMap.put("package", "prepay_id="+prepayid);
                resultMap.put("signType", "MD5");
                //这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误
                resultMap.put("timeStamp", timeStamp + "");
                //再次签名,这个签名用于小程序端调用wx.requesetPayment方法
                resultMap.put("appId",config.getAppID());
                String sign = WXPayUtil.generateSignature(resultMap, config.getKey());
                resultMap.put("paySign", sign);
                System.out.println("生成的签名paySign : "+ sign);
                return R.success(resultMap);
            }else{
                return  R.fail(444,"error");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return  R.fail(444,"error");
        }
    }

退款

官网:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_4
参考文档:

下载商家证书,再将证书放到项目中(resource/config)

注意是.p12的文件

下载官网的demo,把里面的所有工具类放入项目中

准备好8大参数

appid:公众账号ID
mch_id:商户号
nonce_str:随机字符串
out_trade_no:商户订单号
out_refund_no:商户退款单号
total_fee:订单金额
refund_fee:退款金额
sign:自己的签名。利用上面7个参数生成

写代码调用退款微信接口

public String wxRefundFee(String province, String oderno, String refunfee) {
        String wxUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund"; // 获取退款的api接口

        MyConfig config = null;
        try {
            config = new MyConfig();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 1.0 拼凑微信退款需要的参数
        String appid = config.getAppID();
        String mchid = config.getMchID();
        String outTradeNo = oderno; //商户订单号
        String outRefundNo = "un"+oderno;//商户退款单号

        // 车票金额
        ZycxOrder zycxOrder = orderMapper.findOrderByOrderno(oderno); //查看订单信息
        String Fee = StringUtils.substringBefore(String.valueOf(Float.valueOf(zycxOrder.getWebticketprice())*100),".");


        // 退票的手续费
        String refee = StringUtils.substringBefore(String.valueOf(Float.valueOf(refunfee) * 100), ".");
        String refundNeedFee = String.valueOf(Integer.parseInt(Fee) -Integer.parseInt(refee));
        System.out.println("退票费用计算成功");
        System.out.println("===========refee========" + refee);
        System.out.println("=========refundNeedFee==========" + refundNeedFee);
        //生成的随机字符串
        String nonceStr = WXPayUtil.generateNonceStr();

        System.out.println("===Fee========" + Fee);
        System.out.println("======refunfee=====" + refunfee);
        System.out.println("====refundNeedFee=======" + refundNeedFee);
        // 2.0 生成map集合
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid); // 微信公众号的appid
        packageParams.put("mch_id", mchid); // 商务号
        packageParams.put("nonce_str", nonceStr); // 随机生成后数字,保证安全性
        packageParams.put("out_trade_no", outTradeNo);
        packageParams.put("out_refund_no", outRefundNo);
        packageParams.put("total_fee", Fee); // 总费用
        packageParams.put("refund_fee", refundNeedFee); // 退款的费用

        try {
            // 3.0 利用上面的参数,先去生成自己的签名
            String sign = WXPayUtil.generateSignature(packageParams, AuthUtil.PATERNERKEY);
            // 4.0 将签名再放回map中,它也是一个参数
            packageParams.put("sign", sign);
            // 5.0将当前的map结合转化成xml格式
            String xml = WXPayUtil.mapToXml(packageParams);
            // 6.0获取需要发送的url地址
            System.out.println("发送前的xml为:" + xml);
            // 7,向微信发送请求转账请求
            String resource = "static/apiclient_cert.p12";
            System.out.println("开始查看绝对路径");

            WXPayRequest wxPayRequest = new WXPayRequest(config);
            WXPay wxPay = new WXPay(config);
            Map<String, String> refund = wxPay.refund(packageParams);

            System.out.println("返回的refund为:" + refund.toString());
            logger.info("返回的refund为: {}", refund.toString());
            // 8,将微信返回的xml结果转成map格式
            if (refund.get("return_code").equals("SUCCESS")) {
                // 退款成功
                return refund.toString();
            } else {
                return "wx fail";
            }


        } catch (Exception e) {

            logger.error("退款失败:{}", e);
            e.printStackTrace();
        }
        return WXPayConstants.FAIL;
    }

退款可能会遇到的问题

  1. No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

需要修改jdk的配置
https://blog.csdn.net/qq_41078608/article/details/124625998

我的myconfig继承与微信官方demo里面的wxpayconfig

package com.zhongyun.zycx.config;

import com.zhongyun.zycx.config.wxpay.IWXPayDomain;
import org.springframework.core.io.ClassPathResource;

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

/**
 * @author liangchao
 * @version 1.0
 * @date 2021/10/9 16:18
 */
public class MyConfig extends WXPayConfig {

    private byte[] certData;
    public MyConfig() throws Exception {

logger.error("进入MyConfig");
        // 生产
        String certPath = "/usr/tomcat/apache-tomcat-9.0.53/webapps/apiclient_cert.p12";
        // 测试
        /*String certPath = "E:\\aprogram\\zycx\\src\\main\\resources\\templates\\apiclient_cert.p12";*/
        File file = new File(certPath);
        InputStream certStream = new FileInputStream(file);
        this.certData = new byte[(int) file.length()];
        certStream.read(this.certData);
        certStream.close();
		//  这个踩了好多坑,一致读取不到p12的文件
       /* String certPath = "E:\\aprogram\\zycx\\src\\main\\resources\\static\\apiclient_cert.p12";
        System.out.println("myconfig开始查看绝对路径");
        ClassPathResource classPathResource = new ClassPathResource(certPath);
        File file = classPathResource.getFile();

        System.out.println("文件路径myconfig=============" + file.getAbsolutePath());
        InputStream certStream = new FileInputStream(file);
        this.certData = new byte[(int) file.length()];
        certStream.read(this.certData);
        certStream.close();*/
    }

    @Override
    public String getAppID() {
        return "wxxxxxxxxc";
    }

    @Override
    public String getMchID() {
        return "1xxxxxx";
    }

    @Override
    public String getKey() {
        return "xxxxx9d524dxxxxx6";
    }

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

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

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

    @Override
    public IWXPayDomain getWXPayDomain() {
        return new IWXPayDomain() {
            @Override
            public void report(String domain, long elapsedTimeMillis, Exception ex) {
            }

            @Override
            public DomainInfo getDomain(WXPayConfig config) {
                return new DomainInfo("api.mch.weixin.qq.com", false);
            }
        };
    }
}


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
你好!关于微信小程序的云开发退款问题,我可以为您提供一些指导。首先,请确保您已经了解微信支付相关的退款规则和流程。 在微信小程序的云开发中,退款通常涉及到两个方面:用户退款和后台退款。用户退款是指用户通过小程序发起退款申请,而后台退款是指开发者在后台进行退款操作。 对于用户退款,您可以通过微信支付的相关接口实现,具体步骤如下: 1. 用户在小程序中发起退款申请,并提供退款原因等必要信息。 2. 小程序调用微信支付退款接口,将退款请求发送给微信支付后台。 3. 微信支付后台验证退款请求的合法性,并进行退款处理。 4. 微信支付后台将退款结果返回给小程序,小程序根据退款结果进行相应的处理通知用户。 对于后台退款,您可以在小程序的服务端代码中调用微信支付的相关接口实现,具体步骤如下: 1. 在小程序的服务端代码中,构造退款请求参数,包括订单号、退款金额等必要信息。 2. 使用微信支付退款接口发送退款请求。 3. 接收并处理微信支付后台返回的退款结果。 需要注意的是,退款操作需要保证数据的安全性和准确性,建议在实际操作中加入适当的安全措施和数据验证机制。 此外,您还可以参考微信支付官方文档,了解更多关于小程序退款的详细操作步骤和接口使用说明。 希望以上信息能对您有所帮助!如有更多问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LC超人在良家

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

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

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

打赏作者

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

抵扣说明:

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

余额充值