我的编程空间,编程开发者的网络收藏夹
学习永远不晚

【微信支付】java-微信小程序支付-V3接口

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

【微信支付】java-微信小程序支付-V3接口

一、对接前准备

最开始需要在微信支付的官网注册一个商户;
在管理页面中申请关联小程序,通过小程序的 appid 进行关联;商户号和appid之间是多对多的关系
进入微信公众平台,功能-微信支付中确认关联

具体流程请浏览官方文档:接入前准备-小程序支付 | 微信支付商户平台文档中心

流程走完之后,需要获取以下参数:

1,商户 id: mchId,

2,小程序id:appId
3,商户证书序列号: 这个商户证书序列号在申请完证书之后就可以看到
4, 商户APIV3密钥, 我对接的是v3 接口 所以用APIV3密钥

当你按照文档下载商户证书zip,解压得到4个文件,一定要保存好。不能泄露

二、开始写代码

pom引入微信库


    com.github.wechatpay-apiv3
    wechatpay-apache-httpclient
    0.4.7


    com.alibaba
    fastjson
    1.2.80

yml文件写入配置

wxpay:  #应用编号  appId: xxxxxxxxxxxxx  #商户号  mchId: xxxxxxxxxxxxx  # APIv3密钥  apiV3Key: xxxxxxxxxxxxx  # 支付通知回调, 本地测试内网穿透地址  notifyUrl: http://405c3382p5.goho.co:25325/wenbo-pay/notify/payNotify  # 退款通知回调,  本地测试内网穿透地址  refundNotifyUrl: http://405c3382p5.goho.co:25325/wenbo-pay/notify/refundNotify  # 密钥路径,resources根目录下  keyPemPath: apiclient_key.pem  # 商户证书序列号  serialNo: xxxxxxxxxxxxx  # 小程序密钥  appSecret: xxxxxxxxxxxxx

商户API私钥 放入resources根目录下  能获取到就行

编写配置类获取yml配置

package com.example.pay.config;import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;import lombok.Data;import lombok.extern.slf4j.Slf4j;import org.apache.http.impl.client.CloseableHttpClient;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.stereotype.Component;import java.io.IOException;import java.io.InputStream;import java.nio.charset.StandardCharsets;import java.security.GeneralSecurityException;import java.security.PrivateKey;@Component@Data@Slf4j@ConfigurationProperties(prefix = "wxpay")public class WechatPayConfig {        private String appId;        private String mchId;        private String apiV3Key;        private String notifyUrl;        private String refundNotifyUrl;        private String keyPemPath;        private String serialNo;        public PrivateKey getPrivateKey(String keyPemPath) {        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(keyPemPath);        if (inputStream == null) {            throw new RuntimeException("私钥文件不存在");        }        return PemUtil.loadPrivateKey(inputStream);    }        @Bean    public Verifier getVerifier() throws GeneralSecurityException, IOException, HttpCodeException, NotFoundException {        log.info("获取证书管理器实例");        //获取商户私钥        PrivateKey privateKey = getPrivateKey(keyPemPath);        //私钥签名对象        PrivateKeySigner privateKeySigner = new PrivateKeySigner(serialNo, privateKey);        //身份认证对象        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);        // 使用定时更新的签名验证器,不需要传入证书        CertificatesManager certificatesManager = CertificatesManager.getInstance();        certificatesManager.putMerchant(mchId, wechatPay2Credentials, apiV3Key.getBytes(StandardCharsets.UTF_8));        return certificatesManager.getVerifier(mchId);    }        @Bean(name = "wxPayClient")    public CloseableHttpClient getWxPayClient(Verifier verifier) {        //获取商户私钥        PrivateKey privateKey = getPrivateKey(keyPemPath);        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()                .withMerchant(mchId, serialNo, privateKey)                .withValidator(new WechatPay2Validator(verifier));        // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新        return builder.build();    }    }

封装 支付-退款 请求API

package com.example.pay.config;import com.alibaba.fastjson.JSONObject;import lombok.extern.slf4j.Slf4j;import org.apache.http.HttpEntity;import org.apache.http.HttpStatus;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.util.EntityUtils;import org.springframework.stereotype.Component;import javax.annotation.Resource;@Component@Slf4jpublic class WechatPayRequest {    @Resource    private CloseableHttpClient wxPayClient;        public String wechatHttpOrderPost(String url, String paramsStr) {        try {            HttpPost httpPost = new HttpPost(url);            StringEntity stringEntity = new StringEntity(paramsStr, "utf-8");            stringEntity.setContentType("application/json");            httpPost.setEntity(stringEntity);            httpPost.setHeader("Accept", "application/json");            CloseableHttpResponse response = wxPayClient.execute(httpPost);            //响应体            HttpEntity entity = response.getEntity();            String body = entity == null ? "" : EntityUtils.toString(entity);            //响应状态码            int statusCode = response.getStatusLine().getStatusCode();            //处理成功,204是,关闭订单时微信返回的正常状态码            if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {                log.info("成功, 返回结果 = " + body);            } else {                String msg = "微信支付请求失败,响应码 = " + statusCode + ",返回结果 = " + body;                log.info("支付模块-生成订单 = " + msg);                throw new RuntimeException(msg);            }            return body;        } catch (Exception e) {            throw new RuntimeException(e.getMessage());        }    }        public String wechatHttpPost(String url, String paramsStr) {        try {            HttpPost httpPost = new HttpPost(url);            StringEntity stringEntity = new StringEntity(paramsStr, "utf-8");            stringEntity.setContentType("application/json");            httpPost.setEntity(stringEntity);            httpPost.setHeader("Accept", "application/json");            CloseableHttpResponse response = wxPayClient.execute(httpPost);            //响应体            HttpEntity entity = response.getEntity();            String body = entity == null ? "" : EntityUtils.toString(entity);            //响应状态码            int statusCode = response.getStatusLine().getStatusCode();            //处理成功,204是,关闭订单时微信返回的正常状态码            if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {                log.info("成功, 返回结果 = " + body);                // 请求成功或已处理成功,返回成功的响应                return "退款处理中";            } else if (statusCode == HttpStatus.SC_BAD_REQUEST || statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR) {                // 请求参数错误或系统错误,返回失败的响应                JSONObject json = JSONObject.parseObject(body);                return json.getString("message");            } else if (statusCode == HttpStatus.SC_FORBIDDEN) {                // 权限问题,没有退款权限                return "没有退款权限";            } else if (statusCode == HttpStatus.SC_NOT_FOUND) {                // 订单号不存在                return "订单号不存在";            } else if (statusCode == 429) {                // 频率限制                return "退款请求频率过高,请稍后重试";            } else if (statusCode == HttpStatus.SC_PAYMENT_REQUIRED) {                // 余额不足                return "商户余额不足,请充值后重试";            } else {                // 其他状态码,返回通用的失败响应                return "退款失败,请稍后重试";            }        } catch (Exception e) {            log.info("支付模块-退款失败 = " + e.getMessage());            JSONObject json = JSONObject.parseObject(e.getMessage());            return json.getString("message");        }    }}

支付回调解密处理

package com.example.pay.config;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.TypeReference;import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;import lombok.extern.slf4j.Slf4j;import org.apache.http.HttpEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.util.EntityUtils;import javax.servlet.http.HttpServletRequest;import java.io.BufferedReader;import java.io.IOException;import java.nio.charset.StandardCharsets;import java.time.DateTimeException;import java.time.Duration;import java.time.Instant;import java.util.Map;import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;@Slf4jpublic class WechatPayValidator {        private static final long RESPONSE_EXPIRED_MINUTES = 5;    private final Verifier verifier;    private final String requestId;    private final String body;    public WechatPayValidator(Verifier verifier, String requestId, String body) {        this.verifier = verifier;        this.requestId = requestId;        this.body = body;    }    protected static IllegalArgumentException parameterError(String message, Object... args) {        message = String.format(message, args);        return new IllegalArgumentException("parameter error: " + message);    }    protected static IllegalArgumentException verifyFail(String message, Object... args) {        message = String.format(message, args);        return new IllegalArgumentException("signature verify fail: " + message);    }    public final boolean validate(HttpServletRequest request) {        try {            //处理请求参数            validateParameters(request);            //构造验签名串            String message = buildMessage(request);            String serial = request.getHeader(WECHAT_PAY_SERIAL);            String signature = request.getHeader(WECHAT_PAY_SIGNATURE);            //验签            if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {                throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",                        serial, message, signature, requestId);            }        } catch (IllegalArgumentException e) {            log.warn(e.getMessage());            return false;        }        return true;    }    private void validateParameters(HttpServletRequest request) {        // NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last        String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};        String header = null;        for (String headerName : headers) {            header = request.getHeader(headerName);            if (header == null) {                throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);            }        }        //判断请求是否过期        String timestampStr = header;        try {            Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));            // 拒绝过期请求            if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {                throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);            }        } catch (DateTimeException | NumberFormatException e) {            throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);        }    }    private String buildMessage(HttpServletRequest request) {        String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);        String nonce = request.getHeader(WECHAT_PAY_NONCE);        return timestamp + "\n"                + nonce + "\n"                + body + "\n";    }    private String getResponseBody(CloseableHttpResponse response) throws IOException {        HttpEntity entity = response.getEntity();        return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : "";    }        public static Map decryptFromResource(String resource, String apiV3Key, Integer type) {        String msg = type == 1 ? "支付成功" : "退款成功";        log.info(msg + ",回调通知,密文解密");        try {            //通知数据            Map resourceMap = JSONObject.parseObject(resource, new TypeReference>() {            });            //数据密文            String ciphertext = resourceMap.get("ciphertext");            //随机串            String nonce = resourceMap.get("nonce");            //附加数据            String associatedData = resourceMap.get("associated_data");            log.info("密文: {}", ciphertext);            AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));            String resourceStr = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),                    nonce.getBytes(StandardCharsets.UTF_8),                    ciphertext);            log.info(msg + ",回调通知,解密结果 : {}", resourceStr);            return JSONObject.parseObject(resourceStr, new TypeReference>() {            });        } catch (Exception e) {            throw new RuntimeException("回调参数,解密失败!");        }    }        public static String readData(HttpServletRequest request) {        BufferedReader br = null;        try {            StringBuilder result = new StringBuilder();            br = request.getReader();            for (String line; (line = br.readLine()) != null; ) {                if (result.length() > 0) {                    result.append("\n");                }                result.append(line);            }            return result.toString();        } catch (IOException e) {            throw new RuntimeException(e);        } finally {            if (br != null) {                try {                    br.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

编写下单 退款 controller    这里注意 微信用户openid   

package com.example.pay.controller;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.TypeReference;import com.example.pay.config.WechatPayConfig;import com.example.pay.config.WechatPayRequest;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import java.nio.charset.StandardCharsets;import java.security.PrivateKey;import java.security.Signature;import java.util.Base64;import java.util.HashMap;import java.util.Map;import java.util.Random;@Slf4j@RestController@RequestMapping("/pay")public class PayController {    @Resource    private WechatPayConfig wechatPayConfig;    @Resource    private WechatPayRequest wechatPayRequest;        @GetMapping("/transactions")    public Map transactions() {              // 统一参数封装        Map params = new HashMap<>(10);        // 1,appid:公众号或移动应用的唯一标识符。        params.put("appid", wechatPayConfig.getAppId());        // 2,mch_id:商户号,由微信支付分配。        params.put("mchid", wechatPayConfig.getMchId());        // 3.description body:商品描述。        params.put("description", "奥迪a4l 2023-限量款");        // 4.out_trade_no:商户订单号,由商户自定义。        params.put("out_trade_no", "we56f45waf4w6a5fwa");        // 5.notify_url:接收微信支付异步通知回调地址。        params.put("notify_url", wechatPayConfig.getNotifyUrl());        // 6.total_fee:订单总金额,单位为分。        Map amountMap = new HashMap<>(4);        // 金额单位为分        amountMap.put("total", 999999);        amountMap.put("currency", "CNY");        params.put("amount", amountMap);        // 7.openid:用户在商户appid下的唯一标识。        Map payerMap = new HashMap<>(4);        // openid  需要前端小程序通过用户code 请求微信接口获取用户唯一openid  不懂的看官方文档:https://developers.weixin.qq.com/doc/aispeech/miniprogram/quickuse.html        payerMap.put("openid", "xxxxxxxxxxxxxxxxxxxx");        params.put("payer", payerMap);        String paramsStr = JSON.toJSONString(params);        log.info("请求参数 ===> {}" + paramsStr);        // 微信预支付下单接口路径        String payUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";        // 获取支付 prepay_id参数        String resStr = wechatPayRequest.wechatHttpOrderPost(payUrl, paramsStr);        Map resMap = JSONObject.parseObject(resStr, new TypeReference>() {        });        Object prepayId = resMap.get("prepay_id");        // 获取签名        String paySign;        try {            StringBuilder sb = new StringBuilder();            // 应用id            sb.append(wechatPayConfig.getAppId()).append("\n");            // 支付签名时间戳            sb.append(System.currentTimeMillis() / 1000).append("\n");            // 随机字符串            sb.append("5w7er7wa4fwa5e").append("\n");            // 预支付交易会话ID  这个要注意 key = "prepay_id=xxxxxx"            sb.append("prepay_id=").append(prepayId).append("\n");            // 签名            Signature sign = Signature.getInstance("SHA256withRSA");            // 获取商户私钥并进行签名            PrivateKey privateKey = wechatPayConfig.getPrivateKey(wechatPayConfig.getKeyPemPath());            sign.initSign(privateKey);            sign.update(sb.toString().getBytes(StandardCharsets.UTF_8));            // 得到签名            paySign = Base64.getEncoder().encodeToString(sign.sign());        } catch (Exception e) {            log.error("支付模块_生成交易签名失败!" + e);            return new HashMap<>();        }        // 将签名时数据和签名一起返回前端用于前端吊起支付        Map map = new HashMap<>();        // 小程序id        map.put("appId", wechatPayConfig.getAppId());        // 时间戳        map.put("timeStamp", System.currentTimeMillis() / 1000);        // 随机字符串        map.put("nonceStr", "56523268632356");        // 预支付交易会话ID        map.put("package", "prepay_id=" + prepayId);        // 签名方式        map.put("signType", "RSA");        // 签名        map.put("paySign", paySign);        return map;    }        @GetMapping("/refundOrder")    public String refundOrder() {        log.info("根据订单号申请退款,订单号: {}", "要退款的订单号  这里写死");        // 退款请求路径        String url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";        // 设置参数        Map params = new HashMap<>(2);        // 要退款的订单编号订单编号        params.put("out_trade_no", "57984wera64");        // 商户自定义退款记录单号 用于退款记录的单号 跟退款订单号不是一样的        int outRefundNo = new Random().nextInt(999999999);        log.info("退款申请号:{}", outRefundNo);        params.put("out_refund_no", outRefundNo + "");        // 退款原因        params.put("reason", "申请退款");        // 退款通知回调地址        params.put("notify_url", wechatPayConfig.getRefundNotifyUrl());        Map amountMap = new HashMap<>();        //退款金额,单位:分        amountMap.put("refund", 999999);        //原订单金额,单位:分        amountMap.put("total", 99999);        //退款币种        amountMap.put("currency", "CNY");        params.put("amount", amountMap);        String paramsStr = JSON.toJSONString(params);        // todo 插入一条退款记录到数据库        log.info("请求参数 ===> {}" + paramsStr);        String res = wechatPayRequest.wechatHttpPost(url, paramsStr);        log.info("退款结果:{}", res);        return res;    }}

支付 退款 回调controller

package com.example.pay.controller;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.TypeReference;import com.example.pay.config.WechatPayConfig;import com.example.pay.config.WechatPayValidator;import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.HashMap;import java.util.Map;import java.util.concurrent.locks.ReentrantLock;@RestController@Slf4j@RequestMapping("/callback")public class CallbackController {    @Resource    private WechatPayConfig wechatPayConfig;    @Resource    private Verifier verifier;    private final ReentrantLock lock = new ReentrantLock();        @PostMapping("/payNotify")    public Map payNotify(HttpServletRequest request, HttpServletResponse response) {        log.info("支付回调");        // 处理通知参数        Map bodyMap = getNotifyBody(request);        if (bodyMap == null) {            return falseMsg(response);        }        log.warn("=========== 在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱 ===========");        if (lock.tryLock()) {            try {                // 解密resource中的通知数据                String resource = bodyMap.get("resource").toString();                Map resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 1);                String orderNo = resourceMap.get("out_trade_no").toString();                // String transactionId = resourceMap.get("transaction_id").toString();                // 更改状态 获取订单号  修改订单状态为已支付                // TODO 根据订单号,做幂等处理,并且在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱                log.warn("=========== 根据订单号,做幂等处理 ===========");            } finally {                //要主动释放锁                lock.unlock();            }        }        //成功应答        return trueMsg(response);    }        @PostMapping("/refundNotify")    public Map refundNotify(HttpServletRequest request, HttpServletResponse response) {        log.info("退款回调");        // 处理通知参数        Map bodyMap = getNotifyBody(request);        if (bodyMap == null) {            return falseMsg(response);        }        log.warn("=========== 在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱 ===========");        if (lock.tryLock()) {            try {                // 解密resource中的通知数据                String resource = bodyMap.get("resource").toString();                Map resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 2);                String orderNo = resourceMap.get("out_trade_no").toString();//                String transactionId = resourceMap.get("transaction_id").toString();                log.info("退款所有参数" + resourceMap);                // TODO 根据订单号,做幂等处理,并且在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱                // 更改订单状态为已退款                log.warn("=========== 根据订单号,做幂等处理 ===========");            } finally {                //要主动释放锁                lock.unlock();            }        }        //成功应答        return trueMsg(response);    }    private Map getNotifyBody(HttpServletRequest request) {        //处理通知参数        String body = WechatPayValidator.readData(request);        log.info("退款回调参数:{}", body);        // 转换为Map        Map bodyMap = JSONObject.parseObject(body, new TypeReference>() {        });        // 微信的通知ID(通知的唯一ID)        String notifyId = bodyMap.get("id").toString();        // 验证签名信息        WechatPayValidator wechatPayValidator                = new WechatPayValidator(verifier, notifyId, body);        if (!wechatPayValidator.validate(request)) {            log.error("通知验签失败");            return null;        }        log.info("通知验签成功");        return bodyMap;    }    private Map falseMsg(HttpServletResponse response) {        Map resMap = new HashMap<>(8);        //失败应答        response.setStatus(500);        resMap.put("code", "ERROR");        resMap.put("message", "通知验签失败");        return resMap;    }    private Map trueMsg(HttpServletResponse response) {        Map resMap = new HashMap<>(8);        //成功应答        response.setStatus(200);        resMap.put("code", "SUCCESS");        resMap.put("message", "成功");        return resMap;    }}

整体项目结构

请求预支付订单 得到预支付订单参数 小程序拿着这些参数拉起支付页面进行支付

 

支付完成后 微信会回调我们预留的回调接口 

这里使用的是花生壳内网穿透进行回调测试的 

退款业务就不一一截图了  图片太多显得文章拉胯


总结

来源地址:https://blog.csdn.net/T_2021_7_10/article/details/132276992

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

【微信支付】java-微信小程序支付-V3接口

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python3微信支付(小程序支付)V3接口的实现

本文主要介绍了Python3微信支付(小程序支付)V3接口的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-01-17

微信小程序支付接口实例分析

这篇文章主要介绍“微信小程序支付接口实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“微信小程序支付接口实例分析”文章能帮助大家解决问题。  小程序调起支付API 小程序调起支付数据签名字段列表
2023-06-26

微信小程序接入微信支付实现过程详解

这篇文章主要介绍了微信小程序接入微信支付实现过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2022-12-26

〔支付接入〕微信的 h5 支付和 jsapi 支付

✨ 目录 🎈 申请商户号🎈 申请商户证书🎈 设置APIv3密钥🎈 下载 SDK 开发包🎈 下载平台证书🎈 关联 AppID 账
2023-08-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录