当前位置:网站首页>Withdrawal of wechat applet (enterprise payment to change)
Withdrawal of wechat applet (enterprise payment to change)
2022-07-06 09:15:00 【Mr.Tomcat】
List of articles
- demand
- Preparation
- 1、 Log in to the official website of wechat merchant platform :[ Wechat payment - China's leading third-party payment platform | Wechat payment provides a safe and fast payment method (qq.com)](https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F)
- 2、 Find the enterprise in the product center and pay in change , And open the enterprise payment to change function
- 3、 find AppID Account management , Add Association AppID
- 4、 Bind wechat merchant ID to applet
- 5、 apply API Certificates and APIv2 secret key , Keep it well , We'll use it later
- 6、 Get merchant number
- Code implementation (SpringBoot)
- Last
demand
Implement a cash withdrawal function in wechat applet , The money withdrawn actually comes from other functions in the system .
Of course, this function , You need a wechat payment merchant number , And there should be sufficient balance in the account .
Preparation
1、 Log in to the official website of wechat merchant platform : Wechat payment - China's leading third-party payment platform | Wechat payment provides a safe and fast payment method (qq.com)
2、 Find the enterprise in the product center and pay in change , And open the enterprise payment to change function
3、 find AppID Account management , Add Association AppID
4、 Bind wechat merchant ID to applet
5、 apply API Certificates and APIv2 secret key , Keep it well , We'll use it later
notes :API The suffix of the certificate file is .p12
6、 Get merchant number
Code implementation (SpringBoot)
1、 Introduce relevant official dependencies
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
2、 stay yaml File add configuration
withDraw:
apiKey: xxxxxxxx
mchid: xxxxxx
mch_appid: xxxxxxxxx
// This path represents resouce root directory
certPath: /xxxxxxxx.p12
count: 10
quota: 200
3、 Write configuration classes
@Component
public class WithDrawConfig implements WXPayConfig {
// from yaml Injection allocation
@Value("${withDraw.mch_appid}")
private String mch_appid;
@Value("${withDraw.apiKey}")
private String apiKey;
@Value("${withDraw.mchid}")
private String mchid;
@Value("${withDraw.certPath}")
private String certPath;
@Override
public String getAppID() {
return mch_appid;
}
@Override
public String getMchID() {
return mchid;
}
@Override
public String getKey() {
return apiKey;
}
@Override
public InputStream getCertStream() {
// To get the certificate , The certificate is recommended to be placed in resource Under the table of contents
return this.getClass().getResourceAsStream(certPath);
}
@Override
public int getHttpConnectTimeoutMs() {
return 8000;
}
@Override
public int getHttpReadTimeoutMs() {
return 10000;
}
}
4、 Prepare withdrawal tools
@Slf4j
@Component
@RequiredArgsConstructor
public class WithDrawUtils {
@Value("${withDraw.mch_appid}")
private String mch_appid;
@Value("${withDraw.mchid}")
private String mchid;
@Value("${withDraw.apiKey}")
private String apiKey;
private final WithDrawConfig withDrawConfig;
// Generate order number date time + Random character
public String getOrderNumber() {
SimpleDateFormat date = new SimpleDateFormat("yyyyMMddHHmmss");
return date.format(new Date()) + RandomStringUtils.randomNumeric(4);
}
public Map<String, String> fillRequest(Map<String, String> reqData) throws Exception {
reqData.put("mch_appid", mch_appid);
reqData.put("mchid", mchid);
reqData.put("nonce_str", WXPayUtil.generateNonceStr().toUpperCase());
reqData.put("sign", WXPayUtil.generateSignature(reqData, apiKey, WXPayConstants.SignType.MD5));
return reqData;
}
public String getMd5ByString(String str) {
StringBuilder hexString = new StringBuilder();
try {
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(str.getBytes());
byte[] hash = mdTemp.digest();
for (byte b : hash) {
if ((0xff & b) < 0x10) {
hexString.append("0").append(Integer.toHexString((0xFF & b)));
} else {
hexString.append(Integer.toHexString(0xFF & b));
}
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return hexString.toString();
}
/** * Convert objects directly to String Type of XML Output * * @param obj * @return */
public String convertToXml(Object obj) {
// Create output stream
StringWriter sw = new StringWriter();
try {
// utilize jdk Implementation of the built-in conversion class in
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
// format xml Format of output
marshaller.setProperty(Marshaller.JAXB_FRAGMENT,
Boolean.TRUE);
// Converting objects into output streams xml
marshaller.marshal(obj, sw);
} catch (JAXBException e) {
e.printStackTrace();
}
return sw.toString();
}
public String getRestInstance(String url, String data) throws Exception {
String UTF8 = "UTF-8";
URL httpUrl = new URL(url);
char[] password = mchid.toCharArray();// Certificate password
InputStream certStream = withDrawConfig.getCertStream();// Get the stream of certificates
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(certStream, password);
// Instantiate the keystore & Initialize the key factory
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, password);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), (TrustManager[]) null, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpURLConnection httpURLConnection = (HttpURLConnection) httpUrl.openConnection();
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setConnectTimeout(withDrawConfig.getHttpConnectTimeoutMs());
httpURLConnection.setReadTimeout(withDrawConfig.getHttpReadTimeoutMs());
httpURLConnection.connect();
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(data.getBytes(UTF8));
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF8));
StringBuilder stringBuffer = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
}
String resp = stringBuffer.toString();
try {
bufferedReader.close();
} catch (IOException ignored) {
}
try {
inputStream.close();
} catch (IOException ignored) {
}
try {
outputStream.close();
} catch (IOException ignored) {
}
if (certStream != null) {
try {
certStream.close();
} catch (IOException ignored) {
}
}
return resp;
}
}
5、 Withdrawal business realization
Official interface document :【 Wechat payment 】 Payment developer documentation (qq.com)
// Start withdrawing cash , Generate order number
String orderNumber = withDrawUtils.getOrderNumber();
// Customized entity class that encapsulates the required parameters for withdrawal
WithDrawDTO withDrawDTO = new WithDrawDTO();
withDrawDTO.setPartner_trade_no(orderNumber);
withDrawDTO.setDesc("xxxxx");
withDrawDTO.setAmount(appletWithDrawDTO.getAmount());
// This parameter represents , Enable real name verification , You can also turn off , See the parameter description in the official document for details
withDrawDTO.setCheck_name("FORCE_CHECK");
withDrawDTO.setRe_user_name(appletWithDrawDTO.getName());
// Wechat applet users openid
withDrawDTO.setOpenid(wxUser.getOpenid());
Map<String, String> params = JSON.parseObject(JSON.toJSONString(withDrawDTO), new TypeReference<Map<String, String>>() {
});
params = withDrawUtils.fillRequest(params);
withDrawDTO.setNonce_str(params.get("nonce_str"));
withDrawDTO.setMchid(params.get("mchid"));
withDrawDTO.setMch_appid(params.get("mch_appid"));
withDrawDTO.setSign(params.get("sign"));
String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
String post = withDrawUtils.getRestInstance(url, withDrawUtils.convertToXml(withDrawDTO));
Map<String, String> result = WXPayUtil.xmlToMap(post);
//result Is the return parameter after calling the interface , You can judge whether it is successful according to the return parameters
WithDrawEnum resultEnum;
if ("SUCCESS".equals(result.get("result_code"))) {
// Withdrawal succeeded
resultEnum = WithDrawEnum.fromText("SUCCESS");
return resultEnum;
} else {
// Withdrawal failed
resultEnum = WithDrawEnum.fromText(result.get("err_code"));
throw new BadRequestException(resultEnum);
}
6、 Withdraw the enumeration class that returns the error code
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum WithDrawEnum {
SUCCESS(0, " Withdrawal succeeded "),
FAIL(400, " Withdrawal failed , The balance is less than the withdrawal amount "),
HANDLE_FRE(5000, " Too often "),
NO_AUTH(5001, " No permission for this interface "),
AMOUNT_LIMIT(5002, " The amount exceeds the limit "),
PARAM_ERROR(5003, " Parameter error "),
OPENID_ERROR(5004, "Openid error "),
SEND_FAILED(5005, " Payment error "),
NOTENOUGH(5006, " Lack of balance "),
SYSTEMERROR(5007, " The system is busy , Please try again later ."),
NAME_MISMATCH(5008, " Name verification error "),
SIGN_ERROR(5009, " Signature error "),
XML_ERROR(5010, " Error sending content "),
FATAL_ERROR(5011, " The two sending parameters are inconsistent "),
FREQ_LIMIT(5012, " Frequency limit exceeded , Please try again later ."),
MONEY_LIMIT(5013, " You have reached the upper limit of today's total payment / This payment limit has been reached "),
CA_ERROR(5014, " Merchant certificate verification error "),
V2_ACCOUNT_SIMPLE_BAN(5015, " Unable to pay users without real names "),
PARAM_IS_NOT_UTF8(5016, " The sending parameter contains irregular characters "),
SENDNUM_LIMIT(5017, " The number of payments made by this user today exceeds the limit , If necessary, please enter 【 WeChat payment merchant platform - Product center - Pay in change - Product settings 】 Make changes "),
RECV_ACCOUNT_NOT_ALLOWED(5018, " The collection account is not in the collection account list "),
PAY_CHANNEL_NOT_ALLOWED(5019, " This merchant ID is not configured with this function "),
SEND_MONEY_LIMIT(5020, " The upper limit of today's merchant payment limit has been reached "),
RECEIVED_MONEY_LIMIT(5021, " You have reached the limit of payment to this user today ");
private int code;
private String msg;
public static WithDrawEnum fromText(String text) {
if (text != null) {
for (WithDrawEnum b : WithDrawEnum.values()) {
if (text.equalsIgnoreCase(b.name())) {
return b;
}
}
}
return null;
}
}
Last
Call of wechat related interfaces , The main thing is to be patient with the instructions of the document , To achieve business needs .
边栏推荐
- Advanced Computer Network Review(4)——Congestion Control of MPTCP
- Redis geospatial
- ant-design的走马灯(Carousel)组件在TS(typescript)环境中调用prev以及next方法
- [oc]- < getting started with UI> -- common controls uibutton
- Improved deep embedded clustering with local structure preservation (Idec)
- QML type: overlay
- Pytest之收集用例规则与运行指定用例
- LeetCode:39. Combined sum
- Kratos战神微服务框架(一)
- LeetCode41——First Missing Positive——hashing in place & swap
猜你喜欢
The carousel component of ant design calls prev and next methods in TS (typescript) environment
What is MySQL? What is the learning path of MySQL
Parameterization of postman
Blue Bridge Cup_ Single chip microcomputer_ Measure the frequency of 555
不同的数据驱动代码执行相同的测试场景
CUDA implementation of self defined convolution attention operator
CUDA realizes focal_ loss
Advance Computer Network Review(1)——FatTree
UML diagram memory skills
Redis之持久化实操(Linux版)
随机推荐
[three storage methods of graph] just use adjacency matrix to go out
Redis cluster
[sword finger offer] serialized binary tree
What is MySQL? What is the learning path of MySQL
[oc]- < getting started with UI> -- learning common controls
Master slave replication of redis
Go redis initialization connection
Export IEEE document format using latex
What is an R-value reference and what is the difference between it and an l-value?
【文本生成】论文合集推荐丨 斯坦福研究者引入时间控制方法 长文本生成更流畅
[OC-Foundation框架]---【集合数组】
MySQL uninstallation and installation methods
Leetcode problem solving 2.1.1
七层网络体系结构
[OC foundation framework] - [set array]
How to intercept the string correctly (for example, intercepting the stock in operation by applying the error information)
Redis之cluster集群
An article takes you to understand the working principle of selenium in detail
LeetCode41——First Missing Positive——hashing in place & swap
BMINF的後訓練量化實現