小言_互联网的博客

微信支付Native下单API接口正确调用姿势

419人阅读  评论(0)

        商户Native支付下单接口,微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。

文档地址:微信支付-开发者文档

目录

一、Native下单接口简介

二、如何正确调通接口

(1) 测试调用接口

(2)签名生成规则

三、下单支付JAVA核心代码

(1)获取接口签名方法

(2)获取私钥对象方法

(3)接口签名加密方法

(4)构建加密信息字符串

(5)构建下单支付请求报文

(6)调用下单支付接口

四、需要用到的部分依赖包


一、Native下单接口简介

请求URL:https://api.mch.weixin.qq.com/v3/pay/transactions/native

请求方式:POST

请求参数:


  
  1. {
  2. "mchid": "1900006XXX",
  3. "out_trade_no": "native12177525012014070332333",
  4. "appid": "wxdace645e0bc2cXXX",
  5. "description": "Image形象店-深圳腾大-QQ公仔",
  6. "notify_url": "https://weixin.qq.com/",
  7. "amount": {
  8. "total": 1,
  9. "currency": "CNY"
  10. }
  11. }

参数说明:

mchid 商户号  :在微信商户平台(微信支付 - 中国领先的第三方支付平台 | 微信支付提供安全快捷的支付方式)中获取

 out_trade_no 商户订单号:自己生成的业务订单编号(只能是数字、大小写字母,且在同一个商户号下唯一)

description:商品描述信息

notify_url:回调通知地址(通知URL必须为直接可访问的URL,不允许携带其他参数,要求必须为https地址,本地可以借助于内网穿透工具来完成测试。)

amount :订单金额信息,注意total单位是分,不是元,这个跟支付宝接口有点不同,支付宝接口的单位是元,微信支付接口的单位是分 ,currency在国内使用的话,直接默认值CNY就行。

appid:使用公众号APPID(微信公众号需要先进行实名认证缴费300元)

然后让公众号和商户进行关联

业务流程时序图

二、如何正确调通接口

(1) 测试调用接口

首先拿到接口地址和请求参数去postman中测试一下

 接口返回返回提示告诉我们:Http头Authorization值格式错误,请参考《微信支付商户REST API签名规则》,也就是说这个接口需要进行签名验证。

(2)签名生成规则

签名生成规则文档地址:签名生成-接口规则 | 微信支付商户平台文档中心

在进行签名过程中,会用到这几个参数

① 商户API证书

 证书获取流程:什么是商户API证书?如何获取商户API证书?

② 商户证书序列号

API证书添加成功之后,点击管理就能看到商户证书序列号。

三、下单支付JAVA核心代码

(1)获取接口签名方法

getToken方法的作用是获取接口签名,具体参数解释

method:GET/POST

url:接口url地址

body:获取请求中的请求报文主体,

请求方法为GET时,报文主体为空。

当请求方法为POST或PUT时,请使用真实发送的JSON报文

signatureType :签名类型字符串常量:WECHATPAY2-SHA256-RSA2048

nonceStr :随机字符串,可以固定值。


  
  1. public static String getToken (String method, HttpUrl url, String body) throws IOException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
  2. String nonceStr = "593BEC0C930BF1AFEB40B4A08C8FB242";
  3. long timestamp = System.currentTimeMillis() / 1000;
  4. String message = buildMessage(method, url, timestamp, nonceStr, body);
  5. String signature = sign(message.getBytes( "utf-8"));
  6. return signatureType + " mchid=\"" + mchid + "\","
  7. + "nonce_str=\"" + nonceStr + "\","
  8. + "timestamp=\"" + timestamp + "\","
  9. + "serial_no=\"" + merchantSerialNumber + "\","
  10. + "signature=\"" + signature + "\"";
  11. }

(2)获取私钥对象方法

参数说明:private_key的值来源于证书文件apiclient_key.pem文件类的所有内容。


  
  1. /**
  2. * 获取私钥。
  3. *
  4. * @return 私钥对象
  5. */
  6. public static PrivateKey getPrivateKey () throws IOException {
  7. try {
  8. String privateKey = private_key.replace( "-----BEGIN PRIVATE KEY-----", "")
  9. .replace( "-----END PRIVATE KEY-----", "")
  10. .replaceAll( "\\s+", "");
  11. KeyFactory kf = KeyFactory.getInstance( "RSA");
  12. return kf.generatePrivate(
  13. new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
  14. } catch (NoSuchAlgorithmException e) {
  15. throw new RuntimeException( "当前Java环境不支持RSA", e);
  16. } catch (InvalidKeySpecException e) {
  17. throw new RuntimeException( "无效的密钥格式");
  18. }
  19. }

(3)接口签名加密方法


  
  1. public static String sign (byte[] message) throws NoSuchAlgorithmException, IOException, InvalidKeyException, SignatureException {
  2. Signature sign = Signature.getInstance( "SHA256withRSA");
  3. sign.initSign(getPrivateKey());
  4. sign.update(message);
  5. return Base64.getEncoder().encodeToString(sign.sign());
  6. }

(4)构建加密信息字符串


  
  1. public static String buildMessage (String method, HttpUrl url, long timestamp, String nonceStr, String body) {
  2. String canonicalUrl = url.encodedPath();
  3. if (url.encodedQuery() != null) {
  4. canonicalUrl += "?" + url.encodedQuery();
  5. }
  6. return method + "\n"
  7. + canonicalUrl + "\n"
  8. + timestamp + "\n"
  9. + nonceStr + "\n"
  10. + body + "\n";
  11. }

(5)构建下单支付请求报文


  
  1. /**
  2. * 构建下单支付请求JSON字符串
  3. *
  4. * @return
  5. */
  6. public static String buildNativePayJson (Double total_amount, String out_trade_no) {
  7. JSONObject jsonObject = new JSONObject();
  8. // 应用ID
  9. jsonObject.put( "appid", appid);
  10. // 商户号
  11. jsonObject.put( "mchid", mchid);
  12. // 商户订单号
  13. jsonObject.put( "out_trade_no", out_trade_no);
  14. // 商品描述
  15. jsonObject.put( "description", "易微帮在线充值" + total_amount + "元");
  16. // 回调通知URL
  17. jsonObject.put( "notify_url", notify_url);
  18. JSONObject amount = new JSONObject();
  19. // 单位:分
  20. amount.put( "total", Convert.toInt(total_amount * 100));
  21. //货币类型
  22. amount.put( "currency", "CNY");
  23. jsonObject.put( "amount", amount);
  24. return jsonObject.toJSONString();
  25. }

(6)调用下单支付接口


  
  1. //商户订单号
  2. String out_trade_no = PayUtil.getOrderNum();
  3. String body = WxPayUtil.buildNativePayJson(amount, out_trade_no);
  4. String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/native";
  5. HttpUrl httpurl = HttpUrl.parse(url);
  6. String sign = WxPayUtil.getToken( "POST", httpurl, body);
  7. String response = HttpUtil.createPost(url)
  8. .header( "Authorization", sign)
  9. .body(body)
  10. .execute().body();

下单支付接口调用成功之后,response字符串的格式如下。


  
  1. {
  2. "code_url": "weixin://wxpay/bizpayurl?pr=p4lpSuKzz"
  3. }

后续使用,将code_url的值生成二维码,展现给用户扫码即可。 

可以来我的个人网站参考一下应用场景。

页面地址:易微帮-专业IT技术协助平台

四、需要用到的部分依赖包


  
  1. <!--微信支付v3接口-->
  2. <dependency>
  3. <groupId>com.github.wechatpay-apiv3 </groupId>
  4. <artifactId>wechatpay-java </artifactId>
  5. <version>0.2.5 </version>
  6. </dependency>
  7. <!-- hutool工具包 -->
  8. <dependency>
  9. <groupId>cn.hutool </groupId>
  10. <artifactId>hutool-all </artifactId>
  11. <version>5.8.12 </version>
  12. </dependency>


转载:https://blog.csdn.net/qq_19309473/article/details/129094700
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场