微信小程序-微信支付

本文介绍了微信小程序支付的开发过程,包括前端获取code、后端换取openid、调用微信统一下单接口生成预支付id,以及二次签名的步骤。在统一下单过程中详细阐述了必填参数、注意事项和解决签名错误的方法。最后提到了支付成功后的回调函数和关键工具类的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近写了一个微信小程序的后端,微信支付(Java版)。在这里分享一下开发过程吧。

在这里插入图片描述
首先我们要先去了解微信小程序支付开发的过程。

这里说一下流程。

  1. 微信小程序端获取到code,由微信小程序前端传code到后端,
  2. 后端接收到code去调用微信官方接口换取openid。
  3. 生成商户订单,即通过xml格式包含文档中必填的参数去调用统一下单接口(附下图),返回prepay_id.
  4. 当然微信小程序需要二次签名,同样通过必填参数封装,返回给微信小程序端。(其中有很多坑,下文慢慢讲解)

正文开始

1、微信小程序前端获取到code

//获取code的方法
	wx.login({
   
    success: res => {
   
        console.log("向后台传递获取用户的信息的地址");
        console.log(res.code);
       // 发送 res.code 到后台换取 openId
       //此处可以请求后台接口获取openid
   }
})

2.后台接收到code后,通过拼接字符串请求地址,返回openid(在后续附上工具类)

public static String getOpenId(String code) {
   
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + 你的APP_ID +
                "&secret=" + 你的APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
        HttpUtil httpUtil = new HttpUtil();
        try {
   
            HttpResult httpResult = httpUtil.doGet(url, null, null);
            if (httpResult.getStatusCode() == 200) {
   
                JsonParser jsonParser = new JsonParser();
                JsonObject obj = (JsonObject) jsonParser.parse(httpResult.getBody());
                System.out.println("getOpenId: " + obj.toString());
                if (obj.get("errcode") != null) {
   
                    System.out.println("getOpenId returns errcode: " + obj.get("errcode"));
                    return "";
                } else {
   
                    return obj.get("openid").toString();
                }
                //return httpResult.getBody();
            }
        } catch (Exception e) {
   
            e.printStackTrace();
        }
        return "";
    }

3.其次是调用统一下单接口,(这一步也是很多人采坑的地方)官方详细文档

  1. 统一下单接口访问的接口为:https://api.mch.weixin.qq.com/pay/unifiedorder
  2. 统一下单接口必填参数为:[共十个]appid(小程序ID),mch_id(商户号),nonce_str(随机字符串),sign(签名),body(商品描述),out_trade_no(商户订单号),total_fee(标价金额),spbill_create_ip(终端ip),notify_url(回调地址),trade_type(交易类型)

**注意:**这里的nonce_str必须与再次签名的随机字符串为同一值。

我这里是通过封装一个实体类,对类进行赋值取值。 (当然,嫌麻烦的可以直接全部写在配置类中)

public class PayInfo implements Serializable {
   
    private String appid;//appid
    private String body;//商品描述
    private String mch_id;//商户号
    //private String device_info; //设备号,小程序传"WEB"
    private String nonce_str;//随机字符串
    private String notify_url;//通知地址
    private String openid;//用户标识
    private String out_trade_no;//商户订单号
    private String sign;//签名
    private String sign_type;  //签名类型
    private String spbill_create_ip;//终端ip
    //private String detail;//商品详情
    //private String attach;附加数据
    private String time_expire;//交易结束时间
    private String time_start;//起始交易时间
    private int total_fee;//商户金额
    private String trade_type; //交易类型,JSAPI
    //private String limit_pay;  //指定支付方式,no_credit
    private String TimeStamp;
    private String repay_id;//这里应该设置package,但是是关键字。
    private String key;

…省略get和set…

这一步是 对实体类设置需要的值。(酌情修改参数,不必填的可以注释掉,上面写了必填参数!) 注意:微信官方要求md5加密必须符合字母表顺序,这一步在写实体类的时候要注意(属性名要按字母表写)。

set和get方法不影响。

private PayInfo createPayInfo(String openId, String clientIP, String randomNonceStr) {
   
        Date date = new Date();
        String timeStart = TimeUtils.getFormatTime(date, Constant.TIME_FORMAT);
        String timeExpire = TimeUtils.getFormatTime(TimeUtils.addDay(date, Constant.TIME_EXPIRE), Constant.TIME_FORMAT);

        String randomOrderId = CommonUtil.getRandomOrderId();

        PayInfo payInfo = new PayInfo();
        payInfo.setAppid(Constant.APP_ID);
        payInfo.setMch_id(Constant.MCH_ID);
        payInfo.setDevice_info("WEB");
        payInfo.setNonce_str(randomNonceStr);
        payInfo.setSign_type("MD5");  //默认即为MD5
        payInfo.setBody("JSAPI支付测试");//这里如果是中文需要进行转码,不然可能会报错
        payInfo.setAttach("支付测试4luluteam");
        payInfo.setOut_trade_no(randomOrderId);
        payInfo.setTotal_fee(1);
        payInfo.setSpbill_create_ip(clientIP);
        payInfo.setTime_start(timeStart);
        payInfo.setTime_expire(timeExpire);
        payInfo.setNotify_url(Constant.URL_NOTIFY);
        payInfo.setTrade_type("JSAPI");
        payInfo.setLimit_pay("no_credit");
        payInfo.setOpenid(openId);

        return payInfo;

设置好参数,这一步是对字符串进行拼接。目的是md5加密!(酌情删减)

 private String getSign(PayInfo payInfo) throws Exception {
   
        StringBuffer sb = new StringBuffer();
        sb.append("appid=" + payInfo.getAppid())
                .append("&attach=" + payInfo.getAttach())
                .append("&body=" + payInfo.getBody())
                .append("&device_info=" + payInfo.getDevice_info())
                .append("&limit_pay=" + payInfo.getLimit_pay())
                .append("&mch_id=" + payInfo.getMch_id())
                .append("&nonce_str=" + payInfo.getNonce_str())
                .append("&notify_url=" + payInfo.getNotify_url())
                .append("&openid=" + payInfo.getOpenid())
                .append("&out_trade_no=" + payInfo.getOut_trade_no())
                .append("&sign_type=" + payInfo.getSign_type())
                .append("&spbill_create_ip=" + payInfo.getSpbill_create_ip())
                .append("&time_expire=" + payInfo.getTime_expire())
                .append("&time_start=" + payInfo.getTime_start())
                .append("&total_fee=" + payInfo.getTotal_fee())
                .append("&trade_type=" + payInfo.getTrade_type())
                .append("&key=" + Constant.APP_KEY);

        log.error("排序后的拼接参数:" + sb.toString());

        return CommonUtil.getMD5(sb.toString().trim()).toUpperCase
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值