当前位置:网站首页>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 .
边栏推荐
- [oc foundation framework] - < copy object copy >
- Digital people anchor 618 sign language with goods, convenient for 27.8 million people with hearing impairment
- LeetCode:39. Combined sum
- Mise en œuvre de la quantification post - formation du bminf
- Intel Distiller工具包-量化实现2
- LeetCode:41. Missing first positive number
- QML control type: Popup
- How to intercept the string correctly (for example, intercepting the stock in operation by applying the error information)
- 五层网络体系结构
- KDD 2022 paper collection (under continuous update)
猜你喜欢
一改测试步骤代码就全写 为什么不试试用 Yaml实现数据驱动?
自定义卷积注意力算子的CUDA实现
Kratos战神微服务框架(二)
[oc]- < getting started with UI> -- common controls - prompt dialog box and wait for the prompt (circle)
Reids之删除策略
LeetCode41——First Missing Positive——hashing in place & swap
LeetCode41——First Missing Positive——hashing in place & swap
Once you change the test steps, write all the code. Why not try yaml to realize data-driven?
[OC-Foundation框架]---【集合数组】
BN folding and its quantification
随机推荐
postman之参数化详解
数学建模2004B题(输电问题)
[today in history] February 13: the father of transistors was born The 20th anniversary of net; Agile software development manifesto was born
Mongodb installation and basic operation
Redis之Geospatial
IDS cache preheating, avalanche, penetration
The carousel component of ant design calls prev and next methods in TS (typescript) environment
Redis之哨兵模式
七层网络体系结构
【shell脚本】使用菜单命令构建在集群内创建文件夹的脚本
CSP salary calculation
【图的三大存储方式】只会用邻接矩阵就out了
Mise en œuvre de la quantification post - formation du bminf
Implement window blocking on QWidget
[OC foundation framework] - [set array]
Mathematical modeling 2004b question (transmission problem)
CUDA实现focal_loss
UML圖記憶技巧
Five layer network architecture
LeetCode:221. Largest Square