收藏
回答

付款码支付提示签名验证不通过,不知道是哪里出了问题?

package net.shop.system.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import net.shop.framework.common.utils.Result;
import net.shop.system.query.SysAliPayQuery;
import net.shop.system.utils.HttpClientUtil;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import okhttp3.HttpUrl;
import java.security.PrivateKey;
import java.security.Signature;

/**
* 微信付款码支付
*/
@RestController
@RequestMapping("sys/wechat")
@Tag(name="微信付款码支付")
@AllArgsConstructor
public class SysWechatPayController {

    protected static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    protected static final SecureRandom RANDOM = new SecureRandom();
//    protected static final PrivateKey privateKey = null; //need to be initialized
    protected static final String certificateSerialNumber = "XXXXXX"; //need to be initialized
    protected static final String merchantId = "XXXXXX"; //need to be initialized

    public String getToken(String method, HttpUrl url, String body) throws UnsupportedEncodingException {
        String nonceStr = generateNonceStr();
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("utf-8"));
        return "mchid=\"" + merchantId + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + certificateSerialNumber + "\","
                + "signature=\"" + signature + "\"";
    }
    public 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";
    }
    public PrivateKey getPrivateKey(String filename) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    public String sign(byte[] message) {
        try {
            PrivateKey privateKey = getPrivateKey("D:\\project\\shop\\cert\\apiclient_key.pem");
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey);
            sign.update(message);
            return Base64.getEncoder().encodeToString(sign.sign());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名计算失败", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的私钥", e);
        } catch (IOException e) {
            throw new RuntimeException("无效的密钥格式", e);
        }
    }
    protected long generateTimestamp() {
        return System.currentTimeMillis() / 1000;
    }

    protected String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }
    @PostMapping("userPay")
    @Operation(summary = "用户支付")
    public Result userPay(@RequestBody @Valid SysAliPayQuery query){
        try{
            String json= "{";
            json+="\"appid\" : \"wxf46b8243f657189f\",";
            json+="\"mchid\" : \"1676902789\",";
            json+="\"description\" : \""+query.getTitle()+"\",";
            json+="\"out_trade_no\" : \""+query.getOrderNum()+"\",";
            json+="\"support_fapiao\" : false,";
            json+="\"payer\" : {";
            json+="\"auth_code\" : \""+query.getAuthCode()+"\"";
            json+="},";
            json+="\"amount\" : {";
            json+="\"total\" : 100,";
            json+="\"currency\" : \"CNY\"";
            json+="},";
            json+="\"scene_info\" : {";
            json+="\"store_info\" : {";
            json+="\"id\" : \"0001\",";
            json+="\"out_id\" : \"111112\"";
            json+="}";
            json+="},";
            json+="\"detail\" : {";
            json+="\"goods_detail\" : [";
            json+="{";
            json+="\"merchant_goods_id\" : \"1246464644\",";
            json+="\"wxpay_goods_id\" : \"1001\",";
            json+="\"goods_name\" : \""+query.getTitle()+"\",";
            json+="\"quantity\" : 1,";
            json+="\"unit_price\" : 100";
            json+="}";
            json+="]";
            json+="}";
            json+="}";
            HttpUrl httpurl = HttpUrl.parse("https://api.mch.weixin.qq.com/v3/certificates");

            Map headers = new HashMap<>();
            headers.put("Authorization","WECHATPAY2-SHA256-RSA2048 "+getToken("GET", httpurl, ""));
            headers.put("Accept","application/json");
            headers.put("Content-Type","application/json; charset=utf-8");

            String url1 = "https://api.mch.weixin.qq.com/v3/pay/transactions/codepay";
            HttpClientUtil.postJson(url1, null, headers, json,false);
            return Result.ok();
        }
        catch (Exception ex){
            return Result.error("系统内部错误!");
        }
    }
}


最后一次编辑于  07-07
回答关注问题邀请回答
收藏

1 个回答

登录 后发表内容