JAVA微信扫码支付模式一线下支付功能实现

一、准备工作

无数人来追问模式一的开发,所以在这就贴出来,仅供参考。关于模式一和模式二的区别,我有解释过很多次,无非就是模式一的二维码是针对商品的,模式二的二维码是针对订单的,其他具体细节我就不费口舌了,各位可以自行去官方查看文档,然后是选模式一还是模式二就得看自己的业务了。

1.1、有关配置参数

还是之前那四样,APP_ID和APP_SECRET可以在公众平台找着,MCH_ID和API_KEY则在商户平台找到,特别是API_KEY要在商户平台设置好,这个东东关系到参数校验的正确与否,所以一定要设置正确。扫码支付模式一其实与扫码支付模式二类似,实际只会用到APP_ID、MCH_ID和API_KEY,其他的都不用。模式一的官方文档地址在这:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4

1.2、有关概念

在这里我想先修正一个概念,在之前模式二开发过程中我曾提到了一个“支付回调地址”这样的概念,其作用实际就是客户在扫描完成支付后,微信服务器要访问我们提供的这个地址,给我们发送支付结果,以便我们核实订单进行发货,这是其他支付工具比较普遍的概念和叫法。不过后来我翻了一下微信官网的文档,发现在模式一开发中,他们把这个叫做“异步通知url”而不是什么“支付回调地址”,但本质这指的是一个意思。可是为什么我要在这提到这个东东呢?这是因为在模式一中,实际上还有另外一个所谓的“支付回调”称之为“扫码支付回调URL”,这东东与上面的“异步通知url”可就不一样了,简单理解可以认为是咱们的服务器上一个用来辅助完成下单的接口。模式一的开发同时需要“扫码支付回调URL”与“异步通知url”两个接口配合才能完成,所以这里大家要辨别好了。

“异步通知url”在调用统一下单接口时进行设置,可以动态设置,只要这个接口按照有关规则接收参数响应参数即可。而“扫码支付回调URL”则较为固定,它在微信公众平台设置,设置后需要10分钟左右才能生效,大家登录微信公众平台后,选择微信支付,在开发配置选项卡下面就可以找着:

这里咱们要设置一个自己服务器的地址(再说一遍公网地址,就是让微信服务器能找着你)。

1.3、开发环境

我这里以最基本的Servlet 3.0作为示例环境。关于引用第三方的jar包,相比较于模式二开发,除了用到了xml操作的jdom,以外就一个Google ZXing的二维码包和log4j包。如下图:

为了方便调试,建议各位先在这个环境下调通了再移植到真实项目当中去。

二、开发实战

在动手之前,我建议大家先去官方文档那好好看看那个时序图,理解了那个时序图,写代码也就不是什么难事了,当然如果看图你没办法理解,也可以结合我下面的代码来试着理解。

2.1、二维码生成

首先是二维码,二维码中的内容为链接,形式为:

weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX

具体可以参考官方文档模式一生成二维码规则。接下来我们需要将该链接生成二维码,我这里使用了Google ZXing来生成二维码。

package com.wqy; 

import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap; 

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 

import org.apache.log4j.Logger; 

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.wqy.util.PayCommonUtil;
import com.wqy.util.PayConfigUtil; 

/**
 * Servlet implementation class Pay1
 */
@WebServlet("/Pay1")
public class Pay1 extends HttpServlet {
  private static final long serialVersionUID = 1L;
  private static Logger logger = Logger.getLogger(Pay1.class); 

  public static int defaultWidthAndHeight=200; 

  /**
   * @see HttpServlet#HttpServlet()
   */
  public Pay1() {
    super();
    // TODO Auto-generated constructor stub
  } 

  /**
   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
   *   response)
   */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException { 

    // TODO Auto-generated method stub
    String nonce_str = PayCommonUtil.getNonce_str();
    long time_stamp = System.currentTimeMillis() / 1000;
    String product_id = "hd_goodsssss_10";
    String key = PayConfigUtil.API_KEY; // key 

    SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
    packageParams.put("appid", PayConfigUtil.APP_ID);
    packageParams.put("mch_id", PayConfigUtil.MCH_ID);
    packageParams.put("time_stamp", String.valueOf(time_stamp));
    packageParams.put("nonce_str", nonce_str);
    packageParams.put("product_id", product_id);
    String sign = PayCommonUtil.createSign("UTF-8", packageParams,key);//MD5哈希
    packageParams.put("sign", sign);  

    //生成参数
    String str = ToUrlParams(packageParams);
    String payurl = "weixin://wxpay/bizpayurl?" + str;
    logger.info("payurl:"+payurl); 

    //生成二维码
    Map<EncodeHintType, Object> hints=new HashMap<EncodeHintType, Object>();
    // 指定纠错等级
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
    // 指定编码格式
    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    hints.put(EncodeHintType.MARGIN, 1);
    try {
      BitMatrix bitMatrix = new MultiFormatWriter().encode(payurl,BarcodeFormat.QR_CODE, defaultWidthAndHeight, defaultWidthAndHeight, hints);
      OutputStream out = response.getOutputStream();
      MatrixToImageWriter.writeToStream(bitMatrix, "png", out);//输出二维码
      out.flush();
      out.close(); 

    } catch (WriterException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  } 

  public String ToUrlParams(SortedMap<Object, Object> packageParams){
    //实际可以不排序
    StringBuffer sb = new StringBuffer();
    Set es = packageParams.entrySet();
    Iterator it = es.iterator();
    while (it.hasNext()) {
      Map.Entry entry = (Map.Entry) it.next();
      String k = (String) entry.getKey();
      String v = (String) entry.getValue();
      if (null != v && !"".equals(v)) {
        sb.append(k + "=" + v + "&");
      }
    } 

    sb.deleteCharAt(sb.length()-1);//删掉最后一个&
    return sb.toString();
  } 

  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
   *   response)
   */
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
  } 

}

2.2、扫描支付回调url接口

当客户用微信扫了上面的二位码之后,微信服务器就会访问此接口,在这里我们要完成统一下单获取交易会话标识,处理的主要流程如下:

1)、接收微信服务器发送过来的参数,对参数进行签名校验;

2)、取出参数product_id,这是二维码上唯一能够透传过来的参数,其他参数可参照官方文档模式一3.1 输入参数;

3)、根据product_id处理自己的业务,比如计算支付金额,生成订单号等;

4)、调用统一下单接口获取交易会话标识prepay_id;

4.1)、准备好相关参数(如appid、mch_id、支付金额、订单号、商品描述等),调用微信统一下单接口(与模式二调用统一下单接口类似),留意一下这里要加上上面提到的“异步通知url”,也就是后面会说道的异步通知url接口,具体参数参考官方文档统一下单请求参数;

4.2)、接收统一下单接口返回的参数,对参数进行验签;

4.3)、取出参数prepay_id,这是交易会话标识,极其重要,其他参数可参考官方文档统一下单返回结果;

5)、准备好相关参数(如appid、mch_id、return_code、prepay_id等),响应最开始的支付回调(如果上面步骤如果错误,如验签失败则可以返回错误参数给微信服务器),具体参数可参照官方文档模式一3.2 输出参数。

package com.wqy; 

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.SortedMap;
import java.util.TreeMap; 

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 

import org.apache.log4j.Logger; 

import com.wqy.util.HttpUtil;
import com.wqy.util.PayCommonUtil;
import com.wqy.util.PayConfigUtil; 

/**
 * Servlet implementation class Notify1
 */
@WebServlet("/Notify1")
public class Notify1 extends HttpServlet {
  private static final long serialVersionUID = 1L;
  private static Logger logger = Logger.getLogger(Notify1.class); 

  /**
   * @see HttpServlet#HttpServlet()
   */
  public Notify1() {
    super();
    // TODO Auto-generated constructor stub
  } 

  /**
   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
   *   response)
   */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // TODO Auto-generated method stub 

    // 读取xml
    InputStream inputStream;
    StringBuffer sb = new StringBuffer();
    inputStream = request.getInputStream();
    String s;
    BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
    while ((s = in.readLine()) != null) {
      sb.append(s);
    }
    in.close();
    inputStream.close(); 

    SortedMap<Object, Object> packageParams = PayCommonUtil.xmlConvertToMap(sb.toString());
    logger.info(packageParams);  

    // 账号信息
    String key = PayConfigUtil.API_KEY; // key 

    String resXml="";//反馈给微信服务器
    // 验签
    if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {
      //appid openid mch_id is_subscribe nonce_str product_id sign 

      //统一下单
      String openid = (String)packageParams.get("openid");
      String product_id = (String)packageParams.get("product_id");
      //解析product_id,计算价格等 

      String out_trade_no = String.valueOf(System.currentTimeMillis()); // 订单号
      String order_price = "1"; // 价格  注意:价格的单位是分
      String body = product_id;  // 商品名称 这里设置为product_id
      String attach = "XXX店"; //附加数据 

      String nonce_str0 = PayCommonUtil.getNonce_str(); 

      // 获取发起电脑 ip
      String spbill_create_ip = PayConfigUtil.CREATE_IP;
      String trade_type = "NATIVE";  

      SortedMap<Object,Object> unifiedParams = new TreeMap<Object,Object>();
      unifiedParams.put("appid", PayConfigUtil.APP_ID); // 必须
      unifiedParams.put("mch_id", PayConfigUtil.MCH_ID); // 必须
      unifiedParams.put("out_trade_no", out_trade_no); // 必须
      unifiedParams.put("product_id", product_id);
      unifiedParams.put("body", body); // 必须
      unifiedParams.put("attach", attach);
      unifiedParams.put("total_fee", order_price); // 必须
      unifiedParams.put("nonce_str", nonce_str0); // 必须
      unifiedParams.put("spbill_create_ip", spbill_create_ip); // 必须
      unifiedParams.put("trade_type", trade_type); // 必须
      unifiedParams.put("openid", openid);
      unifiedParams.put("notify_url", PayConfigUtil.NOTIFY_URL);//异步通知url 

      String sign0 = PayCommonUtil.createSign("UTF-8", unifiedParams,key);
      unifiedParams.put("sign", sign0); //签名 

      String requestXML = PayCommonUtil.getRequestXml(unifiedParams);
      logger.info(requestXML);
      //统一下单接口
      String rXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);  

      //统一下单响应
      SortedMap<Object, Object> reParams = PayCommonUtil.xmlConvertToMap(rXml);
      logger.info(reParams);  

      //验签
      if (PayCommonUtil.isTenpaySign("UTF-8", reParams, key)) {
        // 统一下单返回的参数
        String prepay_id = (String)reParams.get("prepay_id");//交易会话标识 2小时内有效 

        String nonce_str1 = PayCommonUtil.getNonce_str(); 

        SortedMap<Object,Object> resParams = new TreeMap<Object,Object>();
        resParams.put("return_code", "SUCCESS"); // 必须
        resParams.put("return_msg", "OK");
        resParams.put("appid", PayConfigUtil.APP_ID); // 必须
        resParams.put("mch_id", PayConfigUtil.MCH_ID);
        resParams.put("nonce_str", nonce_str1); // 必须
        resParams.put("prepay_id", prepay_id); // 必须
        resParams.put("result_code", "SUCCESS"); // 必须
        resParams.put("err_code_des", "OK"); 

        String sign1 = PayCommonUtil.createSign("UTF-8", resParams,key);
        resParams.put("sign", sign1); //签名 

        resXml = PayCommonUtil.getRequestXml(resParams);
        logger.info(resXml); 

      }else{
        logger.info("签名验证错误");
        resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
            + "<return_msg><![CDATA[签名验证错误]]></return_msg>" + "</xml> ";
      } 

    }else{
      logger.info("签名验证错误");
      resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
          + "<return_msg><![CDATA[签名验证错误]]></return_msg>" + "</xml> ";
    } 

    //------------------------------
    //处理业务完毕
    //------------------------------
    BufferedOutputStream out = new BufferedOutputStream(
        response.getOutputStream());
    out.write(resXml.getBytes());
    out.flush();
    out.close();  

  } 

  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
   *   response)
   */
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
  } 

}

至此,用户的微信单就会显示出要支付的金额及商品描述等,接下来就是等待客户完成支付。

2.3、异步通知url接口

当用户在微信上完成支付操作后,微信服务器就会异步通知这个接口,给我们发送最终的支付结果,以便我们核实订单进行发货等操作,注意这个接口和模式二的开发是一模一样的。大概流程如下:

1)、接收微信服务器发送过来的参数,对参数进行签名校验;

2)、取出参数result_code、订单号out_trade_no、订单金额total_fee及其他业务相关的参数,具体参数可参照官方文档支付结果通用通知的通知参数;

3)、处理业务,如校验订单号及订单金额、修改订单状态等;

4)、准备好相关参数(return_code和return_msg),应答微信服务器。

注意,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)

package com.wqy; 

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.SortedMap; 

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 

import org.apache.log4j.Logger; 

import com.wqy.util.PayCommonUtil;
import com.wqy.util.PayConfigUtil; 

/**
 * Servlet implementation class Re_notify
 */
@WebServlet("/Re_notify")
public class Re_notify extends HttpServlet {
  private static final long serialVersionUID = 1L;
  private static Logger logger = Logger.getLogger(Re_notify.class); 

  /**
   * @see HttpServlet#HttpServlet()
   */
  public Re_notify() {
    super();
    // TODO Auto-generated constructor stub
  } 

  /**
   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
   *   response)
   */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // TODO Auto-generated method stub
    // 读取参数
    InputStream inputStream;
    StringBuffer sb = new StringBuffer();
    inputStream = request.getInputStream();
    String s;
    BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
    while ((s = in.readLine()) != null) {
      sb.append(s);
    }
    in.close();
    inputStream.close(); 

    SortedMap<Object, Object> packageParams = PayCommonUtil.xmlConvertToMap(sb.toString());
    logger.info(packageParams); 

    // 账号信息
    String key = PayConfigUtil.API_KEY; // key 

    String resXml = ""; // 反馈给微信服务器
    // 判断签名是否正确
    if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {
      // ------------------------------
      // 处理业务开始
      // ------------------------------
      if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
        // 这里是支付成功
        ////////// 执行自己的业务逻辑////////////////
        String mch_id = (String) packageParams.get("mch_id");
        String openid = (String) packageParams.get("openid");
        String is_subscribe = (String) packageParams.get("is_subscribe");
        String out_trade_no = (String) packageParams.get("out_trade_no"); 

        String total_fee = (String) packageParams.get("total_fee"); 

        logger.info("mch_id:" + mch_id);
        logger.info("openid:" + openid);
        logger.info("is_subscribe:" + is_subscribe);
        logger.info("out_trade_no:" + out_trade_no);
        logger.info("total_fee:" + total_fee); 

        ////////// 执行自己的业务逻辑//////////////// 

        logger.info("支付成功");
        // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
        resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; 

      } else {
        logger.info("支付失败,错误信息:" + packageParams.get("err_code"));
        resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
      } 

    } else {
      logger.info("签名验证错误");
      resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
          + "<return_msg><![CDATA[签名验证错误]]></return_msg>" + "</xml> ";
    } 

    // ------------------------------
    // 处理业务完毕
    // ------------------------------
    BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
    out.write(resXml.getBytes());
    out.flush();
    out.close();
  } 

  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
   *   response)
   */
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
  } 

}

三、测试结果

3.1、生成的支付二维码链接

3.2、支付回调url接口接收到的参数

3.3、发起统一下单请求参数

3.4、统一下单返回参数

3.5、支付回调url接口最终的响应参数

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java通过JsApi方式实现微信支付

    要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回.由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分. 示例代码如下: function onBridgeReady(){ WeixinJSBridge

  • java服务端微信APP支付接口详解

    一.微信APP支付接入商户服务中心 [申请流程指引] (https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317780&token=84f23b4e9746c5963128711f225476cfd49ccf8c&lang=zh_CN) 二.开始开发 1.配置相关的配置信息 1.1.配置appid(Androi

  • 微信支付H5调用支付详解(java版)

    最近项目需要微信支付,然后看了下微信公众号支付,,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验. 一.配置公众号微信支付  需要我们配置微信公众号支付地址和测试白名单. 比如:支付JS页面的地址为 http://www.xxx.com/shop/pay/ 那此处配置www.xxx.com/shop/pay/ 二.开发流程 借用微信公众号支付api(地址 http://pay.weixin.qq.com/wiki/d

  • 微信APP支付Java代码

    本文实例为大家分享了java微信APP支付代码,供大家参考,具体内容如下 import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Random; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.apache.htt

  • Java微信支付之公众号支付、扫码支付实例

    微信支付现在已经变得越来越流行了,随之也出现了很多以可以快速接入微信支付为噱头的产品,不过方便之余也使得我们做东西慢慢依赖第三方,丧失了独立思考的能力,这次打算分享下我之前开发过的微信支付. 一 .H5公众号支付 要点:正确获取openId以及统一下单接口,正确处理支付结果通知,正确配置支付授权目录 H5的支付方式是使用较为广泛的方式,这种支付方式主要用于微信内自定义菜单的网页,依赖手机上安装的微信客户端,高版本的微信才支持微信支付,下面按我的流程注意说明 1  编写用于支付的页面,由于是测试用

  • Java SpringMVC实现PC端网页微信扫码支付(完整版)

    一:前期微信支付扫盲知识 前提条件是已经有申请了微信支付功能的公众号,然后我们需要得到公众号APPID和微信商户号,这个分别在微信公众号和微信支付商家平台上面可以发现.其实在你申请成功支付功能之后,微信会通过邮件把Mail转给你的,有了这些信息之后,我们就可以去微信支付服务支持页面:https://pay.weixin.qq.com/service_provider/index.shtml 打开这个页面,点击右上方的链接[开发文档]会进入到API文档说明页面,看起来如下 选择红色圆圈的扫码支付就

  • 微信支付java版本之查询订单

    本文实例为大家分享了微信支付订单的查询接口,供大家参考,具体内容如下 1.接口简介 2.代码实现 package com.zhrd.bussinss.platform.controller.shop; import java.io.File; import java.io.FileInputStream; import java.security.KeyStore; import java.text.SimpleDateFormat; import java.util.Date; import

  • java实现微信支付(服务端)

    废话不多说,直接看代码. RequestHandler requestHandler = new RequestHandler(super.getRequest(),super.getResponse()); //获取token //两小时内有效,两小时后重新获取 Token = requestHandler.GetToken(); //更新token 到应用中 requestHandler.getTokenReal(); System.out.println("微信支付获取token=====

  • java开发微信公众号支付

    最近做了微信公众号支付的开发,由于是第一次做也摸索了几天的时间,也只是达到了实现功能的水平,并没有太多考虑到性能问题,所以这篇文章比较适合初学者. 微信公众号支付的总体其实很简单,大致就分为三步.第一步需要获取用户授权:第二步调用统一下单接口获取预支付id:第三步H5调起微信支付的内置的js.下面介绍具体每一步的开发流程. 一    首先要明确微信公众号支付属于网页版支付,所以相较于app的直接调取微信支付要多一步微信授权.也就是需要获取用户的openid.微信公众号使用的交易类型是JSAPI,

  • Java微信支付-微信红包

    微信红包的使用已经很广泛,本篇文章介绍了微信发红包的实例,需要有认证的公众号,且开通了微信支付,商户平台且开通了现金红包的权限即可. https://pay.weixin.qq.com商户登陆地址.选择查看营销中心的现金红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_1 现金红包的官网文档说明 先看几个图 简单的测试.前提需要你去商户平台先充值.不支持预支付.本文只是总结微信现金红包接口的调用与

随机推荐