当前位置:网站首页>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 .
边栏推荐
- LeetCode:34. Find the first and last positions of elements in a sorted array
- CUDA实现focal_loss
- Redis' bitmap
- How to intercept the string correctly (for example, intercepting the stock in operation by applying the error information)
- Intel Distiller工具包-量化实现1
- [OC]-<UI入门>--常用控件-提示对话框 And 等待提示器(圈)
- Once you change the test steps, write all the code. Why not try yaml to realize data-driven?
- LeetCode:498. Diagonal traversal
- Kratos战神微服务框架(二)
- UML圖記憶技巧
猜你喜欢
[OC-Foundation框架]-<字符串And日期与时间>
LeetCode41——First Missing Positive——hashing in place & swap
[OC]-<UI入门>--常用控件的学习
Redis之五大基础数据结构深入、应用场景
KDD 2022 paper collection (under continuous update)
Pytest之收集用例规则与运行指定用例
Kratos ares microservice framework (II)
[oc]- < getting started with UI> -- learning common controls
如何正确截取字符串(例:应用报错信息截取入库操作)
Reids之缓存预热、雪崩、穿透
随机推荐
Chapter 1 :Application of Artificial intelligence in Drug Design:Opportunity and Challenges
使用标签模板解决用户恶意输入的问题
LeetCode:221. Largest Square
LeetCode:673. Number of longest increasing subsequences
Redis之持久化实操(Linux版)
LeetCode:41. Missing first positive number
QML control type: menu
Master slave replication of redis
Redis之哨兵模式
Redis之连接redis服务命令
Redis' bitmap
[OC-Foundation框架]---【集合数组】
注意力机制的一种卷积替代方式
KDD 2022 paper collection (under continuous update)
Redis cluster
Advance Computer Network Review(1)——FatTree
[OC]-<UI入门>--常用控件-UIButton
什么是MySQL?MySql的学习之路是怎样的
Advanced Computer Network Review(4)——Congestion Control of MPTCP
Kratos ares microservice framework (II)