微信支付分(先享后付)对接记录:

本文详细记录了微信支付分(先享后付)的对接步骤,包括申请开通、技术准备、用户服务开启、订单创建与管理、扣款流程等关键环节。对接过程中涉及API证书升级、签名规则、回调通知等技术要点,适用于网约车等场景。

微信支付分(先享后付)对接记录:

微信支付分对接步骤

    1. 填写开通支付分的申请表格 此步骤大概需要审核 1-3 个工作日; (模板-服务信息配置表-【先享后付免确认】-【商户名】.xls) 填写商户信息 和回调地址(支持三套环境)
    1. 拿到审核结果 对技术而言 需要serviceId appid appSecret 和API密钥(签名用) apiclient_cert.xxx 证书文件(退款用)

      升级 V3 证书

    1. 仔细阅读微信官方对接文档 对接流程
    1. 微信支付分-网约车场景接入流程图(非官方)

      4.1[外链图片转存失败(img-CIx8eVTb-1563787158097)(tomas.test.upcdn.net/java/订单状态流程图1 (1)].jpg)

    4.2 接口说明

    1 用户下单叫车

    用户在商户端下单叫车,一般交互方式为:用户输入出发地/目的地呼叫车辆后,后台查询用户是否可使用服务,若否,则弹出开启微信支付分说明页或按钮,用户点击后,调用开启服务接口(跳转至微信端,进行服务开启),每个用户第一次使用微信支付分方式打车,均需进行一次开启动作。(仅需一次) 微信官方推荐做法个人认为流氓到极致. 我们对此做了改变 引导用户自己在产品中 开启免密支付服务 下单(接到乘客开始服务)时只需要MQ 通知 支付系统 创建免确认支付分订单即可.

    2 查询用户是否可使用服务

    ●接口名称:查询用户是否可使用服务

    ●文档名称:【先享后付-开启支付分服务】

    3.1 请求创建订单

    ●接口名称:创建先享后付订单

    ●文档名称:【先享后付-创建订单】

    3.2 引导用户开启服务

    ●接口名称:小程序跳转接口(开启服务) //文档提供了两种跳转方法,商户自行选择一种即可,此接口支持小程序/app/H5

    ●文档名称:【先享后付-引导用户开通】

    4 行程开始

    商户请求创建订单后,若用户【开启服务成功】+【风险评估通过】则会收到微信支付的异步回调通知,此时可提供网约车服务给用户。

    ●接口名称:用户确认订单通知商户规则

    ●文档名称:【先享后付-用户确认订单通知】

    该步骤可能出现创建订单失败、用户确认订单失败、回调通知异常等情况,导致长时间接收不到微信支付的异步回调通知,此时可进行查询订单状态操作,主动查询确认订单状态。

    ●接口名称:查询先享后付订单

    ●文档名称:【先享后付-查询订单详情】

    5 行程结束

    用户完成打车服务,行程结束

    6 请求完结订单

    商户根据行程订单金额,请求完结订单,发起扣款请求

    ●接口名称:完结先享后付订单

    ●文档名称:【先享后付-完结订单发起扣款】

    7 扣款成功

    微信支付完成扣款,并将扣款结果异步回调通知给商户

    ●接口名称:收款成功通知商户规则

    ●文档名称:【先享后付-扣款成功回调】

    该步骤可能出现扣款失败、回调通知异常等情况,导致长时间接收不到微信支付的异步回调通知,此时可进行查询订单状态操作,避免重复扣款。

    ●接口名称:查询先享后付订单

    ●文档名称:【先享后付-查询订单详情】

    超级坑的技术文档: 签名规则统一以下面网页介绍的为准:

    https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/qian-ming-sheng-cheng

下面是Java 接入过程:

第一步: 阅读微信支付分给的接口规则 说明: https://wechatpay-api.gitbook.io/wechatpay-api-v3/

第二步: 微信支付API v3要用第三方CA的证书 所以涉及到 API证书升级

  • 新接入商户请参考什么是API证书?如何获取API证书?

  • 已经接入并使用微信支付颁发证书的商户请参考微信支付API证书升级指引(技术人员)
    API v3已不支持使用微信支付颁发的证书。
    商户升级API证书时,需要完成三个步骤:

    ①:商户号的超级管理员到商户平台升级证书,获取到权威CA颁发的API证书。 (查看指引

    ②:超级管理员将权威CA颁发的API证书(共包含三个文件: 证书pkcs12格式、证书pem格式、证书密钥pem格式)转交给技术人员。

    ③:技术人员用新证书文件替换服务器上原微信支付颁发的API证书,无需对现有系统进行代码修改。

    (注意)这里升级API证书不影响原有的 API 密钥 代码不需要做改动直接替换 apiclient_cert.p12文件即可

第三步: 拿到API证书和密钥文件.

第四步: 引入微信支付API v3的Apache HttpClient装饰器: GitHub 地址

​ 注意: 微信支付API v3Apache HttpClient扩展,实现了请求签名的生成和应答签名的验证。如不想使用次封装客户端 可自己实现 签名和应答解密过程.

​ Maven

​ 加入JitPack仓库

	<repositories>
		<repository>
		    <id>jitpack.io</id>
		    <url>https://jitpack.io</url>
		</repository>
	</repositories>

加入以下依赖

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

第五步: 请求微信支付分API前准备

   //微信支付商户开通后 微信会提供appid
    public String appId;
    
    //微信支付商户开通后 微信会提供appSecret
    public String appSecret;
    
    //商户号
    public String mchId; 
    
    //32位的api密钥,微信商户平台-账户设置-安全设置-api安全 密钥 用于拉起支付签名
    public String partnerkey;
    
    //openId 是微信用户针对公众号的标识,授权的部分这里不解释
    public String openId;
    
    //微信支付成功后异步通知地址 必须要求80端口并且地址不能带参数
    public String notifyUrl;
    
    //微信支付成功后同步通知地址 必须要求80端口并且地址不能带参数
    public String returnUrl;
    
    //证书apiclient_cert.p12文件位置 可加载
    public String certPath;
    
    //微信支付分 分配的服务 ID
    public String serviceId;
    
    //v3接口 CA证书 apiclient_key.pem私钥内容 
    public String privateKey;
    
    //v3接口 CA证书 apiclient_cert.pem证书内容
    public String certificate;
    
    // APIv3密钥 32 位
    public String AES_KEY = "xxx"; 
    
    //商户证书序列号 CA证书 可查看微信商户平台-账户设置-安全设置-api安全密钥
    public String  MC_HSERIAL_NO = "xxxxx"; 

第六步: 请求支付分 API : 签约 创建订单 确认订单

​ DEMO参见: https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient/blob/master/src/test/java/com/wechat/pay/contrib/apache/httpclient/HttpClientBuilderTest.java

几个示例核心代码:

示例: 查询用户签约状态
    public static final String USER_SERVICE_STATE_URL = "https://api.mch.weixin.qq.com/payscore/user-service-state";
    
   PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
        new ByteArrayInputStream(privateKey.getBytes("utf-8"))); 
//privateKey= //v3接口 CA证书 apiclient_key.pem私钥内容 

    httpClient = WechatPayHttpClientBuilder.create()
        .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
        .withValidator(response -> true)
        .build();
  URIBuilder uriBuilder =   new URIBuilder(USER_SERVICE_STATE_URL);
                        uriBuilder.setParameter("service_id", yourServiceIdxxx);
                        uriBuilder.setParameter("appid", yourAppIdxxx);
                        uriBuilder.setParameter("openid", userOpenIdxxx);
 CloseableHttpResponse response=null;
        try {
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            httpGet.addHeader("Accept", "application/json");
            // NOTE: 建议指定charset=utf-8。低于4.4.6版本的HttpCore,不能正确的设置字符集,可能导致签名错误
            response = getHttpDefaultClient().execute(httpGet);
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                String result = EntityUtils.toString(response.getEntity());// 返回json格式:
                return JSONObject.parseObject(result);
            }else {
                String result = EntityUtils.toString(response.getEntity());// 返回json格式:
                log.info("微信支付V3 url={} result={} responseEntity={}",uriBuilder.build(), result,JSON.toJSONString(response.getEntity()));
            }
        } catch (Exception e) {
            log.error("微信支付V3 请求url={}异常 ",uriBuilder.build());
        }finally {
            if(null!=response){
                response.close();
            }
        }

 示例: 创建支付分订单 
 
     public static final String PAYSCORE_PAYAFTER_ORDERS_URL = "https://api.mch.weixin.qq.com/v3/payscore/payafter-orders";

  //【先享后付-创建订单】参数 转化成javaBean/或者 JSONOjbect 设置参数 

 //注意我这里need_user_confirm 参数 如果传 false 表不需要用户确认 
   PayAfterOrdersModel  payAfterOrdersModel=PayAfterOrdersModel.builder().appid(appId)
      .need_user_confirm(Boolean.FALSE).openid(recordModel.getOpenId()).risk_amount(PAY_SIGN_RISK_AMOUNT).out_order_no(model.getObjId())
          .service_start_time(DateTimeUtils.dateFormat(model.getServiceStartTime(),"yyyyMMddHHmmss"))
                  .service_start_location(WxPayUtil.subString(model.getServiceStartLocation(),20)).service_introduction(PAY_SIGN_FEE_DESC).service_id(config.getServiceId()).build();

 Fees fee=new Fees();
        fee.setFee_name("xx费");
        fee.setFee_amount(amount); //支付金额
        fee.setFee_desc("xxx");
        List<Fees> fees=new ArrayList<>();
        fees.add(fee);
payAfterOrdersModel.setFees(fees);
 //如果有优惠请设置优惠信息  此处不做设置
 
 //构造 Client
   PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
        new ByteArrayInputStream(privateKey.getBytes("utf-8"))); 
//privateKey= //v3接口 CA证书 apiclient_key.pem私钥内容 

    httpClient = WechatPayHttpClientBuilder.create()
        .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
        .withValidator(response -> true)
        .build();
 //请求支付分
  HttpPost httpPost = new HttpPost(PAYSCORE_PAYAFTER_ORDERS_URL);
        StringEntity reqEntity = new StringEntity(JSONObject.toJSONString(payAfterOrdersModel), ContentType.create("application/json", "utf-8"));
        httpPost.setEntity(reqEntity);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-Type", "application/json");
        CloseableHttpResponse response = httpClient.execute(httpPost);
        try {
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                String result = EntityUtils.toString(response.getEntity());// 返回json格式:
                log.info("微信支付V3 url={} result={} ",url,result);
                return JSONObject.parseObject(result);
            }else {
                String result = EntityUtils.toString(response.getEntity());// 返回json格式:
                log.info("微信支付V3 url={} result={} response.getEntity()={}",url,result,JSON.toJSONString(response.getEntity()));
            }
        } catch (Exception e) {
            log.error("微信支付V3 请求url={} 参数={} 异常 e={}",url, JSON.toJSONString(json),e.getMessage());
        }finally {
            response.close();
        }
 
  后续 完结订单   (注意请求完结订单的时有个finish_ticket 只有用户确认了订单才能拿到) 如果是创建的免确认订单 需要创建完订单后 查询订单详情 返回值中有 finish_ticket字段 
 

第七步: 接收回调消息:

… 去博客园看完整文章内容吧 这里只写了部分

原文链接地址**

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值