欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java整合微信支付功能詳細(xì)示例

 更新時(shí)間:2023年07月08日 11:32:43   作者:abilities  
這篇文章主要給大家介紹了關(guān)于java整合微信支付功能的相關(guān)資料,支付是一個(gè)復(fù)雜且測(cè)試起來需要的配置特別復(fù)雜的模塊,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考下

微信服務(wù)商戶號(hào)和普通商戶號(hào)的區(qū)別

1. 適用范圍不同:

微信服務(wù)商戶號(hào)適用于代理商、第三方服務(wù)商等,也就是說,只有中間商才可以成功創(chuàng)建微信服務(wù)商戶號(hào)。而普通商戶號(hào)適用于普通商家。

2. 支付方式不同:

微信服務(wù)商戶號(hào)支持多個(gè)子商戶從屬于一個(gè)服務(wù)商,實(shí)現(xiàn)統(tǒng)一線上收款和資金結(jié)算,同時(shí)支持分賬等多種支付方式,方便代理商為子商戶提供中間擔(dān)保結(jié)算、派單抽成、資金歸集、單一入口、風(fēng)控應(yīng)用等服務(wù)。

普通商戶號(hào)只能被單獨(dú)占有,支持一種支付方式,即從客戶直接收款,對(duì)于多個(gè)門店的商家,需要分別開通每個(gè)門店的商戶號(hào),管理起來比較繁瑣。

3. 申請(qǐng)及審核方式不同:

申請(qǐng)微信服務(wù)商戶號(hào)需要提供相關(guān)商業(yè)資質(zhì)證明,如公司注冊(cè)證明、公司經(jīng)營(yíng)資質(zhì)證明等,審核通過后方可獲得認(rèn)證。

普通商戶號(hào)的申請(qǐng)相對(duì)較為簡(jiǎn)單,只需要提供公司營(yíng)業(yè)執(zhí)照、結(jié)算銀行賬號(hào)等資料,審核通過后即可開通商戶號(hào)。

總之,微信服務(wù)商戶號(hào)適合代理商、第三方服務(wù)商等機(jī)構(gòu)場(chǎng)景,可以實(shí)現(xiàn)代理收款、分賬結(jié)算等多種支付服務(wù),方便代理商為子商戶提供完整的商業(yè)解決方案;而普通商戶號(hào)適合單個(gè)商家接受在線收款,管理更為簡(jiǎn)單。

使用

這里我們就先配置服務(wù)商號(hào)

微信商戶號(hào)中配置信息

  • 需要提供企業(yè)相關(guān)的資料進(jìn)行等待審核大概在一周左右
  • 開通商戶號(hào)
  • 創(chuàng)建子商戶號(hào)
  • 生成API3私鑰和密鑰
  • 授權(quán)支付回調(diào)目錄
  • 在微信開發(fā)者平臺(tái)中小程序關(guān)聯(lián)服務(wù)商戶號(hào)

代碼

Jar依賴

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-csv</artifactId>
    <version>2.11.2</version>
</dependency>
<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-apache-httpclient</artifactId>
    <version>0.2.2</version>
</dependency>

配置微信API

#微信配置
wx-applet:
  url: https://api.mch.weixin.qq.com/papay/querycontract
  payUrl: https://api.mch.weixin.qq.com/pay/pappayapply
  notifyUrl: https://chillman.com.cn/applet/applyPayNotify
  qureyOrderUrl: https://chillman.com.cn/pay/paporderquery
  appId: 小程序應(yīng)用ID
  appSecret: 小程序密鑰
  mchId: 子商戶id
#微信支付配置
wechat-pay:
  url: https://api.mch.weixin.qq.com
  appId: 小程序Id
  mchId: 商戶號(hào)
  mchSerialNo: 
  apiV3Key: 私鑰key
  #  商戶key
  mchPrivateKey: 私鑰
  notifyUrl: 回調(diào)地址
  apiClientKey: 私鑰
  certificatesUrl: https://api.mch.weixin.qq.com/v3/certificates

微信API工具類

package com.snow.param;
import lombok.Data;
/**
 * @Author: zhaohaoxin
 * @Date: 2023-06-02-16:10
 */
@Data
public class PlaceAnOrderParam2 {
    private  String sp_appid;
    private  String sp_mchid;
    private  String sub_appid;
    private  String sub_mchid;
    private  String description;
    private  String out_trade_no;
    private  String notify_url;
    private AmountParam amount;
    private PayerParam payer;
    public PlaceAnOrderParam2(String sp_appid, String sp_mchid, String sub_appid, String sub_mchid, String description, String out_trade_no, String notify_url, AmountParam amount, PayerParam payer) {
        this.sp_appid = sp_appid;
        this.sp_mchid = sp_mchid;
        this.sub_appid = sub_appid;
        this.sub_mchid = sub_mchid;
        this.description = description;
        this.out_trade_no = out_trade_no;
        this.notify_url = notify_url;
        this.amount = amount;
        this.payer = payer;
    }
}
package com.snow.service.imple;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snow.api.WXPayRequest;
import com.snow.constant.PathConstant;
import com.snow.dto.WXPayDto;
import com.snow.param.OrderStatusParam;
import com.snow.param.PlaceAnOrderParam;
import com.snow.param.PlaceAnOrderParam2;
import com.snow.param.SingParam;
import com.snow.service.WXPayService;
import com.snow.sgin.NewPaySignUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class WXPayServiceImpl implements WXPayService {
    @Autowired
    private WXPayRequest wxPayRequest;
    @Autowired
    private NewPaySignUtil newPaySignUtil;
    public static final String SING_TYPE = "RSA_1_256";
    public static final String PATH_JSAPI = "/v3/pay/partner/transactions/jsapi";
    @Override
    public String WXPayUnifyOrder(PlaceAnOrderParam placeAnOrderParam) {
        try {
            String reqBody = "";
            if (placeAnOrderParam != null) {
                ObjectMapper objectMapper = new ObjectMapper();
                reqBody = objectMapper.writeValueAsString(placeAnOrderParam);
            }
            return wxPayRequest.requestOnce(PATH_JSAPI, reqBody);
        }catch (Exception e){
            log.error("調(diào)用微信支付統(tǒng)一下單失敗",e);
            return StringUtils.EMPTY;
        }
    }
    @Override
    public String WXPayUnifyOrder(PlaceAnOrderParam2 placeAnOrderParam) {
        try {
            String reqBody = "";
            if (placeAnOrderParam != null) {
                ObjectMapper objectMapper = new ObjectMapper();
                reqBody = objectMapper.writeValueAsString(placeAnOrderParam);
            }
            return wxPayRequest.requestOnce(PathConstant.PATH_JSAPI, reqBody);
        }catch (Exception e){
            log.error("調(diào)用微信支付統(tǒng)一下單失敗",e);
            return StringUtils.EMPTY;
        }
    }
    @Override
    public String getOrderStatus(OrderStatusParam orderStatusParam) {
        try {
            String reqBody = "";
            String url = PathConstant.PATH_GET_ORDER + orderStatusParam.getOutTradeNo() + "?mchid="+orderStatusParam.getMchid();
            return wxPayRequest.requestOnce(url,reqBody);
        }catch (Exception e){
            log.error("調(diào)用查詢訂單狀態(tài)接口失敗",e);
            return StringUtils.EMPTY;
        }
    }
    @Override
    public WXPayDto getWXPaySing(SingParam singParam) {
        String appid = singParam.getAppid();
        long timeStamp = System.currentTimeMillis() / 1000;
        String nonceStr = RandomStringUtils.randomAlphanumeric(32);
        String prepayId = "prepay_id=" + singParam.getPrepayId();
        String preStr = appid+"\n"
                +timeStamp+"\n"
                +nonceStr+"\n"
                +prepayId+"\n";
        String paySign = newPaySignUtil.getSign(SING_TYPE, preStr);
        WXPayDto wxPayDto = new WXPayDto(timeStamp,prepayId,nonceStr,paySign);
        return wxPayDto;
    }
}

發(fā)起支付后獲取微信小程序根據(jù)prepayId參數(shù)調(diào)用支付方法彈出支付會(huì)話框

微信回調(diào)

package com.snow.controller;
import com.alibaba.fastjson.JSON;
import com.snow.annotation.SystemLog;
import com.snow.business.domain.XqSnowOrder;
import com.snow.business.domain.XqSnowOrderExample;
import com.snow.business.service.XqSnowOrderService;
import com.snow.common.exception.RequestWechatException;
import com.snow.common.utils.DateUtils;
import com.snow.enumz.OrderStateEnum;
import com.snow.pem.PayResponseUtils;
import com.snow.pem.StaticParameter;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.security.GeneralSecurityException;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Controller
@RestController
@RequestMapping("/wxPay/callBack")
@Slf4j
public class WXPayCallBackController {
    @Value("${wechat-pay.apiV3Key}")
    private String apiV3Key;
    @Autowired
    private XqSnowOrderService orderService;
    @SystemLog(menu = "微信支付支付結(jié)果通知回調(diào)")
    @PostMapping("wxPayRequest")
    public String wxPayRequest(HttpServletRequest request, HttpServletResponse response){
        log.info("==微信回調(diào)開始==");
        Map<String, String> map = new HashMap<>();
        try {
            InputStream in = request.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            StringBuffer param = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) {
                param.append(line);
            }
            String callBackParam = param.toString();
            JSONObject object = JSONObject.fromObject(callBackParam);
            log.info("微信回調(diào)參數(shù)={}" + callBackParam);
            //回調(diào)摘要
            String summary = object.getString("summary");
            //如果驗(yàn)證簽名序列號(hào)通過
            if (verifiedSign(request,callBackParam)){
                JSONObject resource = object.getJSONObject("resource");
                String associatedData = resource.getString("associated_data");
                String nonce = resource.getString("nonce");
                String ciphertext = resource.getString("ciphertext");
                AesUtil aesUtil = new AesUtil(apiV3Key.getBytes());
                String res = aesUtil.decryptToString(associatedData.getBytes(), nonce.getBytes(), ciphertext);
                JSONObject resObj = JSONObject.fromObject(res);
                log.info("微信通知支付成功通知參數(shù)={}",resObj);
                //交易狀態(tài)
                String tradeState = resObj.getString("trade_state");
                //訂單號(hào)
                String outTradeNo = resObj.getString("out_trade_no");
                //支付完成時(shí)間
                String time_end = resObj.getString("success_time");
                //微信交易訂單號(hào)
                String transactionId = resObj.getString("transaction_id");
                //訂單金額
                com.alibaba.fastjson.JSONObject amount = JSON.parseObject(resObj.getString("amount"));
                //總金額
                String total = amount.getString("total");
                //用戶支付金額
                String payerTotal = amount.getString("payer_total");
                OrderStateEnum orderStateEnum = OrderStateEnum.OK;
                if (tradeState.equals("SUCCESS")){
                    //查詢訂單狀態(tài)
                    XqSnowOrderExample snowOrderExample = new XqSnowOrderExample();
                    snowOrderExample.createCriteria().andorderNoEqualTo(outTradeNo);
                    XqSnowOrder snowOrder = orderService.selectFirstByExample(snowOrderExample);
                    //訂單已經(jīng)處理
                    if(snowOrder.getPayStatus().equals(orderStateEnum.getState()) ){
                        log.info("扣款失敗訂單已經(jīng)處理,訂單號(hào):"+outTradeNo+",訂單狀態(tài):"+snowOrder.getPayStatus());
                        map.put("code", "SUCCESS");
                        map.put("message", "成功");
                        return JSON.toJSONString(map);
                    }
                    Date timeEnd = null;
                    try {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
                        timeEnd = sdf.parse(time_end);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    BigDecimal cashFee = new BigDecimal(payerTotal).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                    XqSnowOrder snowOrderEdition = new XqSnowOrder();
                    //微信支付交易號(hào)
                    snowOrderEdition.setWxOrderNo(transactionId);
                    //修改訂單狀態(tài)為已支付
                    snowOrderEdition.setPayStatus(orderStateEnum.getState());
                    snowOrderEdition.setPayTime(timeEnd);
                    if (Integer.valueOf(total)-Integer.valueOf(payerTotal)>0){
                        //有優(yōu)惠
                        //代金券或立減優(yōu)惠金額
                        //優(yōu)惠功能
                        if(resObj.containsKey("promotion_detail")){
                            JSONArray promotionDetails = JSONArray.fromObject(resObj.getString("promotion_detail"));
                            if(promotionDetails != null){
                                JSONObject promotionDetail = promotionDetails.getJSONObject(0);
                                String coupon_fee = promotionDetail.getString("amount");
                                if (!StringUtils.isEmpty(coupon_fee)){
                                    BigDecimal couponFee = new BigDecimal(coupon_fee).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                                    //tMoheOrder.setWxCouponFee(couponFee);
                                    log.info("訂單號(hào):{},有優(yōu)惠-->couponFee:,{}",outTradeNo,coupon_fee);
                                }
                                //代金券或立減優(yōu)惠ID
                                String coupon_id_$n = promotionDetail.getString("coupon_id");
                                if (!StringUtils.isEmpty(coupon_id_$n)){
                                    //tMoheOrder.setWxCouponId(coupon_id_$n);
                                    log.info("訂單號(hào):{},,代金券或立減優(yōu)惠ID:{}",outTradeNo,coupon_id_$n);
                                }
                            }
                        }
                        log.info("此訂單有優(yōu)惠,訂單號(hào):"+outTradeNo);
                    }
                    //沒有優(yōu)惠
                    XqSnowOrderExample snowOrderExampleEdit = new XqSnowOrderExample();
                    snowOrderExampleEdit.createCriteria().andorderNoEqualTo(outTradeNo);
                    orderService.updateByExampleSelective(snowOrderEdition,snowOrderExampleEdit);
                    log.info("扣款訂單微信支付處理成功,此訂單已經(jīng)支付,訂單號(hào)碼:"+outTradeNo);
                }else{
                    log.info("微信返回支付錯(cuò)誤摘要:"+summary);
                }
                map.put("code", "SUCCESS");
                map.put("message", "成功");
            }else{
                log.info("扣款回調(diào)簽名驗(yàn)證失敗");
            }
        } catch (IOException e) {
            log.error("微信支付支付結(jié)果通知回調(diào)接口異常:",e);
        } catch (ParseException e) {
            log.error("微信支付支付結(jié)果通知回調(diào)接口異常:",e);
        } catch (RequestWechatException e) {
            log.error("微信支付支付結(jié)果通知回調(diào)接口異常:",e);
        } catch (GeneralSecurityException e) {
            log.error("微信支付支付結(jié)果通知回調(diào)接口異常:",e);
        }
        return JSON.toJSONString(map);
    }
    /**
     * 驗(yàn)證微信簽名
     * @param request
     * @param body
     * @return
     * @throws GeneralSecurityException
     * @throws IOException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws ParseException
     */
    private boolean verifiedSign(HttpServletRequest request,String body) throws GeneralSecurityException, ParseException, RequestWechatException {
        //微信返回的證書序列號(hào)
        String serialNo = request.getHeader("Wechatpay-Serial");
        //微信返回的隨機(jī)字符串
        String nonceStr = request.getHeader("Wechatpay-Nonce");
        //微信返回的時(shí)間戳
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        //微信返回的簽名
        String wechatSign = request.getHeader("Wechatpay-Signature");
        //組裝簽名字符串
        String signStr = Stream.of(timestamp, nonceStr, body)
                .collect(Collectors.joining("\n", "", "\n"));
        //當(dāng)證書容器為空 或者 響應(yīng)提供的證書序列號(hào)不在容器中時(shí)  就應(yīng)該刷新了
        if (StaticParameter.certificateMap.isEmpty() || !StaticParameter.certificateMap.containsKey(serialNo)) {
            PayResponseUtils.refreshCertificate();
        }
        //根據(jù)序列號(hào)獲取平臺(tái)證書
        X509Certificate certificate = StaticParameter.certificateMap.get(serialNo);
        //獲取失敗 驗(yàn)證失敗
        if (certificate == null){
            return false;
        }
        //SHA256withRSA簽名
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(certificate);
        signature.update(signStr.getBytes());
        //返回驗(yàn)簽結(jié)果
        return signature.verify(Base64Utils.decodeFromString(wechatSign));
    }
}

效果

以上就是小程序支付的整個(gè)流程

總結(jié)

到此這篇關(guān)于java整合微信支付功能的文章就介紹到這了,更多相關(guān)java整合微信支付內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC 中文亂碼的解決方案

    SpringMVC 中文亂碼的解決方案

    這篇文章主要介紹了SpringMVC 中文亂碼的解決方案,幫助大家更好的理解和學(xué)習(xí)使用SpringMVC,感興趣的朋友可以了解下
    2021-04-04
  • Java小程序求圓的周長(zhǎng)和面積實(shí)例

    Java小程序求圓的周長(zhǎng)和面積實(shí)例

    這篇文章主要介紹了首先用蒙塔卡洛算法求圓周率近似值,然后根據(jù)此近似值輸出圓的周長(zhǎng)和面積,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-09-09
  • Java實(shí)現(xiàn)的簡(jiǎn)單圖片上傳功能示例

    Java實(shí)現(xiàn)的簡(jiǎn)單圖片上傳功能示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的簡(jiǎn)單圖片上傳功能,結(jié)合實(shí)例形式分析了java圖片傳輸相關(guān)的檢驗(yàn)、傳輸、接收等相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • Java教程之引用類型數(shù)組和繼承的意義詳解

    Java教程之引用類型數(shù)組和繼承的意義詳解

    這篇文章主要介紹了Java教程之引用類型數(shù)組和繼承的意義詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 初探Java內(nèi)部類的使用

    初探Java內(nèi)部類的使用

    Java內(nèi)部類一般可以分為以下三種:成員內(nèi)部類、靜態(tài)內(nèi)部類和匿名內(nèi)部類。這篇文章主要帶大家初探一下Java內(nèi)部類的使用,感興趣的可以了解一下
    2022-09-09
  • java 使用idea將工程打成jar并創(chuàng)建成exe文件類型執(zhí)行的方法詳解

    java 使用idea將工程打成jar并創(chuàng)建成exe文件類型執(zhí)行的方法詳解

    這篇文章主要介紹了java 使用idea將工程打成jar并創(chuàng)建成exe文件類型執(zhí)行,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-09-09
  • SpringSessionRedis配置及發(fā)現(xiàn)的問題講解

    SpringSessionRedis配置及發(fā)現(xiàn)的問題講解

    今天小編就為大家分享一篇關(guān)于SpringSessionRedis配置及發(fā)現(xiàn)的問題講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • 基于IDEA查看maven依賴結(jié)構(gòu)流程解析

    基于IDEA查看maven依賴結(jié)構(gòu)流程解析

    這篇文章主要介紹了基于IDEA查看maven依賴結(jié)構(gòu)流程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Kotlin與java8的SAM轉(zhuǎn)換對(duì)比(進(jìn)階)

    Kotlin與java8的SAM轉(zhuǎn)換對(duì)比(進(jìn)階)

    這篇文章主要介紹了Kotlin與java8的SAM轉(zhuǎn)換對(duì)比,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Mockito如何mock靜態(tài)方法問題

    Mockito如何mock靜態(tài)方法問題

    本文介紹了如何在Mockito 3.4.0版本及以上版本中mock靜態(tài)方法,包括如何在pom文件中添加相關(guān)jar包、如何使用Mockito.mockStatic(Class mockClass)方法以及注意事項(xiàng)等
    2025-02-02

最新評(píng)論