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

2023微信支付对接全流程

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

北京

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

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

看不清楚,换张图片

免费获取短信验证码

2023微信支付对接全流程

简单说一下微信支付的几种类型的应用场景以及前提条件
官方文档:https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml

前提条件:

需要一个载体公众号或者小程序,公众号要是服务号不是订阅号。
2.小程序和公众号支付都要认证,要300rmb。
3.需要一个商户号,绑定公众号或者小程序。

1.jsapi支付:

就是在微信平台内,微信内置浏览器或者小程序唤起微信支付

对接流程:

在自己的后台请求微信接口下预订单,然后将下单参数各种加密传到前端,用微信浏览器内置对象方法唤起支付WeixinJSBridge.invoke,小程序用
wx.requestPayment唤起支付,用户支付成功后将回调给你在下单参数中的回调地址,你再根据订单号自己处理结果。注意,两个方法的参数名相同,但是小程序支付唤起参数requestPayment下单接口参数中的openid和appid必须用小程序的,微信浏览器的同理。

2.h5支付:

普通浏览器,或者app的webview里面访问下单接口返回的h5_url,可通过访问该url来拉起微信客户端,完成支付。

对接流程:

在自己的后台请求微信接口下预订单,然后接口返回h5_url,前端浏览器访问这个url即可唤起客户端。

3Native下单

生成二维码,用户扫码支付,这个比较适用于PC网站等非移动端。

对接流程:

在自己的后台请求微信接口下预订单,然后接口返回code_url,将这个code_url转换成二维码即可。

以上这几个几乎满足所有需求情况了,上点代码,研究全流程细节和坑点

开发示例

这里jspapi为例
1.申请个公众号 https://mp.weixin.qq.com/,必须是服务号不然无法开通支付。
2.在后台通过微信认证,要不然商户号没办法绑定你的公众号
在这里插入图片描述
3.申请个商户号 https://pay.weixin.qq.com/
4.商户号绑定公众号,在商户号后台
在这里插入图片描述
5.这里开始看后台代码,接口参数缺的我们再找,首先微信支付的加密解密签名太复杂,而且也不是我们关注的点,已经有大佬写好了,IJPay,不仅微信,还封装了、支付宝支付、银联支付常用的支付方式以及各种常用的接口,源码及示例工程gitee :https://gitee.com/luozhizkang/IJPay
也可以引个maven,这里只引微信支付需要的

            com.github.javen205            IJPay-WxPay            2.9.4        

参数准备类

@Component@Datapublic class WxPayV3Bean {    @Value("${wxPay.appId}")    private String appId ;//小程序appid    @Value("${wxPay.keyPath}")    private String keyPath;    @Value("${wxPay.certPath}")    private String certPath ;    @Value("${wxPay.certP12Path}")    private String certP12Path ;    @Value("${wxPay.platformCertPath}")    private String platformCertPath ;    @Value("${wxPay.mchId}")    private String mchId;//商户号mchId    @Value("${wxPay.apiKey}")    private String apiKey ;    @Value("${wxPay.apiKey3}")    private String apiKey3 ;    @Value("${wxPay.domain}")    private String domain;//支付成功回调地址}

剩下这几个参数怎么获取呢?
在这里插入图片描述
在商户平台中按照指引“申请api证书”,会得到几个文件
在这里插入图片描述
keyPath就是 apiclient_key.pem的绝对路径,例如:D://xxx/apiclient_key.pem
certPath就是 apiclient_cert.pem的绝对路径
certP12Path就是 apiclient_cert.p12的绝对路径
platformCertPath 等会要根据上面的秘钥和证书生成一个文件名字叫platformCertPath.pem,你只需要将绝对路径写好在这就行了,后面程序启动再通过接口下载。例如:D://xxx/platformCertPath.pem
apiKey 可以不用填。
domain就是支付成功的回调地址,这个回调地址的域名要在商户平台配置。

建个controller

@RestController@RequestMapping("/api/v3")public class WxPayV3Controller {private final Logger log = LoggerFactory.getLogger(this.getClass());private final static int OK = 200;@ResourceWxPayV3Bean wxPayV3Bean;String serialNo;String platSerialNo;@RequestMapping("/getSerialNumber")@ResponseBodypublic String serialNumber() {return getSerialNumber();}@RequestMapping("/getPlatSerialNumber")@ResponseBodypublic String platSerialNumber() {return getPlatSerialNumber();}private String getSerialNumber() {if (StrUtil.isEmpty(serialNo)) {// 获取证书序列号X509Certificate certificate = PayKit.getCertificate(wxPayV3Bean.getCertPath());if (null != certificate) {serialNo = certificate.getSerialNumber().toString(16).toUpperCase();// 提前两天检查证书是否有效boolean isValid = PayKit.checkCertificateIsValid(certificate, wxPayV3Bean.getMchId(), -2);log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN));}//            System.out.println("输出证书信息:\n" + certificate.toString());//            // 输出关键信息,截取部分并进行标记//            System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16));//            System.out.println("版本号:" + certificate.getVersion());//            System.out.println("签发者:" + certificate.getIssuerDN());//            System.out.println("有效起始日期:" + certificate.getNotBefore());//            System.out.println("有效终止日期:" + certificate.getNotAfter());//            System.out.println("主体名:" + certificate.getSubjectDN());//            System.out.println("签名算法:" + certificate.getSigAlgName());//            System.out.println("签名:" + certificate.getSignature().toString());}System.out.println("serialNo:" + serialNo);return serialNo;}private String getPlatSerialNumber() {if (StrUtil.isEmpty(platSerialNo)) {// 获取平台证书序列号X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(wxPayV3Bean.getPlatformCertPath()));platSerialNo = certificate.getSerialNumber().toString(16).toUpperCase();}System.out.println("platSerialNo:" + platSerialNo);return platSerialNo;}private String savePlatformCert(String associatedData, String nonce, String cipherText, String certPath) {try {AesUtil aesUtil = new AesUtil(wxPayV3Bean.getApiKey3().getBytes(StandardCharsets.UTF_8));// 平台证书密文解密// encrypt_certificate 中的  associated_data nonce  ciphertextString publicKey = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),nonce.getBytes(StandardCharsets.UTF_8),cipherText);// 保存证书FileWriter writer = new FileWriter(certPath);writer.write(publicKey);// 获取平台证书序列号X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));return certificate.getSerialNumber().toString(16).toUpperCase();} catch (Exception e) {e.printStackTrace();return e.getMessage();}}@RequestMapping("/get")@ResponseBodypublic String v3Get() {// 获取平台证书列表try {IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.GET,WxDomainEnum.CHINA.toString(),OtherApiEnum.GET_CERTIFICATES.toString(),wxPayV3Bean.getMchId(),getSerialNumber(),null,wxPayV3Bean.getKeyPath(),"");String timestamp = response.getHeader("Wechatpay-Timestamp");String nonceStr = response.getHeader("Wechatpay-Nonce");String serialNumber = response.getHeader("Wechatpay-Serial");String signature = response.getHeader("Wechatpay-Signature");String body = response.getBody();int status = response.getStatus();log.info("serialNumber: {}", serialNumber);log.info("status: {}", status);log.info("body: {}", body);int isOk = 200;if (status == isOk) {JSONObject jsonObject = JSONUtil.parseObj(body);JSONArray dataArray = jsonObject.getJSONArray("data");// 默认认为只有一个平台证书JSONObject encryptObject = dataArray.getJSONObject(0);JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");String associatedData = encryptCertificate.getStr("associated_data");String cipherText = encryptCertificate.getStr("ciphertext");String nonce = encryptCertificate.getStr("nonce");String serialNo = encryptObject.getStr("serial_no");final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, wxPayV3Bean.getPlatformCertPath());log.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo);}// 根据证书序列号查询对应的证书来验证签名结果boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());System.out.println("verifySignature:" + verifySignature);return body;} catch (Exception e) {e.printStackTrace();return null;}}@RequestMapping("/nativePay")@ResponseBodypublic String nativePay() {try {String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(wxPayV3Bean.getAppId()).setMchid(wxPayV3Bean.getMchId()).setDescription("IJPay 让支付触手可及").setOut_trade_no(PayKit.generateStr()).setTime_expire(timeExpire).setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX").setNotify_url(wxPayV3Bean.getDomain().concat("/v3/payNotify")).setAmount(new Amount().setTotal(1));log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST,WxDomainEnum.CHINA.toString(),BasePayApiEnum.NATIVE_PAY.toString(),wxPayV3Bean.getMchId(),getSerialNumber(),null,wxPayV3Bean.getKeyPath(),JSONUtil.toJsonStr(unifiedOrderModel));log.info("统一下单响应 {}", response);// 根据证书序列号查询对应的证书来验证签名结果boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());log.info("verifySignature: {}", verifySignature);return response.getBody();} catch (Exception e) {e.printStackTrace();return e.getMessage();}}@RequestMapping("/jsApiPay")@ResponseBodypublic String jsApiPay(@RequestParam(value = "openId", required = false, defaultValue = "o-_-itxuXeGW3O1cxJ7FXNmq8Wf8") String openId) {try {String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(wxPayV3Bean.getAppId()).setMchid(wxPayV3Bean.getMchId()).setDescription("IJPay 让支付触手可及").setOut_trade_no(PayKit.generateStr()).setTime_expire(timeExpire).setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX").setNotify_url(wxPayV3Bean.getDomain().concat("/v3/payNotify")).setAmount(new Amount().setTotal(1)).setPayer(new Payer().setOpenid(openId));log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST,WxDomainEnum.CHINA.toString(),BasePayApiEnum.JS_API_PAY.toString(),wxPayV3Bean.getMchId(),getSerialNumber(),null,wxPayV3Bean.getKeyPath(),JSONUtil.toJsonStr(unifiedOrderModel));log.info("统一下单响应 {}", response);// 根据证书序列号查询对应的证书来验证签名结果boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());log.info("verifySignature: {}", verifySignature);if (response.getStatus() == OK && verifySignature) {String body = response.getBody();JSONObject jsonObject = JSONUtil.parseObj(body);String prepayId = jsonObject.getStr("prepay_id");//这些参数传到前端去,是小程序或者微信浏览器唤起支付的参数Map<String, String> map = WxPayKit.jsApiCreateSign(wxPayV3Bean.getAppId(), prepayId, wxPayV3Bean.getKeyPath());log.info("唤起支付参数:{}", map);return JSONUtil.toJsonStr(map);}return JSONUtil.toJsonStr(response);} catch (Exception e) {e.printStackTrace();return e.getMessage();}}//支付成功回调@RequestMapping(value = "/payNotify", method = {org.springframework.web.bind.annotation.RequestMethod.POST, org.springframework.web.bind.annotation.RequestMethod.GET})@ResponseBodypublic void payNotify(HttpServletRequest request, HttpServletResponse response) {Map<String, String> map = new HashMap<>(12);try {String timestamp = request.getHeader("Wechatpay-Timestamp");String nonce = request.getHeader("Wechatpay-Nonce");String serialNo = request.getHeader("Wechatpay-Serial");String signature = request.getHeader("Wechatpay-Signature");log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);String result = HttpKit.readData(request);log.info("支付通知密文 {}", result);// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp,wxPayV3Bean.getApiKey3(), wxPayV3Bean.getPlatformCertPath());log.info("支付通知明文 {}", plainText);if (StrUtil.isNotEmpty(plainText)) {//完成订单充值com.alibaba.fastjson.JSONObject plain = com.alibaba.fastjson.JSONObject.parseObject(plainText);orderService.updateOrderStatus(plain.getString("out_trade_no"));response.setStatus(200);map.put("code", "SUCCESS");map.put("message", "SUCCESS");} else {response.setStatus(500);map.put("code", "ERROR");map.put("message", "签名错误");}response.setHeader("Content-type", ContentType.JSON.toString());response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));response.flushBuffer();} catch (Exception e) {e.printStackTrace();}}}

上面的代码也是从IJPay的示例工程中copy来的,如果运行有什么问题直接去gitee去复制源码,我上面有贴gitee地址
启动成功后,调用 /get 接口下载 platformCertPath.pem
调用 /jsApiPay 接口生成微信预支付订单,并将参数传到前端,唤起支付,用户支付成功后会回调到 /payNotify 接口,但是回调地址的域名必须在商户后台配置过,在产品中心->开发配置 里面设置业务域名,如果是本地调试,可以用花生壳或者natapp伪装一个域名,建议用natapp。
前端唤起:
微信浏览器

//order是调用/jsApiPay接口返回的参数WeixinJSBridge.invoke('getBrandWCPayRequest', order,function(res) {if (res.err_msg == "get_brand_wcpay_request:ok") {// 使用以上方式判断前端返回,微信团队郑重提示://res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。} else {}});

小程序

//order是调用/jsApiPay接口返回的参数wx.requestPayment({            'timeStamp':order.timeStamp,            'nonceStr': order.nonceStr,            'package': order.package,            'signType': order.signType,            'paySign': order.paySign,            'success':function(res){                           },            'fail':function(res){                         },          })

这里一定要记得 /jsApiPay接口的 openid 如果是公众号的方式获取的,wxPayV3Bean.getAppId 也要是公众号的appid,小程序同理。
openid是微信的 相对于载体的用户唯一标识,公众号用户openid获取方式文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
用户openid获取简单流程就是
1.引导用户访问
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
scope 为snsapi_base时只能获取appid ,scope为snsapi_userinfo 可以获取用户的具体信息,可以来做微信登录(其他参数自己文档里看)
用授权成功后候回调到 REDIRECT_URI 并带着参数code
2.拿这个code到后台
访问接口
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
获得用户的 appid

以上就是本人对接微信支付的过程记录,如果碰到什么问题欢迎大家留言讨论

来源地址:https://blog.csdn.net/weixin_45029496/article/details/128470112

免责声明:

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

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

2023微信支付对接全流程

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

下载Word文档

猜你喜欢

springboot中怎么对接微信支付

springboot中怎么对接微信支付,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。对接的完整流程如下首先是配置gzh.appid=公众号appidwxPay.mchId=
2023-06-20

php微信支付流程是什么

今天小编给大家分享一下php微信支付流程是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。微信支付基本流程微信支付的基本流
2023-07-06

微信小程序支付流程(前端)

微信小程序的支付只要用到官方的支付API : wx.requestPayment(Object object) 官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/api/paym
2023-08-19

Java后端如何对接微信支付

本篇内容主要讲解“Java后端如何对接微信支付”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java后端如何对接微信支付”吧!首先我们要明确目标,我们点击微信支付官网,我们主要聚焦于这三种支付方
2023-06-22

Java对接微信支付(史上最详细)

Java对接微信支付(史上最详细) 本文将介绍如何使用Java对接微信支付,包括获取支付参数、支付回调处理等步骤。本文适用于已经熟悉微信支付基本原理的读者。 开发环境 JDK 1.8MavenSpring Boot 2.x微信支付开发文档
2023-08-17

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

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

微信支付、支付宝支付等常用第三方支付通道接口手续费对比

微信支付、支付宝等第三方支付,需要和银联、网联对接,有清算机构和银行的交易处理通道成本。费率指支付手续费的费率,不同行业、不同的支付平台、不同的支付额度或次数所对应的通道费率是不一样的。
2023-01-28

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

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

小程序开通微信支付的流程是什么

这篇文章主要介绍“小程序开通微信支付的流程是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“小程序开通微信支付的流程是什么”文章能帮助大家解决问题。  小程序开通微信支付的流程  最先便是务必要掌
2023-06-26

面试官:说说微信小程序的支付流程?

小程序支付和以往的网页、APP微信支付大同小异,可以说小程序的支付变得更加简洁,不需要设置支付目录、域名授权等操作。

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录