微信支付-小程序支付全流程

点击蓝色字关注我们!

一个努力中的公众号

长的好看的人都关注了

c2ac4bca82cab9a81192283308c956a7.png

本文给大家讲解微信小程序支付全流程,以及相关功能源代码,项目不开放,带来不便尽请谅解。小程序支付主要包含如下几步骤,1.预下单-调用微信统一下单接口进行预下单。2.小程序拿到支付参数唤醒支付。3.支付成功后发起退款申请
本文使用okHttpUtil进行接口交互 使用goole的gson与阿里的fastJson进行解析JsonObect,
使用封装的http工具类进行携带证书进行接口交互
使用封装的工具类实现map转xml等。相关工具类代码过多,所以在本文最后有下载方式

下面是正文:

微信支付文档:  https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

一.获取微信用户的openId:
    用户登录小程序 通过授权得到微信code,然后将微信code、秘钥、密文传递后端,后端进行解密后 得到微信openId(前端也可以进行解密,但建议放后端)
下面是获取openId的代码(java)

//微信接口url 
https://api.weixin.qq.com/sns/jscode2session

/**
 * 解析小程序登录数据获取参数
 * @param code  ---微信code
 * @param encryptedData --- 加密参数
 * @param iv --- 秘钥
 * @return
 */
public Result<?> getAuthByApplet(String code, String encryptedData,
     String iv) {

       Map<String, Object> resultMap = new HashMap<>();
   try {
    log.debug("=========小程序获取unionId=============: "+ code);
       //封装参数
             Map<String, String> params = new HashMap<String, String>();
      //获取小程序的openId
      params.put("appid", appletId);
      //微信秘钥

      params.put("secret", appletSecret);
      params.put("js_code", code);
      params.put("grant_type", "authorization_code");
      //调用接口进行读取参数
      JsonObject retJson =  OkHttpUtils.doGetRetJson(appletOpenIdUrl, params);
      log.debug(retJson.toString());
      //如果获取到了openId
      if(retJson.get("openid") != null) {
         //获取会话密钥(session_key)
         String session_key = retJson.get("session_key").getAsString();
     resultMap.put("session_key", session_key);
     resultMap.put("openId", retJson.get("openid").getAsString());
      }else{
         throw new Exception("code已失效,请重新获取");
      }
       return Result.ok(resultMap);
   } catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new RuntimeException();
   }
}

得到openId后要进行业务保存,因为小程序很多接口都依赖openId,而且同一小程序下,每个微信号的openId是一样的。


二:统一下单与小程序支付
    通过业务系统的封装参数,得到支付的商品信息,价格,业务订单后,封装参数,进行加密得到sign签名,然后调用统一下单接口进行下单,成功后返回小程序支付参数。

(需要注意的是 微信预下单请求参数要求是xml格式,全String类型)

//微信预下单接口url
https://api.mch.weixin.qq.com/pay/unifiedorder

   /**
* 微信支付-统一下单
* @param body --- 商品描述
* @param outTradeNo --- 业务系统订单号
* @param totalFee --- 支付金额
* @param spBillCreateIP ---支付人所在
* @param openId --- 支付人的微信openId

* @return

*/
@Override

public Map<String, String> toPay(String body, String outTradeNo,              String totalFee, String spBillCreateIP, String openId) {

try{

Map<String, String> map = new HashMap<>();       //封装支付必须参数

SortedMap<Object,Object> params = new TreeMap<Object,Object>();

//支付类型 String tradeType = "JSAPI";

      //支付后回调地址

      String notifyUrl = "";

String nonceStr = RandomUtil.randomString(16);
//小程序id
params.put("appid", appletId);
//商户平台id
params.put("mch_id", mchId);
//随机字符串
params.put("nonce_str", nonceStr);
//商品描述
params.put("body", body);
//商品订单号
params.put("out_trade_no", outTradeNo);
//价格的单位为分
params.put("total_fee", totalFee);
//支付ip
params.put("spbill_create_ip", spBillCreateIP);
//异步回调api
params.put("notify_url", notifyUrl);
//JSAPI、h5调用
params.put("trade_type", tradeType);
//支付用户openid
params.put("openid", openId);
String sign = WxPaySignatureUtils.createSign(params, key);
params.put("sign", sign);
String requestXML = WxPaySignatureUtils.getRequestXml(params);
log.info("发送给微信的报文:" + requestXML);
log.info("加密后的的签名字符串:" + sign);
//调用微信接口
String result = OkHttpUtils.postXml(unifiedorder, requestXML);
log.info("-------------------请求返回结果------------------");
log.info(result);
map = WXPayUtil.xmlToMap(result);
//如果返回有数据
if(map != null){
//并且返回有sign
if(map.get("sign") != null){
return map;
}
}
return map;
}catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException();
}
}

接口请求成功后,微信返回也是xml格式的报文,需要将xml转为map或其他,本文使用map接收参数,预下单后,微信会返回预付订单标识,标识用于进支付

//预付订单标识
String prepayId = resultMap.get("prepay_id");

然后封装小程序支付 所需参数

//签名类型,默认为MD5
String signType = "MD5";
SortedMap<Object,Object> params = new TreeMap<Object,Object>();
params.put("appId", appletId);
params.put("timeStamp", timestamp + "");
params.put("timeStamp", timestamp + "");
params.put("nonceStr", nonceStr);
params.put("package", "prepay_id=" + prepayId);
params.put("signType", signType);
//生成签名
String sign = WxPaySignatureUtils.createSign(params, key);
params.put("paySign", sign);

将支付参数返回给小程序,小程序通过组件 requestPayment 唤醒支付
小程序支付代码如下:

wx.requestPayment({

      timeStamp:param.result.timeStamp,

      nonceStr: param.result.nonceStr,

      package: param.result.package,

      signType:param.result.signType,

      paySign: param.result.paySign,

      success: function(res){

        console.log(res);

        wx.showToast({

          title: '支付成功',

          icon: 'success',

          duration: 2000

          });          

      },

      fail: function(res) {

        wx.showModal({

          title:'支付失败',

          content:'<text>',

          showCancel: false

        })

      }

    })


三: 退款
    小程序支付成功后,可以通过支付订单号进行退款操作,需要注意的是,退款需要http携带商户证书进行支付,这里图图已经封装好工具类只需要修改下证书的url就可以愉快使用了

//微信退款使用的url
https://api.mch.weixin.qq.com/secapi/pay/refund

/**
 * 微信支付-退款
 * @param transaction_id   ---微信支付订单
 * @param out_refund_no --- 系统退款单号
 * @param total_fee  --- 订单总金额
 * @param refund_fee  --- 退款金额
 * @return
 */
@Override
public Map<String, String> refundToPay(String transaction_id, String out_refund_no, String out_trade_no, int total_fee, int refund_fee) {
   //定义返回参数
   Map<String, String> map = new HashMap<>();
   try{
      SortedMap<Object,Object> params = new TreeMap<Object,Object>();
      String notifyUrl = "https://baidu.com";
      String nonceStr = RandomUtil.randomString(16);
      //小程序id
      params.put("appid", appletId);
      //商户平台id
      params.put("mch_id", mchId);
      //随机字符串
           params.put("nonce_str", nonceStr);
      //系统订单号
           params.put("out_trade_no", out_trade_no);
      //微信订单号
           params.put("transaction_id", transaction_id);
      //系统退款单号
          params.put("out_refund_no", out_refund_no);
      //订单金额
          params.put("total_fee", total_fee);
      //退款金额
          params.put("refund_fee", refund_fee);
      //签名
         String sign = WxPaySignatureUtils.createSign(params, key);
      params.put("sign", sign);
      //封装请求报文
        String requestXML = WxPaySignatureUtils.getRequestXml(params);
      log.info("发送给微信的报文:" + requestXML);
      log.info("加密后的的签名字符串:" + sign);
      //调用微信接口
        String result = WXPayUtil.doRefundRequest(mchId, refund, requestXML, certificateUrl);
      log.info("-------------------请求返回结果------------------");
      log.info(result);
      if(StrUtil.isNotEmpty(result)){
         map = WXPayUtil.xmlToMap(result);
         //如果返回有数据
                  if(map != null){
            //并且返回有sign
            if(map.get("sign") != null){
               return map;
            }
         }
      }else{
         log.info("-------------------请求返回空结果------------------");
      }
      return map;
   }catch (Exception e) {
      log.error(e.getMessage(), e);
      throw new RuntimeException();
   }
}

本文中所使用到的工具类,图图已经帮大家打包好了,一份在百度网盘,为防止百度网盘失效,在图图的QQ群中也有一份。

百度网盘下载链接

链接:https://pan.baidu.com/s/1YbMrvO3qK1rdmyYyET2xzw

提取码:ljv6

本文先总结到此,后面继续更新技术一些文章。大家一起加油鸭!

如果对您有帮助 请点个关注,万分感谢
          

                                (QQ招聘群  710566091
                                 微信招聘群 请加图图微信)

89a85b0803073e55df09ecbbb4aca58e.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
老规矩,先看本节效果图我们实现这个支付功能完是借助小程序云开发实现的,不用搭建自己的服务器,不用买域名,不用备案域名,不用支持https。只需要一个简单的云函数,就可以轻松的实现微信小程序支付功能。核心代码就下面这些一,创建一个云开发小程序关于如何创建云开发小程序,这里我就不再做具体讲解。不知道怎么创建云开发小程序的同学,可以去翻看我之前的文章,或者看下我录制的视频:https://edu.csdn.net/course/play/9604/204528创建云开发小程序有几点注意的1,一定不要忘记在app.js里初始化云开发环境。2,创建完云函数后,一定要记得上传二, 创建支付的云函数1,创建云函数pay三,引入三方依赖tenpay我们这里引入三方依赖的目的,是创建我们支付时需要的一些参数。我们安装依赖是使用里npm 而npm必须安装node,关于如何安装node,我这里不做讲解,百度一下,网上一大堆。1,首先右键pay,然后选择在终端中打开2,我们使用npm来安装这个依赖。在命令行里执行 npm i tenpay安装完成后,我们的pay云函数会多出一个package.json 文件到这里我们的tenpay依赖就安装好了。四,编写云函数pay完整代码如下//云开发实现支付 const cloud = require('wx-server-sdk')cloud.init() //1,引入支付的三方依赖 const tenpay = require('tenpay'); //2,配置支付信息 const config = ;exports.main = async(event, context) => 一定要注意把appid,mchid,partnerKey换成你自己的。到这里我们获取小程序支付所需参数的云函数代码就编写完成了。不要忘记上传这个云函数。出现下图就代表上传成功五,写一个简单的页面,用来提交订单,调用pay云函数。这个页面很简单,1,自己随便编写一个订单号(这个订单号要大于6位)2,自己随便填写一个订单价(单位是分)3,点击按钮,调用pay云函数。获取支付所需参数。下图是官方支付api所需要的一些必须参数。下图是我们调用pay云函数获取的参数,和上图所需要的是不是一样。六,调用wx.requestPayment实现支付下图是官方的示例代码这里不在做具体讲解了,完整的可以看视频。实现效果1,调起支付键盘2,支付完成3,log日志,可以看出不同支付状态的回调上图是支付成功的回调,我们可以在支付成功回调时,改变订单支付状态。下图是支付失败的回调,下图是支付完成的状态。到这里我们就轻松的实现了微信小程序支付功能了。是不是很简单啊,完整的讲解可以看视频。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值