Зайдите на официальный сайт IJpay, и вы сразу увидите его. Совершите оплату в пределах досягаемости
。Очень уверенный и сильный
Он агрегирует различные платежи,ИнкапсулированныйWeChat Pay、QQ платеж、Оплата через Alipay、JD Pay、Оплата UnionPay、PayPal платежи другие часто используемые способы оплаты и различные часто используемые интерфейсы.。Не зависит от какой-либо третьей стороны mvc Фреймворк — это просто инструмент, который можно легко использовать для быстрого завершения разработки платежных модулей. Он может быть легко встроен в любую систему, а также обладает высокими возможностями в gitee. Stars
проекты с открытым исходным кодом.
Речь идет об интеграции платежей WeChat.
В файле application.yml
Это сертификат, загруженный с платформы WeChat.
нравиться:
certPath: apiclient_cert.pem
certKeyPath apiclient_key.pem
platFormPath платформа.pem
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-WxPay</artifactId>
<version>2.9.6</version>
</dependency>
Примечание:Controller
слой Не должно существовать try-catch
Блоки кода собраны здесь просто для удобства понимания кода. В реальных проектах их всё равно можно извлекать как угодно😋
package cn.cnvp.web.api.wechart;
import cn.cnvp.web.token.message.JsonResult;
import cn.cnvp.web.utils.WxUtils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.AesUtil;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.core.utils.DateTimeZoneUtil;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
import com.ijpay.wxpay.enums.v3.OtherApiEnum;
import com.ijpay.wxpay.model.v3.Amount;
import com.ijpay.wxpay.model.v3.Payer;
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: Blue 2113438464@QQ.com
* @Date: 2023/8/21 23:52
* @Description: WeChat Контролер оплаты
*/
@Slf4j
@Api(tags = "WeChat Контролер оплаты")
@RestController
@RequestMapping("/api/wx/pay/v1")
@Scope("prototype")
public class WxPayApiController {
/**Вичат-апплет**/
@Value("${wechat.ma.appId}")
String appid;
/**Вичат-апплет secretId**/
@Value("${wechat.ma.secret}")
String secret;
/**Идентификатор продавца**/
@Value("${wechat.ma.mchid}")
String mchid;
/**Ключ торговца**/
@Value("${wechat.ma.mchKey}")
String mchKey;
/**Адрес обратного вызова**/
@Value("${wechat.ma.notifyUrl}")
String notifyUrl;
/**Сертификатадрес**/ @Value("${wechat.ma.certPath}")
String certPath;
/**Адрес ключа сертификата**/
@Value("${wechat.ma.certKeyPath}")
String certKeyPath;
/**Вичатплатформа Сертификат**/ @Value("${wechat.ma.platFormPath}")
String platFormPath;
/**
* WeChat Pay
* @param openId Открытый идентификатор пользователя
*/
@RequestMapping("/jsApiPay")
@ResponseBody
public JsonResult 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()
// APPID
.setAppid(appid)
// Номер продавца
.setMchid(mchid)
.setDescription("IJPay Совершите оплату в пределах досягаемости")
.setOut_trade_no(PayKit.generateStr())
.setTime_expire(timeExpire)
.setAttach("Структура разработки системы Вичат https://gitee.com/javen205/TNWX")
.setNotify_url(notifyUrl)
.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(),
mchid,
getSerialNumber(),
null,
certKeyPath,
JSONUtil.toJsonStr(unifiedOrderModel)
);
log.info("Единый ответ на заказ {}", response);
// Проверьте результат подписи, запросив соответствующий серийный номер Сертификата.
boolean verifySignature = WxPayKit.verifySignature(response, platFormPath);
log.info("verifySignature: {}", verifySignature);
if (response.getStatus() == HttpStatus.HTTP_OK && verifySignature) {
String body = response.getBody();
JSONObject jsonObject = JSONUtil.parseObj(body);
String prepayId = jsonObject.getStr("prepay_id");
Map<String, String> map = WxPayKit.jsApiCreateSign(appid, prepayId, certKeyPath);
log.info("Отменить параметры платежа: {}", map);
return JsonResult.success("Достичь успеха",JSONUtil.toJsonStr(map));
}
} catch (Exception e) {
e.printStackTrace();
}
return JsonResult.error("вызвать не удалось");
}
/**
* WeChat Оплатить обратный звонок
*/
@RequestMapping(value = "/payNotify")
public 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,
mchKey, platFormPath);
log.info("Открытый текст уведомления о платеже {}", plainText);
if (StrUtil.isNotEmpty(plainText)) {
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();
}
}
private String getSerialNumber() {
// Получить серийный номер сертификата
X509Certificate certificate = PayKit.getCertificate(certPath);
if (null != certificate) {
String serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
// Проверьте, действителен ли Сертификат за два дня заранее.
boolean isValid = PayKit.checkCertificateIsValid(certificate, mchid, -2);
log.info("Доступен ли Сертификат? {} Сертификат действителен в течение {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN));
System.out.println("serialNo:" + serialNo);
return serialNo;
}
return null;
}
@RequestMapping("/get")
@ResponseBody
public String v3Get() {
// Получить список платформ
try {
IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.GET,
WxDomainEnum.CHINA.toString(),
OtherApiEnum.GET_CERTIFICATES.toString(),
mchid,
getSerialNumber(),
null,
certKeyPath,
""
);
String serialNumber = response.getHeader("Wechatpay-Serial");
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, platFormPath);
log.info("Серийный номер сертификата платформы: {} serialNo: {}", platSerialNo, serialNo);
}
// Проверьте результат подписи, запросив соответствующий серийный номер Сертификата.
boolean verifySignature = WxPayKit.verifySignature(response, platFormPath);
System.out.println("verifySignature:" + verifySignature);
return body;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Сохранить платформу
* @param associatedData associated_data
* @param nonce nonce
* @param cipherText cipherText
* @param certPath Путь сохранения сертификата
*/
private String savePlatformCert(String associatedData, String nonce, String cipherText, String certPath) {
try {
AesUtil aesUtil = new AesUtil(mchKey.getBytes(StandardCharsets.UTF_8));
// Расшифровка зашифрованного текста Сертификата Платформы
// encrypt_certificate в associated_data nonce ciphertext
String publicKey = aesUtil.decryptToString(
associatedData.getBytes(StandardCharsets.UTF_8),
nonce.getBytes(StandardCharsets.UTF_8),
cipherText
);
// держать Сертификат cn.hutool.core.io.file.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();
}
}
}
Коды в онлайн-кейсах очень простые, просто прочитайте их и все будет в порядке.
Сертификат Файл:platForm.pem
,Мы вызываем метод get выше,Вы можете скачать Сертификат,Загрузка будет завершена черезymlКонфигурациясоздание путиplatForm.pem
Сертификат
вызовjsApiPay
Интерфейс входящийopenID(Другие методы можно использовать позже.),Верните следующую строку JSON, чтобы указать успех
<template>
<view class="content">
<button @click="pay">платить</button>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello',
sign :{}
}
},
onLoad() {
},
methods: {
pay(){
uni.request({
// GetWeChat Адрес для подписи оплаты
url:"http://192.168.0.231:8087/api/wx/pay/v1/jsApiPay?openId=oEmg75RAQX-7uRqGUkSy0tGcfzpI",
// успешный обратный вызов
success: (res) => {
let sign =JSON.parse(res.data.data);
// Только для примера, а не реальная информация о параметрах.
uni.requestPayment({
provider: 'wxpay',
timeStamp: sign.timeStamp,
nonceStr: sign.nonceStr,
package: sign.package,
signType: sign.signType,
paySign: sign.paySign,
success: function (res) {
console.log('success:' + JSON.stringify(res));
},
fail: function (err) {
console.log('fail:' + JSON.stringify(err));
}
});
}
})
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
Адрес асинхронного обратного вызова, настроенный в yml (требуется доступ к внешней сети)
В этой статье лишь кратко описано использование Springboot, интегрирующего IJpay для оплаты WeChat. Эта статья предназначена для записей. Вы можете продолжить узнавать об этом больше.