1. 程式人生 > 實用技巧 >微信APP支付入門

微信APP支付入門

場景介紹

適用於商戶在移動端APP中整合微信支付功能。

商戶APP呼叫微信提供的SDK呼叫微信支付模組,商戶APP會跳轉到微信中完成支付,支付完後跳回到商戶APP內,最後展示支付結果。

目前微信支付支援手機系統有:IOS(蘋果)、Android(安卓)和WP(Windows Phone)。

互動細節如下:

步驟1:使用者進入商戶APP,選擇商品下單、確認購買,進入支付環節。商戶服務後臺生成支付訂單,簽名後將資料傳輸到APP端。以微信提供的DEMO為例,見圖8.1。

步驟2:使用者點選後發起支付操作,進入到微信介面,調起微信支付,出現確認支付介面,見圖8.2。

步驟3:使用者確認收款方和金額,點選立即支付後出現輸入密碼介面,可選擇零錢或銀行卡支付見圖8.3。

圖8.1 商戶APP介面例項

圖8.2 跳轉到微信支付

圖8.3 使用者確認支付

第四步:輸入正確密碼後,支付完成,使用者端微信出現支付詳情頁面。見圖8.4。

第五步:回跳到商戶APP中,商戶APP根據支付結果個性化展示訂單處理結果。見圖8.5。

圖8.4 支付成功提示頁面

圖8.5 返回到商戶APP提示


業務流程

以下是互動時序圖,統一下單API、支付結果通知API和查詢訂單API等都涉及簽名過程,呼叫都必須在商戶伺服器端完成。如圖8.6所示。

圖8.6 APP支付時序圖

商戶系統和微信支付系統主要互動說明:

步驟1:使用者在商戶APP中選擇商品,提交訂單,選擇微信支付。

步驟2:商戶後臺收到使用者支付單,呼叫微信支付統一下單介面。參見【統一下單API】。

步驟3:統一下單介面返回正常的prepay_id,再按簽名規範重新生成簽名後,將資料傳輸給APP。參與簽名的欄位名為appid,partnerid,prepayid,noncestr,timestamp,package。注意:package的值格式為Sign=WXPay

步驟4:商戶APP調起微信支付。api參見本章節【app端開發步驟說明

步驟5:商戶後臺接收支付通知。api參見【支付結果通知API

步驟6:商戶後臺查詢支付結果。,api參見【查詢訂單API

maven 使用github 開源的微信工具包 github 地址:
https://github.com/binarywang/weixin-java-pay-demo
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>3.8.0</version>
</dependency>

springboot 配置

#微信支付
wx:
  pay:
    appId: wx6cfe5b3****  
    mchId: 157931****   #商戶號
    mchKey: dbe****************************  #商戶key
    subAppId:
    subMchId:
    keyPath: classpath:/cer/apiclient_cert.p12  #存放證書的路徑
    orderCallback: http://121.36.107.6:30000/pay/wx/order/callback  # 支付回撥
    refundCallback: http://121.36.107.6:30000/pay/wx/refund/callback  # 退款回撥

package com.pactera.traintravel.config;

import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Binary Wang
 */
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayProperties.class)
@AllArgsConstructor
public class WxPayConfiguration {
  private WxPayProperties properties;

  @Bean
  @ConditionalOnMissingBean
  public WxPayService wxService() {
    WxPayConfig payConfig = new WxPayConfig();
    payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
    payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
    payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
    payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
    payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
    payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));

    // 可以指定是否使用沙箱環境
    payConfig.setUseSandboxEnv(false);

    WxPayService wxPayService = new WxPayServiceImpl();
    wxPayService.setConfig(payConfig);
    return wxPayService;
  }

}

controller 程式碼

package com.github.binarywang.demo.wx.pay.controller;

import com.github.binarywang.wxpay.bean.coupon.*;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.util.Date;


/**
 * @author Binary Wang
 */
@Api("微信支付")
@RestController
@RequestMapping("/pay")
@AllArgsConstructor
public class WxPayController {
  private WxPayService wxService;

  /**
   * <pre>
   * 查詢訂單(詳見https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
   * 該介面提供所有微信支付訂單的查詢,商戶可以通過查詢訂單介面主動查詢訂單狀態,完成下一步的業務邏輯。
   * 需要呼叫查詢介面的情況:
   * ◆ 當商戶後臺、網路、伺服器等出現異常,商戶系統最終未接收到支付通知;
   * ◆ 呼叫支付介面後,返回系統錯誤或未知交易狀態情況;
   * ◆ 呼叫被掃支付API,返回USERPAYING的狀態;
   * ◆ 呼叫關單或撤銷介面API之前,需確認支付狀態;
   * 介面地址:https://api.mch.weixin.qq.com/pay/orderquery
   * </pre>
   *
   * @param transactionId 微信訂單號
   * @param outTradeNo    商戶系統內部的訂單號,當沒提供transactionId時需要傳這個。
   */
  @ApiOperation(value = "查詢訂單")
  @GetMapping("/queryOrder")
  public WxPayOrderQueryResult queryOrder(@RequestParam(required = false) String transactionId,
                                          @RequestParam(required = false) String outTradeNo)
    throws WxPayException {
    return this.wxService.queryOrder(transactionId, outTradeNo);
  }

  @ApiOperation(value = "查詢訂單")
  @PostMapping("/queryOrder")
  public WxPayOrderQueryResult queryOrder(@RequestBody WxPayOrderQueryRequest wxPayOrderQueryRequest) throws WxPayException {
    return this.wxService.queryOrder(wxPayOrderQueryRequest);
  }

  /**
   * <pre>
   * 關閉訂單
   * 應用場景
   * 以下情況需要呼叫關單介面:
   * 1. 商戶訂單支付失敗需要生成新單號重新發起支付,要對原訂單號呼叫關單,避免重複支付;
   * 2. 系統下單後,使用者支付超時,系統退出不再受理,避免使用者繼續,請呼叫關單介面。
   * 注意:訂單生成後不能馬上呼叫關單介面,最短呼叫時間間隔為5分鐘。
   * 介面地址:https://api.mch.weixin.qq.com/pay/closeorder
   * 是否需要證書:   不需要。
   * </pre>
   *
   * @param outTradeNo 商戶系統內部的訂單號
   */
  @ApiOperation(value = "關閉訂單")
  @GetMapping("/closeOrder/{outTradeNo}")
  public WxPayOrderCloseResult closeOrder(@PathVariable String outTradeNo) throws WxPayException {
    return this.wxService.closeOrder(outTradeNo);
  }

  @ApiOperation(value = "關閉訂單")
  @PostMapping("/closeOrder")
  public WxPayOrderCloseResult closeOrder(@RequestBody WxPayOrderCloseRequest wxPayOrderCloseRequest) throws WxPayException {
    return this.wxService.closeOrder(wxPayOrderCloseRequest);
  }

  /**
   * 呼叫統一下單介面,並組裝生成支付所需引數物件.
   *
   * @param request 統一下單請求引數
   * @param <T>     請使用{@link com.github.binarywang.wxpay.bean.order}包下的類
   * @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的類物件
   */
  @ApiOperation(value = "統一下單,並組裝所需支付引數")
  @PostMapping("/createOrder")
  public <T> T createOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
    return this.wxService.createOrder(request);
  }

  /**
   * 統一下單(詳見https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
   * 在發起微信支付前,需要呼叫統一下單介面,獲取"預支付交易會話標識"
   * 介面地址:https://api.mch.weixin.qq.com/pay/unifiedorder
   *
   * @param request 請求物件,注意一些引數如appid、mchid等不用設定,方法內會自動從配置物件中獲取到(前提是對應配置中已經設定)
   */
  @ApiOperation(value = "原生的統一下單介面")
  @PostMapping("/unifiedOrder")
  public WxPayUnifiedOrderResult unifiedOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
    return this.wxService.unifiedOrder(request);
  }

  /**
   * <pre>
   * 微信支付-申請退款
   * 詳見 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
   * 介面連結:https://api.mch.weixin.qq.com/secapi/pay/refund
   * </pre>
   *
   * @param request 請求物件
   * @return 退款操作結果
   */
  @ApiOperation(value = "退款")
  @PostMapping("/refund")
  public WxPayRefundResult refund(@RequestBody WxPayRefundRequest request) throws WxPayException {
    return this.wxService.refund(request);
  }

  /**
   * <pre>
   * 微信支付-查詢退款
   * 應用場景:
   *  提交退款申請後,通過呼叫該介面查詢退款狀態。退款有一定延時,用零錢支付的退款20分鐘內到賬,
   *  銀行卡支付的退款3個工作日後重新查詢退款狀態。
   * 詳見 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
   * 介面連結:https://api.mch.weixin.qq.com/pay/refundquery
   * </pre>
   * 以下四個引數四選一
   *
   * @param transactionId 微信訂單號
   * @param outTradeNo    商戶訂單號
   * @param outRefundNo   商戶退款單號
   * @param refundId      微信退款單號
   * @return 退款資訊
   */
  @ApiOperation(value = "退款查詢")
  @GetMapping("/refundQuery")
  public WxPayRefundQueryResult refundQuery(@RequestParam(required = false) String transactionId,
                                            @RequestParam(required = false) String outTradeNo,
                                            @RequestParam(required = false) String outRefundNo,
                                            @RequestParam(required = false) String refundId)
    throws WxPayException {
    return this.wxService.refundQuery(transactionId, outTradeNo, outRefundNo, refundId);
  }

  @ApiOperation(value = "退款查詢")
  @PostMapping("/refundQuery")
  public WxPayRefundQueryResult refundQuery(@RequestBody WxPayRefundQueryRequest wxPayRefundQueryRequest) throws WxPayException {
    return this.wxService.refundQuery(wxPayRefundQueryRequest);
  }

  @ApiOperation(value = "支付回撥通知處理")
  @PostMapping("/notify/order")
  public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
    final WxPayOrderNotifyResult notifyResult = this.wxService.parseOrderNotifyResult(xmlData);
    // TODO 根據自己業務場景需要構造返回物件
    return WxPayNotifyResponse.success("成功");
  }

  @ApiOperation(value = "退款回撥通知處理")
  @PostMapping("/notify/refund")
  public String parseRefundNotifyResult(@RequestBody String xmlData) throws WxPayException {
    final WxPayRefundNotifyResult result = this.wxService.parseRefundNotifyResult(xmlData);
    // TODO 根據自己業務場景需要構造返回物件
    return WxPayNotifyResponse.success("成功");
  }

  @ApiOperation(value = "掃碼支付回撥通知處理")
  @PostMapping("/notify/scanpay")
  public String parseScanPayNotifyResult(String xmlData) throws WxPayException {
    final WxScanPayNotifyResult result = this.wxService.parseScanPayNotifyResult(xmlData);
    // TODO 根據自己業務場景需要構造返回物件
    return WxPayNotifyResponse.success("成功");
  }

  /**
   * 傳送微信紅包給個人使用者
   * <pre>
   * 文件詳見:
   * 傳送普通紅包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
   *  介面地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
   * 傳送裂變紅包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
   *  介面地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack
   * </pre>
   *
   * @param request 請求物件
   */
  @ApiOperation(value = "傳送紅包")
  @PostMapping("/sendRedpack")
  public WxPaySendRedpackResult sendRedpack(@RequestBody WxPaySendRedpackRequest request) throws WxPayException {
    return this.wxService.sendRedpack(request);
  }

  /**
   * <pre>
   *   查詢紅包記錄
   *   用於商戶對已發放的紅包進行查詢紅包的具體資訊,可支援普通紅包和裂變包。
   *   請求Url    https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
   *   是否需要證書    是(證書及使用說明詳見商戶證書)
   *   請求方式    POST
   * </pre>
   *
   * @param mchBillNo 商戶發放紅包的商戶訂單號,比如10000098201411111234567890
   */
  @ApiOperation(value = "查詢紅包")
  @GetMapping("/queryRedpack/{mchBillNo}")
  public WxPayRedpackQueryResult queryRedpack(@PathVariable String mchBillNo) throws WxPayException {
    return this.wxService.queryRedpack(mchBillNo);
  }

  /**
   * <pre>
   * 掃碼支付模式一生成二維碼的方法
   * 二維碼中的內容為連結,形式為:
   * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
   * 其中XXXXX為商戶需要填寫的內容,商戶將該連結生成二維碼,如需要打印發布二維碼,需要採用此格式。商戶可呼叫第三方庫生成二維碼圖片。
   * 文件詳見: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
   * </pre>
   *
   * @param productId  產品Id
   * @param logoFile   商戶logo圖片的檔案物件,可以為空
   * @param sideLength 要生成的二維碼的邊長,如果為空,則取預設值400
   * @return 生成的二維碼的位元組陣列
   */
  public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) {
    return this.wxService.createScanPayQrcodeMode1(productId, logoFile, sideLength);
  }

  /**
   * <pre>
   * 掃碼支付模式一生成二維碼的方法
   * 二維碼中的內容為連結,形式為:
   * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
   * 其中XXXXX為商戶需要填寫的內容,商戶將該連結生成二維碼,如需要打印發布二維碼,需要採用此格式。商戶可呼叫第三方庫生成二維碼圖片。
   * 文件詳見: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
   * </pre>
   *
   * @param productId 產品Id
   * @return 生成的二維碼URL連線
   */
  public String createScanPayQrcodeMode1(String productId) {
    return this.wxService.createScanPayQrcodeMode1(productId);
  }

  /**
   * <pre>
   * 掃碼支付模式二生成二維碼的方法
   * 對應連結格式:weixin://wxpay/bizpayurl?sr=XXXXX。請商戶呼叫第三方庫將code_url生成二維碼圖片。
   * 該模式連結較短,生成的二維碼列印到結賬小票上的識別率較高。
   * 文件詳見: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
   * </pre>
   *
   * @param codeUrl    微信返回的交易會話的二維碼連結
   * @param logoFile   商戶logo圖片的檔案物件,可以為空
   * @param sideLength 要生成的二維碼的邊長,如果為空,則取預設值400
   * @return 生成的二維碼的位元組陣列
   */
  public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) {
    return this.wxService.createScanPayQrcodeMode2(codeUrl, logoFile, sideLength);
  }

  /**
   * <pre>
   * 交易保障
   * 應用場景:
   *  商戶在呼叫微信支付提供的相關介面時,會得到微信支付返回的相關資訊以及獲得整個介面的響應時間。
   *  為提高整體的服務水平,協助商戶一起提高服務質量,微信支付提供了相關介面呼叫耗時和返回資訊的主動上報介面,
   *  微信支付可以根據商戶側上報的資料進一步優化網路部署,完善服務監控,和商戶更好的協作為使用者提供更好的業務體驗。
   * 介面地址: https://api.mch.weixin.qq.com/payitil/report
   * 是否需要證書:不需要
   * </pre>
   */
  @ApiOperation(value = "提交交易保障資料")
  @PostMapping("/report")
  public void report(@RequestBody WxPayReportRequest request) throws WxPayException {
    this.wxService.report(request);
  }

  /**
   * <pre>
   * 下載對賬單
   * 商戶可以通過該介面下載歷史交易清單。比如掉單、系統錯誤等導致商戶側和微信側資料不一致,通過對賬單核對後可校正支付狀態。
   * 注意:
   * 1、微信側未成功下單的交易不會出現在對賬單中。支付成功後撤銷的交易會出現在對賬單中,跟原支付單訂單號一致,bill_type為REVOKED;
   * 2、微信在次日9點啟動生成前一天的對賬單,建議商戶10點後再獲取;
   * 3、對賬單中涉及金額的欄位單位為“元”。
   * 4、對賬單介面只能下載三個月以內的賬單。
   * 介面連結:https://api.mch.weixin.qq.com/pay/downloadbill
   * 詳情請見: <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下載對賬單</a>
   * </pre>
   *
   * @param billDate   對賬單日期 bill_date    下載對賬單的日期,格式:20140603
   * @param billType   賬單型別    bill_type    ALL,返回當日所有訂單資訊,預設值,SUCCESS,返回當日成功支付的訂單,REFUND,返回當日退款訂單
   * @param tarType    壓縮賬單    tar_type    非必傳引數,固定值:GZIP,返回格式為.gzip的壓縮包賬單。不傳則預設為資料流形式。
   * @param deviceInfo 裝置號    device_info    非必傳引數,終端裝置號
   * @return 儲存到本地的臨時檔案
   */
  @ApiOperation(value = "下載對賬單")
  @GetMapping("/downloadBill/{billDate}/{billType}/{tarType}/{deviceInfo}")
  public WxPayBillResult downloadBill(@PathVariable String billDate, @PathVariable String billType,
                                      @PathVariable String tarType, @PathVariable String deviceInfo) throws WxPayException {
    return this.wxService.downloadBill(billDate, billType, tarType, deviceInfo);
  }

  @ApiOperation(value = "下載對賬單")
  @PostMapping("/downloadBill")
  public WxPayBillResult downloadBill(WxPayDownloadBillRequest wxPayDownloadBillRequest) throws WxPayException {
    return this.wxService.downloadBill(wxPayDownloadBillRequest);
  }

  /**
   * <pre>
   * 提交刷卡支付
   * 文件地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
   * 應用場景:
   * 收銀員使用掃碼裝置讀取微信使用者刷卡授權碼以後,二維碼或條碼資訊傳送至商戶收銀臺,由商戶收銀臺或者商戶後臺呼叫該介面發起支付。
   * 提醒1:提交支付請求後微信會同步返回支付結果。當返回結果為“系統錯誤”時,商戶系統等待5秒後呼叫【查詢訂單API】,查詢支付實際交易結果;當返回結果為“USERPAYING”時,商戶系統可設定間隔時間(建議10秒)重新查詢支付結果,直到支付成功或超時(建議30秒);
   * 提醒2:在呼叫查詢介面返回後,如果交易狀況不明晰,請呼叫【撤銷訂單API】,此時如果交易失敗則關閉訂單,該單不能再支付成功;如果交易成功,則將扣款退回到使用者賬戶。當撤銷無返回或錯誤時,請再次呼叫。注意:請勿扣款後立即呼叫【撤銷訂單API】,建議至少15秒後再呼叫。撤銷訂單API需要雙向證書。
   * 介面地址:   https://api.mch.weixin.qq.com/pay/micropay
   * 是否需要證書:不需要。
   * </pre>
   */
  @ApiOperation(value = "提交刷卡支付")
  @PostMapping("/micropay")
  public WxPayMicropayResult micropay(@RequestBody WxPayMicropayRequest request) throws WxPayException {
    return this.wxService.micropay(request);
  }

  /**
   * <pre>
   * 撤銷訂單API
   * 文件地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
   * 應用場景:
   *  支付交易返回失敗或支付系統超時,呼叫該介面撤銷交易。如果此訂單使用者支付失敗,微信支付系統會將此訂單關閉;如果使用者支付成功,微信支付系統會將此訂單資金退還給使用者。
   *  注意:7天以內的交易單可呼叫撤銷,其他正常支付的單如需實現相同功能請呼叫申請退款API。提交支付交易後呼叫【查詢訂單API】,沒有明確的支付結果再呼叫【撤銷訂單API】。
   *  呼叫支付介面後請勿立即呼叫撤銷訂單API,建議支付後至少15s後再呼叫撤銷訂單介面。
   *  介面連結 :https://api.mch.weixin.qq.com/secapi/pay/reverse
   *  是否需要證書:請求需要雙向證書。
   * </pre>
   */
  @ApiOperation(value = "撤銷訂單")
  @PostMapping("/reverseOrder")
  public WxPayOrderReverseResult reverseOrder(@RequestBody WxPayOrderReverseRequest request) throws WxPayException {
    return this.wxService.reverseOrder(request);
  }

  @ApiOperation(value = "獲取沙箱環境簽名key")
  @GetMapping("/getSandboxSignKey")
  public String getSandboxSignKey() throws WxPayException {
    return this.wxService.getSandboxSignKey();
  }

  @ApiOperation(value = "發放代金券")
  @PostMapping("/sendCoupon")
  public WxPayCouponSendResult sendCoupon(@RequestBody WxPayCouponSendRequest request) throws WxPayException {
    return this.wxService.sendCoupon(request);
  }

  @ApiOperation(value = "查詢代金券批次")
  @PostMapping("/queryCouponStock")
  public WxPayCouponStockQueryResult queryCouponStock(@RequestBody WxPayCouponStockQueryRequest request) throws WxPayException {
    return this.wxService.queryCouponStock(request);
  }

  @ApiOperation(value = "查詢代金券資訊")
  @PostMapping("/queryCouponInfo")
  public WxPayCouponInfoQueryResult queryCouponInfo(@RequestBody WxPayCouponInfoQueryRequest request) throws WxPayException {
    return this.wxService.queryCouponInfo(request);
  }

  @ApiOperation(value = "拉取訂單評價資料")
  @PostMapping("/queryComment")
  public String queryComment(Date beginDate, Date endDate, Integer offset, Integer limit) throws WxPayException {
    return this.wxService.queryComment(beginDate, endDate, offset, limit);
  }

}
企業微信介面要確保是否開通相應的能力,才可以呼叫。
package com.github.binarywang.demo.wx.pay.controller;

import com.github.binarywang.wxpay.bean.entpay.*;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;

/**
 * <pre>
 * 企業付款相關介面
 * Created by Binary Wang on 2018/9/27.
 * </pre>
 *
 * @author <a href="https://github.com/binarywang">Binary Wang</a>
 */
@Api("企業付款")
@RequestMapping("/pay")
@RestController
@AllArgsConstructor
public class EntPayController {
  private WxPayService wxService;

  /**
   * <pre>
   * 企業付款業務是基於微信支付商戶平臺的資金管理能力,為了協助商戶方便地實現企業向個人付款,針對部分有開發能力的商戶,提供通過API完成企業付款的功能。
   * 比如目前的保險行業向客戶退保、給付、理賠。
   * 企業付款將使用商戶的可用餘額,需確保可用餘額充足。檢視可用餘額、充值、提現請登入商戶平臺“資金管理”https://pay.weixin.qq.com/進行操作。
   * 注意:與商戶微信支付收款資金並非同一賬戶,需要單獨充值。
   * 文件詳見:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
   * 介面連結:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
   * </pre>
   *
   * @param request 請求物件
   */
  @ApiOperation(value = "企業付款到零錢")
  @PostMapping("/entPay")
  public EntPayResult entPay(@RequestBody EntPayRequest request) throws WxPayException {
    return this.wxService.getEntPayService().entPay(request);
  }

  /**
   * <pre>
   * 查詢企業付款API
   * 用於商戶的企業付款操作進行結果查詢,返回付款操作詳細結果。
   * 文件詳見:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
   * 介面連結:https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo
   * </pre>
   *
   * @param partnerTradeNo 商戶訂單號
   */
  @ApiOperation(value = "查詢企業付款到零錢的結果")
  @GetMapping("/queryEntPay/{partnerTradeNo}")
  public EntPayQueryResult queryEntPay(@PathVariable String partnerTradeNo) throws WxPayException {
    return this.wxService.getEntPayService().queryEntPay(partnerTradeNo);
  }


  /**
   * <pre>
   * 獲取RSA加密公鑰API.
   * RSA演算法使用說明(非對稱加密演算法,演算法採用RSA/ECB/OAEPPadding模式)
   * 1、 呼叫獲取RSA公鑰API獲取RSA公鑰,落地成本地檔案,假設為public.pem
   * 2、 確定public.pem檔案的存放路徑,同時修改程式碼中檔案的輸入路徑,載入RSA公鑰
   * 3、 用標準的RSA加密庫對敏感資訊進行加密,選擇RSA_PKCS1_OAEP_PADDING填充模式
   * (eg:Java的填充方式要選 " RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING")
   * 4、 得到進行rsa加密並轉base64之後的密文
   * 5、 將密文傳給微信側相應欄位,如付款介面(enc_bank_no/enc_true_name)
   *
   * 介面預設輸出PKCS#1格式的公鑰,商戶需根據自己開發的語言選擇公鑰格式
   * 文件詳見:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4
   * 介面連結:https://fraud.mch.weixin.qq.com/risk/getpublickey
   * </pre>
   *
   * @return the public key
   * @throws WxPayException the wx pay exception
   */
  @ApiOperation(value = "獲取RSA加密公鑰")
  @GetMapping("/getPublicKey")
  public String getPublicKey() throws WxPayException {
    return this.wxService.getEntPayService().getPublicKey();
  }

  /**
   * 企業付款到銀行卡.
   * <pre>
   * 用於企業向微信使用者銀行卡付款
   * 目前支援介面API的方式向指定微信使用者的銀行卡付款。
   * 文件詳見:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2
   * 介面連結:https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
   * </pre>
   *
   * @param request 請求物件
   * @return the ent pay bank result
   * @throws WxPayException the wx pay exception
   */
  @ApiOperation(value = "企業付款到銀行卡")
  @PostMapping("/payBank")
  public EntPayBankResult payBank(EntPayBankRequest request) throws WxPayException {
    return this.wxService.getEntPayService().payBank(request);
  }

  /**
   * 企業付款到銀行卡查詢.
   * <pre>
   * 用於對商戶企業付款到銀行卡操作進行結果查詢,返回付款操作詳細結果。
   * 文件詳見:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_3
   * 介面連結:https://api.mch.weixin.qq.com/mmpaysptrans/query_bank
   * </pre>
   *
   * @param partnerTradeNo 商戶訂單號
   * @return the ent pay bank query result
   * @throws WxPayException the wx pay exception
   */
  @ApiOperation(value = "查詢企業付款到銀行卡的結果")
  @GetMapping("/queryPayBank/{partnerTradeNo}")
  public EntPayBankQueryResult queryPayBank(@PathVariable String partnerTradeNo) throws WxPayException {
    return this.wxService.getEntPayService().queryPayBank(partnerTradeNo);
  }

}

API列表

https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_4#

最佳實踐

https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5