前端:
前提:微信开放平台申请appId后,到微信商户平台关联此appId
按照上图勾选和填写
支付代码如下:
pay() {
let that = this;
// 参数 根据自己项目更改
let vInfo = {};
vInfo.orderType = 1;
vInfo.totalPrice = 0;
// 绑定APPID
uni.getProvider({
/* 获取服务类型,可选值如下:
* @param share: 分享
* @param oauth: 授权登录
* @param push: 推送
* @param payment: 支付类型
*/
service: 'payment',
success: (res) => {
if (res.provider.indexOf('wxpay') != -1) {
uni.request({
url: config + `/wechat/payment`,
method: 'POST',
data: vInfo,
header: {
'Content-Type': 'application/json'
},
success(res) {
if (res.errMsg == 'request:ok') {
let info = res.data;
var orderInfos = {
"appid": info.appid, // 应用ID(AppID)
"partnerid": info.partnerid, // 商户号(PartnerID)
"prepayid": info.prepayid, // 预支付交易会话ID
"package": info.package, // 固定值
"noncestr": info.noncestr, // 随机字符串
"timestamp": info.timestamp, // 时间戳(单位:秒)
"sign": info.sign, // 签名,这里用的 MD5 签名
};
uni.requestPayment({
provider: "wxpay",
orderInfo: orderInfos,
success(res) {
// 支付成功
},
fail(err) {
console.log("微信支付失败");
}
});
}
},
fail(err) {
console.log("支付失败:", err)
}
})
}
}
});
}
后端使用java语言
添加依赖:
<!-- 微信支付SDk-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.7</version>
</dependency>
<!-- 微信支付java-sdk工具包 -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.11</version>
</dependency>
代码:
package **************;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.car.server.config.AppPayV3Bean;
import com.car.server.config.AppWXPayConstants;
import com.car.server.entity.pay.*;
import com.car.server.service.WxPayService;
import com.car.server.utils.R;
import com.car.server.utils.pay.AesUtil;
import com.car.server.utils.pay.AppWXPaySignatureCertificateUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
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.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
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.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.*;
@Slf4j
@RestController
@RequestMapping("wechat")
public class AppPayController {
private CloseableHttpClient httpClient;
private CertificatesManager certificatesManager;
private Verifier verifier;
/**
* App下单 具体下单场景查看官方文档
*
* @return
* @throws Exception
*/
@PostMapping("payment")
public String requestwxChatPay(@RequestBody WXPayOrderReqVO obj) throws Exception {
String title = obj.getOrderType() == 1 ? "" : obj.getOrderType() == 2 ? "" : obj.getOrderType() == 3 ? "" : "";
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(PayConstants.privateKey.getBytes("utf-8")));
// 获取证书管理器实例
certificatesManager = CertificatesManager.getInstance();
// 向证书管理器增加需要自动更新平台证书的商户信息
certificatesManager.putMerchant(PayConstants.MCH_ID, new WechatPay2Credentials(PayConstants.MCH_ID,
new PrivateKeySigner(PayConstants.MCH_SERIAL_NO, merchantPrivateKey)),
PayConstants.API_3KEY.getBytes(StandardCharsets.UTF_8));
// 从证书管理器中获取verifier
verifier = certificatesManager.getVerifier(PayConstants.MCH_ID);
httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(PayConstants.MCH_ID, PayConstants.MCH_SERIAL_NO, merchantPrivateKey)
.withValidator(new WechatPay2Validator(certificatesManager.getVerifier(PayConstants.MCH_ID)))
.build();
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/app");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
//时间戳,
String times = System.currentTimeMillis() + "";
//订单编号(自定义 这里以时间戳+随机数)
Random random = new Random();
String orderSn = times+random.nextInt(1000);
//组合请求参数JSON格式
ObjectNode rootNode = objectMapper.createObjectNode();
rootNode.put("mchid", PayConstants.MCH_ID)
.put("appid", PayConstants.APP_ID)
.put("notify_url", PayConstants.NOTIFY_URL + "notify")
.put("description", title)
.put("out_trade_no", orderSn);
rootNode.putObject("amount")
.put("total", obj.getTotalPrice()*100)
.put("currency", "CNY");
try {
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
//获取预支付ID
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
//微信成功响应
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
//时间戳
String timestamp = System.currentTimeMillis() / 1000 + "";
//随机字符串
String nonce = RandomUtil.randomString(32);
StringBuilder builder = new StringBuilder();
// Appid
builder.append(PayConstants.APP_ID).append("\n");
// 时间戳
builder.append(timestamp).append("\n");
// 随机字符串
builder.append(nonce).append("\n");
JsonNode jsonNode = objectMapper.readTree(bodyAsString);
// 预支付会话ID
builder.append(jsonNode.get("prepay_id").textValue()).append("\n");
//获取签名
String sign = this.sign(builder.toString().getBytes("utf-8"), merchantPrivateKey);
JSONObject jsonMap = new JSONObject();
jsonMap.put("noncestr", nonce);
jsonMap.put("timestamp", timestamp);
jsonMap.put("prepayid", jsonNode.get("prepay_id").textValue());
jsonMap.put("sign", sign);
jsonMap.put("package", PayConstants.PACKAGE);
jsonMap.put("appid", PayConstants.APP_ID);
jsonMap.put("partnerid", PayConstants.MCH_ID);
return jsonMap.toJSONString();//响应签名数据,前端拿着响应数据调起微信SDK
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 计算签名
*
* @param message
* @param yourPrivateKey
* @return
*/
private String sign(byte[] message, PrivateKey yourPrivateKey) {
try {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(yourPrivateKey);
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return "";
}
}
PayConstants接口:
package com.car.server.entity.pay;
/**
* 支付参数配置
*/
public interface PayConstants {
String NOTIFY_URL = ""; //回调地址
String MCH_ID = ""; //商户号
String MCH_SERIAL_NO = ""; //商户证书序列号
String API_3KEY = ""; //Api密钥
String APP_ID = ""; //ApId
String PACKAGE = "Sign=WXPay"; //签名国定字符串
String privateKey = "";//商户私钥
}
WXPayOrderReqVO:
package *******;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 预支付请求类
*/
@Data
@Accessors(chain = true)
public class WXPayOrderReqVO {
@ApiModelProperty("订单支付类型(1.** 2. ** 3. **)")
private Integer orderType;//附加数据,回调时可根据这个数据辨别订单类型或其他
@ApiModelProperty("总金额(单位:分)")
private Integer totalPrice;
@ApiModelProperty("openid")
private String openid;
@ApiModelProperty("商品订单号")
private String orderSn;
}