首页 > 其他分享 >微信支付接口接入

微信支付接口接入

时间:2024-10-11 09:49:52浏览次数:1  
标签:String 商户 接入 微信 request 接口 支付

微信支付接口接入

微信支付接入文档参考(https://pay.weixin.qq.com/docs/merchant/products/jsapi-payment/preparation.html)

1. 接入前准备

具体步骤如下所示:

1、选择接入模式:普通商户或普通服务商, 官网说明地址:https://pay.weixin.qq.com/docs/merchant/development/glossary/mode.html

2、申请参数:AppID、商户号

申请接入微信支付:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml , 按照指引提交相关资料等待审核。

资料审核通过以后会获取商户的相关信息(商户id、API v3密钥、商户API证书) , 这些信息在支付的时候需要使用到。

3、配置应用:https://pay.weixin.qq.com/docs/merchant/products/jsapi-payment/preparation.html

相关说明: 微信支付支付多种支付方式,本次我们选择的支付方式为JSAPI支付,属于C扫B方式。

微信支付相关API

JSAPI下单接口:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/direct-jsons/jsapi-prepay.html

JSAPI调起支付接口:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/jsapi-transfer-payment.html

SDK和示例Demo:https://pay.weixin.qq.com/docs/merchant/sdk-tools/quickstart-java.html

关于JSAPI下单接口和JSAPI调起支付接口有什么区别?

2. 微信下单接口

参考API文档开发微信下单接口

接口说明:

支持商户:【普通商户】

请求方式:【POST】/v3/pay/transactions/jsapi

请求域名:【主域名】https://api.mch.weixin.qq.com 使用该域名将访问就近的接入点

请求参数:

HTTP请求头

**Authorization **必填string

请参考 签名认证 生成认证信息

Accept必填string

请设置为 application/json

Content-Type必填string

请设置为 application/json

HTTP请求体

appid必填string(32)

【公众号ID】 公众号ID

mchid必填string(32)

【直连商户号】 直连商户号

description必填string(127)

【商品描述】 商品描述

out_trade_no必填string(32)

【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。

notify_url必填string(255)

【通知地址】 异步接收微信支付结果通知的回调地址,通知URL必须为外网可访问的URL,不能携带参数。 公网域名必须为HTTPS,如果是走专线接入,使用专线NAT IP或者私有回调域名可使用HTTP

amount必填object

【订单金额】 订单金额

payer必填object

【支付者】 支付者信息

请求示例

curl -X POST
https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi
-H "Authorization: WECHATPAY2-SHA256-RSA2048 mchid="1900000001",..."
-H "Accept: application/json"
-H "Content-Type: application/json"
-d '{
"appid" : "wxd678efh567hg6787",
"mchid" : "1230000109",
"description" : "Image形象店-深圳腾大-QQ公仔",
"out_trade_no" : "1217752501201407033233368018",
"time_expire" : "2018-06-08T10:34:56+08:00",
"attach" : "自定义数据说明",
"notify_url" : " https://www.weixin.qq.com/wxpay/pay.php",
"goods_tag" : "WXG",
"support_fapiao" : true,
"amount" : {
"total" : 100,
"currency" : "CNY"
},
"payer" : {
"openid" : "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o\t"
},
"detail" : {
"cost_price" : 608800,
"invoice_id" : "微信123",
"goods_detail" : [
{
"merchant_goods_id" : "1246464644",
"wechatpay_goods_id" : "1001",
"goods_name" : "iPhoneX 256G",
"quantity" : 1,
"unit_price" : 528800
}
]
},
"scene_info" : {
"payer_client_ip" : "14.23.150.211",
"device_id" : "013467007045764",
"store_info" : {
"id" : "0001",
"name" : "腾讯大厦分店",
"area_code" : "440305",
"address" : "广东省深圳市南山区科技中一道10000号"
}
},
"settle_info" : {
"profit_sharing" : false
}
}'

应答参数:

200 OK

prepay_id必填string(64)

【预支付交易会话标识】 预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时

应答示例

{
"prepay_id" : "wx201410272009395522657a690389285100"
}

2.1 接口分析

参考api接口文档定义封装响应数据的实体类型WeChatPayVo,如下所示:

@Data       // 请求微信JSAPI下单接口响应数据模型
@Schema(description = "支付下单响应数据模型")
public class WeChatPayVo {

    @Schema(description = "时间戳")
    private String timeStamp ;      // 时间戳

    @Schema(description = "随机字符串")
    private String nonceStr ;       // 随机字符串

    @Schema(description = "订单详情扩展字符串")
    @JsonProperty(value = "package")
    private String packageVal ;     // 订单详情扩展字符串

    @Schema(description = "签名方式")
    private String signType ;      // 签名方式

    @Schema(description = "签名")
    private String paySign ;       // 签名   
}

在配置文件中配置微信支付相关参数

# 微信支付所需要的账号信息#
wechat.v3pay.appid=

# 商户号 
wechat.v3pay.merchantId=

# 商户API私钥路径
wechat.v3pay.privateKeyPath=apiclient_key.pem

# 商户证书序列号
wechat.v3pay.merchantSerialNumber=

# 商户APIV3密钥
wechat.v3pay.apiV3key=

# 异步回调地址
wechat.v3pay.notifyUrl=http://127.0.0.1/api/payment/wxPay/notify

2.2 接口开发

编写一个微信支付接口

@Operation(summary = "微信下单")
@Parameters({
    @Parameter(name = "paymentType",description = "支付类型:1301-订单 1302-充值",in = ParameterIn.PATH,required = true),
    @Parameter(name = "orderNo",description = "订单号",required = true,in = ParameterIn.PATH),
})
@PostMapping("/createJsapi/{paymentType}/{orderNo}")
public Result<WeChatPayVo> createJsapi(@PathVariable String paymentType, @PathVariable String orderNo) {
    WeChatPayVo weChatPayVo = wxPayService.createJsapi(paymentType, orderNo);
    return Result.ok(weChatPayVo);
}

业务层代码: 在WxPayService接口中添加如下接口方法:

// WxPayService
public abstract WeChatPayVo createJsapi(String paymentType, String orderNo);

// WxPayServiceImpl
@Override
public WeChatPayVo createJsapi(String paymentType, String orderNo) {

    try {

        // 根据订单的编号查询订单数据(下面两行代码无需考虑,这里只是获取订单信息)
        Result<OrderInfo> orderInfoResult = orderInfoFeignClient.getOrderInfo(orderNo);
        OrderInfo orderInfo = orderInfoResult.getData();

        // 可以提前保存交易信息
        //  paymentInfoService.savePaymentInfo(orderInfo);
        
        //	构建service
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();

        // 构建请求参数对象
        PrepayRequest request = new PrepayRequest();

        // 注意在这个包下 com.wechat.pay.java.service.payments.jsapi.model.Amount
        Amount amount = new Amount();
        amount.setTotal(1);
        request.setAmount(amount);

        request.setAppid(wxPayV3Config.getAppid());
        request.setMchid(wxPayV3Config.getMerchantId());
        request.setDescription(orderInfo.getOrderTitle());   // 订单标题
        request.setNotifyUrl(wxPayV3Config.getNotifyUrl());
        request.setOutTradeNo(orderNo);

        // 设置支付者
        Result<UserInfo> userInfoResult = userInfoFeignClient.findByUserId(AuthContextHolder.getUserId());
        UserInfo userInfo = userInfoResult.getData();
        String wxOpenId = userInfo.getWxOpenId();
        Payer payer = new Payer() ;
        payer.setOpenid(wxOpenId);
        request.setPayer(payer);

        // response包含了调起支付所需的所有参数,可直接用于前端调起支付
        PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);

        // 解析响应结果构建
        WeChatPayVo weChatPayVo = new WeChatPayVo() ;
        weChatPayVo.setTimeStamp(response.getTimeStamp());
        weChatPayVo.setNonceStr(response.getNonceStr());
        weChatPayVo.setPackageVal(response.getPackageVal());
        weChatPayVo.setSignType(response.getSignType());
        weChatPayVo.setPaySign(response.getPaySign());

        // 返回数据
        return weChatPayVo;

    } catch (Exception e){
        e.printStackTrace();
        throw new GuiguException(201,"微信下单异常");
    }
}

定义一个实体类封装微信支付所需要的参数, 并且在该实体类中配置RSAAutoCertificateConfig到spring容器中,代码如下所示:

@Configuration
@ConfigurationProperties(prefix="wechat.v3pay") //读取节点
@Data
public class WxPayV3Config {

    private String appid;
    public String merchantId;               /** 商户号 */
    public String privateKeyPath;           /** 商户API私钥路径 */
    public String merchantSerialNumber;     /** 商户证书序列号 */
    public String apiV3key;                 /** 商户APIV3密钥 */
    private String notifyUrl;               /** 回调地址 */

    @Bean
    public RSAAutoCertificateConfig autoCertificateConfig() {
        RSAAutoCertificateConfig rsaAutoCertificateConfig = new RSAAutoCertificateConfig.Builder()
                .merchantId(merchantId)
                .privateKeyFromPath(privateKeyPath)
                .merchantSerialNumber(merchantSerialNumber)
                .apiV3Key(apiV3key)
                .build();
        return rsaAutoCertificateConfig ;
    }
}

3. 查询支付状态

微信支付订单号查询订单:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/query-by-wx-trade-no.html

微信支付工具类示例Demo:https://github.com/wechatpay-apiv3/wechatpay-java

3.1 接口开发

控制层代码:

在WxPayApiController中添加如下方法:

@Operation(summary = "支付状态查询")
@GetMapping("/queryPayStatus/{orderNo}")
public Result queryPayStatus(@PathVariable String orderNo) {
    boolean result = wxPayService.queryPayStatus(orderNo);
    return Result.ok(result);
}

业务层代码:

在WxPayService中添加如下业务接口方法

// WxPayService
public abstract boolean queryPayStatus(String orderNo);

// WxPayServiceImpl
@Override
public boolean queryPayStatus(String orderNo) {

    try {

        //	构建JsapiServiceExtension对象
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();

        // 构建请求参数对象
        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        queryRequest.setMchid(wxPayV3Config.getMerchantId());
        queryRequest.setOutTradeNo(orderNo);

        // 发送查询请求
        Transaction result = service.queryOrderByOutTradeNo(queryRequest);

        // 更新支付信息数据的支付状态
        if(result != null && result.getTradeState() == Transaction.TradeStateEnum.SUCCESS) {
            paymentInfoService.updatePaymentStatus(result);		//更改订单状态
            return true ;
        }

    } catch (ServiceException e){			// API返回失败, 例如ORDER_NOT_EXISTS
        log.error("code={}, message={}" , e.getErrorCode() , e.getErrorMessage());
        log.error("reponse body={}" , e.getResponseBody());
        e.printStackTrace();
        return false ;
    }

    return false ;
}

支付成功后可以修改订单的支付状态!

4. 异步通知

微信支付通过支付通知接口将用户支付成功消息通知给商户。异步通知规则如下所示:

用户支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理该消息,并返回应答。

对后台通知交互时,如果微信收到商户的应答不符合规范或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。(通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m)

支付通知API官网地址:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/payment-notice.html

API字典官网地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_5.shtml

上述的两个地址都可以查询对应的接口文档,但是存在差异化,建议以第二个地址为准。

支付通知示例代码地址:https://github.com/wechatpay-apiv3/wechatpay-java

4.1 接口开发

表现层代码

在WxPayApiController中添加如下的接口方法

// WxPayApiController
@Operation(summary = "微信支付异步通知接口")
@PostMapping("/notify")
public ResponseEntity<Map<String , String>> notify(HttpServletRequest request){
    Map<String , String> result = new HashMap<>() ;
    try {
        wxPayService.wxnotify(request);
        result.put("code" , "SUCCESS") ;
        result.put("message" , "成功") ;
        return ResponseEntity.status(HttpStatus.OK).body(result);
    }catch (Exception e) {
        e.printStackTrace();
        result.put("code" , "FAIL") ;
        result.put("message" , "失败") ;
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result) ;
    }
}

业务层代码

参考支付通知示例代码,在WxPayService中添加如下的接口方法

// WxPayService
public abstract void wxnotify(HttpServletRequest request);

// WxPayServiceImpl
@Override
public void wxnotify(HttpServletRequest request) {

    // 获取请求参数
    String wechatPaySerial = request.getHeader("Wechatpay-Serial");
    String nonce = request.getHeader("Wechatpay-Nonce");
    String timestamp = request.getHeader("Wechatpay-Timestamp");
    String signature = request.getHeader("Wechatpay-Signature");

    // HTTP请求体 body。切记使用原始报文,不要用JSON对象序列化后的字符串,避免验签的body和原文不一致。
    String requestBody = PayUtil.readData(request);

    // 构造 RequestParam
    RequestParam requestParam = new RequestParam.Builder()
        .serialNumber(wechatPaySerial)
        .nonce(nonce)
        .signature(signature)
        .timestamp(timestamp)
        .body(requestBody)
        .build();

    // 初始化 NotificationParser
    NotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);

    // 解析请求参数得到Transaction对象
    Transaction result = parser.parse(requestParam, Transaction.class);

    // 更新支付信息数据的支付状态
    if(result != null && result.getTradeState() == Transaction.TradeStateEnum.SUCCESS) {
        paymentInfoService.updatePaymentStatus(result);		//更改订单状态
    }
}

标签:String,商户,接入,微信,request,接口,支付
From: https://www.cnblogs.com/lilyflower/p/18457825

相关文章

  • Java 接口缓存(Redis + 注解)
      为了提升用户体验并优化那些因数据量庞大而导致响应缓慢的统计类接口,我们可以采用以下策略来实现接口数据的缓存机制:实现步骤:引入缓存机制:利用Redis作为缓存存储,因其速度快且支持高并发访问。前端请求处理:在前端请求到达后端之前,通过拦截器(Interceptor)进行处......
  • webservice接口调用报:由于 ContractFilter 在 EndpointDispatcher 不匹配,因此 Action
    1、问题:<s:Envelopexmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcodexmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</faultcode><faul......
  • 【Kubernets】容器网络基础二:通讲CNI(Container Network Interface)容器网络接口实现方
    文章目录背景知识Underlay网络Overlay网络一、基本概念二、工作原理三、实现方案四、应用场景两者对比示意图CNI实现有哪些?FlannelFlannel的工作原理Flannel的主要组件数据传输机制总结Calico一、架构基础二、核心组件与功能三、路由与数据包转发四、安全策略五、数......
  • 通信接入技术
    一、xDSL1、xDSL:利用电话线中的高频信息传输数据,高频信号损耗大,容易受噪声干扰。【速率越高,传输距离越近】1.1ADSL虚拟拨号:采用专门的协议PPPoverEthernet,拨号后直接由验证服务器进行检验,用户需输入用户名和密码,检验通过后就建立起一条高速的用户数字并分配相应的动态IP。......
  • 08 JAVA 继承多态抽象类接口
    1函数题1,super.a来明确访问父类的字段。super(a);表示调用父类的构造函数,并传递参数a2,抽象类继承需要写新的构造器,重写抽象方法classCircleextendsshape{privatedoubleradius;publicCircle(doubleradius){this.radius=radius;}//构......
  • 【EBS】EBS系统各模块API及接口
    OracleEBS系统常用API及接口:模块应用场景类型API/接口AP付款核销APIap_pay_invoice_pkg.ap_pay_invoiceAP应付发票审批APIap_approval_pkg.approvalAP预付款核销APIap_prepay_pkg.apply_prepay_fr_prepayAP创建应付发票APIap_import_invoices_......
  • 微信公众号小说漫画系统 fileupload.php 任意文件上传复现
    0x01漏洞描述:        在微信公众号小说漫画系统的fileupload.php接口中,存在任意文件上传漏洞,该漏洞允许未经身份验证的攻击者上传恶意文件,从而实现代码执行。这种安全隐患使得攻击者能够在服务器上写入后门程序,获取服务器权限,并最终控制整个Web服务器。攻击者可......
  • 【孤岛划分】分布式能源接入弹性配电网模型研究【IEEE33节点】(Matlab代码实现)
     目录......
  • .Net微信服务商平台ApiV3接口
    转载:https://www.cnblogs.com/xilen/p/15380183.html开始在开始之前建议仔细读微信官方文档,接口规则及api文档https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay-1.shtmlhttps://pay.weixin.qq.com/wiki/doc/apiv3_partner/index.shtml目录整个流程开......
  • 第31篇 实现数据同步的webapi接口
    调用接口实现数据同步demo讲解1.demo整体架构如下2.SynchronizeModel类库这个类库是主要用于实体对象模型的转换,包括请求参数实体RequestModel,数据库实体DBEntity,响应数据实体ResponseModel等,2.1新建一个数据库实体:///<summary>///被测件(雷达)模块信息表///</sum......