Skip to content

4.12微信支付

微信支付:https://pay.weixin.qq.com/

微信支付方式:https://pay.weixin.qq.com/static/product/product_intro.shtml?name=jsapi

开发准备

账号申请

  • 申请商户号
  • 申请公众号或小程序应用或app

支付方式选择

  • PC端:Native支付
  • 移动端:H5支付

JSAPI支付和Native支付区别: JSAPI支付的金额需要用户收到输入。 Native支付的金额是用户扫描微信二维码后自动带出。

开发准备

https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_1.shtml

  • 申请APPID——申请公众号或小程序应用或app获得

  • 申请mchid ——申请商户号获得

  • APPID及mchid——申请公众号或小程序应用或app获得

  • 配置API key——根据文档获得

  • 下载并配置商户证书

    image-20240415153736074

mchid:1600686718
appId:wx6f3cca7cd16125e9
appSecret:a1e164e950e15dcb8a20017f12bcc5a
apiV3Key:IZOBZjAPlCaCjDCPizQCooP1OfXewn4i
私钥:apiclient_key.pem
证书序列号:51BCB144BAF201F5314A0841EAC3239A9F3F2E5F

开发

开发指引:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_2.shtml

不要看最新的:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml

下载微信支付demo:https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient

下载好wechatpay-apache-httpclient-master.zip,仔细看test的代码

依赖

<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-apache-httpclient</artifactId>
    <version>0.4.9</version>
</dependency>

初始化httpclient

java
@Before
    public void setup() throws IOException {

        // 加载商户私钥(privateKey:私钥字符串)
        PrivateKey merchantPrivateKey = PemUtil
                .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));

        // 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥)
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),apiV3Key.getBytes("utf-8"));

        // 初始化httpClient
        httpClient = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier)).build();
    }

native下单(生成二维码)

java
@org.junit.Test
    public void CreateOrder() throws Exception{
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
        // 请求body参数
        // 金额
        JSONObject amount = new JSONObject();
        amount.put("total", 100);
        amount.put("currency", "CNY");
        // 商定
        JSONObject settlement = new JSONObject();
        settlement.put("appid", appId);
        settlement.put("mchid", mchId);
        settlement.put("description","测试");
        settlement.put("out_trade_no", "2014102800030956");
        settlement.put("notify_url", notify_url);
        settlement.put("amount", amount);

        String reqdata = JSON.toJSONString(settlement);

        StringEntity entity = new StringEntity(reqdata,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "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()));
            } 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();
        }
    }

草料二维码:https://cli.im/text/other

支付通知(异步通知)

https://pay.weixin.qq.com/docs/merchant/apis/native-payment/payment-notice.html

参数解密

下面详细描述对通知数据进行解密的流程:

  1. 用商户平台上设置的APIv3密钥【微信商户平台—>账户设置—>API安全—>设置APIv3密钥】,记为key;
  2. 针对resource.algorithm中描述的算法(目前为AEAD_AES_256_GCM),取得对应的参数nonce和associated_data;
  3. 使用key、nonce和associated_data,对数据密文resource.ciphertext进行解密,得到JSON形式的资源对象;
js
{
    "id": "EV-2018022511223320873",
    "create_time": "2015-05-20T13:29:35+08:00",
    "resource_type": "encrypt-resource",
    "event_type": "TRANSACTION.SUCCESS",
    "summary": "支付成功",
    "resource": {
        "original_type": "transaction",
        "algorithm": "AEAD_AES_256_GCM",
        "ciphertext": "",
        "associated_data": "",
        "nonce": ""
    }
}

对resource对象进行解密后,得到的资源对象示例

js
{
    "transaction_id":"1217752501201407033233368018",
    "amount":{
        "payer_total":100,
        "total":100,
        "currency":"CNY",
        "payer_currency":"CNY"
    },
    "mchid":"1230000109",
    "trade_state":"SUCCESS",
    "bank_type":"CMC",
    "promotion_detail":[
        {
            "amount":100,
            "wechatpay_contribute":0,
            "coupon_id":"109519",
            "scope":"GLOBAL",
            "merchant_contribute":0,
            "name":"单品惠-6",
            "other_contribute":0,
            "currency":"CNY",
            "stock_id":"931386",
            "goods_detail":[
                {
                    "goods_remark":"商品备注信息",
                    "quantity":1,
                    "discount_amount":1,
                    "goods_id":"M1006",
                    "unit_price":100
                },
                {
                    "goods_remark":"商品备注信息",
                    "quantity":1,
                    "discount_amount":1,
                    "goods_id":"M1006",
                    "unit_price":100
                }
            ]
        },
        {
            "amount":100,
            "wechatpay_contribute":0,
            "coupon_id":"109519",
            "scope":"GLOBAL",
            "merchant_contribute":0,
            "name":"单品惠-6",
            "other_contribute":0,
            "currency":"CNY",
            "stock_id":"931386",
            "goods_detail":[
                {
                    "goods_remark":"商品备注信息",
                    "quantity":1,
                    "discount_amount":1,
                    "goods_id":"M1006",
                    "unit_price":100
                },
                {
                    "goods_remark":"商品备注信息",
                    "quantity":1,
                    "discount_amount":1,
                    "goods_id":"M1006",
                    "unit_price":100
                }
            ]
        }
    ],
    "success_time":"2018-06-08T10:34:56+08:00",
    "payer":{
        "openid":"oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"
    },
    "out_trade_no":"1217752501201407033233368018",
    "AppID":"wxd678efh567hg6787",
    "trade_state_desc":"支付成功",
    "trade_type":"MICROPAY",
    "attach":"自定义数据",
    "scene_info":{
        "device_id":"013467007045764"
    }
}

取出订单id和自己需要的数据

通知应答

接收成功: HTTP应答状态码需返回200或204,无需返回应答报文。

接收失败: HTTP应答状态码需返回5XX或4XX,同时需返回应答报文,格式如下:

js
{  
    "code": "FAIL",
    "message": "失败"
}