栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

微信APP下单API【V3版本】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

微信APP下单API【V3版本】

APP下单API
接口说明
适用对象: 直连商户
请求URL:https://api.mch.weixin.qq.com/v3/pay/transactions/app
请求方式:POST

  1. pom文件包
		
            com.github.wechatpay-apiv3
            wechatpay-apache-httpclient
            0.2.2
        
  1. 返回包装实体类实体类
public class AppOrderApi {
    private String appId;     //应用ID    appId
    private String mchId;     //商户号
    private String nonceStr; //随机字符串
    private String sign;      //签名
    private String prepay_id;  //预支付交易会话ID
    private String time;      //时间戳

}
  1. 工具类
public class WxPayHandler{
	 public AppOrderApi createAppOrderAPI(PayOrder order, String appId) {
        log.info("===info=== wx pay createAppOrderAPI unionId: {}, paymentId: {}", order.getUnionId(), order.getPaymentId());
        try {
            JSONObject params = new JSONObject();
            params.put("appid", appId);    // 应用ID
            params.put("mchid", MCH_ID);   // 直连商户号
            params.put("description", order.getGoodsTitle());   //商品描述
            params.put("out_trade_no", order.getUnionId()); // 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("total", order.getAmount());
            params.put("amount", jsonObject);    //订单金额信息
            params.put("notify_url", PAY_CALLBACK_URL); // 通知URL必须为直接可访问的URL,不允许携带查询串,要求必须为https地址。
            AppOrderApi result = CreateOrder(params.toJSONString(),order);
            // 密钥加密方式【最后一个也要有换行符号】:
            //应用id
            //时间戳以秒为单位
            //随机字符串
            //下单后的Prepay_id
            result.setSign(sign((appId + "n" + (order.getAddTime().getTime() / 1000) + "n" + order.getUnionId() + "n" + result.getPrepay_id() + "n").getBytes()));	// 封装签名
            return result;
        } catch (Exception e) {
            log.error("===error=== wx pay executeQuery error msg: {}", e.getMessage());
            return null;
        }
    }

 	public AppOrderApi CreateOrder(String reqdata,PayOrder order) throws Exception {
 		// MCH_ID:商户号id,SERIAL_NUMBER:证书序列号,CERTICATE_PRIVATE_PATH:私钥地址,SECRET_KEY_V3:秘钥
        CloseableHttpClient httpClient = CloseableHttpClientUtil.init(MCH_ID, SERIAL_NUMBER, CERTICATE_PRIVATE_PATH, SECRET_KEY_V3);
        //请求URL
        HttpPost httpPost = new HttpPost(WxConstants.APP_ORDER_API);
        // 请求body参数
        StringEntity entity = new StringEntity(reqdata, "UTF-8");
        log.info("请求参数:" + reqdata);
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json");
        //完成签名并执行请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) { //处理成功
                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
                AppOrderApi wxRefundInfo = JSONObject.parseObject(EntityUtils.toString(response.getEntity()), AppOrderApi.class);
                return wxRefundInfo;
            } else if (statusCode == 204) { //处理成功,无返回Body
                System.out.println("success");
            } else {
                System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
        } finally {
            response.close();
        }
        return null;
    }
// SHA256加密
    String sign(byte[] message) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(getPrivateKey(CERTICATE_PRIVATE_PATH));	// 私钥地址
        sign.update(message);

        return base64.getEncoder().encodeToString(sign.sign());
    }
    // 获取私钥
    public static 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("无效的密钥格式");
        }
    }
}

//封装Client

public class CloseableHttpClientUtil {

    public static CloseableHttpClient init(String merchantId, String serialNumber, String filename, String secret_key) {

        try {
            PrivateKey privateKey = WxPayHandler.getPrivateKey(filename);

            // 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥)
            AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                    new WechatPay2Credentials(merchantId, new PrivateKeySigner(serialNumber, privateKey)), secret_key.getBytes(StandardCharsets.UTF_8));

            return WechatPayHttpClientBuilder.create()
                    .withMerchant(merchantId, serialNumber, privateKey)
                    .withValidator(new WechatPay2Validator(verifier)).build();
        } catch (Exception e) {
            throw new RuntimeException("初始化 CloseableHttpClient  失败", e);
        }

    }

}

//获取私钥

public class PrivateKeyUtils {

    public static PrivateKey getPrivateKey(String filename) {
        // 加载商户私钥(privateKey:私钥字符串)
        try {
            return PemUtil.loadPrivateKey(new ByteArrayInputStream(analysisPem(filename).getBytes(StandardCharsets.UTF_8)));
        } catch (Exception e) {
            throw new RuntimeException("加载 PrivateKey 失败", e);
        }
    }

    
    private static String analysisPem(String filename) throws IOException {

        String content = new String(Files.readAllBytes(Paths.get(filename)), StandardCharsets.UTF_8);
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\s+", "");

            return privateKey;
        } catch (Exception e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        }
    }

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/582091.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号