JAVA实现小程序微信支付-支付成功回调-程序员宅基地

技术标签: java  微信  小程序  业务应用技术  

第一步配置API key:微信支付文档

第二步下载并配置商户证书:微信支付文档

第三步对接微信支付接口:微信支付文档

  • 添加pom依赖
<!-- 微信支付API	-->
<dependency>
	<groupId>com.github.wechatpay-apiv3</groupId>
	<artifactId>wechatpay-java</artifactId>
	<version>0.2.12</version>
</dependency>
<!-- SBSS 用到的HTTP工具包:okhttp 3.13.1 -->
<dependency>
   <groupId>com.squareup.okhttp3</groupId>
   <artifactId>okhttp</artifactId>
   <version>3.13.1</version>
</dependency>
<!--工具类-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.3.1</version>
</dependency>
  • yml配置文件
weixin:
  # AppID(小程序ID)
  appId: xxxxxxx
  # AppSecret(小程序密钥)
  appSecret: xxxxxxx
  # 接口链接
  url: https://api.weixin.qq.com
  # 认证类型
  schema: xxxxxxx
  # 商户号ID
  mchid: xxxxxxx
  # 商户证书序号
  serialNo: xxxxxxx
  # 商户私钥字符串
  privateKey: xxxxxxx
  #支付接口链接
  payUrl: https://api.mch.weixin.qq.com
  #回调接口链接
  notifyUrl: https://xxx.xxx.com
  #支付金额:1元
  amount: 100
  #apiv3密钥
  apiV3Key: xxxxxxx
  • 微信支付配置
package com.example.demo.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;


@Data
@Component
public class WechatConfig {
    

    /**
     * AppID(小程序ID)
     */
    @Value("${weixin.appId}")
    private String appId;

    /**
     * AppSecret(小程序密钥)
     */
    @Value("${weixin.appSecret}")
    private String appSecret;

    /**
     * 微信接口链接
     */
    @Value("${weixin.url}")
    private String url;

    /**
     * 商户私钥字符串(下载并配置商户证书中的私钥)
     */
    @Value("${weixin.privateKey}")
    private String privateKey;

    /**
     * 商户号
     */
    @Value("${weixin.mchid}")
    private String mchid;

    /**
     * 商户证书序号
     */
    @Value("${weixin.serialNo}")
    private String serialNo;

    /**
     * 认证类型
     */
    @Value("${weixin.schema}")
    private String schema;

    /**
     * 支付接口链接
     */
    @Value("${weixin.payUrl}")
    private String payUrl;

    /**
     * 回调路径
     */
    @Value("${weixin.notifyUrl}")
    private String notifyUrl;

    /**
     * 支付金额(单位是分)
     */
    @Value("${weixin.amount}")
    private BigDecimal amount;
	
	/**
     * 认证类型
     */
    @Value("${weixin.apiV3Key}")
    private String apiV3Key;
}

  • 生成请求签名方法

微信支付文档

package com.example.demo.util;

import com.example.demo.config.WechatConfig;
import com.wechat.pay.java.core.util.PemUtil;
import okhttp3.HttpUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

@Component
public class WechatCreateToken {
    

    @Autowired
    private WechatConfig wechatConfig;

    /**
     * 获取签名认证信息
     * @param method 请求类型
     * @param url 请求路径
     * @param timestamp 时间戳
     * @param nonceStr 随机数
     * @param body 请求参数
     * @return 结果
     */
    public String getAuthorization(String method, HttpUrl url, long timestamp, String nonceStr, String body){
    
        //构造签名串
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        //Base64编码得到签名值
        String signature = sign(message);
        return "mchid=\"" + wechatConfig.getMchid() + "\","
                + "serial_no=\"" + wechatConfig.getSerialNo() + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "signature=\"" + signature + "\"";
    }

    /**
     * 构造签名串
     * @param method 请求类型
     * @param url 请求路径
     * @param timestamp 时间戳
     * @param nonceStr 随机数
     * @param body 请求参数
     * @return 结果
     */
    String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
    
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
    
            canonicalUrl += "?" + url.encodedQuery();
        }
        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

    /**
     *对签名结果进行Base64编码得到签名值
     * @param message 参数
     * @return 结果
     */
    public String sign(String message){
    
        try {
    
            //加载商户私钥(privateKey:私钥字符串)
            Signature sign = Signature.getInstance("SHA256withRSA");
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKeyFromString(wechatConfig.getPrivateKey());
            sign.initSign(merchantPrivateKey);
            sign.update(message.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(sign.sign());
        } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
    
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     *获取支付签名值
     * @param timestamp 时间戳
     * @param nonceStr 随机数
     * @param prepayId 预支付交易会话标识
     * @return 结果
     */
    public String getPaySignStr(long timestamp, String nonceStr,String prepayId){
    
        //签名
        String message = wechatConfig.getAppId() + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + "prepay_id=" + prepayId + "\n";
        return sign(message);
    }
}

  • 微信支付第三方接口方法
package com.example.demo.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.demo.config.WechatConfig;
import okhttp3.HttpUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;


@Component
public class WechatUtil {
    

    @Autowired
    private WechatConfig wechatConfig;

    @Autowired
    private WechatCreateToken wechatCreateToken;

    /**
     * 获取小程序全局唯一后台接口调用凭据,token有效期为7200s
     * @return 结果
     */
    public String getAccessToken(){
    
        //请求参数
        JSONObject paramMap = new JSONObject();
        paramMap.put("grant_type","client_credential");
        paramMap.put("appid", wechatConfig.getAppId());
        paramMap.put("secret", wechatConfig.getAppSecret());
        String body = HttpUtil.createGet(wechatConfig.getUrl() + "/cgi-bin/token")
                .form(paramMap)
                .execute()
                .body();
        //返回值
        JSONObject result = JSONUtil.parseObj(body);
        if (result.get("errcode") != null){
    
            throw new IllegalArgumentException("获取token失败");
        }
        return result.get("access_token", String.class);
    }

    /**
     * 手机号验证
     * @param accessToken 接口调用凭证
     * @param code 微信code
     * @return 结果
     */
    public String getPhoneNumber(String accessToken,String code){
    
        //请求参数
        JSONObject paramMap = new JSONObject();
        paramMap.put("code", code);
        String body = HttpUtil.createPost(wechatConfig.getUrl() + "/wxa/business/getuserphonenumber?access_token=" + accessToken)
                .header("Content-Type", "application/json")
                .body(paramMap.toString())
                .execute()
                .body();
        //返回值
        JSONObject result = JSONUtil.parseObj(body);
        if (result.get("errcode").equals(0)){
    
            //用户手机号信息
            Map phoneInfo = result.get("phone_info", Map.class);
            return String.valueOf(phoneInfo.get("phoneNumber"));
        }else {
    
            throw new IllegalArgumentException("code无效");
        }
    }

    /**
     * 获取用户openid
     * @param code 微信code
     * @return 结果
     */
    public String getOpenid(String code){
    
        //请求参数
        JSONObject paramMap = new JSONObject();
        paramMap.put("js_code", code);
        paramMap.put("appid", wechatConfig.getAppId());
        paramMap.put("secret", wechatConfig.getAppSecret());
        paramMap.put("grant_type", "authorization_code");
        String body = HttpUtil.createGet(wechatConfig.getUrl() + "/sns/jscode2session")
                .form(paramMap)
                .execute()
                .body();
        //返回值
        JSONObject result = JSONUtil.parseObj(body);
        if (result.get("openid") != null){
    
            return result.get("openid", String.class);
        }else {
    
            throw new IllegalArgumentException("微信认证失败");
        }
    }

    /**
     *获取微信支付的必要参数
     */
    public Map<String,Object> getPaySignParam(String openid) {
    
        //商户订单号(自定义)
        String orderNo = "WX" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(12);
        //预支付交易会话标识
        String prepayId = getPrepayId(openid, orderNo);
        //时间戳
        long timestamp = System.currentTimeMillis() / 1000;
        //随机数
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        //签名
        String paySign = wechatCreateToken.getPaySignStr(timestamp, nonceStr, prepayId);
        //返回参数
        HashMap<String, Object> resultParam = new HashMap<>();
        resultParam.put("orderId", orderNo);
        resultParam.put("timeStamp", timestamp + "");
        resultParam.put("nonceStr", nonceStr);
        resultParam.put("package", "prepay_id=" + prepayId);
        resultParam.put("signType", "RSA");
        resultParam.put("paySign", paySign);
        return resultParam;
    }

    /**
     * 获取预支付交易会话标识(生成订单)
     * @param openid 微信id
     * @param orderNo 商户订单号
     * @return 结果
     */
    public String getPrepayId(String openid,String orderNo){
    
        //请求参数
        JSONObject param = new JSONObject();
        //小程序id
        param.put("appid", wechatConfig.getAppId());
        //商户号id
        param.put("mchid", wechatConfig.getMchid());
        //商品描述
        param.put("description", "xxx费用");
        //商户订单号
        param.put("out_trade_no", orderNo);
        //支付通知回调接口(需要https路径)
        param.put("notify_url", wechatConfig.getNotifyUrl() + "/notifyUrl");
        //金额
        JSONObject amountParam = new JSONObject();
        amountParam.put("total", wechatConfig.getAmount());
        amountParam.put("currency", "CNY");
        param.put("amount", amountParam);
        //支付者信息
        JSONObject payerParam = new JSONObject();
        payerParam.put("openid", openid);
        param.put("payer",payerParam);
        //随机数
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        //时间戳
        long timestamp = System.currentTimeMillis() / 1000;
        //下单生成预订单
        String body = param.toString();
        //生成签名
        String authorization = wechatConfig.getSchema() + " " + wechatCreateToken.getAuthorization("POST", Objects.requireNonNull(HttpUrl.parse(wechatConfig.getPayUrl() + "/v3/pay/transactions/jsapi")), timestamp, nonceStr, body);
        String result = HttpUtil.createPost(wechatConfig.getPayUrl() + "/v3/pay/transactions/jsapi")
                .header("Authorization", authorization)
                .header("Content-Type", "application/json")
                .header("Accept","application/json")
                .body(body)
                .execute()
                .body();
        //返回值
        JSONObject data = JSONUtil.parseObj(result);
        if (data.get("prepay_id") == null){
    
            throw new IllegalArgumentException("下单失败");
        }
        return data.get("prepay_id",String.class);
    }

    /**
     *获取订单信息
     */
    public Map<String,Object> getOrderInfo(String orderNo){
    
        //请求参数
        JSONObject paramMap = new JSONObject();
        paramMap.put("mchid", wechatConfig.getMchid());
        //随机数
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        //时间戳
        long timestamp = System.currentTimeMillis() / 1000;
        String authorization = wechatConfig.getSchema() + " " + wechatCreateToken.getAuthorization("GET", Objects.requireNonNull(HttpUrl.parse(wechatConfig.getPayUrl() + "/v3/pay/transactions/out-trade-no/" + orderNo + "?mchid=" + wechatConfig.getMchid())), timestamp, nonceStr, "");
        String result = HttpUtil.createGet(wechatConfig.getPayUrl() + "/v3/pay/transactions/out-trade-no/" + orderNo)
                .header("Authorization",authorization)
                .header("Accept","application/json")
                .form(paramMap)
                .execute()
                .body();
        JSONObject data = JSONUtil.parseObj(result);
        String tradeState = data.get("trade_state",String.class);
        if ("SUCCESS".equals(tradeState)) {
    //支付成功
            Map<String,Object> map = new HashMap<>();
            map.put("out_trade_no",data.get("out_trade_no",String.class));
            map.put("success_time",data.get("success_time",Date.class));
            BigDecimal money = new BigDecimal(data.get("amount", Map.class).get("payer_total").toString());
            map.put("amount",money.divide(new BigDecimal(100),2, RoundingMode.HALF_UP));
            return map;
        } else {
    
            throw new IllegalArgumentException("支付失败");
        }
    }

}

实体类

package com.example.demo.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import java.io.Serializable;

@Data
public class LoginDTO implements Serializable{
    

    @NotBlank(message = "手机code不能为空")
    @ApiModelProperty("手机code")
    private String weixinCode;

    @NotBlank(message = "登录code不能为空")
    @ApiModelProperty("登录code")
    private String loginCode;
}

package com.example.demo.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

@Data
public class WechatDTO implements Serializable {
    

    @ApiModelProperty("随机串")
    private String nonceStr;

    @ApiModelProperty("签名")
    private String signature;

    @ApiModelProperty("证书序列号")
    private String serialNo;

    @ApiModelProperty("时间戳")
    private String timestamp;

    @ApiModelProperty("加密类型")
    private String signatureType;

    @ApiModelProperty("报文")
    private String body;

}

控制层controller

package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.dto.LoginDTO;
import com.example.demo.dto.WechatDTO;
import com.example.demo.service.WechatService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;

@RestController
public class WechatController {
    

    @Autowired
    private WechatService wechatService;

    @ApiOperation(value = "授权登录获取手机号")
    @RequestMapping(value = "/auth", method = RequestMethod.POST)
    public String login(@Valid @RequestBody LoginDTO loginDTO){
    
        return wechatService.login(loginDTO);
    }

    @ApiOperation(value = "获取支付签名")
    @GetMapping("/getPaySign")
    public Map<String,Object> getPaySign(){
    
        return wechatService.getPaySign();
    }

    @ApiOperation(value = "获取订单信息")
    @GetMapping("/getOrderInfo")
    public Map<String,Object> getOrderInfo(String orderNo){
    
        return wechatService.getOrderInfo(orderNo);
    }

    @ApiOperation("支付通知(回调)")
    @RequestMapping(value = "/notifyUrl",method = RequestMethod.POST)
    @ResponseBody
    public JSONObject payNotifyUrl(HttpServletRequest request) {
    
        //获取报文
        String body = getRequestBody(request);
        //随机串
        String nonceStr = request.getHeader("Wechatpay-Nonce");
        //微信传递过来的签名
        String signature = request.getHeader("Wechatpay-Signature");
        //证书序列号(微信平台)
        String serialNo = request.getHeader("Wechatpay-Serial");
        //时间戳
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        //加密类型
        String signatureType = request.getHeader("Wechatpay-Signature-Type");
        WechatDTO wechatDTO = new WechatDTO();
        wechatDTO.setBody(body);
        wechatDTO.setNonceStr(nonceStr);
        wechatDTO.setSerialNo(serialNo);
        wechatDTO.setTimestamp(timestamp);
        wechatDTO.setSignatureType(signatureType);
        wechatDTO.setSignature(signature);
        wechatService.payNotifyUrl(wechatDTO);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code","SUCCESS");
        jsonObject.put("message","成功");
        return jsonObject;
    }

    /**
     * 读取请求数据流
     */
    private String getRequestBody(HttpServletRequest request) {
    
        StringBuffer sb = new StringBuffer();
        try (ServletInputStream inputStream = request.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        ) {
    
            String line;
            while ((line = reader.readLine()) != null) {
    
                sb.append(line);
            }
        } catch (IOException e) {
    
            throw new IllegalArgumentException(e);
        }
        return sb.toString();
    }

}

service接口

package com.example.demo.service;

import com.example.demo.dto.LoginDTO;
import com.example.demo.dto.WechatDTO;

import java.util.Map;

public interface WechatService {
    

    String login(LoginDTO loginDTO);

    Map<String,Object> getPaySign();

    void payNotifyUrl(WechatDTO wechatDTO);

    Map<String, Object> getOrderInfo(String orderNo);
}

业务逻辑处理

package com.example.demo.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.config.WechatConfig;
import com.example.demo.dto.LoginDTO;
import com.example.demo.dto.WechatDTO;
import com.example.demo.service.WechatService;
import com.example.demo.util.AesUtil;
import com.example.demo.util.WechatUtil;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.core.notification.NotificationParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Map;

@Slf4j
@Service
public class WechatServiceImpl implements WechatService {
    

    @Autowired
    private WechatUtil wechatUtil;

    @Autowired
    private WechatConfig wechatConfig;

    @Override
    public String login(LoginDTO loginDTO) {
    
        //获取微信用户ID,存储在数据库中
        String openid = wechatUtil.getOpenid(loginDTO.getLoginCode());
        //获取小程序全局唯一后台接口调用凭据
        String accessToken = wechatUtil.getAccessToken();
        //微信获取手机号
        String phoneNumber = wechatUtil.getPhoneNumber(accessToken, loginDTO.getWeixinCode());
        return phoneNumber;
    }

    @Override
    public Map<String,Object> getPaySign() {
    
        //获取数据库存储的微信id
        String openid = "xxxx";
        return wechatUtil.getPaySignParam(openid);
    }

    @Override
    public Map<String, Object> getOrderInfo(String orderNo) {
    
        return wechatUtil.getOrderInfo(orderNo);
    }

	@Override
    public void payNotifyUrl(WechatDTO wechatDTO) {
    
        //第一种
        manualDecryption(wechatDTO);
        //第二种
        notificationParser(wechatDTO);
    }
}

  • 支付回调接口-解密参数

微信支付文档

第一种使用AesUtil解密工具类

package com.example.demo.util;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AesUtil {
    

    static final int KEY_LENGTH_BYTE = 32;

    static final int TAG_LENGTH_BIT = 128;

    private final byte[] aesKey;

    public AesUtil(byte[] key) {
    
        if (key.length != KEY_LENGTH_BYTE) {
    
          throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
        }
        this.aesKey = key;
    }

    public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException {
    
        try {
    
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData);
            return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), StandardCharsets.UTF_8);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
    
            throw new IllegalStateException(e);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
    
            throw new IllegalArgumentException(e);
        }
    }
}

业务处理

      public void manualDecryption(WechatDTO wechatDTO){
    
        //证书序列号(微信平台)
        if (wechatDTO.getSerialNo().equals(wechatConfig.getSerialNo())){
    
            throw new IllegalArgumentException("验签失败");
        }
        //附加数据
        String associatedData = (String) JSONUtil.getByPath(JSONUtil.parse(wechatDTO.getBody()), "resource.associated_data");
        //数据密文
        String ciphertext = (String) JSONUtil.getByPath(JSONUtil.parse(wechatDTO.getBody()), "resource.ciphertext");
        //随机串
        String nonce = (String) JSONUtil.getByPath(JSONUtil.parse(wechatDTO.getBody()), "resource.nonce");
        //解密
        try {
    
            //验签成功
            String decryptData = new AesUtil(wechatConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8)).decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);
            //支付参数
            Transaction transaction = JSONObject.parseObject(decryptData, Transaction.class);
            log.info("参数-------" + JSONObject.toJSONString(transaction));
            //订单编号(本地生成)
            String outTradeNo = transaction.getOutTradeNo();
            //通过本地订单编号处理业务逻辑(并将付款编号保存到本地)
            log.info("订单编码" + outTradeNo);
            //业务逻辑处理
            if (transaction.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)) {
    

            }
        } catch (GeneralSecurityException | IOException e) {
    
            log.error("解密失败:"+JSONObject.toJSONString(wechatDTO.getBody()));
            throw new IllegalArgumentException(e);
        }
    }

第二种初始化获取证书

package com.example.demo.config;

import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class WechatInitConfig {
    

    private Config config;

    @Autowired
    private WechatConfig wechatConfig;


    @PostConstruct
    public void init(){
    
        config = new RSAAutoCertificateConfig.Builder()
                .merchantId(wechatConfig.getMchid())
                .privateKey(wechatConfig.getPrivateKey())
                .merchantSerialNumber(wechatConfig.getSerialNo())
                .apiV3Key(wechatConfig.getApiV3Key())
                .build();
    }

    @Bean("NotificationParser")
    public NotificationParser getNotificationParser(){
    
        return new NotificationParser((NotificationConfig) config);
    }
}

业务数据处理

     
      @Autowired
      private NotificationParser notificationParser;
      
      public void notificationParser(WechatDTO wechatDTO){
    
        // 获取HTTP请求头中的 Wechatpay-Signature 、 Wechatpay-Nonce 、 Wechatpay-Timestamp 、 Wechatpay-Serial 、 Request-ID 、Wechatpay-Signature-Type 对应的值,构建 RequestParam 。
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatDTO.getSerialNo())
                .nonce(wechatDTO.getNonceStr())
                .signature(wechatDTO.getSignature())
                .timestamp(wechatDTO.getTimestamp())
                // 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048
                .signType(wechatDTO.getSignatureType())
                .body(wechatDTO.getBody())
                .build();
        Transaction transaction = notificationParser.parse(requestParam, Transaction.class);
        System.out.println("参数-------"+ JSONObject.toJSONString(transaction));
        //处理业务逻辑
        Transaction.TradeStateEnum tradeState = transaction.getTradeState();
        //订单编号(本地生成)
        String outTradeNo = transaction.getOutTradeNo();
        System.out.println("订单编号"+outTradeNo);
        //付款编号 (微信返回)
        String transactionId = transaction.getTransactionId();
        //通过本地订单编号处理业务逻辑(并将付款编号保存到本地)
        System.out.println("付款编号"+transactionId);
        if (tradeState.equals(Transaction.TradeStateEnum.SUCCESS)) {
    
            //业务处理
        }
    }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_46300599/article/details/137788262

智能推荐

CCF-201403-4(无线网络)_29. 7-44.无线网络 【问题描述】   目前在一个很大的平面房间里有 n 个无线路由-程序员宅基地

文章浏览阅读179次。一:问题1.问题描述目前在一个很大的平面房间里有 n 个无线路由器,每个无线路由器都固定在某个点上。任何两个无线路由器只要距离不超过 r 就能互相建立网络连接。  除此以外,另有 m 个可以摆放无线路由器的位置。你可以在这些位置中选择至多 k 个增设新的路由器。  你的目标是使得第 1 个路由器和第 2 个路由器之间的网络连接经过尽量少的中转路由器。请问在最优方案下中转路由器的最少个数是..._29. 7-44.无线网络 【问题描述】   目前在一个很大的平面房间里有 n 个无线路由

将JTable加入到JScrollPane后,无法向JScrollPane中添加其他的组件的解决方案_java jscrollpane添加jtable后怎么点击不了-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。我们知道,如果不将JTable添加到JScrollPane中,则表头不会显示出来。但是加进去后,如果想再向JScrollPane中添加其他的组件,是添加不进去的。如果用JScrollPane.getViewport().add(Component view)的方法,则只会显示你新加进去的组件。如果用JScrollPane.add(Component view);的方法,则新添加进的组件只会在你的鼠_java jscrollpane添加jtable后怎么点击不了

实验题123-程序员宅基地

文章浏览阅读13次。【代码】实验题123。

发布一个基于QT的数据采集源码_qt 数据采集-程序员宅基地

文章浏览阅读3.1k次。先上图1. 正弦波 [size=0.83em]半小时前 上传2. 三角波 3. 方波 接着是源码:PC端: pc_source.zip (12.97 KB, 下载次数: 138) 上传的是源码。编译环境为:Visual Studio 2008 + QT 4.8.6 + Qwt 6.0.2 + QtSerialPort(最新版)。如果要编译的话,将上述库下载后编译为lib文件后加入工程即可。..._qt 数据采集

高德爬虫2.0_高德地图爬虫-程序员宅基地

文章浏览阅读3.4k次。# 结果展示读取品牌名称,并根据品牌名称获取相关城市的POI数据,并将其写入Excel文件# 写在最前面修改前日期:2021-06-05 00:03:50修改后:增加代码解析(因为质量分太低了。。。)www一个月断断续续的更改,函数循环加主体循环把自己无限绕进去了,终于改完了感谢@Fzy,@Tj,@Xk的指导_高德地图爬虫

随便推点

LVGL-tileview控件_lvgl tileview-程序员宅基地

文章浏览阅读1.7k次。控件特点以page为基础扩展的控件,增加了释放后会有动画定格效果。lv_tileview_set_tile_act(tileview, ext->act_id.x + x_move, ext->act_id.y + y_move, true);//切入时开启动画效果。static void drag_end_handler(lv_obj_t * tileview){ lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tilevie_lvgl tileview

Office365完整离线安装包下载及自定义安装教程-程序员宅基地

文章浏览阅读8.9k次。Office 365是微软打造的一款适用于教育机构使用的office办公软件,这里为大家提供了一个Office 365离线安装包下载工具,让office 365离线包下载到本地再安装,而不是联网下载安装,避免有多台设备需要安装时耗时占用宽带,且方便自定义,欢迎下载使用。Office365部署方法概要提示:全文内容归结起来其实也就2条命令下载:D:\365\setup.exe /do..._office365完整离线安装包下载及自定义安装教程

论文解读--2D Car Detection in Radar Data with PointNets-程序员宅基地

文章浏览阅读788次,点赞23次,收藏18次。对于许多自动驾驶功能,高精度的感知车辆环境是一个重要的前提。现代高分辨率雷达传感器为每个目标产生多个雷达目标,这使得这些传感器特别适合于二维目标探测任务。这项工作提出了一种方法,使用PointNets完全依赖稀疏雷达数据检测二维物体。在文献中,目前只提出了对对象进行对象分类或边界盒估计的方法。相比之下,该方法便于分类和使用单一雷达传感器对物体的边界盒估计。为此,对雷达数据进行分割,进行二维目标分类,并对二维边界盒进行回归,以估计一个模态的二维边界盒。_2d car detection in radar data with pointnets

基于Java+jsp+Servlet的学生考勤签到管理系统_jsp+servlet(ajax+servlet)实现考勤报表-程序员宅基地

文章浏览阅读141次。项目简介:本系统是一款为大学生毕业设计的系统,基于java+jsp+servlet的学生考勤签到系统。_jsp+servlet(ajax+servlet)实现考勤报表

尚硅谷Docker实战教程学习总结文档_尚硅谷文档-程序员宅基地

文章浏览阅读1.2k次,点赞3次,收藏10次。学习前的思路:1.是什么2.能干什么3.去哪里下4.怎么用5.跑起来docker解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。_尚硅谷文档

jQuery技巧总结_jquery 问号 用法-程序员宅基地

文章浏览阅读1.3k次。视频看完了,在这次学习中我发现了这位老师的几个好习惯。老师在完成一部分的功能之后都会去验证,这样做能及时发现问题,而且也易于调试,调试的时候非常有针对性;还有就是老师的条理性非常强,尤其体现在完成那些逻辑性的句子的时候先通过注释把自己的想法写出来,然后再根据注释一点点的用代码实现;还有一点非常重要的就是老师在完成代码的时候善于去整理代码,将一些重复的代码封装在函数中,希望发现的这几个好习惯也会成为_jquery 问号 用法

推荐文章

热门文章

相关标签