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

智能推荐

874计算机科学基础综合,2018年四川大学874计算机科学专业基础综合之计算机操作系统考研仿真模拟五套题...-程序员宅基地

文章浏览阅读1.1k次。一、选择题1. 串行接口是指( )。A. 接口与系统总线之间串行传送,接口与I/0设备之间串行传送B. 接口与系统总线之间串行传送,接口与1/0设备之间并行传送C. 接口与系统总线之间并行传送,接口与I/0设备之间串行传送D. 接口与系统总线之间并行传送,接口与I/0设备之间并行传送【答案】C2. 最容易造成很多小碎片的可变分区分配算法是( )。A. 首次适应算法B. 最佳适应算法..._874 计算机科学专业基础综合题型

XShell连接失败:Could not connect to '192.168.191.128' (port 22): Connection failed._could not connect to '192.168.17.128' (port 22): c-程序员宅基地

文章浏览阅读9.7k次,点赞5次,收藏15次。连接xshell失败,报错如下图,怎么解决呢。1、通过ps -e|grep ssh命令判断是否安装ssh服务2、如果只有客户端安装了,服务器没有安装,则需要安装ssh服务器,命令:apt-get install openssh-server3、安装成功之后,启动ssh服务,命令:/etc/init.d/ssh start4、通过ps -e|grep ssh命令再次判断是否正确启动..._could not connect to '192.168.17.128' (port 22): connection failed.

杰理之KeyPage【篇】_杰理 空白芯片 烧入key文件-程序员宅基地

文章浏览阅读209次。00000000_杰理 空白芯片 烧入key文件

一文读懂ChatGPT,满足你对chatGPT的好奇心_引发对chatgpt兴趣的表述-程序员宅基地

文章浏览阅读475次。2023年初,“ChatGPT”一词在社交媒体上引起了热议,人们纷纷探讨它的本质和对社会的影响。就连央视新闻也对此进行了报道。作为新传专业的前沿人士,我们当然不能忽视这一热点。本文将全面解析ChatGPT,打开“技术黑箱”,探讨它对新闻与传播领域的影响。_引发对chatgpt兴趣的表述

中文字符频率统计python_用Python数据分析方法进行汉字声调频率统计分析-程序员宅基地

文章浏览阅读259次。用Python数据分析方法进行汉字声调频率统计分析木合塔尔·沙地克;布合力齐姑丽·瓦斯力【期刊名称】《电脑知识与技术》【年(卷),期】2017(013)035【摘要】该文首先用Python程序,自动获取基本汉字字符集中的所有汉字,然后用汉字拼音转换工具pypinyin把所有汉字转换成拼音,最后根据所有汉字的拼音声调,统计并可视化拼音声调的占比.【总页数】2页(13-14)【关键词】数据分析;数据可..._汉字声调频率统计

linux输出信息调试信息重定向-程序员宅基地

文章浏览阅读64次。最近在做一个android系统移植的项目,所使用的开发板com1是调试串口,就是说会有uboot和kernel的调试信息打印在com1上(ttySAC0)。因为后期要使用ttySAC0作为上层应用通信串口,所以要把所有的调试信息都给去掉。参考网上的几篇文章,自己做了如下修改,终于把调试信息重定向到ttySAC1上了,在这做下记录。参考文章有:http://blog.csdn.net/longt..._嵌入式rootfs 输出重定向到/dev/console

随便推点

uniapp 引入iconfont图标库彩色symbol教程_uniapp symbol图标-程序员宅基地

文章浏览阅读1.2k次,点赞4次,收藏12次。1,先去iconfont登录,然后选择图标加入购物车 2,点击又上角车车添加进入项目我的项目中就会出现选择的图标 3,点击下载至本地,然后解压文件夹,然后切换到uniapp打开终端运行注:要保证自己电脑有安装node(没有安装node可以去官网下载Node.js 中文网)npm i -g iconfont-tools(mac用户失败的话在前面加个sudo,password就是自己的开机密码吧)4,终端切换到上面解压的文件夹里面,运行iconfont-tools 这些可以默认也可以自己命名(我是自己命名的_uniapp symbol图标

C、C++ 对于char*和char[]的理解_c++ char*-程序员宅基地

文章浏览阅读1.2w次,点赞25次,收藏192次。char*和char[]都是指针,指向第一个字符所在的地址,但char*是常量的指针,char[]是指针的常量_c++ char*

Sublime Text2 使用教程-程序员宅基地

文章浏览阅读930次。代码编辑器或者文本编辑器,对于程序员来说,就像剑与战士一样,谁都想拥有一把可以随心驾驭且锋利无比的宝剑,而每一位程序员,同样会去追求最适合自己的强大、灵活的编辑器,相信你和我一样,都不会例外。我用过的编辑器不少,真不少~ 但却没有哪款让我特别心仪的,直到我遇到了 Sublime Text 2 !如果说“神器”是我能给予一款软件最高的评价,那么我很乐意为它封上这么一个称号。它小巧绿色且速度非

对10个整数进行按照从小到大的顺序排序用选择法和冒泡排序_对十个数进行大小排序java-程序员宅基地

文章浏览阅读4.1k次。一、选择法这是每一个数出来跟后面所有的进行比较。2.冒泡排序法,是两个相邻的进行对比。_对十个数进行大小排序java

物联网开发笔记——使用网络调试助手连接阿里云物联网平台(基于MQTT协议)_网络调试助手连接阿里云连不上-程序员宅基地

文章浏览阅读2.9k次。物联网开发笔记——使用网络调试助手连接阿里云物联网平台(基于MQTT协议)其实作者本意是使用4G模块来实现与阿里云物联网平台的连接过程,但是由于自己用的4G模块自身的限制,使得阿里云连接总是无法建立,已经联系客服返厂检修了,于是我在此使用网络调试助手来演示如何与阿里云物联网平台建立连接。一.准备工作1.MQTT协议说明文档(3.1.1版本)2.网络调试助手(可使用域名与服务器建立连接)PS:与阿里云建立连解释,最好使用域名来完成连接过程,而不是使用IP号。这里我跟阿里云的售后工程师咨询过,表示对应_网络调试助手连接阿里云连不上

<<<零基础C++速成>>>_无c语言基础c++期末速成-程序员宅基地

文章浏览阅读544次,点赞5次,收藏6次。运算符与表达式任何高级程序设计语言中,表达式都是最基本的组成部分,可以说C++中的大部分语句都是由表达式构成的。_无c语言基础c++期末速成