1.微信支付申请流程和步骤

1.注册微信支付账号和微信小程序账号

2.获取微信小程序的APPID

3.获取微信商家的商户ID

4.获取微信商家的API私钥

5.配置微信支付回调地址

6.绑定微信小程序和微信支付的关系

7. 搭建Springboot 工程定义后台编写支付接口

8. 发布部署接口服务项目

9. 使用微信小程序或者Uniapp完成微信支付的调用

10.对支付接口的封装以及前端代码的封装

11.配置jwt 和openid的token派发,让接口更加安全可靠

12.原生微信小程序完成支付对接

2.申请注册流程和文档

官方地址:https://pay.weixin.qq.com/index.php

官方文档:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml

PC端微信小程序Navtive文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_0.shtml

微信小程序支付对接文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml

生成私钥的代码

/**

* 获取一定长度的随机字符串

* @param length 指定字符串长度

* @return 一定的长度的字符串

**/

public static String getRandomStringByLength(int length){

String base = “abcdefghijklmnopqrstuvwxyz0123456789”;

Random rondom = new Random();

StringBuffer sb = new StringBuffer();

for(int i = 0; i < random.length; i++){

int number = random.nextInt(base.length());

sb.append(base.charAt(number));

}

return sb.toString();

}

3.Springboot对接微信支付

3.1 后端获取openid

进入微信官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html

controller :

package com.kuang.weixinpay.controller;

import com.google.gson.Gson;

import com.kuang.weixinpay.anno.IgnoreToken;

import com.kuang.weixinpay.common.exception.KuangShenException;

import com.kuang.weixinpay.common.pay.HttpClientUtils;

import com.kuang.weixinpay.config.properties.WeixinLoginProperties;

import com.kuang.weixinpay.vo.R;

import lombok.extern.log4j.Log4j2;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.util.StringUtils;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

import java.util.Map;

@RestController

@Log4j2

public class ApiLoginController extends ApiBaseController {

/***

* @Author

* @Description openid接口的获取

* @Date 22:22 2021/4/24

* @Param [code]

* @return com.kuangstudy.weixinpay.vo.R

* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html

* https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html

*

**/

@IgnoreToken

@GetMapping(“/wxlogin”)

public R callback(String code) {

// 1:判断code是否合法

if (StringUtils.isEmpty(code)) {

throw new KuangShenException(22008, “登录失败,尝试刷新重新扫码登录!”);

}

// 2:通过code获取access_token

// 完成的连接:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

// 参考地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html

String baseAccessTokenUrl = WeixinLoginProperties.WX_OPEN_GATEWAY +

“?appid=%s” +

“&secret=%s” +

“&js_code=%s” +

“&grant_type=authorization_code”;

log.info(“1:appid:{},appscrect:{}”, WeixinLoginProperties.WX_OPEN_APP_ID, WeixinLoginProperties.WX_OPEN_APP_SECRET);

String accessTokenUrl = String.format(baseAccessTokenUrl, WeixinLoginProperties.WX_OPEN_APP_ID, WeixinLoginProperties.WX_OPEN_APP_SECRET, code);

String result = null;

try {

//2:执行请求,获取微信请求返回得数据

result = new HttpClientUtils().get(accessTokenUrl);

log.info(“2—->微信返回的日志信息是:code:{},result:{}”, code, result);

// 3: 对微信返回得数据进行转换

Gson gson = new Gson();

Map resultMap = gson.fromJson(result, HashMap.class);

log.info(“3—->微信返回的日志信息是:code:{},resultMap:{}”, code, resultMap);

if (resultMap.get(“errcode”) != null) {

throw new KuangShenException(22006, “微信登录出错!”);

}

// 4: 解析微信用户得凭证openid

String openid = (String) resultMap.get(“openid”);

if (StringUtils.isEmpty(openid)) {

throw new KuangShenException(22009, “登录失败,尝试刷新重新扫码登录!!!”);

}

// 5:封装返回

return R.ok().data(“openid”, openid).data(“resultMap”,resultMap);

} catch (Exception e) {

return R.error().code(601).message(“微信解析失败”);

}

}

}

微信登录的实体类

package com.kuang.weixinpay.config.properties;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.PropertySource;

import org.springframework.core.env.Environment;

import org.springframework.stereotype.Component;

@Component

@PropertySource(“classpath:application.yml”)

public class WeixinLoginProperties implements InitializingBean {

@Value(“${weixin.login.info.gateway}”)

private String gateway;

@Value(“${weixin.login.info.appid}”)

private String appid;

@Value(“${weixin.login.info.appsecret}”)

private String appsecret;

@Value(“${weixin.login.info.redirectUrl}”)

private String redirectUrl;

public static String WX_OPEN_GATEWAY;

public static String WX_OPEN_APP_ID;

public static String WX_OPEN_APP_SECRET;

public static String WX_OPEN_REDIRECT_URL;

@Override

public void afterPropertiesSet() throws Exception {

WX_OPEN_APP_ID = appid;

WX_OPEN_GATEWAY = gateway;

WX_OPEN_APP_SECRET = appsecret;

WX_OPEN_REDIRECT_URL = redirectUrl;

}

}

application.yml 进行配置

微信登录相关

weixin:

login:

info:

微信登录网关

gateway: https://api.weixin.qq.com/sns/jscode2session

微信小程序APPID

appid: xxxxx

微信小程序API私钥

appsecret: xxxxx

微信小程序登录成功回调地址

redirectUrl: xxxxx

3.2 定义微信支付接口

微信小程序支付

package com.kuang.weixinpay.config.properties;

import lombok.Data;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.context.annotation.Configuration;

@Configuration

@ConfigurationProperties(prefix = “weixin.pay.info”)

@Data

public class WeixinPayProperties {

// 定义微信解密获取手机号码的接口地址,固定的

private String gateway;

//小程序APPID

private String appid;

//小程序APPID

private String type;

//小程序APPSceret

private String appsecret;

//商户ID

private String mchid;

//回调地址

private String notifyPath;

}

配置的xml 文件

pay:

info:

微信支付网关

gateway: https://api.mch.weixin.qq.com/pay/unifiedorder

微信支付API秘钥

appsecret: xxxxx

微信商户id

mchid: xxxxx

签约产品的类

type: JSAPI

微信小程序APPID

appid: xxxxx

支付成功回调地址,如果是微信小程序可以不配置

notifyPath: xxxxx

微信支付成功信息配置

package com.kuang.weixinpay.common.pay.weixin.request;

import com.kuang.weixinpay.common.pay.weixin.ReportReqData;

import com.kuang.weixinpay.common.pay.weixin.config.WeiXinConstants;

import com.kuang.weixinpay.common.pay.weixin.sign.Signature;

import com.kuang.weixinpay.common.pay.weixin.util.WeiXinRequest;

import com.kuang.weixinpay.common.pay.weixin.util.XMLParser;

import com.kuang.weixinpay.config.properties.WeixinPayProperties;

import lombok.extern.log4j.Log4j2;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import java.util.HashMap;

import java.util.Map;

/**

* 数据提交并且生成二维码

* WeixinSubmit

* 创建人:小威

* 时间:2015年10月16日-下午2:14:47

*

* @version 1.0.0

*/

@Log4j2

@Component

public class QrCodeRequest {

@Autowired

private WeixinPayProperties weixinPayProperties;

/**

* 微信支付成功信息配置

* 方法名:submitWeixinMessage

* 创建人:mofeng

* 时间:2018年11月28日-下午2:06:06

* 手机:1564545646464

*

* @param data

* @return Map

* @throws

* @since 1.0.0

*/

public Map submitWeixinMessage(ReportReqData data) {

try {

data.setTrade_type(data.getTrade_type());//扫一扫支付方式 NATIVE

data.setSign(Signature.getSign(data.toMap(),weixinPayProperties.getAppsecret()));//签名字符

// 发起支付请求

String returnData = WeiXinRequest.submitData(weixinPayProperties.getGateway(), data.toMap());

// returnData返回的是xml格式

System.out.println(“======================>” + returnData);

if (StringUtils.isNotEmpty(returnData)) {

log.info(“当前支付成功返回的数据: ============>{}”,returnData);

//解析返回的字符串 并且组成map集合

Map map = XMLParser.getMapFromXML(returnData);

System.out.println(“==============================>” + map);

if (null != map && !map.isEmpty()) {

String resultCode = (String) map.get(WeiXinConstants.RESULT);

if (“SUCCESS”.equals(resultCode)) {//链接生成成功

HashMap nmap = new HashMap<>();

String params = data.getAttach().replace(“”, “\””);

nmap.put(“appId”, data.getAppid());

nmap.put(“timeStamp”, System.currentTimeMillis() + “”);

nmap.put(“signType”, “MD5”);

nmap.put(“nonceStr”, data.getNonce_str());

nmap.put(“package”, “prepay_id=” + map.get(“prepay_id”));

nmap.put(“paySign”, Signature.getSign(nmap, weixinPayProperties.getAppsecret()));

nmap.put(“attach”,params);

nmap.put(“orderNumber”, data.getOut_trade_no() + “”);

return nmap;

}

}

}

return null;

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

}

微信小程序支付接口

package com.kuang.weixinpay.controller;

import com.alibaba.fastjson.JSONObject;

import com.kuang.weixinpay.common.pay.weixin.ReportReqData;

import com.kuang.weixinpay.common.pay.weixin.request.QrCodeRequest;

import com.kuang.weixinpay.common.pay.weixin.util.RandomStringGenerator;

import com.kuang.weixinpay.config.properties.WeixinPayProperties;

import com.kuang.weixinpay.entity.Product;

import com.kuang.weixinpay.service.ProductService;

import com.kuang.weixinpay.utils.snow.SnowflakeIdWorker;

import com.kuang.weixinpay.vo.R;

import lombok.extern.log4j.Log4j2;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

import java.util.Map;

/**

* @author

* @Title:

* @Package

* @Description:

* @date 2021/4/2212:05

*/

@RestController

@Log4j2

public class ApiPayController extends ApiBaseController {

@Autowired

private WeixinPayProperties weixinProperties;

@Autowired

private ProductService productService;

@Autowired

private QrCodeRequest qrCodeRequest;

/**

* @Author

* @Description 微信小程序支付的接口

* @Date 10:39 2021/4/25

* @Param [request]

* @return com.kuangstudy.weixinpay.vo.R

**/

@GetMapping(“/weixinpay”)

public R payVip(HttpServletRequest request) {

//开始支付,创建数据体

JSONObject json = new JSONObject();

//业务数据

String productId = request.getParameter(“pid”);

if(StringUtils.isEmpty(productId))return R.error().code(601).message(“产品没找到!”);

// 1:根据产品id查询对应产品信息

Product product = productService.getById(productId);

if(product==null)return R.error().code(601).message(“产品没找到!”);

// 2:生成订单号

String orderNo = new SnowflakeIdWorker(1, 2).nextId() + “”;

String ip = “127.0.0.1”;

// 3:获取微信小程序的openid

String openid = request.getParameter(“openid”);

if(StringUtils.isEmpty(openid))return R.error().code(601).message(“openid没找到!”);

//4:分账接收方用户Id session或者redis

Integer userId = 1;

// 组装微信支付数据

ReportReqData data = new ReportReqData();

// openid

data.setOpenid(openid);

// 签约的类型JSAPI

data.setTrade_type(weixinProperties.getType());

// 微信小程序的appid

data.setAppid(weixinProperties.getAppid());

// 商户id

data.setMch_id(weixinProperties.getMchid());

// 回调地址 如果是微信小程序不用配置也可以,好配置

data.setNotify_url(weixinProperties.getNotifyPath());

// 业务数据

data.setBody(product.getTitle());//套餐名称

data.setOut_trade_no(orderNo);//订单号

data.setProduct_id(productId+””);//商品ID

data.setSpbill_create_ip(ip);//ip地址

data.setTotal_fee(getMoney(product.getPrice()));//金额

data.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));

json.put(“userId”, userId);

json.put(“type”, “productpay”);

json.put(“ip”, ip);

//创建订单

String params = json.toString().replace(“\””, “”);

log.info(“执行支付传递的参数: {}”, params);

data.setAttach(params);

log.info(“操作完毕,开始发起支付”);

//微信支付返回的结果

Map weixinMap = qrCodeRequest.submitWeixinMessage(data);

return R.ok().data(“weixinMap”,weixinMap).data(“xxx”,”xxxx”);

}

/**

* 元转换成分

*

* @param amount

* @return

*/

public static String getMoney(String amount) {

if (amount == null) {

return “”;

}

// 金额转化为分为单位

// 处理包含, ¥ 或者$的金额

String currency = amount.replaceAll(“\\$|\\¥|\\,”, “”);

int index = currency.indexOf(“.”);

int length = currency.length();

Long amLong = 0L;

if (index == -1) {

amLong = Long.valueOf(currency + “00”);

} else if (length – index >= 3) {

amLong = Long.valueOf((currency.substring(0, index + 3)).replace(“.”, “”));

} else if (length – index == 2) {

amLong = Long.valueOf((currency.substring(0, index + 2)).replace(“.”, “”) + 0);

} else {

amLong = Long.valueOf((currency.substring(0, index + 1)).replace(“.”, “”) + “00”);

}

return amLong.toString();

}

}

作者 nasiapp

在线客服
官方客服
我们将24小时内回复。
12:01
您好,有任何疑问请与我们联系!

选择聊天工具: